yshop意向点餐系统v1.2.2
This commit is contained in:
1 parent
d03982bf66
commit
fc575265c3
4685 files changed
+518513
-182051
No files matched your search
@@ -0,0 +1,245 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="cart-popup">
|
||||
<view class="top flex justify-between">
|
||||
<text>已点{{ getCartGoodsNumber }}份</text>
|
||||
<text @tap="handleCartClear">清空</text>
|
||||
</view>
|
||||
<scroll-view class="cart-list" scroll-y>
|
||||
<view class="wrapper">
|
||||
<uv-empty mode="car" v-if="cart.length == 0"></uv-empty>
|
||||
<view class="item" v-for="(item, index) in cart" :key="index">
|
||||
<view class="left">
|
||||
<view class="name">{{ item.name }}</view>
|
||||
<view class="props">{{ item.valueStr }}</view>
|
||||
</view>
|
||||
<view class="center">
|
||||
<text>¥{{ item.price }}</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<button type="default" plain size="mini" class="btn" hover-class="none"
|
||||
@tap="handleCartItemReduce(index)">
|
||||
<view class="iconfont iconsami-select"></view>
|
||||
</button>
|
||||
<view class="number">{{ item.number }}</view>
|
||||
<button type="primary" class="btn" size="min" hover-class="none"
|
||||
@tap="handleCartItemAdd(index)">
|
||||
<view class="iconfont iconadd-select"></view>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="fixed-bottom flex justify-between align-center bg-white ">
|
||||
<view class="mx-2 ont-weight-light">应付:<text class="text-danger">¥{{ getCartGoodsPrice }}</text></view>
|
||||
<view><uv-button type="warning" color="#dd524d" :customStyle="customStyle" size="large" text="去结算" @click="toPay"></uv-button></view>
|
||||
</view>
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
const main = useMainStore()
|
||||
const { orderType,address, store,location,isLogin } = storeToRefs(main)
|
||||
const title = ref('购物车')
|
||||
const cart = ref([])
|
||||
const uToast = ref()
|
||||
|
||||
// onLoad(() => {
|
||||
// cart.value = uni.getStorageSync('cart')
|
||||
// })
|
||||
onShow(() => {
|
||||
//cart.value = []
|
||||
cart.value = uni.getStorageSync('cart')
|
||||
})
|
||||
const getCartGoodsNumber = computed(() => { //计算购物车总数
|
||||
if(cart.value.length == 0) {
|
||||
return 0
|
||||
}
|
||||
return cart.value.reduce((acc, cur) => acc + cur.number, 0)
|
||||
})
|
||||
const getCartGoodsPrice = computed(() =>{ //计算购物车总价
|
||||
if(cart.value.length == 0) {
|
||||
return 0
|
||||
}
|
||||
let price = cart.value.reduce((acc, cur) => acc + cur.number * cur.price, 0);
|
||||
return parseFloat(price).toFixed(2);
|
||||
})
|
||||
const customStyle = computed(() =>{
|
||||
return {
|
||||
paddingLeft:'60rpx',
|
||||
paddingRight:'60rpx'
|
||||
}
|
||||
})
|
||||
const handleCartItemAdd = (index) => {
|
||||
cart.value[index].number += 1
|
||||
uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
|
||||
}
|
||||
const handleCartItemReduce = (index) => {
|
||||
if (cart.value[index].number === 1) {
|
||||
cart.value.splice(index, 1)
|
||||
} else {
|
||||
cart.value[index].number -= 1
|
||||
}
|
||||
if (!cart.value.length) {
|
||||
cartPopupVisible.value = false
|
||||
}
|
||||
uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
|
||||
}
|
||||
const handleCartClear = () => { //清空购物车
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定清空购物车么',
|
||||
success: ({
|
||||
confirm
|
||||
}) => {
|
||||
if (confirm) {
|
||||
cart.value = []
|
||||
uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const toPay = () => {
|
||||
|
||||
if(cart.value.length == 0){
|
||||
uToast.value.show({message:'请先去点餐哦',type: 'error'});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLogin.value) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/login/login'
|
||||
})
|
||||
return
|
||||
} else {
|
||||
if (store.value.status == 0) {
|
||||
uToast.value.show({message:'不在店铺营业时间内',type: 'error'});
|
||||
return;
|
||||
}
|
||||
// 判断当前是否在配送范围内
|
||||
if (orderType.value == 'takeout' && store.value.distance < store.value.far) {
|
||||
uToast.value.show({message:'选中的地址不在配送范围',type: 'error'});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/pay/pay'
|
||||
})
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cart-popup {
|
||||
.top {
|
||||
background-color: $bg-color-primary;
|
||||
//color: $color-primary;
|
||||
color: #5A5B5C;
|
||||
padding: 10rpx 30rpx;
|
||||
font-size: 24rpx;
|
||||
text-align: right;
|
||||
}
|
||||
.cart-list {
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
min-height: 1vh;
|
||||
max-height: 60vh;
|
||||
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 30rpx;
|
||||
margin-bottom: 156rpx;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx 0;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: $border-color;
|
||||
height: 2rpx;
|
||||
transform: scaleY(0.6);
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
margin-right: 30rpx;
|
||||
|
||||
.name {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-color-base;
|
||||
}
|
||||
.props {
|
||||
color: $text-color-assist;
|
||||
font-size: 24rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
margin-right: 120rpx;
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn {
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 100%;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
line-height: 46rpx;
|
||||
}
|
||||
|
||||
.number {
|
||||
font-size: $font-size-base;
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
text-align: center;
|
||||
line-height: 46rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container">
|
||||
<view class="form-box">
|
||||
<view class="form">
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input">
|
||||
<view class="label">收货人</view>
|
||||
<input class="input" placeholder="请输入收货人" v-model="form.realName" placeholder-class="text-color-assist" />
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input">
|
||||
<view class="label">联系方式</view>
|
||||
<input class="input" placeholder="请输入收货人联系方式" v-model="form.phone" placeholder-class="text-color-assist" />
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input">
|
||||
<view class="label">收货地址</view>
|
||||
<view class="input" @click="chooseLocation">{{form.address ? form.address : '请选择收货地址'}}</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input">
|
||||
<view class="label">详细地址</view>
|
||||
<input class="input" placeholder="请输入收货人详细地址" v-model="form.detail" placeholder-class="text-color-assist" />
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input">
|
||||
<view class="label">默认地址</view>
|
||||
<view class="radio-group">
|
||||
<view class="radio" :class="{'checked': !form.isDefault}" style="margin-right: 10rpx;" @tap="form.isDefault=0">否</view>
|
||||
<view class="radio" :class="{'checked': form.isDefault}" @tap="form.isDefault=1">是</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
<view class="btn-section">
|
||||
<button type="primary" size="default" @tap="save">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow } from '@dcloudio/uni-app'
|
||||
import { formatDateTime,prePage } from '@/utils/util'
|
||||
import {
|
||||
getAddressAddAndEdit
|
||||
} from '@/api/address'
|
||||
const main = useMainStore()
|
||||
const { isLogin,addresses } = storeToRefs(main)
|
||||
const title = ref('编辑地址')
|
||||
|
||||
const form = ref({
|
||||
realName: '',
|
||||
isDefault: 0,
|
||||
phone: '',
|
||||
address: '',
|
||||
detail: '',
|
||||
latitude: '',
|
||||
longitude: ''
|
||||
})
|
||||
|
||||
onLoad((option) => {
|
||||
//为了方便演示,这里用本地缓存
|
||||
console.log('option:',option)
|
||||
if (option.id) {
|
||||
form.value = addresses.value.find(item => item.id == option.id)
|
||||
}
|
||||
})
|
||||
|
||||
const save = async() => {
|
||||
let data = {}
|
||||
if (form.value.hasOwnProperty('id')) {
|
||||
data = await getAddressAddAndEdit(form.value);
|
||||
} else {
|
||||
data = await getAddressAddAndEdit(form.value);
|
||||
}
|
||||
if (data) {
|
||||
setTimeout(function(){
|
||||
uni.navigateBack()
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
const chooseLocation = async() => {
|
||||
uni.chooseLocation({
|
||||
success: function (res) {
|
||||
form.value.address = res.address + ' ' + res.name;
|
||||
form.value.latitude = res.latitude;
|
||||
form.value.longitude = res.longitude;
|
||||
}
|
||||
});
|
||||
// let [error, res] = await uni.chooseLocation();
|
||||
// if (res) {
|
||||
// form.value.address = res.address + ' ' + res.name;
|
||||
// form.value.latitude = res.latitude;
|
||||
// form.value.longitude = res.longitude;
|
||||
// }
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: $text-color-base;
|
||||
|
||||
.form-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 200rpx;
|
||||
font-size: $font-size-lg;
|
||||
color: $text-color-base;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.radio {
|
||||
padding: 10rpx 30rpx;
|
||||
border-radius: 6rpx;
|
||||
border: 2rpx solid $text-color-assist;
|
||||
color: $text-color-assist;
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.checked {
|
||||
background-color: $color-primary;
|
||||
color: $text-color-white;
|
||||
border: 2rpx solid $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
font-size: $font-size-base;
|
||||
height: 90rpx;
|
||||
border-radius: 50rem !important;
|
||||
width: 85%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container">
|
||||
<view class="main">
|
||||
<uv-empty v-if="addresses.length == 0" mode="address"></uv-empty>
|
||||
<template v-else>
|
||||
<uv-swipe-action>
|
||||
<uv-swipe-action-item class="address-wrapper" :options="swipeOption"
|
||||
@click="handleSwipeClick(address.id)" v-for="(address, index) in addresses" :key="index">
|
||||
<view class="address" @tap="chooseAddress(address)">
|
||||
<view class="left flex-fill overflow-hidden mr-20">
|
||||
<view class="font-size-lg font-weight-bold text-truncate"
|
||||
style="margin-bottom: 10rpx;white-space:normal;">
|
||||
{{ address.address + ' ' + address.detail }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">
|
||||
{{ address.realName }} {{ address.isDefault ? '默认' : '' }} {{ address.phone }}
|
||||
</view>
|
||||
</view>
|
||||
<image src="/static/images/edit.png" class="edit-icon" @tap.stop="edit(address.id)"></image>
|
||||
</view>
|
||||
</uv-swipe-action-item>
|
||||
</uv-swipe-action>
|
||||
</template>
|
||||
</view>
|
||||
<view class="btn-box">
|
||||
<button type="primary" size="default" @tap="add">新增地址</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow } from '@dcloudio/uni-app'
|
||||
import { formatDateTime,prePage } from '@/utils/util'
|
||||
import {
|
||||
addressAll,
|
||||
addressDelete,
|
||||
shopGetDistanceFromLocation
|
||||
} from '@/api/address'
|
||||
const main = useMainStore()
|
||||
const { isLogin,addresses,store } = storeToRefs(main)
|
||||
const title = ref('我的地址')
|
||||
|
||||
const scene = ref('menu')
|
||||
const is_choose = ref(false)
|
||||
const swipeOption = ref(
|
||||
[{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#D12E32'
|
||||
}
|
||||
}])
|
||||
|
||||
onLoad((option) => {
|
||||
console.log('option:',option)
|
||||
is_choose.value = option.is_choose || false
|
||||
scene.value = option.scene || 'menu'
|
||||
})
|
||||
onShow(() => {
|
||||
init();
|
||||
})
|
||||
|
||||
const init = async() => {
|
||||
let data = await addressAll();
|
||||
if (data) {
|
||||
main.SET_ADDRESSES(data)
|
||||
}
|
||||
}
|
||||
const add = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/address/add'
|
||||
})
|
||||
}
|
||||
const edit = (id) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/address/add?id=' + id
|
||||
})
|
||||
}
|
||||
const handleSwipeClick = async(id) => {
|
||||
let [error, res] = await uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除?'
|
||||
});
|
||||
if (res && res.confirm) {
|
||||
let data = await addressDelete({
|
||||
id: id
|
||||
});
|
||||
if (data) {
|
||||
const index = addresses.value.findIndex(item => item.id == id)
|
||||
const newaddresses = JSON.parse(JSON.stringify(addresses.value))
|
||||
newaddresses.splice(index, 1)
|
||||
main.SET_ADDRESSES(newaddresses)
|
||||
uni.showToast({
|
||||
title: '删除成功!',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
const chooseAddress = async(address) => {
|
||||
if (!is_choose.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('scene.value:',scene.value)
|
||||
|
||||
if (scene.value == 'menu' || scene.value == 'pay') {
|
||||
let data = await shopGetDistanceFromLocation({
|
||||
lat: address.latitude,
|
||||
lng: address.longitude,
|
||||
lat2: main.store.lat,
|
||||
lng2: main.store.lng
|
||||
});
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parseFloat(data) > store.value.distance) {
|
||||
uni.showToast({
|
||||
title: '不在配送范围!',
|
||||
icon: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
main.SET_ADDRESS(address)
|
||||
main.SET_ORDER_TYPE('takeout')
|
||||
main.store.far = data
|
||||
main.store.far_text = data + 'km'
|
||||
main.SET_STORE(main.store)
|
||||
main.SET_LOCATION({
|
||||
latitude: address.lat,
|
||||
longitude: address.lng
|
||||
});
|
||||
|
||||
if (scene.value == 'menu') {
|
||||
uni.switchTab({
|
||||
url: '/pages/menu/menu'
|
||||
})
|
||||
} else if (scene.value == 'pay') {
|
||||
uni.navigateBack();
|
||||
}
|
||||
} else if (scene.value == 'scoreShop') {
|
||||
main.SET_ADDRESS(address)
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 100rpx;
|
||||
|
||||
.address-wrapper {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.address {
|
||||
width: 100%;
|
||||
padding: 40rpx 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
height: 100rpx;
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 0 20rpx rgba($color: $text-color-assist, $alpha: 0.1);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 10rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
height: 80rpx;
|
||||
width: 80%;
|
||||
border-radius: 50rem !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view>
|
||||
<view class="wrap">
|
||||
<view class="bg-white" v-if="cate == 0">
|
||||
<uv-tabs activeColor="#f29100" ref="tabs" :list="list" :current="current" @change="change" :scrollable="false" swiperWidth="750"></uv-tabs>
|
||||
</view>
|
||||
<view class="bg-white" v-else>
|
||||
<uv-tabs activeColor="#f29100" ref="tabs" :list="list1" :current="current" @change="change" :scrollable="false" swiperWidth="750"></uv-tabs>
|
||||
</view>
|
||||
<swiper class="swiper-box" :current="swiperCurrent" @transition="transition" @animationfinish="animationfinish">
|
||||
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in orderList" :key="index">
|
||||
<scroll-view scroll-y style="height: 100%;width: 100%;" @scrolltolower="reachBottom">
|
||||
<view class="page-box">
|
||||
<view v-if="item.length == 0">
|
||||
<view class="centre" v-if="loadStatus[index] != 'loading'">
|
||||
<view class="explain">
|
||||
您还没有相关的账单
|
||||
<view class="tips">可以去看看有那些想买的</view>
|
||||
</view>
|
||||
<view class="btn">
|
||||
<navigator open-type="switchTab" url="/pages/menu/menu">随便逛逛</navigator>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<u-loadmore :status="loadStatus[index]" bgColor="#f2f2f2"></u-loadmore>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="order" v-for="(res, resIndex) in orderList[index]" :key="resIndex">
|
||||
<view class="type">
|
||||
<view>{{res.title}}</view>
|
||||
<view>{{res.mark}}</view>
|
||||
</view>
|
||||
<view class="total">
|
||||
<view>
|
||||
{{res.pm == 0 ? '-':'+'}}¥{{res.number}}元
|
||||
</view>
|
||||
<view>
|
||||
{{formatDateTime(res.createTime)}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="loadStatus[index]" bgColor="#f2f2f2"></u-loadmore>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import { formatDateTime } from '@/utils/util'
|
||||
import {
|
||||
balanceGetBillList
|
||||
} from '@/api/user'
|
||||
const main = useMainStore()
|
||||
const { isLogin } = storeToRefs(main)
|
||||
const title = ref('账单')
|
||||
const orderList = ref([[], [], [], []])
|
||||
const list = ref([
|
||||
{
|
||||
name: '全部'
|
||||
},
|
||||
{
|
||||
name: '消费'
|
||||
},
|
||||
{
|
||||
name: '充值'
|
||||
},
|
||||
{
|
||||
name: '退款'
|
||||
}
|
||||
]
|
||||
)
|
||||
const list1 = ref([
|
||||
{
|
||||
name: '全部'
|
||||
},
|
||||
{
|
||||
name: '消费'
|
||||
}
|
||||
]
|
||||
)
|
||||
const current = ref(0)
|
||||
const swiperCurrent = ref(0)
|
||||
const tabsHeight =ref(0)
|
||||
const dx = ref(0)
|
||||
const loadStatus = ref(['loadmore','loadmore','loadmore','loadmore'])
|
||||
const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const tabs = ref()
|
||||
const cate = ref(0)
|
||||
|
||||
onLoad((option) => {
|
||||
console.log('cate:',option.cate)
|
||||
cate.value = option.cate
|
||||
getBill();
|
||||
})
|
||||
|
||||
const getBill = async() => {
|
||||
if (loadStatus.value[swiperCurrent.value] == 'loading') {
|
||||
return;
|
||||
}
|
||||
loadStatus.value.splice(swiperCurrent.value,1,"loading")
|
||||
let data = await balanceGetBillList({cate:cate.value,type:swiperCurrent.value,page:page.value,pagesize:pageSize.value});
|
||||
if (page.value == 1 ){
|
||||
orderList.value[swiperCurrent.value] = [];
|
||||
}
|
||||
if (data && data.length > 0) {
|
||||
page.value++;
|
||||
orderList.value[swiperCurrent.value] = orderList.value[swiperCurrent.value].concat(data);
|
||||
|
||||
loadStatus.value.splice(swiperCurrent.value,1,"loadmore")
|
||||
} else{
|
||||
loadStatus.value.splice(swiperCurrent.value,1,"nomore")
|
||||
}
|
||||
}
|
||||
const reachBottom = () => {
|
||||
if (loadStatus.value[swiperCurrent.value] == 'nomore') {
|
||||
return;
|
||||
}
|
||||
getBill();
|
||||
}
|
||||
// tab栏切换
|
||||
const change = (e) => {
|
||||
swiperCurrent.value = e.index;
|
||||
page.value = 1;
|
||||
}
|
||||
const transition = ({ detail: { dx } }) => {
|
||||
}
|
||||
const animationfinish = ({ detail }) => {
|
||||
swiperCurrent.value = detail.current;
|
||||
current.value = detail.current;
|
||||
page.value = 1;
|
||||
getBill();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef H5 */
|
||||
page {
|
||||
height: 100%;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order {
|
||||
width: 710rpx;
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx auto;
|
||||
border-radius: 20rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
.total {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
|
||||
.total-price {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
float: right;
|
||||
}
|
||||
.type {
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.centre {
|
||||
text-align: center;
|
||||
margin: 200rpx auto;
|
||||
font-size: 32rpx;
|
||||
image {
|
||||
width: 164rpx;
|
||||
height: 164rpx;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.tips {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
.btn {
|
||||
margin: 80rpx auto;
|
||||
width: 200rpx;
|
||||
border-radius: 32rpx;
|
||||
line-height: 64rpx;
|
||||
color: #ffffff;
|
||||
font-size: 26rpx;
|
||||
background: linear-gradient(270deg, rgba(249, 116, 90, 1) 0%, rgba(255, 158, 1, 1) 100%);
|
||||
}
|
||||
}
|
||||
.wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - var(--window-top));
|
||||
width: 100%;
|
||||
}
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
}
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,557 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container position-relative w-100 h-100 overflow-hidden">
|
||||
<view class="exchange-box">
|
||||
<view class="input-box">
|
||||
<input type="text" v-model="exchange_code" placeholder="请输入兑换码" placeholder-class="text-color-assist font-size-base" />
|
||||
<button type="primary" @click="exchange">兑换</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tabbar">
|
||||
<view class="tab" :class="{active: activeTabIndex == index}"
|
||||
v-for="(item, index) in tabs" :key="index" @tap="handleTab(index)">
|
||||
<view class="title">{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-fill">
|
||||
<scroll-view scroll-y class="coupon-list" @scrolltolower="getCoupons(activeTabIndex)">
|
||||
<view class="wrapper" v-if="0 === activeTabIndex">
|
||||
<uv-empty v-if="myCoupons.length == 0" mode="list"></uv-empty>
|
||||
<view class="coupon" v-for="(item, index) in myCoupons" :key="index" @tap="openDetailModal(item,index)">
|
||||
<view class="taobao">
|
||||
<view class="ticket">
|
||||
<view class="left">
|
||||
<image
|
||||
class="picture"
|
||||
:src="item.image"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="introduce">
|
||||
<view class="top">
|
||||
¥
|
||||
<text class="big">{{item.value}}</text>
|
||||
<view>
|
||||
满{{item.least}}减{{item.value}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="type">{{ item.title }}</view>
|
||||
<view class="date u-line-1">{{formatDateTime(item.startTime, 'yyyy-MM-dd')}}-{{formatDateTime(item.endTime, 'yyyy-MM-dd')}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right" @click.stop="" v-if="activeTabIndex == 1">
|
||||
<view class="use immediate-use" :round="true" @tap="receive(item, index)" >立即领取</view>
|
||||
</view>
|
||||
<view class="right" @click.stop="" v-if="activeTabIndex == 0">
|
||||
<view v-if="item.status == 0" class="use immediate-use" :round="true" @tap="useCouponWith(item)" >立即使用</view>
|
||||
<view v-else class="used">已使用</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="wrapper" v-if="1 === activeTabIndex">
|
||||
<uv-empty v-if="notCoupons.length == 0" mode="list"></uv-empty>
|
||||
<view class="coupon" v-for="(item, index) in notCoupons" :key="index" @tap="openDetailModal(item,index)">
|
||||
<view class="taobao">
|
||||
<view class="ticket">
|
||||
<view class="left">
|
||||
<image
|
||||
class="picture"
|
||||
:src="item.image"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="introduce">
|
||||
<view class="top">
|
||||
¥
|
||||
<text class="big">{{item.value}}</text>
|
||||
<view>
|
||||
满{{item.least}}减{{item.value}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="type">{{ item.title }}</view>
|
||||
<view class="date u-line-1">{{formatDateTime(item.startTime, 'yyyy-MM-dd')}}-{{formatDateTime(item.endTime, 'yyyy-MM-dd')}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right" @click.stop="" v-if="activeTabIndex == 1">
|
||||
<view class="use immediate-use" :round="true" @tap="receive(item, index)" >立即领取</view>
|
||||
</view>
|
||||
<view class="right" @click.stop="" v-if="activeTabIndex == 0">
|
||||
<view v-if="item.status == 0" class="use immediate-use" :round="true" @tap="useCouponWith(item)" >立即使用</view>
|
||||
<view v-else class="used">已使用</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<modal custom :show="detailModalVisible" @cancel="closeDetailModal" width="90%">
|
||||
<view class="modal-content">
|
||||
<view class="d-flex font-size-extra-lg text-color-base just-content-center mb-20">{{ coupon.title }}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">
|
||||
有效期:{{formatDateTime(coupon.startTime, 'yyyy-MM-dd')}}-{{formatDateTime(coupon.endTime, 'yyyy-MM-dd')}}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">
|
||||
领取时间:{{formatDateTime(coupon.createTime)}}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">
|
||||
券价值:满{{ coupon.least }}减{{ coupon.value }}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20" v-if="activeTabIndex == 1">
|
||||
每人限领:{{ coupon.limit }} 张
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">
|
||||
适用范围:{{typeInfo(coupon.type)}}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">
|
||||
适用店铺:{{coupon.shopName}}
|
||||
</view>
|
||||
<view class="d-flex align-items-center just-content-center" v-if="activeTabIndex == 0">
|
||||
<button type="primary" @tap="useCoupon" class="use-coupon-btn">立即使用</button>
|
||||
</view>
|
||||
<view class="d-flex align-items-center just-content-center" v-if="activeTabIndex == 1">
|
||||
<button type="primary" @tap="receive(coupon, couponIndex)" class="use-coupon-btn">立即领取</button>
|
||||
</view>
|
||||
</view>
|
||||
</modal>
|
||||
|
||||
<!--轻提示-->
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow ,onPullDownRefresh,onHide} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,kmUnit } from '@/utils/util'
|
||||
import {
|
||||
couponReceive,
|
||||
couponMine,
|
||||
couponIndexApi
|
||||
} from '@/api/coupon'
|
||||
const main = useMainStore()
|
||||
const { isLogin } = storeToRefs(main)
|
||||
const title = ref('优惠券')
|
||||
|
||||
const tabs = ref([
|
||||
{title: '我的优惠券', page:1, pagesize:10,
|
||||
coupons: []
|
||||
},
|
||||
{title: '未领优惠券', page:1, pagesize:10,
|
||||
coupons: []
|
||||
}
|
||||
])
|
||||
const activeTabIndex = ref(0)
|
||||
const detailModalVisible = ref(false)
|
||||
const coupon = ref({})
|
||||
const couponIndex = ref(0)
|
||||
const exchange_code = ref('')
|
||||
const uToast = ref()
|
||||
const myCoupons = ref([])
|
||||
const notCoupons = ref([])
|
||||
|
||||
onShow(() => {
|
||||
getCoupons(0)
|
||||
})
|
||||
onPullDownRefresh(() => {
|
||||
if(activeTabIndex.value == 0) {
|
||||
myCoupons.value = []
|
||||
}
|
||||
if(activeTabIndex.value == 1) {
|
||||
notCoupons.value = []
|
||||
}
|
||||
tabs.value[activeTabIndex.value].page = 1;
|
||||
getCoupons(activeTabIndex.value)
|
||||
})
|
||||
watch(activeTabIndex, () => {
|
||||
getCoupons(activeTabIndex.value)
|
||||
})
|
||||
|
||||
// 兑换
|
||||
const exchange = async() => {
|
||||
let data = await couponReceive({code:this.exchange_code});
|
||||
if (data) {
|
||||
uToast.value.show({
|
||||
message: '兑换成功',
|
||||
type: 'success'
|
||||
});
|
||||
tabs.value[0].coupons = [];
|
||||
tabs.value[0].page = 1;
|
||||
getCoupons(0)
|
||||
tabs.value[1].coupons = [];
|
||||
tabs.value[1].page = 1;
|
||||
getCoupons(1)
|
||||
}
|
||||
}
|
||||
// 使用范围
|
||||
const typeInfo = (type) => {
|
||||
if (type == 0) {
|
||||
return '通用'
|
||||
}
|
||||
if (type == 1) {
|
||||
return '自取'
|
||||
}
|
||||
if (type == 2) {
|
||||
return '外卖'
|
||||
}
|
||||
}
|
||||
const handleTab = (index) => {
|
||||
console.log('activeTabIndex2:',index)
|
||||
activeTabIndex.value = index
|
||||
}
|
||||
const getCoupons = async(type) => {
|
||||
let page = tabs.value[type].page;
|
||||
let pagesize = tabs.value[type].pagesize;
|
||||
// 我的优惠券
|
||||
let data = [];
|
||||
if (type == 0) {
|
||||
myCoupons.value = await couponMine({page:page,pagesize:pagesize});
|
||||
}
|
||||
// 未领优惠券
|
||||
if (type == 1) {
|
||||
notCoupons.value = await couponIndexApi({page:page,pagesize:pagesize});
|
||||
}
|
||||
//console.log('data:',data)
|
||||
uni.stopPullDownRefresh();
|
||||
|
||||
console.log('tabs.value:',tabs.value[type].title)
|
||||
//tabs.value[type].page++;
|
||||
}
|
||||
const openDetailModal = (coupon,index) => {
|
||||
couponIndex.value = index;
|
||||
coupon.value = coupon
|
||||
detailModalVisible.value = true
|
||||
}
|
||||
const useCouponWith = (coupon) => {
|
||||
//coupon.value = coupon
|
||||
useCoupon();
|
||||
}
|
||||
const closeDetailModal = () => {
|
||||
detailModalVisible.value = false
|
||||
coupon.value = {}
|
||||
}
|
||||
const useCoupon = () => {
|
||||
uni.switchTab({
|
||||
url: '/pages/menu/menu'
|
||||
})
|
||||
}
|
||||
const showTip1 = () => {
|
||||
uni.showToast({
|
||||
title: '您暂时还没有赠送中卡券哦~',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
const showTip2 = () => {
|
||||
uni.showToast({
|
||||
title: '您暂时还没有券码哦~',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
// 领取优惠券
|
||||
const receive = async(coupon,index) => {
|
||||
let data = await couponReceive({id:coupon.id});
|
||||
if (data) {
|
||||
uToast.value.show({
|
||||
message: '领取成功',
|
||||
type: 'success'
|
||||
});
|
||||
detailModalVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifdef H5 */
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.exchange-box {
|
||||
flex-shrink: 0;
|
||||
height: 200rpx;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.input-box {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
width: 70%;
|
||||
flex-shrink: 0;
|
||||
input {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #eee;
|
||||
border-right: 0;
|
||||
border-radius: 8rpx 0 0 8rpx;
|
||||
// padding: 20rpx;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
}
|
||||
button {
|
||||
border-radius: 0 8rpx 8rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tabbar {
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
padding: 15rpx 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $color-primary;
|
||||
|
||||
.title {
|
||||
border-bottom: 5rpx solid $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
height: 80rpx;
|
||||
flex-shrink: 0;
|
||||
.item {
|
||||
padding: 0 20rpx;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: " ";
|
||||
border-right: 1rpx solid $text-color-assist;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: scaleX(0.5) scaleY(0.8);
|
||||
}
|
||||
|
||||
&:nth-last-child(1)::after {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-list {
|
||||
height: calc(100vh - 120rpx - 200rpx);
|
||||
/* #ifdef H5 */
|
||||
height: calc(100vh - 120rpx - 200rpx - 44px);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.coupon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
margin-bottom: 30rpx;
|
||||
//padding: 0 30rpx;
|
||||
border-radius: 6rpx;
|
||||
box-shadow: 0 10rpx 10rpx -10rpx rgba(15, 15, 15, 0.1);
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: $bg-color;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
bottom: 65rpx;
|
||||
left: -15rpx;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: $bg-color;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
bottom: 65rpx;
|
||||
right: -15rpx;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.detail {
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-bottom: 1rpx dashed #c6c6c6;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
.coupon-img {
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.use-coupon-btn {
|
||||
width: 95%;
|
||||
border-radius: 50rem !important;
|
||||
}
|
||||
|
||||
|
||||
.taobao {
|
||||
background-color: white;
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 30rpx;
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.store {
|
||||
font-weight: 500;
|
||||
}
|
||||
.buddha {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.entrance {
|
||||
color: $uv-info;
|
||||
border: solid 2rpx $uv-info;
|
||||
line-height: 48rpx;
|
||||
padding: 0 30rpx;
|
||||
background: none;
|
||||
border-radius: 15px;
|
||||
}
|
||||
}
|
||||
.ticket {
|
||||
display: flex;
|
||||
.left {
|
||||
width: 70%;
|
||||
padding: 20rpx;
|
||||
background-color: white;//rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
border-right: dashed 2rpx rgb(224, 215, 211);
|
||||
display: flex;
|
||||
.picture {
|
||||
//width: 172rpx;
|
||||
border-radius: 20rpx;
|
||||
width: 190rpx;
|
||||
height: 190rpx;
|
||||
}
|
||||
.introduce {
|
||||
margin-left: 10rpx;
|
||||
.top{
|
||||
color:$uv-warning;
|
||||
font-size: 28rpx;
|
||||
.big{
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.type{
|
||||
font-size: 28rpx;
|
||||
color: $uv-info-dark;
|
||||
}
|
||||
.date{
|
||||
margin-top: 10rpx;
|
||||
font-size: 20rpx;
|
||||
color: $uv-info-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
width: 30%;
|
||||
padding: 40rpx 20rpx;
|
||||
background-color: white;//rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.use {
|
||||
height: auto;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
color: #ffffff!important;
|
||||
background-color: $uv-warning!important;
|
||||
line-height: 40rpx;
|
||||
color: rgb(117, 142, 165);
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.used {
|
||||
height: auto;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
//color: #ffffff!important;
|
||||
//background-color: $u-type-warning!important;
|
||||
line-height: 40rpx;
|
||||
//color: rgb(117, 142, 165);
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
.right_log {
|
||||
text-align: center;
|
||||
width: 30%;
|
||||
padding: 80rpx 0rpx;
|
||||
background-color: white;//rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<layout>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="wrap">
|
||||
<view class="top"></view>
|
||||
<view class="content">
|
||||
<view class="title">欢迎登录</view>
|
||||
|
||||
<input class="u-border-bottom" type="number" v-model="mobile" placeholder="请输入手机号" />
|
||||
<view class="tips">未注册的手机号验证后自动创建账号</view>
|
||||
|
||||
|
||||
<view style="display: flex;">
|
||||
<view style="width: 50%;">
|
||||
<input style="height: 100rpx;" class="u-border-bottom" type="number" v-model="captcha" placeholder="请输入验证码" />
|
||||
</view>
|
||||
<view style="width: 50%;">
|
||||
<button style="height: 100rpx;" @tap="getCaptcha" :style="[captchaStyle]" class="getCaptcha">
|
||||
{{captchaText}}
|
||||
<uv-code :seconds="seconds" @end="endCaptcha" @start="startCaptcha" ref="uCode" @change="changeCapcha"></uv-code>
|
||||
<!-- <u-verification-code :seconds="seconds" @end="endCaptcha" @change="changeCapcha" @start="startCaptcha" ref="uCode" >
|
||||
|
||||
</u-verification-code> -->
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button @tap="submit" style="color:#fff;background-color: #f9ae3d;" type="primary" class="login">登录</button>
|
||||
|
||||
</view>
|
||||
<view class="buttom">
|
||||
<view class="loginType">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button type="primary" size="default" class="login-btn" open-type="getPhoneNumber" @getphonenumber="loginForWechatMini">
|
||||
<!-- <image src="/static/images/mine/wechat.png"></image> -->
|
||||
手机号快捷登录
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="hint">
|
||||
<!-- <label class="label"> -->
|
||||
<radio value="isChecked" @tap.stop="onChange" />
|
||||
我已经阅读并遵守
|
||||
<text class="link" @tap="serv(29,'用户协议')">《用户协议》</text>与
|
||||
<text class="link" @tap="serv(30,'隐私政策')">《隐私政策》</text>
|
||||
<!-- </label> -->
|
||||
</view>
|
||||
</view>
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import {
|
||||
userLoginForWechatMini,
|
||||
smsSend,
|
||||
userLogin
|
||||
} from '@/api/auth'
|
||||
import * as util from '@/utils/util'
|
||||
import { mobile as testMobible } from '@/uni_modules/uv-ui-tools/libs/function/test'
|
||||
const main = useMainStore()
|
||||
const title = ref('登录')
|
||||
const mobile = ref('')
|
||||
const captcha = ref('')
|
||||
const captchaText = ref('获取验证码')
|
||||
const password = ref('')
|
||||
const seconds = ref(60)
|
||||
const isChecked = ref(false)
|
||||
const openid = ref(main.openid)
|
||||
const uToast = ref()
|
||||
const uCode = ref()
|
||||
|
||||
const captchaStyle = computed(() => {
|
||||
let style = {};
|
||||
if(mobile.value && captchaText.value == '获取验证码') {
|
||||
style.color = "#fff";
|
||||
style.backgroundColor = '#f9ae3d';
|
||||
}
|
||||
return style;
|
||||
});
|
||||
|
||||
|
||||
const loginForWechatMini = async (e) => {
|
||||
if(!isChecked.value){
|
||||
uToast.value.show({
|
||||
message: '请勾选下面协议',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
if (e.detail.encryptedData && e.detail.iv) {
|
||||
let data = await userLoginForWechatMini({
|
||||
encryptedData: e.detail.encryptedData,
|
||||
iv: e.detail.iv,
|
||||
openid: openid.value
|
||||
});
|
||||
if (data) {
|
||||
main.SET_MEMBER(data.userInfo);
|
||||
main.SET_TOKEN(data.accessToken);
|
||||
uToast.value.show({
|
||||
title: '登录成功',
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function() {
|
||||
uni.navigateBack();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getCaptcha = async () => {
|
||||
|
||||
if (testMobible(mobile.value) == false) {
|
||||
uToast.value.show({
|
||||
message: '手机号码格式不对',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
let data = await smsSend({
|
||||
mobile: mobile.value,
|
||||
scene: 1
|
||||
});
|
||||
if (data) {
|
||||
uCode.value.start();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 验证码开始计时
|
||||
const startCaptcha = () => {
|
||||
console.log('start')
|
||||
}
|
||||
// 验证码结束
|
||||
const endCaptcha = () => {
|
||||
console.log('end')
|
||||
captchaText.value = '获取验证码';
|
||||
}
|
||||
const changeCapcha = (text) => {
|
||||
console.log('change:' + text)
|
||||
captchaText.value = text;
|
||||
}
|
||||
// 提交
|
||||
const submit = () => {
|
||||
|
||||
if (testMobible(mobile.value) == false) {
|
||||
uToast.value.show({
|
||||
message: '手机号码格式不对',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
if(!isChecked.value){
|
||||
uToast.value.show({
|
||||
message: '请勾选下面协议',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
login()
|
||||
|
||||
}
|
||||
|
||||
// 登录
|
||||
const login = async () => {
|
||||
let from = 'routine'
|
||||
// #ifdef H5
|
||||
from = 'h5'
|
||||
if(util.isWeixin()){
|
||||
from = 'wechat'
|
||||
}
|
||||
|
||||
// #endif
|
||||
let data = await userLogin({
|
||||
mobile: mobile.value,
|
||||
code: captcha.value,
|
||||
from: from,
|
||||
openid: openid.value
|
||||
})
|
||||
if (data) {
|
||||
uni.setStorage({
|
||||
key: 'userinfo',
|
||||
data: data.userInfo
|
||||
});
|
||||
uni.setStorage({
|
||||
key: 'accessToken',
|
||||
data: data.accessToken
|
||||
});
|
||||
main.SET_MEMBER(data.userInfo);
|
||||
main.SET_TOKEN(data.accessToken);
|
||||
uToast.value.show({
|
||||
message: '登录成功',
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function() {
|
||||
uni.navigateBack();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
const serv = (id,name) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/mine/content?id=' + id + '&name=' + name
|
||||
})
|
||||
}
|
||||
|
||||
const onChange = () => {
|
||||
isChecked.value = !isChecked.value
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrap {
|
||||
background-color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
.content {
|
||||
width: 600rpx;
|
||||
margin: 0 auto;
|
||||
|
||||
.title {
|
||||
text-align: left;
|
||||
font-size: 60rpx;
|
||||
font-weight: 500;
|
||||
margin-bottom: 100rpx;
|
||||
}
|
||||
input {
|
||||
text-align: left;
|
||||
margin-bottom: 10rpx;
|
||||
padding-bottom: 6rpx;
|
||||
}
|
||||
.tips {
|
||||
color: $uv-info;
|
||||
margin-bottom: 60rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.getCaptcha {
|
||||
background-color: rgb(253, 243, 208);
|
||||
color: $uv-tips-color;
|
||||
border: none;
|
||||
font-size: 30rpx;
|
||||
padding: 12rpx 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.login {
|
||||
background-color: rgb(253, 243, 208);
|
||||
color: $uv-tips-color;
|
||||
border: none;
|
||||
font-size: 30rpx;
|
||||
padding: 12rpx 0;
|
||||
margin-top: 40rpx;
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.alternative {
|
||||
color: $uv-tips-color;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
}
|
||||
.buttom {
|
||||
//position: absolute;
|
||||
bottom: 0;
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
//align-items: center;
|
||||
//justify-content: center;
|
||||
.loginType {
|
||||
padding: 80rpx;
|
||||
//justify-content:space-between;
|
||||
|
||||
.login-btn {
|
||||
background-color: #1aad19!important;
|
||||
width: 100%;
|
||||
border-radius: 50rem !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10rpx 0;
|
||||
text-align: center;
|
||||
image {
|
||||
width: 36rpx;
|
||||
height: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx 40rpx;
|
||||
font-size: 20rpx;
|
||||
color: $uv-tips-color;
|
||||
|
||||
.link {
|
||||
color: $uv-warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<!-- <layout> -->
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="top">
|
||||
<button type="primary" size="default" class="login-btn" @click="logout">
|
||||
确定退出登录
|
||||
</button>
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
<!-- </layout> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
const main = useMainStore()
|
||||
const { member,isLogin } = storeToRefs(main)
|
||||
const uToast = ref()
|
||||
const title = ref('退出')
|
||||
|
||||
const logout = () => {
|
||||
uni.removeStorageSync( 'userinfo');
|
||||
uni.removeStorageSync( 'accessToken');
|
||||
main.SET_MEMBER({});
|
||||
main.SET_TOKEN('');
|
||||
uToast.value.show({
|
||||
message: '已退出',
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function() {
|
||||
uni.navigateBack();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
button{
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<layout>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view>
|
||||
<rich-text :nodes="content"></rich-text>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import {
|
||||
mineServiceContent
|
||||
} from '@/api/user'
|
||||
|
||||
|
||||
const title = ref('内容')
|
||||
const content = ref('')
|
||||
|
||||
onLoad((option) => {
|
||||
if (option.name) {
|
||||
title.value = option.name
|
||||
}
|
||||
if (option.id) {
|
||||
getContent(option.id);
|
||||
}
|
||||
})
|
||||
const getContent = async(id) => {
|
||||
let data = await mineServiceContent({id:id});
|
||||
if (data) {
|
||||
content.value = data.content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,236 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container d-flex flex-column">
|
||||
<view class="flex-fill form">
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input w-100 d-flex align-items-center">
|
||||
<view class="label">头像</view>
|
||||
<view class="input flex-fill">
|
||||
<view class="form-input w-100 d-flex align-items-center" style="position: relative;">
|
||||
<view class="flex user-box">
|
||||
<view class="mr-1">
|
||||
<uv-avatar :src="member.avatar" size="60"></uv-avatar>
|
||||
</view>
|
||||
<view v-if="!member.avatar" class="flex-1" style="right:0;height: 60rpx;">
|
||||
<button style="background-color: #dd524d;color:#fff;" size='mini' open-type="chooseAvatar" @chooseavatar="chooseavatar" type="success">更改头像</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input w-100 d-flex align-items-center">
|
||||
<view class="label">昵称</view>
|
||||
<view class="input flex-fill">
|
||||
<input type="nickname" placeholder="请填写昵称" placeholder-class="text-color-assist font-size-base"
|
||||
v-model="member.nickname">
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input w-100 d-flex align-items-center" style="position: relative;">
|
||||
<view class="label">手机号码</view>
|
||||
<view class="input flex-fill">
|
||||
<input type="text" v-model="member.mobile" disabled>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false">
|
||||
<view class="form-input w-100 d-flex align-items-center">
|
||||
<view class="label">性别</view>
|
||||
<view class="input flex-fill">
|
||||
<view class="radio-group">
|
||||
<view class="radio" :class="{'checked': member.gender == '0'}" style="margin-right: 10rpx;" @tap="member.gender=0">先生</view>
|
||||
<view class="radio" :class="{'checked': member.gender == '1'}" @tap="member.gender=1">女士</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false" :arrow="!member.birthday">
|
||||
<view class="form-input w-100 d-flex align-items-center">
|
||||
<view class="label">生日</view>
|
||||
<view class="input flex-fill">
|
||||
<picker mode="date" :value="member.birthday" :start="startDate" :end="endDate" @change="handleDateChange">
|
||||
{{member.birthday ? member.birthday : '无'}}
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false" last>
|
||||
<view class="form-input w-100 d-flex align-items-center">
|
||||
<view class="label">加入时间</view>
|
||||
<view class="input flex-fill">
|
||||
<input type="text" v-model="member.createTime" disabled>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
<view class="btn-box d-flex align-items-center just-content-center">
|
||||
<button type="primary" class="save-btn" @tap="save">保存</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import { formatDateTime } from '@/utils/util'
|
||||
import {
|
||||
userEdit
|
||||
} from '@/api/user'
|
||||
import { VUE_APP_UPLOAD_URL } from '@/config';
|
||||
const main = useMainStore()
|
||||
const { openid, lang } = storeToRefs(main)
|
||||
|
||||
const title = ref('用户设置')
|
||||
//const currentDate = ref('')
|
||||
const date = ref('')
|
||||
const member = ref({})
|
||||
|
||||
onLoad(() => {
|
||||
member.value = main.member;
|
||||
//this.$util
|
||||
member.value.createTime = formatDateTime(member.value.createTime);
|
||||
})
|
||||
onShow(() => {
|
||||
date.value = getDate({format: true})
|
||||
})
|
||||
|
||||
const startDate = computed(() => {
|
||||
return getDate('start');
|
||||
})
|
||||
const endDate = computed(() => {
|
||||
return getDate('end');
|
||||
})
|
||||
|
||||
const chooseavatar = (e) => {
|
||||
console.log('detal:',e.detail);
|
||||
uni.uploadFile({
|
||||
url: VUE_APP_UPLOAD_URL,
|
||||
filePath: e.detail.avatarUrl,
|
||||
name: 'file',
|
||||
header: {
|
||||
Authorization: 'Bearer ' + member.value.accessToken,
|
||||
lang: lang.value,
|
||||
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
success(uploadFileResult){
|
||||
console.log('uploadFileResult:',uploadFileResult)
|
||||
if (uploadFileResult) {
|
||||
const upload = JSON.parse(uploadFileResult.data);
|
||||
console.log('upload:',upload.data)
|
||||
member.value.avatar = upload.data;
|
||||
}
|
||||
},
|
||||
fail(e){
|
||||
console.log('网络链接错误');
|
||||
console.log(e)
|
||||
}
|
||||
});
|
||||
}
|
||||
const getDate = (type) => {
|
||||
const date = new Date();
|
||||
let year = date.getFullYear();
|
||||
let month = date.getMonth() + 1;
|
||||
let day = date.getDate();
|
||||
|
||||
if (type === 'start') {
|
||||
year = year - 60;
|
||||
} else if (type === 'end') {
|
||||
year = year + 2;
|
||||
}
|
||||
month = month > 9 ? month : '0' + month;;
|
||||
day = day > 9 ? day : '0' + day;
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
const handleDateChange = (e) => {
|
||||
member.value.birthday = e.target.value
|
||||
}
|
||||
const save = async() => {
|
||||
let data = await userEdit({
|
||||
nickname: member.value.nickname,
|
||||
mobile: member.value.mobile,
|
||||
gender: member.value.gender,
|
||||
birthday: member.value.birthday,
|
||||
avatar: member.value.avatar
|
||||
});
|
||||
if (data) {
|
||||
const member = Object.assign(main.member, member.value)
|
||||
main.SET_MEMBER(member)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.form {
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
.label {
|
||||
width: 160rpx;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
}
|
||||
|
||||
.input {
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.radio {
|
||||
padding: 10rpx 30rpx;
|
||||
border-radius: 6rpx;
|
||||
border: 2rpx solid $text-color-assist;
|
||||
color: $text-color-assist;
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.checked {
|
||||
background-color: $color-primary;
|
||||
color: $text-color-white;
|
||||
border: 2rpx solid $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
height: calc((100vh - 40rpx) / 2);
|
||||
}
|
||||
.save-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
.logout-btn {
|
||||
width: 90%;
|
||||
border-radius: 50rem !important;
|
||||
font-size: $font-size-lg;
|
||||
background-color:rgb(237, 81, 29);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,488 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container" style="padding:20rpx;">
|
||||
<view style="padding-bottom: 100rpx;">
|
||||
<view class="bg-white">
|
||||
<view class="section">
|
||||
<!-- store info begin -->
|
||||
<list-cell :hover="false">
|
||||
<view class="w-100 d-flex align-items-center">
|
||||
<view class="d-flex flex-column w-60">
|
||||
<view class="w-100 font-size-lg text-color-base text-truncate">{{ order.shop.name }}</view>
|
||||
</view>
|
||||
<view class="d-flex justify-content-end align-items-center w-40">
|
||||
<view class="iconfont-yshop icon-mobile" @click="makePhoneCall(order.shop)" style="font-size: 45rpx;margin-right: 40rpx;"></view>
|
||||
<view class="iconfont-yshop icon-location" @click="openLocation(order.shop)" style="font-size: 45rpx;"></view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- store info end -->
|
||||
<list-cell :hover="false" padding="50rpx 30rpx">
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="d-flex align-items-center just-content-center">
|
||||
<view class="sort-num">{{ order.numberId }}</view>
|
||||
</view>
|
||||
<!-- steps begin -->
|
||||
<view class="d-flex just-content-center">
|
||||
<view class="steps d-flex flex-column w-80">
|
||||
<view class="steps__img-column">
|
||||
<view class="steps__img-column-item">
|
||||
<view class="iconfont-yshop icon-lamp"></view>
|
||||
</view>
|
||||
<view class="steps__img-column-item">
|
||||
<view class="iconfont-yshop icon-daojishi" v-if="{active: order.paid == 1 && order.status == 0}"></view>
|
||||
<view class="iconfont-yshop icon-daojishi unactive" v-else></view>
|
||||
</view>
|
||||
<view class="steps__img-column-item" v-if="order.orderType == 'takeout'">
|
||||
<view class="iconfont-yshop icon-takeout" v-if="order.status == 1"></view>
|
||||
<view class="iconfont-yshop icon-takeout unactive" v-else></view>
|
||||
</view>
|
||||
<view class="steps__img-column-item" >
|
||||
<view class="iconfont-yshop icon-doorbell" v-if="order.status >= 2"></view>
|
||||
<view class="iconfont-yshop icon-doorbell unactive" v-else></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="steps__text-column">
|
||||
<view class="steps__text-column-item active">
|
||||
<view class="steps__column-item-line bg-transparent"></view>
|
||||
<view class="steps__text-column-item-text">已下单</view>
|
||||
<view class="steps__column-item-line"></view>
|
||||
</view>
|
||||
<view class="steps__text-column-item activ" :class="{active: order.paid == 1}">
|
||||
<view class="steps__column-item-line"></view>
|
||||
<view class="steps__text-column-item-text">制作中</view>
|
||||
<view class="steps__column-item-line"></view>
|
||||
</view>
|
||||
<view class="steps__text-column-item" :class="{active: order.status == 1}" v-if="order.orderType == 'takeout'">
|
||||
<view class="steps__column-item-line"></view>
|
||||
<view class="steps__text-column-item-text">配送中</view>
|
||||
<view class="steps__column-item-line bg-transparent"></view>
|
||||
</view>
|
||||
<view class="steps__text-column-item" :class="{active: order.status >= 2}">
|
||||
<view class="steps__column-item-line"></view>
|
||||
<view class="steps__text-column-item-text">
|
||||
{{ order.orderType == 'takeout' ? '已送达' : '请取餐' }}
|
||||
</view>
|
||||
<view class="steps__column-item-line bg-transparent"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- steps end -->
|
||||
<view v-if="order.status==0 && order.paid > 0" class="d-flex just-content-center align-items-center font-size-base text-color-assist mb-40">
|
||||
您前面还有 <text class="text-color-primary mr-10 ml-10">{{order.preNum}}</text> 单待制作
|
||||
</view>
|
||||
<!-- goods begin -->
|
||||
<view class="w-100 d-flex flex-column position-relative mt-30" style="margin-bottom: -40rpx;">
|
||||
<view class="w-100 d-flex align-items-center mb-40" v-for="(good, index) in order.products" :key="index">
|
||||
<view class="d-flex flex-column w-60 overflow-hidden">
|
||||
<view class="font-size-lg text-color-base mb-10 text-truncate">{{ good.title }}</view>
|
||||
<view class="font-size-sm text-color-assist text-truncate">{{ good.spec }}</view>
|
||||
</view>
|
||||
<view class="d-flex w-40 align-items-center justify-content-between pl-30">
|
||||
<view class="font-size-base text-color-base">x{{ good.number }}</view>
|
||||
<view class="font-size-base text-color-base font-weight-bold">¥{{ good.price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- goods end -->
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
<view class="section">
|
||||
<!-- goods begin -->
|
||||
<list-cell :hover="false" padding="30rpx 30rpx">
|
||||
<view class="w-100 d-flex flex-column position-relative">
|
||||
<view class="w-100 d-flex align-items-center mb-40" v-for="(good, index) in order.cartInfo" :key="index">
|
||||
<image :src="good.image" mode="aspectFill" class="image"></image>
|
||||
<view class="d-flex flex-column w-60 overflow-hidden">
|
||||
<view class="font-size-lg text-color-base mb-10 text-truncate">{{ good.title }}</view>
|
||||
<view class="font-size-sm text-color-assist text-truncate">{{ good.spec }}</view>
|
||||
</view>
|
||||
<view class="d-flex w-40 align-items-center justify-content-between pl-30">
|
||||
<view class="font-size-base text-color-base">x{{ good.number }}</view>
|
||||
<view class="font-size-base text-color-base font-weight-bold">¥{{ good.price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- goods end -->
|
||||
<!-- payment and amount begin -->
|
||||
<list-cell :hover="false" padding="50rpx 30rpx">
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="pay-cell">
|
||||
<view>支付方式</view>
|
||||
<view class="font-weight-bold">{{ order._status._payType }}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>订单金额</view>
|
||||
<view class="font-weight-bold">¥{{ order.totalPrice }}</view>
|
||||
</view>
|
||||
<view class="pay-cell" v-if="order.orderType == 'takeout'">
|
||||
<view>配送费</view>
|
||||
<view class="font-weight-bold">¥{{ order.payPostage }}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>优惠金额</view>
|
||||
<view class="font-weight-bold">¥{{ order.couponPrice }}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>实付金额</view>
|
||||
<view class="font-weight-bold">¥{{ order.payPrice }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- payment and amount end -->
|
||||
</view>
|
||||
<view class="section">
|
||||
<!-- order info begin -->
|
||||
<list-cell :hover="false" padding="50rpx 30rpx">
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="pay-cell">
|
||||
<view>下单时间</view>
|
||||
<view class="font-weight-bold">{{ formatDateTime(order.createTime )}}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>下单门店</view>
|
||||
<view class="font-weight-bold">{{ order.shop.name }}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>订单号</view>
|
||||
<view class="font-weight-bold">{{ order.id }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- order info end -->
|
||||
</view>
|
||||
<!-- order other info begin -->
|
||||
<list-cell :hover="false" padding="50rpx 30rpx 20rpx" last>
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="pay-cell">
|
||||
<view>享用方式</view>
|
||||
<view class="font-weight-bold">{{order.orderType == 'takein' ? '自取' : '外卖'}}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>取餐时间</view>
|
||||
<view class="font-weight-bold">{{order.getTime ? formatDateTime(order.getTime) : '立即取餐'}}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>制作完成时间</view>
|
||||
<view class="font-weight-bold">{{ order.deliveryTime ? formatDateTime(order.deliveryTime) : '无' }}</view>
|
||||
</view>
|
||||
<view class="pay-cell">
|
||||
<view>备注</view>
|
||||
<view class="font-weight-bold">{{ order.remark ? order.remark : '无' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- order other info end -->
|
||||
</view>
|
||||
<view class="fixed-bottom flex justify-end bg-white p-2" v-if="order.paid > 0 && order.refundStatus == 0">
|
||||
<view class="mr-1"><uv-button type="success" v-if="order.status < 2" :plain="true" size="small" text="确认收到餐" @click="receive(order)"></uv-button></view>
|
||||
<view><uv-button type="warning" :plain="true" size="small" text="申请退款" @click="refund(order)"></uv-button></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad} from '@dcloudio/uni-app'
|
||||
import { formatDateTime } from '@/utils/util'
|
||||
import {
|
||||
orderDetail,
|
||||
orderReceive,
|
||||
} from '@/api/order'
|
||||
const title = ref('订单详情')
|
||||
const order = ref({
|
||||
shop:{name:''},
|
||||
_status:{_payType:''}
|
||||
})
|
||||
const numForMading = ref(5)
|
||||
|
||||
onLoad((option) => {
|
||||
detail(option.id);
|
||||
})
|
||||
|
||||
const detail = async(id) => {
|
||||
let data = await orderDetail(id);
|
||||
if (data) {
|
||||
order.value = data;
|
||||
}
|
||||
}
|
||||
const openLocation = () => {
|
||||
let shop = order.value.shop;
|
||||
uni.openLocation({
|
||||
address: shop.addressMap + shop.address + " " + shop.name,
|
||||
latitude: parseFloat(shop.lat),
|
||||
longitude: parseFloat(shop.lng),
|
||||
fail(res) {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
const makePhoneCall = () =>{
|
||||
let shop = order.value.shop;
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: shop.mobile,
|
||||
fail(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 确认收到货
|
||||
const receive = async(order) => {
|
||||
let data = await orderReceive({uni:order.orderId});
|
||||
if (data) {
|
||||
await getOrders(true)
|
||||
}
|
||||
}
|
||||
//提交退款
|
||||
const refund = (order) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/orders/refund?orderId=' + order.orderId + '&payPrice=' + order.payPrice + '&totalPrice=' + order.totalPrice
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.image {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
margin-right: 30rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
// @mixin arch {
|
||||
// content: "";
|
||||
// position: absolute;
|
||||
// background-color: $bg-color;
|
||||
// width: 30rpx;
|
||||
// height: 30rpx;
|
||||
// bottom: -15rpx;
|
||||
// z-index: 10;
|
||||
// border-radius: 100%;
|
||||
// }
|
||||
|
||||
// .section {
|
||||
// position: relative;
|
||||
|
||||
// &::before {
|
||||
// @include arch;
|
||||
// left: -15rpx;
|
||||
// }
|
||||
|
||||
// &::after {
|
||||
// @include arch;
|
||||
// right: -15rpx;
|
||||
// }
|
||||
// }
|
||||
|
||||
.pay-cell {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.invote-box {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
background-color: #ffffff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 120rpx;
|
||||
box-shadow: 0 0 20rpx rgba($color: #000000, $alpha: 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
z-index: 11;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx 10rpx;
|
||||
flex: 1;
|
||||
flex-shrink: 0;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
border-radius: 50rem !important;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
page {
|
||||
min-height: 100%;
|
||||
background-color: $bg-color;
|
||||
}
|
||||
/* #endif */
|
||||
.order-box {
|
||||
padding: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
margin-bottom: 100rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.drinks-img {
|
||||
width: 260rpx;
|
||||
height: 260rpx;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin: 60rpx 0 80rpx;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.drink-btn {
|
||||
width: 320rpx;
|
||||
border-radius: 50rem !important;
|
||||
margin-bottom: 40rpx;
|
||||
font-size: $font-size-base;
|
||||
line-height: 3.0;
|
||||
}
|
||||
|
||||
@mixin arch {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: $bg-color;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
bottom: -15rpx;
|
||||
z-index: 10;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.section {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
@include arch;
|
||||
left: -15rpx;
|
||||
}
|
||||
|
||||
&::after {
|
||||
@include arch;
|
||||
right: -15rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-cell {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-base;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sort-num {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: $text-color-base;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.steps__img-column {
|
||||
display: flex;
|
||||
margin: 30rpx 0;
|
||||
|
||||
.steps__img-column-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
.unactive {
|
||||
color: #919293;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.steps__text-column {
|
||||
display: flex;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.steps__text-column-item {
|
||||
flex: 1;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color-assist;
|
||||
|
||||
&.active {
|
||||
color: $text-color-base;
|
||||
font-weight: bold;
|
||||
|
||||
.steps__column-item-line {
|
||||
background-color: $text-color-base;
|
||||
}
|
||||
}
|
||||
|
||||
.steps__column-item-line{
|
||||
flex: 1;
|
||||
height: 2rpx;
|
||||
background-color: #919293;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
.steps__text-column-item-text {
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-lamp, .icon-daojishi, .icon-takeout, .icon-doorbell{
|
||||
font-size: 60rpx;
|
||||
}
|
||||
.iconfont-yshop {
|
||||
color: #dd524d;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container">
|
||||
<view class="bg-white">
|
||||
<uv-tabs :list="tabList" :current="current" @change="change" keyName="name" :scrollable="false"></uv-tabs>
|
||||
</view>
|
||||
<view class="orders-list d-flex flex-column w-100" style="padding: 20rpx; padding-bottom: 0;">
|
||||
<view class="order-item" v-for="(item, index) in orders" :key="index" style="margin-bottom: 30rpx;" @tap="detail(item.orderId)">
|
||||
<list-cell :hover="false">
|
||||
<view class="w-100 d-flex align-items-center">
|
||||
<view class="flex-fill d-flex flex-column">
|
||||
<view class="font-size-lg text-color-base" style="margin-bottom: 20rpx;">
|
||||
{{ item.shop.name }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">取餐号:{{ item.numberId }}</view>
|
||||
<view class="font-size-sm text-color-assist">订单编号:{{ item.orderId }}</view>
|
||||
</view>
|
||||
<view class="font-size-lg text-color-primary">
|
||||
{{ item._status._title }}
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false" last>
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="w-100 text-truncate font-size-lg text-color-base" style="margin-bottom: 20rpx;">
|
||||
<!-- {{ orderGoodsName(item.cartInfo) }} -->
|
||||
<view class="flex mb-2" v-for="(good,index) in item.cartInfo" :key="index">
|
||||
<image :src="good.image" mode="aspectFill" class="image"></image>
|
||||
<view class="flex flex-column">
|
||||
<view class="font-size-medium mt-1 text-color-base">{{ good.title }}</view>
|
||||
<view class="font-size-sm mt-1">{{ good.spec }}</view>
|
||||
<view class="font-size-sm mt-2">×{{ good.number }} ¥{{ good.price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex justify-content-between align-items-center" style="margin-bottom: 30rpx;">
|
||||
<view class="font-size-sm text-color-assist">
|
||||
{{formatDateTime(item.createTime) }}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base align-items-center">
|
||||
<view style="margin-right: 10rpx;">共{{ goodsNum(item.cartInfo) }}件商品,实付</view>
|
||||
<view class="font-size-lg">¥{{ item.payPrice }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex align-items-center justify-content-end">
|
||||
<view>
|
||||
<button v-if="item.paid > 0 && item.status < 2 && item.refundStatus == 0" class="left-margin" plain size="mini" @tap.stop="receive(item)">确认收到餐</button>
|
||||
<button class="left-margin" plain size="mini" @tap="detail(item.orderId)">订单详情</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
</view>
|
||||
<uv-empty v-if="orders.length == 0" mode="order"></uv-empty>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onPullDownRefresh,onReachBottom} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,kmUnit } from '@/utils/util'
|
||||
import {
|
||||
orderGetOrders,
|
||||
orderReceive
|
||||
} from '@/api/order'
|
||||
const main = useMainStore()
|
||||
const { isLogin } = storeToRefs(main)
|
||||
const title = ref('我的订单')
|
||||
|
||||
const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const orders = ref([])
|
||||
const tabList = ref([{
|
||||
type: -1,
|
||||
name: '全部',
|
||||
}, {
|
||||
type: 0,
|
||||
name: '待支付',
|
||||
}, {
|
||||
type: 1,
|
||||
name: '进行中'
|
||||
}, {
|
||||
type: 4,
|
||||
name: '已完成'
|
||||
}, {
|
||||
type: -3,
|
||||
name: '退款单'
|
||||
}]
|
||||
)
|
||||
const current = ref(0)
|
||||
const type = ref(-1)
|
||||
|
||||
const orderGoodsName = computed(() => { //计算单个饮品添加到购物车的数量
|
||||
return (goods) => {
|
||||
let arr = []
|
||||
goods.forEach(good => arr.push(good.title + '*' + good.number))
|
||||
return arr.join(',')
|
||||
}
|
||||
})
|
||||
const goodsNum = computed(() => { //计算单个饮品添加到购物车的数量
|
||||
return (goods) => {
|
||||
let num = 0;
|
||||
goods.forEach(good => num += parseInt(good.number))
|
||||
return num;
|
||||
}
|
||||
})
|
||||
onLoad(() => {
|
||||
if(!isLogin.value) {
|
||||
uni.navigateTo({url: '/pages/components/pages/login/login'})
|
||||
}
|
||||
getOrders(false)
|
||||
})
|
||||
onPullDownRefresh(() => {
|
||||
getOrders(false)
|
||||
})
|
||||
onReachBottom(() => {
|
||||
getOrders(false)
|
||||
})
|
||||
|
||||
// tab栏切换
|
||||
const change = (e) => {
|
||||
type.value = e.type
|
||||
getOrders(true)
|
||||
}
|
||||
|
||||
const getOrders = async(isRefresh = false) => {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
if(isRefresh) {
|
||||
orders.value = []
|
||||
page.value = 1
|
||||
}
|
||||
let ordersData = await orderGetOrders({page:page.value, limit:pageSize.value,type:type.value});
|
||||
|
||||
if(ordersData) {
|
||||
orders.value = orders.value.concat(ordersData)
|
||||
page.value += 1
|
||||
}
|
||||
uni.stopPullDownRefresh();
|
||||
uni.hideLoading()
|
||||
}
|
||||
const detail = (id) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/orders/detail?id=' + id
|
||||
})
|
||||
}
|
||||
// 确认收到货
|
||||
const receive = async(order) => {
|
||||
let data = await orderReceive({uni:order.orderId});
|
||||
if (data) {
|
||||
await getOrders(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.left-margin {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
.image {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 30rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="p-2">
|
||||
<uv-list>
|
||||
<uv-list-item title="订单金额" :rightText="'¥'+totalPrice"></uv-list-item>
|
||||
<uv-list-item title="退款金额" :rightText="'¥'+payPrice"></uv-list-item>
|
||||
<uv-list-item title="退款类型" rightText="整个订单"></uv-list-item>
|
||||
<uv-list-item title="退款原因" rightText="协商一致"></uv-list-item>
|
||||
<uv-list-item title="退款留言" >
|
||||
<template #footer><uv-input placeholder="请输入内容" border="none" v-model="refundReasonWapExplain"></uv-input></template>
|
||||
</uv-list-item>
|
||||
</uv-list>
|
||||
<view class="mt-2">
|
||||
<uv-button shape="circle" type="warning" :plain="true" size="small" text="申请退款" @click="refund()"></uv-button>
|
||||
</view>
|
||||
<uv-toast ref="toast"></uv-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad} from '@dcloudio/uni-app'
|
||||
import {
|
||||
orderRefund
|
||||
} from '@/api/order'
|
||||
const title = ref('申请退款')
|
||||
const orderId = ref('')
|
||||
const payPrice = ref('')
|
||||
const totalPrice = ref('')
|
||||
const refundReasonWapExplain = ref('')
|
||||
const toast = ref()
|
||||
onLoad((option) => {
|
||||
console.log('option:',option)
|
||||
orderId.value = option.orderId
|
||||
payPrice.value = option.payPrice
|
||||
totalPrice.value = option.totalPrice
|
||||
})
|
||||
|
||||
const refund = async() => {
|
||||
let data = await orderRefund({refundReasonWapExplain:refundReasonWapExplain.value,uni:orderId.value,text:'协商一致'});
|
||||
if (data) {
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,395 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container position-relative w-100 h-100 overflow-hidden">
|
||||
<uv-empty v-if="coupons.length == 0" mode="coupon"></uv-empty>
|
||||
|
||||
<scroll-view scroll-y class="coupon-list">
|
||||
<view class="wrapper">
|
||||
<view class="coupon" v-for="(item, index) in coupons" :key="index" @tap="openDetailModal(item, index)">
|
||||
<view class="taobao">
|
||||
<view class="ticket" :style="{border: item.id == coupon_id ? '1rpx solid red':''}">
|
||||
<view class="left">
|
||||
<image class="picture" :src="item.image" mode="aspectFill"></image>
|
||||
<view class="introduce">
|
||||
<view class="top">
|
||||
¥
|
||||
<text class="big">{{ item.value }}</text>
|
||||
<view>满{{ item.least }}减{{ item.value }}</view>
|
||||
</view>
|
||||
<view class="type">{{ item.title }}</view>
|
||||
<view class="date u-line-1">{{formatDateTime(item.startTime, 'yyyy-MM-dd')}}-{{formatDateTime(item.endTime, 'yyyy-MM-dd')}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right" @click.stop="" v-if="activeTabIndex == 0">
|
||||
<view v-if="item.id != coupon_id" class="use immediate-use" :round="true" @tap="useCouponWith(item)">立即使用</view>
|
||||
<view v-else class="use immediate-use" :round="true" @tap="cancelCoupon(item)">取消使用</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<modal custom :show="detailModalVisible" @cancel="closeDetailModal" width="90%">
|
||||
<view class="modal-content">
|
||||
<view class="d-flex font-size-extra-lg text-color-base just-content-center mb-20">{{ coupon.title }}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">有效期:{{formatDateTime(coupon.startTime, 'yyyy-MM-dd')}}至{{formatDateTime(coupon.endTime, 'yyyy-MM-dd')}}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">领取时间:{{ coupon.createtime_text }}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">卷价值:满{{ coupon.least }}减{{ coupon.value }}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">适用范围:{{ typeInfo(coupon.type) }}</view>
|
||||
<view class="d-flex font-size-sm text-color-base mb-20">适用店铺:{{ coupon.shopName }}</view>
|
||||
<view class="d-flex align-items-center just-content-center" v-if="activeTabIndex == 0">
|
||||
<button type="primary" @tap="useCoupon" class="use-coupon-btn">立即使用</button>
|
||||
</view>
|
||||
</view>
|
||||
</modal>
|
||||
|
||||
<!--轻提示-->
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
toRaw
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow ,onPullDownRefresh,onHide} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,prePage } from '@/utils/util'
|
||||
import {
|
||||
couponMine
|
||||
} from '@/api/coupon'
|
||||
const main = useMainStore()
|
||||
const { isLogin } = storeToRefs(main)
|
||||
const title = ref('优惠券')
|
||||
const activeTabIndex = ref(0)
|
||||
const detailModalVisible = ref(false)
|
||||
const coupon = ref({})
|
||||
const couponIndex = ref(0)
|
||||
const coupons = ref([])
|
||||
const amount = ref(0)
|
||||
const buttonLock = ref(false)
|
||||
const coupon_id = ref(0)
|
||||
const shop_id = ref(0)
|
||||
const type = ref(0)
|
||||
const uToast = ref()
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.amount) {
|
||||
amount.value = options.amount;
|
||||
}
|
||||
if (options.coupon_id) {
|
||||
coupon_id.value = options.coupon_id
|
||||
}
|
||||
if (options.shop_id) {
|
||||
shop_id.value = options.shop_id;
|
||||
}
|
||||
if (options.type) {
|
||||
type.value = options.type;
|
||||
}
|
||||
activeTabIndex.value = 0;
|
||||
getCoupons();
|
||||
})
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
getCoupons();
|
||||
})
|
||||
|
||||
// 使用范围
|
||||
const typeInfo = (type) => {
|
||||
if (type == 0) {
|
||||
return '外卖和自取';
|
||||
}
|
||||
if (type == 1) {
|
||||
return '自取';
|
||||
}
|
||||
if (type == 2) {
|
||||
return '外卖';
|
||||
}
|
||||
}
|
||||
const getCoupons = async() => {
|
||||
let data = await couponMine({shop_id: shop_id.value, type: type.value, page:1, pagesize:10000});
|
||||
uni.stopPullDownRefresh();
|
||||
if (data) {
|
||||
coupons.value = data;
|
||||
}
|
||||
}
|
||||
const openDetailModal = (mycoupon, index) => {
|
||||
couponIndex.value = index;
|
||||
coupon.value = mycoupon;
|
||||
detailModalVisible.value = true;
|
||||
}
|
||||
// 使用优惠券
|
||||
const useCouponWith = (mycoupon) => {
|
||||
coupon.value = mycoupon;
|
||||
useCoupon();
|
||||
}
|
||||
// 取消优惠券
|
||||
const cancelCoupon = () => {
|
||||
coupon.value = {}
|
||||
coupon_id.value = 0
|
||||
prePage().coupon = {}
|
||||
}
|
||||
const closeDetailModal = () => {
|
||||
detailModalVisible.value = false;
|
||||
coupon.value = {};
|
||||
}
|
||||
// 使用优惠及
|
||||
|
||||
const useCoupon = () => {
|
||||
if (buttonLock.value == true) {
|
||||
return;
|
||||
}
|
||||
buttonLock.value = true
|
||||
//console.log('coupon:',coupon.value);
|
||||
if (parseFloat(coupon.value.least) > parseFloat(amount.value)) {
|
||||
//console.log('pages3:');
|
||||
uToast.value.show({
|
||||
message: '订单金额满'+coupon.value.least+'才能使用',
|
||||
type: 'error'
|
||||
});
|
||||
buttonLock.value = false
|
||||
} else {
|
||||
main.SET_COUPON(coupon)
|
||||
console.log('main.myconpon:',main.mycoupon)
|
||||
//prePage().coupon = coupon.value;
|
||||
//prePage().coupons = 1; // 哨兵
|
||||
|
||||
uni.navigateBack({
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifdef H5 */
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
height: 80rpx;
|
||||
flex-shrink: 0;
|
||||
.item {
|
||||
padding: 0 20rpx;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
border-right: 1rpx solid $text-color-assist;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: scaleX(0.5) scaleY(0.8);
|
||||
}
|
||||
|
||||
&:nth-last-child(1)::after {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-list {
|
||||
margin-top: 30rpx;
|
||||
height:calc(100vh - 120rpx);
|
||||
// height: calc(100vh - 120rpx - 200rpx);
|
||||
/* #ifdef H5 */
|
||||
// height: calc(100vh - 120rpx - 200rpx - 44px);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.coupon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 30rpx;
|
||||
//padding: 0 30rpx;
|
||||
border-radius: 6rpx;
|
||||
box-shadow: 0 10rpx 10rpx -10rpx rgba(15, 15, 15, 0.1);
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: $bg-color;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
bottom: 65rpx;
|
||||
left: -15rpx;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: $bg-color;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
bottom: 65rpx;
|
||||
right: -15rpx;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.detail {
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-bottom: 1rpx dashed #c6c6c6;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
.coupon-img {
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.use-coupon-btn {
|
||||
width: 95%;
|
||||
border-radius: 50rem !important;
|
||||
}
|
||||
|
||||
.taobao {
|
||||
background-color: white;
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 30rpx;
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.store {
|
||||
font-weight: 500;
|
||||
}
|
||||
.buddha {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.entrance {
|
||||
color: $uv-info;
|
||||
border: solid 2rpx $uv-info;
|
||||
line-height: 48rpx;
|
||||
padding: 0 30rpx;
|
||||
background: none;
|
||||
border-radius: 15px;
|
||||
}
|
||||
}
|
||||
.ticket {
|
||||
display: flex;
|
||||
.left {
|
||||
width: 70%;
|
||||
padding: 20rpx;
|
||||
background-color: white; //rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
border-right: dashed 2rpx rgb(224, 215, 211);
|
||||
display: flex;
|
||||
.picture {
|
||||
//width: 172rpx;
|
||||
border-radius: 20rpx;
|
||||
width: 190rpx;
|
||||
height: 190rpx;
|
||||
}
|
||||
.introduce {
|
||||
margin-left: 10rpx;
|
||||
.top {
|
||||
color: $uv-warning;
|
||||
font-size: 28rpx;
|
||||
.big {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.type {
|
||||
font-size: 28rpx;
|
||||
color: $uv-info-dark;
|
||||
}
|
||||
.date {
|
||||
margin-top: 10rpx;
|
||||
font-size: 20rpx;
|
||||
color: $uv-info-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
width: 30%;
|
||||
padding: 40rpx 20rpx;
|
||||
background-color: white; //rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.use {
|
||||
height: auto;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
color: #ffffff !important;
|
||||
background-color: $uv-warning !important;
|
||||
line-height: 40rpx;
|
||||
color: rgb(117, 142, 165);
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.used {
|
||||
height: auto;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
//color: #ffffff!important;
|
||||
//background-color: $u-type-warning!important;
|
||||
line-height: 40rpx;
|
||||
//color: rgb(117, 142, 165);
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
.right_log {
|
||||
text-align: center;
|
||||
width: 30%;
|
||||
padding: 80rpx 0rpx;
|
||||
background-color: white; //rgb(255, 245, 244);
|
||||
border-radius: 20rpx;
|
||||
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,814 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container position-relative">
|
||||
<view style="margin-bottom: 130rpx;">
|
||||
<view class="section-1">
|
||||
<template v-if="store.distance > 0">
|
||||
<list-cell class="location">
|
||||
<view class="flex-fill d-flex justify-content-between align-items-center">
|
||||
<view class="store-name flex-fill">{{ orderType == 'takeout' ? '外卖配送' : '点餐自取' }}</view>
|
||||
<uv-switch activeColor="#dd524d" v-model="active" @change="takout">
|
||||
</uv-switch>
|
||||
</view>
|
||||
</list-cell>
|
||||
</template>
|
||||
|
||||
<template v-if="orderType == 'takeout'">
|
||||
<list-cell @click="chooseAddress">
|
||||
<view v-if="address.realName" class="w-100 d-flex flex-column">
|
||||
<view class="d-flex align-items-center justify-content-between mb-10">
|
||||
<view class="font-size-lg text-color-base">
|
||||
{{ address.address + ' ' + address.detail }}
|
||||
</view>
|
||||
<image src="/static/images/navigator-1.png" class="arrow"></image>
|
||||
</view>
|
||||
<view class="d-flex text-color-assist font-size-sm align-items-center">
|
||||
<view class="mr-10">{{ address.realName }}</view>
|
||||
<view>{{ address.phone }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="flex-fill d-flex justify-content-between align-items-center">
|
||||
<view class="store-name flex-fill">选择收货地址</view>
|
||||
<image src="/static/images/navigator-1.png" class="arrow"></image>
|
||||
</view>
|
||||
</list-cell>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="section-1">
|
||||
<template>
|
||||
<list-cell class="location" @click="goToShop">
|
||||
<view class="flex-fill d-flex justify-content-between align-items-center">
|
||||
<view class="store-name flex-fill">{{ store.name }}</view>
|
||||
<image src="/static/images/navigator-1.png" class="arrow"></image>
|
||||
</view>
|
||||
</list-cell>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<list-cell arrow class="meal-time" v-if="orderType == 'takein'">
|
||||
<view class="flex-fill d-flex justify-content-between align-items-center"
|
||||
@click="takeinTIme = !takeinTIme">
|
||||
<view class="title">取餐时间</view>
|
||||
<view class="time">
|
||||
{{ takeinRange[defaultSelector[0]].name }}
|
||||
<u-picker v-model="takeinTIme" :range="takeinRange" range-key="name" mode="selector"
|
||||
@cancel="takeinCancelTime" @confirm="takeinConfirmTime"
|
||||
:default-selector="defaultSelector"></u-picker>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell class="contact" last :hover="false" v-if="orderType == 'takein'">
|
||||
<view class="flex-fill d-flex justify-content-between align-items-center">
|
||||
<view class="title flex-fill">联系电话</view>
|
||||
<view class="time"><input class="text-right" placeholder="请输入手机号码" :value="member.mobile" />
|
||||
</view>
|
||||
<button class="contact-tip font-size-sm">自动填写</button>
|
||||
</view>
|
||||
</list-cell>
|
||||
</template>
|
||||
<template v-if="orderType == 'takeout'">
|
||||
<list-cell>
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="d-flex align-items-center font-size-base text-color-base">
|
||||
<view class="flex-fill">预计送达时间</view>
|
||||
<view class="mr-10">
|
||||
{{ defaultTime }}
|
||||
<u-picker :default-time="defaultTime" v-model="takeoutTIme" :params="paramsTime"
|
||||
mode="time" @cancel="cancelTime" @confirm="choiceTime"></u-picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</template>
|
||||
</view>
|
||||
<!-- 购物车列表 begin -->
|
||||
<view class="section-2">
|
||||
<view class="cart d-flex flex-column">
|
||||
<list-cell last v-for="(item, index) in cart" :key="index">
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="d-flex align-items-center mb-10">
|
||||
<view
|
||||
class="d-flex flex-fill justify-content-between align-items-center text-color-base font-size-lg">
|
||||
<image style="width: 80rpx;height: 80rpx;" mode="aspectFill" :src="item.image">
|
||||
</image>
|
||||
</view>
|
||||
<view class="name-and-props overflow-hidden">
|
||||
<view class="text-color-base font-size-lg">{{ item.name }}</view>
|
||||
</view>
|
||||
<view
|
||||
class="d-flex flex-fill justify-content-between align-items-center text-color-base font-size-lg">
|
||||
<view>x{{ item.number }}</view>
|
||||
<view>¥{{ item.price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-truncate font-size-base text-color-assist">{{ item.valueStr }}</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
<list-cell arrow @click="goToPackages">
|
||||
<view class="flex-fill d-flex justify-content-between align-items-center">
|
||||
<view class="text-color-base">优惠券</view>
|
||||
<view v-if="coupons == 0" class="text-color-base">暂无可用</view>
|
||||
<view v-else-if="coupon.title" class="text-color-danger">
|
||||
{{ coupon.title }}(满{{ coupon.least }}减{{ coupon.value }})
|
||||
</view>
|
||||
<view v-else class="text-color-primary">可用优惠券{{ coupons }}张</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell last>
|
||||
<view class="flex-fill d-flex justify-content-end align-items-center">
|
||||
<view>
|
||||
总计¥{{ total }}
|
||||
<text v-if="orderType == 'takeout'">,配送费¥{{ store.deliveryPrice }}</text>
|
||||
<text v-if="coupon.value">,¥-{{ coupon.value }}</text>
|
||||
,实付
|
||||
</view>
|
||||
<view class="font-size-extra-lg font-weight-bold">¥{{ amount }}</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
<!-- 购物车列表 end -->
|
||||
<view class="d-flex align-items-center justify-content-start font-size-sm text-color-warning"
|
||||
style="padding: 20rpx 0;">
|
||||
</view>
|
||||
<!-- 支付方式 begin -->
|
||||
<view class="payment">
|
||||
<list-cell last :hover="false"><text>支付方式</text></list-cell>
|
||||
<list-cell>
|
||||
<view class="d-flex align-items-center justify-content-between w-100 disabled"
|
||||
@click="setPayType('yue')">
|
||||
<view class="iconfont iconbalance line-height-100 payment-icon"></view>
|
||||
<view class="flex-fill">余额支付(余额¥{{ member.nowMoney }})</view>
|
||||
<view class="font-size-sm" v-if="member.nowMoney == 0">余额不足</view>
|
||||
<view class="iconfont line-height-100 checkbox checked iconradio-button-on" v-if="payType == 'yue'">
|
||||
</view>
|
||||
<view class="iconfont line-height-100 checkbox iconradio-button-off" v-else></view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell last>
|
||||
<view class="d-flex align-items-center justify-content-between w-100" @click="setPayType('weixin')">
|
||||
<view class="iconfont iconwxpay line-height-100 payment-icon" style="color: #7EB73A"></view>
|
||||
<view class="flex-fill">微信支付</view>
|
||||
<view class="iconfont line-height-100 checkbox checked iconradio-button-on" v-if="payType == 'weixin'">
|
||||
</view>
|
||||
<view class="iconfont line-height-100 checkbox iconradio-button-off" v-else></view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- #ifdef H5 -->
|
||||
<list-cell>
|
||||
<view class="d-flex align-items-center justify-content-between w-100" @click="setPayType('alipay')">
|
||||
<view class="iconfont-yshop icon-alipay line-height-100 payment-icon" style="color:#07b4fd" ></view>
|
||||
<view class="flex-fill">支付宝</view>
|
||||
<view class="iconfont line-height-100 checkbox checked iconradio-button-on" v-if="payType == 'alipay'" ></view>
|
||||
<view class="iconfont line-height-100 checkbox iconradio-button-off" v-else ></view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<!-- 支付方式 end -->
|
||||
<!-- 备注 begin -->
|
||||
<list-cell last @click="goToRemark">
|
||||
<view class="d-flex flex-fill align-items-center justify-content-between overflow-hidden" style="margin-bottom: 110rpx;">
|
||||
<view class="flex-shrink-0 mr-20">备注</view>
|
||||
<view class="text-color-primary flex-fill text-truncate text-right">{{ form.remark || '点击填写备注' }}
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<!-- 备注 end -->
|
||||
</view>
|
||||
<!-- 付款栏 begin -->
|
||||
<view style="z-index: 1;"
|
||||
class="w-100 pay-box position-fixed fixed-bottom d-flex align-items-center justify-content-between bg-white">
|
||||
<view class="font-size-sm" style="margin-left: 20rpx;">合计:</view>
|
||||
<view class="font-size-lg flex-fill">¥{{ amount }}</view>
|
||||
<view class="bg-primary h-100 d-flex align-items-center just-content-center text-color-white font-size-base"
|
||||
style="padding: 0 60rpx;" @tap="debounce(submit, 500)">付款</view>
|
||||
</view>
|
||||
<!-- 付款栏 end -->
|
||||
<modal :show="ensureAddressModalVisible" custom :mask-closable="false" :radius="'0rpx'" width="90%">
|
||||
<view class="modal-content">
|
||||
<view class="d-flex justify-content-end">
|
||||
<image src="/static/images/pay/close.png" style="width: 40rpx; height: 40rpx;"
|
||||
@tap="ensureAddressModalVisible = false"></image>
|
||||
</view>
|
||||
<view class="d-flex just-content-center align-items-center" style="margin-bottom: 40px;">
|
||||
<view class="font-size-extra-lg text-color-base">请再次确认下单地址</view>
|
||||
</view>
|
||||
<view
|
||||
class="d-flex font-size-base text-color-base font-weight-bold align-items-center justify-content-between mb-20">
|
||||
<view>{{ address.realName }}</view>
|
||||
<view>{{ address.phone }}</view>
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-assist align-items-center justify-content-between mb-40">
|
||||
<view style="max-width: 60%;">{{ address.address + address.detail }}</view>
|
||||
<button type="primary" size="mini" plain class="change-address-btn" style="white-space: nowrap;"
|
||||
@click="chooseAddress">修改地址</button>
|
||||
</view>
|
||||
<button type="primary" class="pay_btn" @tap="debounce(pay, 500)">确认并付款</button>
|
||||
</view>
|
||||
</modal>
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
nextTick
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow ,onPullDownRefresh,onHide} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,isWeixin } from '@/utils/util'
|
||||
import debounce from '@/uni_modules/uv-ui-tools/libs/function/debounce'
|
||||
|
||||
import {
|
||||
orderSubmit,
|
||||
payUnify,
|
||||
getWechatConfig
|
||||
} from '@/api/order'
|
||||
import {
|
||||
couponCount
|
||||
} from '@/api/coupon'
|
||||
// #ifdef H5
|
||||
import * as jweixin from 'weixin-js-sdk'
|
||||
// #endif
|
||||
const main = useMainStore()
|
||||
const { orderType,address, store,location,isLogin,member,mycoupon } = storeToRefs(main)
|
||||
const active = ref(false)
|
||||
const title = ref('支付')
|
||||
const jsStr = ref('')
|
||||
const cart = ref([])
|
||||
const form = ref({
|
||||
remark: ''
|
||||
})
|
||||
const ensureAddressModalVisible = ref(false)
|
||||
const takeoutTIme = ref(false) // 外卖取餐时间picker
|
||||
const paramsTime = ref({
|
||||
year: false,
|
||||
month: false,
|
||||
day: false,
|
||||
hour: true,
|
||||
minute: true,
|
||||
second: false
|
||||
})
|
||||
const defaultTime = ref('00:00')
|
||||
const takeinTIme = ref(false) // 到店自取时间selector
|
||||
const takeinRange = ref([{
|
||||
name: '立即用餐',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: '10分钟后',
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
name: '20分钟后',
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
name: '30分钟后',
|
||||
value: 30
|
||||
},
|
||||
{
|
||||
name: '40分钟后',
|
||||
value: 40
|
||||
},
|
||||
{
|
||||
name: '50分钟后',
|
||||
value: 50
|
||||
}
|
||||
])
|
||||
const defaultSelector = ref([0])
|
||||
const payType = ref('weixin') // 付款方式
|
||||
const coupons = ref(0) // 可用优惠券数量
|
||||
const coupon = ref(main.mycoupon) // 选中的
|
||||
const subscribeMss = ref({
|
||||
'takein': '',
|
||||
'takeout': '',
|
||||
'takein_made': '',
|
||||
'takeout_made': ''
|
||||
})// 微信订阅信息
|
||||
const uToast = ref()
|
||||
|
||||
const total = computed(() =>{
|
||||
return cart.value.reduce((acc, cur) => acc + cur.number * cur.price, 0);
|
||||
})
|
||||
const amount = computed(() =>{
|
||||
let amount = cart.value.reduce((acc, cur) => acc + cur.number * cur.price, 0);
|
||||
// 加配送费
|
||||
if (store.value.distance > 0 && orderType.value == 'takeout') {
|
||||
amount += parseFloat(store.value.deliveryPrice);
|
||||
}
|
||||
|
||||
|
||||
// 减去优惠券
|
||||
if (main.mycoupon.hasOwnProperty('id')) {
|
||||
amount -= parseFloat(main.mycoupon.value);
|
||||
}
|
||||
return amount.toFixed(2);
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
coupon.value = main.mycoupon
|
||||
let date = new Date(new Date().getTime() + 3600000); // 一个小时后
|
||||
let hour = date.getHours();
|
||||
let minute = date.getMinutes();
|
||||
if (hour < 10) {
|
||||
hour = '0' + hour;
|
||||
}
|
||||
if (minute < 10) {
|
||||
minute = '0' + minute;
|
||||
}
|
||||
defaultTime.value = hour + ':' + minute;
|
||||
|
||||
console.log('member:',member.value)
|
||||
|
||||
if(orderType.value == 'takeout'){
|
||||
active.value = true
|
||||
}else{
|
||||
active.value = false
|
||||
}
|
||||
|
||||
getCoupons();
|
||||
|
||||
let paytype = uni.getStorageSync('paytype');
|
||||
payType.value = paytype ? paytype : 'weixin';
|
||||
|
||||
})
|
||||
onHide(() => {
|
||||
subscribeMss.value = [];
|
||||
coupons.value = 0;
|
||||
})
|
||||
onLoad((option) => {
|
||||
cart.value = uni.getStorageSync('cart')
|
||||
if(option.remark) {
|
||||
form.value.remark = option.remark
|
||||
}
|
||||
})
|
||||
|
||||
const getSubscribeMss = async() => {
|
||||
let data = []
|
||||
if (data) {
|
||||
subscribeMss.value = data;
|
||||
}
|
||||
}
|
||||
// 更改支付方式
|
||||
const setPayType = (paytype) => {
|
||||
payType.value = 'weixin';
|
||||
payType.value= paytype;
|
||||
uni.setStorage({
|
||||
key: 'paytype',
|
||||
data: paytype
|
||||
})
|
||||
}
|
||||
const getCoupons = async() => {
|
||||
//0=通用,1=自取,2=外卖
|
||||
let type = orderType.value == 'takein' ? 1 : 2;
|
||||
let data = await couponCount({
|
||||
shop_id: store.value.id ? store.value.id : 0,
|
||||
type: type
|
||||
});
|
||||
if (data) {
|
||||
coupons.value = data;
|
||||
}
|
||||
}
|
||||
// 选择时间
|
||||
const choiceTime = (value) => {
|
||||
let hour = value.hour;
|
||||
let minute = value.minute;
|
||||
|
||||
let date = new Date(new Date().getTime() + 3600000); // 一个小时后
|
||||
let nowhour = date.getHours();
|
||||
let nowminute = date.getMinutes();
|
||||
|
||||
if ((hour * 60 * 60 + minute * 60) * 1000 - 3600000 < (nowhour * 60 * 60 + nowminute * 60) * 1000) {
|
||||
uToast.value.show({
|
||||
message: '请至少选择一个小时之后',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
if (hour < 10) {
|
||||
hour = '0' + hour;
|
||||
}
|
||||
if (minute < 10) {
|
||||
minute = '0' + minute;
|
||||
}
|
||||
defaultTime,value = hour + ':' + minute;
|
||||
takeoutTIme.value = false;
|
||||
}
|
||||
const cancelTime = (value) => {
|
||||
takeoutTIme.value = false;
|
||||
}
|
||||
// 到店自取-取消选择取餐时间
|
||||
const takeinCancelTime = (value) => {
|
||||
takeinTIme.value = false;
|
||||
}
|
||||
// 到店自取-选择取餐时间
|
||||
const takeinConfirmTime = (value) => {
|
||||
defaultSelector.value = value;
|
||||
}
|
||||
// 是否外卖开关
|
||||
const takout = (value) => {
|
||||
let type = 'takeout';
|
||||
if (value == false) {
|
||||
type = 'takein';
|
||||
}
|
||||
main.SET_ORDER_TYPE(type);
|
||||
|
||||
// 如果存在优惠券看看需不需要清除
|
||||
if (coupon.value.hasOwnProperty('type')) {
|
||||
//0=通用,1=自取,2=外卖
|
||||
if (coupon.value.type != 0) {
|
||||
if (coupon.value.type == 1 && orderType.value == 'takeout') {
|
||||
coupon.value = {};
|
||||
}
|
||||
if (coupon.value.type == 2 && orderType.value == 'takeint') {
|
||||
coupon.value = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
subscribeMss.value = [];
|
||||
coupons.value = 0;
|
||||
getCoupons();
|
||||
}
|
||||
const goToRemark = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/remark/remark?remark=' + form.value.remark
|
||||
});
|
||||
}
|
||||
const chooseAddress = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/address/address?is_choose=true&scene=pay'
|
||||
});
|
||||
}
|
||||
const goToPackages = () => {
|
||||
let newamount = amount.value;
|
||||
let coupon_id = coupon.value.id ? coupon.value.id : 0;
|
||||
let type = orderType.value == 'takein' ? 1 : 2;
|
||||
let shop_id = store.value.id;
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/packages/index?amount=' + newamount + '&coupon_id=' + coupon_id +
|
||||
'&shop_id=' + shop_id + '&type=' + type
|
||||
});
|
||||
}
|
||||
const goToShop = () => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/components/pages/shop/shop`
|
||||
});
|
||||
}
|
||||
const submit = () => {
|
||||
if (orderType.value == 'takeout') {
|
||||
// 外卖类型
|
||||
if (typeof address.value.id == 'undefined') {
|
||||
uToast.value.show({
|
||||
message: '请选择收货地址',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
// 起送价钱
|
||||
if (store.value.min_price > total.value) {
|
||||
uToast.value.show({
|
||||
message: '本店外卖起送价为¥' + store.value.min_price,
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
pay();
|
||||
|
||||
} else {
|
||||
pay();
|
||||
}
|
||||
}
|
||||
const pay = async() => {
|
||||
let that = this;
|
||||
// #ifdef MP-WEIXIN
|
||||
await new Promise(function(revolve) {
|
||||
//订阅号信息id
|
||||
let subscribeMss = ['KBtfY9G1IWCzC6q-ZKo-Q-MmdP7aaF79nx0XFcBf3h4'];
|
||||
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '为更好的促进您与商家的交流,小程序需要在您成交时向您发送消息',
|
||||
confirmText: "同意",
|
||||
cancelText: "拒绝",
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.requestSubscribeMessage({
|
||||
tmplIds: subscribeMss,
|
||||
complete(res) {
|
||||
console.log(res)
|
||||
revolve(true)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
revolve(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
// #endif
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
});
|
||||
|
||||
let data = {
|
||||
orderType: orderType.value, // 购买类型:takein=自取,takeout=外卖
|
||||
addressId:orderType.value == 'takeout' ? address.value.id : 0, // 外卖配送地址
|
||||
shopId: store.value.id, // 店铺id
|
||||
mobile: member.value.mobile, // 联系电话
|
||||
gettime: takeinRange.value[defaultSelector.value[0]].value, // 取餐时间
|
||||
payType: payType.value, // 支付类型
|
||||
remark: form.value.remark, // 备注
|
||||
productId: [],
|
||||
spec: [],
|
||||
number: [],
|
||||
couponId: coupon.value.id ? coupon.value.id : 0 // 优惠券id
|
||||
};
|
||||
|
||||
cart.value.forEach((item, index) => {
|
||||
data.productId.push(item.id);
|
||||
data.spec.push(item.valueStr.replace(/,/g, '|'));
|
||||
//data.spec.push(item.valueStr);
|
||||
data.number.push(item.number);
|
||||
});
|
||||
|
||||
//console.log(data);
|
||||
let order = await orderSubmit(data);
|
||||
if (!order) {
|
||||
uni.hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (payType.value == 'weixin') {
|
||||
// 微信支付
|
||||
weixinPay(order);
|
||||
} else if (payType.value == 'yue') {
|
||||
// 余额支付
|
||||
balancePay(order);
|
||||
} else if (payType.value == 'alipay') {
|
||||
// 余额支付
|
||||
aliPay(order);
|
||||
}
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
const balancePay = async(order) => {
|
||||
let from = 'routine'
|
||||
// #ifdef H5
|
||||
from = 'h5'
|
||||
// #endif
|
||||
let pay = await payUnify({
|
||||
uni: order.orderId,
|
||||
from: from,
|
||||
paytype: 'yue'
|
||||
});
|
||||
|
||||
uni.hideLoading();
|
||||
if (!pay) {
|
||||
return;
|
||||
}
|
||||
|
||||
member.value.money -= amount.value
|
||||
main.SET_MEMBER(member.value)
|
||||
uni.removeStorageSync('cart');
|
||||
uni.switchTab({
|
||||
url: '/pages/order/order',
|
||||
fail(res) {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
const weixinPay = async(order) => {
|
||||
let from = 'routine'
|
||||
// #ifdef H5
|
||||
from = 'h5'
|
||||
if(isWeixin()){
|
||||
from = 'wechat'
|
||||
}
|
||||
|
||||
// #endif
|
||||
//let that = this;
|
||||
let data = await payUnify({
|
||||
uni: order.orderId,
|
||||
from: from,
|
||||
paytype: 'weixin'
|
||||
});
|
||||
console.log('param2:',data)
|
||||
if (!data) {
|
||||
uni.hideLoading();
|
||||
return;
|
||||
}
|
||||
if (data.trade_type == 'MWEB') {
|
||||
// #ifdef H5
|
||||
// 微信外的H5
|
||||
console.log('data:',data)
|
||||
location.href = data.data;
|
||||
// #endif
|
||||
console.log('data1:',data)
|
||||
} else if (data.trade_type == 'JSAPI') {
|
||||
console.log('param:',data)
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: data.data.timeStamp,
|
||||
nonceStr: data.data.nonceStr,
|
||||
package: data.data.package,
|
||||
signType: 'MD5',
|
||||
paySign: data.data.paySign,
|
||||
success: function(res) {
|
||||
|
||||
uni.removeStorageSync('cart');
|
||||
uni.switchTab({
|
||||
url: '/pages/order/order'
|
||||
});
|
||||
},
|
||||
fail: function(err) {
|
||||
console.log('fail:' + JSON.stringify(err));
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
} else if (data.trade_type == 'W-JSAPI'){
|
||||
//公众号支付
|
||||
|
||||
|
||||
}else if (data.trade_type == 'APP') {
|
||||
|
||||
}
|
||||
}
|
||||
const aliPay = async(order) => {
|
||||
|
||||
// #ifdef H5
|
||||
//let that = this;
|
||||
if(isWeixin()){
|
||||
uni.showToast({
|
||||
title: '请普通浏览器打开进行支付宝支付~',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
let data = await payUnify({
|
||||
uni: order.orderId,
|
||||
from: 'h5',
|
||||
paytype: 'alipay'
|
||||
});
|
||||
|
||||
console.log('data:',data.data)
|
||||
// 支付宝支付,这里只要提交表单
|
||||
let form = data.data
|
||||
const div = document.createElement('formdiv');
|
||||
div.innerHTML = form;
|
||||
document.body.appendChild(div);
|
||||
//document.forms[0].setAttribute('target', ' self');
|
||||
document.forms[0].submit();
|
||||
//div.remove();
|
||||
|
||||
// #endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
position: relative;
|
||||
margin-right: -10rpx;
|
||||
}
|
||||
|
||||
.location {
|
||||
.store-name {
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 50rpx;
|
||||
line-height: 100%;
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.section-1 {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.contact {
|
||||
.contact-tip {
|
||||
margin-left: 10rpx;
|
||||
border: 2rpx solid $color-primary;
|
||||
padding: 6rpx 10rpx;
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
.name-and-props {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
.payment {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.disabled {
|
||||
color: $text-color-grey;
|
||||
}
|
||||
|
||||
.payment-icon {
|
||||
font-size: 44rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
font-size: 36rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.checked {
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.1);
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
.change-address-btn {
|
||||
line-height: 2;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.pay_btn {
|
||||
width: 100%;
|
||||
border-radius: 50rem !important;
|
||||
line-height: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.choice {
|
||||
background-color: $bg-color-grey;
|
||||
border-radius: 38rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $font-size-sm;
|
||||
padding: 0 38rpx;
|
||||
color: $text-color-assist;
|
||||
|
||||
.dinein,
|
||||
.takeout {
|
||||
width: 50%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.active {
|
||||
padding: 14rpx 38rpx;
|
||||
color: #ffffff;
|
||||
background-color: $color-primary;
|
||||
border-radius: 38rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.takeout {
|
||||
margin-left: 20rpx;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
padding: 14rpx 0;
|
||||
}
|
||||
|
||||
.dinein.active {
|
||||
//margin-left: -38rpx;
|
||||
}
|
||||
|
||||
.takeout.active {
|
||||
//margin-right: -38rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container w-100 h-100 overflow-hidden">
|
||||
<view class="textarea">
|
||||
<textarea placeholder-class="text-color-assist font-size-base" v-model="remark"
|
||||
class="bg-white w-100 border-box font-size-base remark"
|
||||
:class="{'text-color-danger': remarkLength > 50, 'text-color-assist' : remarkLength <=50}"
|
||||
placeholder="请填写备注信息" focus/>
|
||||
<view class="tips" :class="{'text-color-danger': remarkLength > 50, 'text-color-assist' : remarkLength <=50}">
|
||||
{{ remarkLength }}/50
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex font-size-base text-color-assist" style="margin: 40rpx 0;">
|
||||
快捷输入
|
||||
</view>
|
||||
<view class="quick-inputs d-flex flex-wrap justify-content-start">
|
||||
<view class="quick-input" v-for="(item, index) in quickInputs" :key="index" @tap="handleQuickInput(item)">
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex just-content-center align-items-center" style="margin-top: 60rpx;">
|
||||
<button type="primary" class="submit-btn font-size-base" @tap="submit">完成</button>
|
||||
</view>
|
||||
<!--轻提示-->
|
||||
<uv-toast ref="uToast"></uv-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { onLoad} from '@dcloudio/uni-app'
|
||||
|
||||
const remark = ref('')
|
||||
const quickInputs = ref( ['请放门把手上', '请放门口', '请放前台桌上', '如地址封闭管理,请电话与我联系'])
|
||||
const uToast = ref()
|
||||
|
||||
onLoad((opt) => {
|
||||
remark.value = opt.remark
|
||||
})
|
||||
|
||||
const remarkLength = computed(() => {
|
||||
return remark.value.length
|
||||
})
|
||||
const isDanger = computed(() => {
|
||||
return remark.value.length > 50
|
||||
})
|
||||
|
||||
const handleQuickInput = (item) => {
|
||||
remark.value = remark.value.concat(" ", item)
|
||||
}
|
||||
const submit = () => {
|
||||
if (remark.value.length > 50) {
|
||||
uToast.value.show({
|
||||
message: '不能超过50个字符',
|
||||
type: 'error'
|
||||
});
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: "/pages/components/pages/pay/pay?remark=" + remark.value
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
padding: 30rpx 40rpx;
|
||||
|
||||
.textarea {
|
||||
position: relative;
|
||||
|
||||
.remark {
|
||||
border-radius: 8rpx;
|
||||
padding: 30rpx 40rpx;
|
||||
height: 320rpx;
|
||||
color: $font-size-base;
|
||||
}
|
||||
|
||||
.tips {
|
||||
position: absolute;
|
||||
bottom: 30rpx;
|
||||
right: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.quick-inputs {
|
||||
padding-right: 20rpx;
|
||||
|
||||
.quick-input {
|
||||
background-color: #FFFFFF;
|
||||
border: 2rpx solid $color-primary;
|
||||
color: $color-primary;
|
||||
font-size: $font-size-base;
|
||||
padding: 16rpx 26rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 90%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view>
|
||||
<view>
|
||||
<uv-search margin="30rpx" v-model="keywork" @custom="search(keywork)"></uv-search>
|
||||
</view>
|
||||
<view v-for="(item,index) in list" :key="index">
|
||||
<uni-card @click="choice(item)" :border="item.id == store.id" :title="item.name" :thumbnail="item.image" :thumb-width="80" :sub-title="item.status_text">
|
||||
<view class="body">
|
||||
<view class="body-left">
|
||||
<view>距离您 {{kmUnit(item.dis)}}</view>
|
||||
<view v-if="item.distance > 0">配送距离:{{item.distance + 'km '}} & 配送费:{{item.delivery_price}}</view>
|
||||
<view v-else>外卖不配送</view>
|
||||
<view>{{item.addressMap + ' ' + item.address}}</view>
|
||||
<view>营业时间 {{formatDateTime(item.startTime,'hh:mm')}} - {{formatDateTime(item.endTime,'hh:mm')}}</view>
|
||||
</view>
|
||||
<view class="body-right">
|
||||
<uv-button @click="openLocation(item)">导航</uv-button>
|
||||
<uv-button @click="call(item.mobile)">致电</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-card>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow ,onPullDownRefresh,onHide} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,kmUnit,prePage } from '@/utils/util'
|
||||
import {
|
||||
shopNearby,
|
||||
menuGoods
|
||||
} from '@/api/goods'
|
||||
import {
|
||||
shopGetList
|
||||
} from '@/api/market'
|
||||
const main = useMainStore()
|
||||
const { store,location } = storeToRefs(main)
|
||||
const title = ref('店铺')
|
||||
const list = ref([])
|
||||
const keywork = ref('')
|
||||
const page = ref(1)
|
||||
const pagesize = ref(10)
|
||||
|
||||
onLoad(() => {
|
||||
getShop();
|
||||
})
|
||||
|
||||
const getShop = async(keywork = '') => {
|
||||
let data = await shopGetList({
|
||||
lat: location.value.latitude ? location.value.latitude : 0,
|
||||
lng: location.value.longitude ? location.value.longitude : 0,
|
||||
kw: keywork,
|
||||
shop_id: 0
|
||||
});
|
||||
if (data) {
|
||||
//console.log(data);
|
||||
if (page.value == 1) {
|
||||
list.value = data;
|
||||
} else {
|
||||
for(let i in data) {
|
||||
list.value.push(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//打开定位
|
||||
const openLocation = (shop) => {
|
||||
//console.log(shop);
|
||||
uni.openLocation({
|
||||
latitude: parseFloat(shop.lat),
|
||||
longitude: parseFloat(shop.lng),
|
||||
name:shop.name,
|
||||
address: shop.addressMap + shop.address,
|
||||
fail: (res) => {
|
||||
console.log(res);
|
||||
}
|
||||
})
|
||||
}
|
||||
// 打电话
|
||||
const call = (mobile) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber:mobile
|
||||
})
|
||||
}
|
||||
// 搜索按钮
|
||||
const search = (keywork) => {
|
||||
page.value = 1;
|
||||
getShop(keywork);
|
||||
}
|
||||
// 选中店铺
|
||||
const choice = (shop) => {
|
||||
main.SET_STORE(shop);
|
||||
uni.$emit('refreshMenu')
|
||||
uni.switchTab({
|
||||
url:'/pages/menu/menu',
|
||||
success(res) {
|
||||
},
|
||||
fail(res) {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.body {
|
||||
|
||||
.body-left {
|
||||
display: inline-block;
|
||||
width: 77%;
|
||||
padding-left: 6rpx;
|
||||
}
|
||||
.body-right {
|
||||
display: inline-block;
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.u-border {
|
||||
border: 1rpx solid #1296db;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,314 @@
|
||||
<template>
|
||||
<layout>
|
||||
<uv-sticky
|
||||
bg-color="#F5F5F5"
|
||||
offset-top="0"
|
||||
customNavHeight="0"
|
||||
>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:safeAreaInsetTop="true"
|
||||
height="0"
|
||||
bgColor="transparent"
|
||||
leftIcon=""
|
||||
/>
|
||||
<!-- #ifndef MP -->
|
||||
<blank size="10"></blank>
|
||||
<!-- #endif -->
|
||||
|
||||
<blank size="5"></blank>
|
||||
</uv-sticky>
|
||||
|
||||
<blank size="10"></blank>
|
||||
<view class="container">
|
||||
<view class="banner">
|
||||
<uv-swiper class="bg" height="300" imgMode="aspectFill" keyName="image" :list="listAds" indicatorMode="dot" indicatorStyle="bottom"></uv-swiper>
|
||||
<view class="intro">
|
||||
<view class="greet">您好,{{ isLogin ? member.nickname : '游客' }}</view>
|
||||
<view class="note">java-springboot-意向点餐外卖系统</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view class="entrance">
|
||||
<view class="item " @tap="takein">
|
||||
<view>
|
||||
<view class="font-md">自取</view>
|
||||
<view class="font-small text-light-black flex-1">下单免排队</view>
|
||||
</view>
|
||||
<view class="index-img">
|
||||
<image src="/static/images/index002.png" mode="aspectFit" class="img-01"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item" @tap="takeout">
|
||||
<view>
|
||||
<view class="font-md">外卖</view>
|
||||
<view class="font-small text-light-black">美食送到家</view>
|
||||
</view>
|
||||
<view class="index-img"><image src="/static/images/index003.png" mode="aspectFit" class="img-02"></image></view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="integral_section">
|
||||
<view class="top">
|
||||
<text class="title">我的卡券</text>
|
||||
<text class="value">{{member.couponCount}}</text>
|
||||
</view>
|
||||
<view class="bottom">
|
||||
可抵扣商品价格哦
|
||||
</view>
|
||||
</view>
|
||||
<view class="qrcode_section" @tap="coupons">
|
||||
去领个券
|
||||
<view class="iconfont iconarrow-right"></view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import {
|
||||
menuAds
|
||||
} from '@/api/market'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMainStore } from '@/store/store'
|
||||
//
|
||||
const main = useMainStore()
|
||||
const { member,store, isLogin} = storeToRefs(main)
|
||||
//const store = ref(main.store)
|
||||
const listAds = ref([])
|
||||
// const isLogin = ref(main.isLogin)
|
||||
|
||||
const handGetListAds = async () => {
|
||||
let shop_id = store.id ? store.id : 0;
|
||||
let data = await menuAds({
|
||||
shop_id: shop_id
|
||||
});
|
||||
if (data) {
|
||||
listAds.value = data.list;
|
||||
console.log('listAds:',listAds.value)
|
||||
uni.setStorage({
|
||||
key: 'isActive',
|
||||
data: data.isActive
|
||||
});
|
||||
if(data.list.length > 0){
|
||||
uni.setStorage({
|
||||
key: 'shopAd',
|
||||
data: data.list[0].image
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const takein = () => {
|
||||
main.SET_ORDER_TYPE('takein')
|
||||
uni.switchTab({
|
||||
url: '/pages/menu/menu'
|
||||
})
|
||||
}
|
||||
|
||||
const takeout = () => {
|
||||
main.SET_ORDER_TYPE('takeout')
|
||||
uni.switchTab({
|
||||
url: '/pages/menu/menu'
|
||||
})
|
||||
}
|
||||
|
||||
const coupons = () => {
|
||||
console.log("--> % orderType:\n", main.orderType)
|
||||
console.log("--> % isLogin:\n", main.isLogin)
|
||||
if(!main.isLogin) {
|
||||
uni.navigateTo({url: '/pages/components/pages/login/login'})
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/coupons/coupons'
|
||||
})
|
||||
}
|
||||
|
||||
const goScore = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/scoreproduct/list'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
// main.init()
|
||||
handGetListAds()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.index-img {
|
||||
width: 120px;
|
||||
height: 120rpx;
|
||||
position: relative;
|
||||
left:-20rpx
|
||||
}
|
||||
.img-01 {
|
||||
width: 100px;
|
||||
height: 100rpx;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
.img-02 {
|
||||
width: 110px;
|
||||
height: 110rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* #ifdef H5 */
|
||||
page {
|
||||
height: auto;
|
||||
min-height: 100%;
|
||||
}
|
||||
/* #endif */
|
||||
page {
|
||||
background-color: #ffffff!important;
|
||||
}
|
||||
.banner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
//height: 300rpx;
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
height: 300rpx;
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: absolute;
|
||||
top: calc(50rpx + var(--status-bar-height));
|
||||
left: 40rpx;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.greet {
|
||||
font-size: $font-size-lg;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.note {
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 50rpx;
|
||||
}
|
||||
|
||||
.entrance {
|
||||
position: relative;
|
||||
//top:0;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: #ffffff;
|
||||
box-shadow: $box-shadow;
|
||||
padding: 30rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50rpx;
|
||||
.item {
|
||||
//flex: 1;
|
||||
display: flex;
|
||||
//flex-direction: column;
|
||||
justify-content: center;
|
||||
//align-items: center;
|
||||
position: relative;
|
||||
|
||||
&:nth-child(1):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 1rpx;
|
||||
background-color: #ddd;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
transform: scaleX(0.5) scaleY(0.8);
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 90rpx;
|
||||
// color: #5A5B5C;
|
||||
color: #dd524d;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
color: $text-color-base;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
position: relative;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: #ffffff;
|
||||
box-shadow: $box-shadow;
|
||||
//padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.integral_section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
color: $text-color-base;
|
||||
font-size: $font-size-base;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.value {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-color-assist;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.qrcode_section {
|
||||
color: $color-primary;
|
||||
display: flex;
|
||||
//flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: $font-size-sm;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,373 @@
|
||||
<template>
|
||||
<layout>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container">
|
||||
<view style="padding: 0 30rpx;">
|
||||
<!-- user box begin -->
|
||||
<view class="d-flex flex-column bg-white user-box">
|
||||
|
||||
<view class="d-flex align-items-center">
|
||||
<view class="avatar rounded-circle">
|
||||
<image :src="isLogin ? member.avatar ? member.avatar : '/static/images/mine/default.png' : '/static/images/mine/default.png'"></image>
|
||||
</view>
|
||||
<view class="d-flex flex-column flex-fill overflow-hidden" style="margin-top: 20rpx;">
|
||||
<view v-if="isLogin"
|
||||
class="font-size-lg font-weight-bold d-flex justify-content-start align-items-center"
|
||||
@tap="serv({type:'pages',pages:'/pages/components/pages/mine/userinfo'})">
|
||||
<view class="text-truncate">{{ member.nickname }}</view>
|
||||
<view class="iconfont iconarrow-right line-height-100"></view>
|
||||
</view>
|
||||
<view v-else class="font-size-lg font-weight-bold" @tap="login">游客</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- user grid begin -->
|
||||
<view class="w-100 d-flex align-items-center just-content-center">
|
||||
<view class="user-grid" @tap="serv({type:'pages',pages:'/pages/components/pages/coupons/coupons'})">
|
||||
<view class="value font-size-extra-lg font-weight-bold text-color-base">
|
||||
{{ isLogin ? member.couponCount : 0}}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">优惠券</view>
|
||||
</view>
|
||||
<view class="user-grid" @tap="serv({type:'pages', pages: '/pages/components/pages/balance/bill?cate=1'})">
|
||||
<view class="value font-size-extra-lg font-weight-bold text-color-base">
|
||||
{{ isLogin ? member.integral : 0 }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">积分</view>
|
||||
</view>
|
||||
<view class="user-grid">
|
||||
<view class="value font-size-extra-lg font-weight-bold text-color-base">
|
||||
{{ isLogin ? member.nowMoney : 0 }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">余额</view>
|
||||
</view>
|
||||
<view class="user-grid" @tap="serv({type:'pages', pages: '/pages/components/pages/balance/bill?cate=0'})">
|
||||
<view class="value font-size-extra-lg font-weight-bold text-color-base">
|
||||
{{ isLogin ? member.sumMoney : 0 }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">历史消费</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- user grid end -->
|
||||
</view>
|
||||
<!-- user box end -->
|
||||
|
||||
</view>
|
||||
<!-- service box begin -->
|
||||
<view class="service-box">
|
||||
<view class="font-size-lg text-color-base font-weight-bold" style="margin-bottom: 20rpx;">我的服务</view>
|
||||
<view class="u-m-t-20">
|
||||
<uv-cell-group>
|
||||
<block v-for="(item, index) in services" :key='index'>
|
||||
<uv-cell :title="item.name" v-if="item.type == 'contact'" :isLink="true">
|
||||
<template #icon>
|
||||
<image :src="item.image" style="width: 40rpx;height: 40rpx;" class="mr-1"></image>
|
||||
</template>
|
||||
</uv-cell>
|
||||
<uv-cell :isLink="true" :title="item.name" v-else-if="item.type == 'call'" v-on:click="makePhoneCall(item.phone)">
|
||||
<template #icon>
|
||||
<image :src="item.image" style="width: 40rpx;height: 40rpx;" class="mr-1"></image>
|
||||
</template>
|
||||
</uv-cell>
|
||||
<uv-cell :isLink="true" :title="item.name" v-else @tap="serv(item)">
|
||||
<template #icon>
|
||||
<image :src="item.image" style="width: 40rpx;height: 40rpx;" class="mr-1"></image>
|
||||
</template>
|
||||
</uv-cell>
|
||||
</block>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,kmUnit } from '@/utils/util'
|
||||
import {
|
||||
userGetUserInfo,
|
||||
mineService
|
||||
} from '@/api/user'
|
||||
const main = useMainStore()
|
||||
const { member,isLogin } = storeToRefs(main)
|
||||
|
||||
const title = ref('个人中心')
|
||||
const services = ref([])
|
||||
|
||||
const growthValue = computed(() => {
|
||||
if (!isLogin.value) return 0
|
||||
const {
|
||||
currentValue,
|
||||
needValue
|
||||
} = member.value
|
||||
return currentValue / (currentValue + needValue) * 100
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
getServices();
|
||||
})
|
||||
onShow(() => {
|
||||
getUserInfo();
|
||||
})
|
||||
|
||||
|
||||
const getUserInfo = async() => {
|
||||
if (isLogin.value) {
|
||||
let data = await userGetUserInfo();
|
||||
if (data) {
|
||||
main.SET_MEMBER(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
const getServices = async() => {
|
||||
let data = await mineService();
|
||||
if (data) {
|
||||
services.value = data;
|
||||
}
|
||||
}
|
||||
const makePhoneCall = (phoneNumber) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phoneNumber,
|
||||
})
|
||||
}
|
||||
const login = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/login/login'
|
||||
})
|
||||
}
|
||||
const packages = () => {
|
||||
if (!isLogin.value) {
|
||||
login()
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/packages/index'
|
||||
})
|
||||
}
|
||||
const serv = (item) => {
|
||||
switch (item.type) {
|
||||
case 'pages':
|
||||
if (!isLogin.value) {
|
||||
login()
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: item.pages
|
||||
})
|
||||
break;
|
||||
case 'miniprogram':
|
||||
uni.navigateToMiniProgram({
|
||||
appId: item.app_id
|
||||
})
|
||||
break;
|
||||
case 'menu':
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/mine/service?id=' + item.id + '&name=' + item.name
|
||||
})
|
||||
break;
|
||||
case 'content':
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/mine/content?id=' + item.id + '&name=' + item.name
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
height: auto;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
height: calc(410 / 594 * 750rpx);
|
||||
}
|
||||
|
||||
.hym-btn {
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
right: 40rpx;
|
||||
color: $color-primary;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50rem;
|
||||
font-size: $font-size-sm;
|
||||
box-shadow: 0 0 20rpx rgba(66, 66, 66, 0.1);
|
||||
|
||||
&::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.user-box {
|
||||
position: relative;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 30rpx;
|
||||
margin-top: 70rpx;
|
||||
box-shadow: $box-shadow;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
position: relative;
|
||||
margin-top: -35rpx;
|
||||
margin-left: 35rpx;
|
||||
margin-right: 35rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 0 20rpx rgba($color: #000000, $alpha: 0.2);
|
||||
|
||||
image {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
bottom: -10rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 50rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: $color-warning;
|
||||
font-size: 24rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
box-shadow: 0 0 20rpx rgba($color: #000000, $alpha: 0.2);
|
||||
|
||||
image {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.level-benefit {
|
||||
margin-left: 35rpx;
|
||||
padding: 10rpx 0 10rpx 30rpx;
|
||||
border-radius: 50rem 0 0 50rem;
|
||||
}
|
||||
|
||||
.user-grid {
|
||||
width: 25%;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.value {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.level-benefit-box {
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 30rpx;
|
||||
box-shadow: 0 10rpx 8rpx rgba($color: #878889, $alpha: 0.1);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 30rpx;
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
padding: 30rpx 0 20rpx;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
|
||||
.grid {
|
||||
width: 20%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: $font-size-sm;
|
||||
color: $text-color-assist;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.banner {
|
||||
width: 100%;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.service-box {
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
padding: 32rpx 30rpx 10rpx;
|
||||
box-shadow: $box-shadow;
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
color: $text-color-assist;
|
||||
font-size: $font-size-sm;
|
||||
padding-bottom: -40rpx;
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
width: 25%;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.opacity-0 {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<view class="container">
|
||||
<view class="bg-white">
|
||||
<uv-tabs :list="tabList" :current="current" @change="change" keyName="name" :scrollable="false"></uv-tabs>
|
||||
</view>
|
||||
<view class="orders-list d-flex flex-column w-100" style="padding: 20rpx; padding-bottom: 0;">
|
||||
<view class="order-item" v-for="(item, index) in orders" :key="index" style="margin-bottom: 30rpx;" >
|
||||
<list-cell :hover="false">
|
||||
<view class="w-100 d-flex align-items-center">
|
||||
<view class="flex-fill d-flex flex-column">
|
||||
<view class="font-size-lg text-color-base" style="margin-bottom: 20rpx;">
|
||||
{{ item.shop.name }}
|
||||
</view>
|
||||
<view class="font-size-sm text-color-assist">取餐号:{{ item.numberId }}</view>
|
||||
<view class="font-size-sm text-color-assist">订单编号:{{ item.orderId }}</view>
|
||||
</view>
|
||||
<view class="font-size-lg text-color-primary">
|
||||
{{ item._status._title }}
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
<list-cell :hover="false" last>
|
||||
<view class="w-100 d-flex flex-column">
|
||||
<view class="w-100 text-truncate font-size-lg text-color-base" style="margin-bottom: 20rpx;">
|
||||
<!-- {{ orderGoodsName(item.cartInfo) }} -->
|
||||
<view class="flex mb-2" v-for="(good,index) in item.cartInfo" :key="index">
|
||||
<image :src="good.image" mode="aspectFill" class="image"></image>
|
||||
<view class="flex flex-column">
|
||||
<view class="font-size-medium mt-1 text-color-base">{{ good.title }}</view>
|
||||
<view class="font-size-sm mt-1">{{ good.spec }}</view>
|
||||
<view class="font-size-sm mt-2">×{{ good.number }} ¥{{ good.price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex justify-content-between align-items-center" style="margin-bottom: 30rpx;">
|
||||
<view class="font-size-sm text-color-assist">
|
||||
{{formatDateTime(item.createTime) }}
|
||||
</view>
|
||||
<view class="d-flex font-size-sm text-color-base align-items-center">
|
||||
<view style="margin-right: 10rpx;">共{{ goodsNum(item.cartInfo) }}件商品,实付</view>
|
||||
<view class="font-size-lg">¥{{ item.payPrice }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-flex align-items-center justify-content-end">
|
||||
<view>
|
||||
<button v-if="item.paid > 0 && item.status < 2 && item.refundStatus == 0" class="left-margin" plain size="mini" @tap.stop="receive(item)">确认收到餐</button>
|
||||
<button class="left-margin" plain size="mini" @tap="detail(item.orderId)">订单详情</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</list-cell>
|
||||
</view>
|
||||
</view>
|
||||
<uv-empty v-if="orders.length == 0" mode="order"></uv-empty>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onLoad,onPullDownRefresh,onReachBottom} from '@dcloudio/uni-app'
|
||||
import { formatDateTime,kmUnit } from '@/utils/util'
|
||||
import {
|
||||
orderGetOrders,
|
||||
orderReceive
|
||||
} from '@/api/order'
|
||||
const main = useMainStore()
|
||||
const { isLogin } = storeToRefs(main)
|
||||
const title = ref('我的订单')
|
||||
|
||||
const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const orders = ref([])
|
||||
const tabList = ref([{
|
||||
type: -1,
|
||||
name: '全部',
|
||||
}, {
|
||||
type: 0,
|
||||
name: '待支付',
|
||||
}, {
|
||||
type: 1,
|
||||
name: '进行中'
|
||||
}, {
|
||||
type: 4,
|
||||
name: '已完成'
|
||||
}, {
|
||||
type: -3,
|
||||
name: '退款单'
|
||||
}]
|
||||
)
|
||||
const current = ref(0)
|
||||
const type = ref(-1)
|
||||
|
||||
const orderGoodsName = computed(() => { //计算单个饮品添加到购物车的数量
|
||||
return (goods) => {
|
||||
let arr = []
|
||||
goods.forEach(good => arr.push(good.title + '*' + good.number))
|
||||
return arr.join(',')
|
||||
}
|
||||
})
|
||||
const goodsNum = computed(() => { //计算单个饮品添加到购物车的数量
|
||||
return (goods) => {
|
||||
let num = 0;
|
||||
goods.forEach(good => num += parseInt(good.number))
|
||||
return num;
|
||||
}
|
||||
})
|
||||
onLoad(() => {
|
||||
if(!isLogin.value) {
|
||||
uni.navigateTo({url: '/pages/components/pages/login/login'})
|
||||
}
|
||||
getOrders(false)
|
||||
})
|
||||
onPullDownRefresh(() => {
|
||||
getOrders(false)
|
||||
})
|
||||
onReachBottom(() => {
|
||||
getOrders(false)
|
||||
})
|
||||
|
||||
// tab栏切换
|
||||
const change = (e) => {
|
||||
//console.log('e;',e.type)
|
||||
//console.log('e.index;',e.index)
|
||||
type.value = e.type
|
||||
getOrders(true)
|
||||
}
|
||||
|
||||
const getOrders = async(isRefresh = false) => {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
if(isRefresh) {
|
||||
orders.value = []
|
||||
page.value = 1
|
||||
}
|
||||
let ordersData = await orderGetOrders({page:page.value, limit:pageSize.value,type:type.value});
|
||||
|
||||
if(ordersData) {
|
||||
orders.value = orders.value.concat(ordersData)
|
||||
page.value += 1
|
||||
}
|
||||
uni.stopPullDownRefresh();
|
||||
uni.hideLoading()
|
||||
}
|
||||
const detail = (id) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/components/pages/orders/detail?id=' + id
|
||||
})
|
||||
}
|
||||
// 确认收到货
|
||||
const receive = async(order) => {
|
||||
let data = await orderReceive({uni:order.orderId});
|
||||
if (data) {
|
||||
await getOrders(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.left-margin {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
.image {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 30rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user