first commit
1
.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,13 @@
|
||||
import { createSSRApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
|
||||
import uviewPlus from 'uview-plus'
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App);
|
||||
App.mpType = 'app';
|
||||
app.use(uviewPlus)
|
||||
return {
|
||||
app,
|
||||
};
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<view class="home">
|
||||
<view class=""
|
||||
style=" margin-top: 200rpx; display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||
<image :src="Service.GetIconImg('/static/index/logo/logo.png')" style="width: 150rpx; height: 150rpx; "
|
||||
mode=""></image>
|
||||
<view class="" style="font-size: 36rpx; font-weight: 800; margin-top: 20rpx;">
|
||||
菜农·商家端
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="margin: 30rpx 30rpx; margin-top: 150rpx;">
|
||||
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
欢迎登陆
|
||||
</view>
|
||||
|
||||
<view class="" style="font-size: 28rpx; margin-top: 20rpx; ">
|
||||
手机号登录,安全又便捷
|
||||
</view>
|
||||
|
||||
<view v-if="type" class="" >
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.phone" type="number" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入手机号"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.password" type="password" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入密码"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<view class="" style="margin-top: 30rpx;" v-if="!isLogin">
|
||||
<up-input v-model="qudPow" type="password" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="确认密码"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<!-- <view class=""
|
||||
style=" display: flex; align-items: center; justify-content: space-between; margin-top: 30rpx; border: 1rpx solid #dadbde; box-sizing: border-box; padding: 20rpx 30rpx; border-radius: 200rpx; ">
|
||||
<up-code-input v-model="login.code" mode="line" size='24'></up-code-input>
|
||||
<view class="wrap">
|
||||
<up-toast ref="uToastRef"></up-toast>
|
||||
<up-code :seconds="seconds" @end="end" @start="start" ref="uCodeRef"
|
||||
@change="codeChange"></up-code>
|
||||
<view @click="getCode">{{tips}}</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
|
||||
</view>
|
||||
<!-- <view v-else class="">
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.phone" type="number" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入账号"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.phone" type="number" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入密码"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view class="" style="margin-top: 40rpx; width: 100%; height: 80rpx; line-height: 80rpx; border-radius: 40rpx; background-color: #FFDE1D; color: #fff; font-size: 30rpx; text-align: center;" @click="loginshop()">
|
||||
登录
|
||||
</view>
|
||||
|
||||
<view class="" style="width: 90%; margin: 0 auto; margin-top: 20rpx; display: flex; justify-content: space-between; color: #999; font-size: 28rpx;">
|
||||
<view class="">
|
||||
忘记密码
|
||||
</view>
|
||||
<view class="" @click="isLogin = !isLogin">
|
||||
{{isLogin?'去注册':'已有账号去登录'}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- <view class="" @click="type=!type" style="text-align: center; color: #637aff; margin: 50rpx 0; ">
|
||||
{{ !type?'使用验证码登录':'使用密码登录' }}
|
||||
</view> -->
|
||||
|
||||
<view class="" style="display: flex; justify-content: center; align-items: center;color: black; margin-top: 50rpx; " @click="isuser= !isuser">
|
||||
<view class="" style="margin-right: 10rpx;">
|
||||
<up-icon :name="!isuser?'checkmark-circle':'checkmark-circle-fill'" :color="!isuser?'#999':'var(--nav-mian)'" size="20"></up-icon>
|
||||
</view>
|
||||
我同意
|
||||
<text style="color: #FF6B23;">《用户协议》</text>
|
||||
和
|
||||
<text style="color: #FF6B23;">《隐私政策》</text>
|
||||
</view>
|
||||
<view class="" style="text-align: center; margin-top: 20rpx;">
|
||||
<!-- 新用户?系统将自动为您注册 -->
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service ,CNRiderLoginService } from "@/Service/CN/CNRiderLoginService"
|
||||
import { ref } from "vue";
|
||||
|
||||
let qudPow = ref<string>('')
|
||||
|
||||
let login = ref({
|
||||
phone: '',
|
||||
code: '',
|
||||
password:''
|
||||
})
|
||||
|
||||
const tips = ref('');
|
||||
const seconds = ref(60);
|
||||
const uCodeRef = ref(null);
|
||||
|
||||
let type = ref(true)
|
||||
|
||||
let isLogin = ref<boolean>(true)//登录注册状态
|
||||
|
||||
let isuser = ref<boolean>(false)//用户同意协议
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
//登录
|
||||
const loginshop = () =>{
|
||||
if(login.value.phone==''){
|
||||
return Service.Msg('请输入手机号/账号!')
|
||||
}
|
||||
|
||||
if(login.value.password==''){
|
||||
return Service.Msg('请输入密码!')
|
||||
}
|
||||
|
||||
if(!isLogin.value && qudPow.value==''){
|
||||
return Service.Msg('请确认密码!')
|
||||
}
|
||||
|
||||
|
||||
if(!isLogin.value && login.value.password!=qudPow.value){
|
||||
return Service.Msg('两次密码不同!')
|
||||
}
|
||||
|
||||
|
||||
console.log(isuser.value)
|
||||
|
||||
if(!isuser.value){
|
||||
return Service.Msg('请勾选同意用户协议!')
|
||||
}
|
||||
|
||||
|
||||
|
||||
CNRiderLoginService.RiderLogin(login.value).then(res=>{
|
||||
if(res.code==0){
|
||||
Service.Msg('登录成功!')
|
||||
Service.SetUserToken(res.data.accToken)
|
||||
if(res.data.type==-1){
|
||||
Service.GoPage('/pages/shop/Apply')
|
||||
}else{
|
||||
Service.GoPageTab('/pages/index/index')
|
||||
}
|
||||
}else{
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const codeChange = (text) => {
|
||||
tips.value = text;
|
||||
};
|
||||
|
||||
|
||||
const getCode = () => {
|
||||
if (uCodeRef.value.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被start()方法中的提示覆盖
|
||||
Service.Msg('验证码已发送')
|
||||
// 通知验证码组件内部开始倒计时
|
||||
uCodeRef.value.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
Service.Msg('倒计时结束后再发送')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const end = () => {
|
||||
console.log('倒计时结束');
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
console.log('倒计时开始');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.home {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: linear-gradient(to bottom, #FFDE1D, #fff 40%);
|
||||
overflow: hidden;
|
||||
}
|
||||
.chen{
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view style="margin: 20rpx 100rpx;">
|
||||
<up-form labelPosition="left" labelWidth='90' :model="password" ref="form1">
|
||||
<up-form-item label="姓名" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input clearable='true' placeholder="请输入联系人姓名"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="手机号" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input clearable='true' placeholder="请输入手机号"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
<view class="" style="margin-top: 20rpx;">
|
||||
<button @click="save()" :disabled='!password.password || !password.code ' class="logout-btn">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { ref } from "vue";
|
||||
import { Service } from "../../Service/Service";
|
||||
|
||||
|
||||
let password = ref({
|
||||
password: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
background-color: var(--nav-banbacor);
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
border-radius: 10rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 30rpx;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logout-btn:active {
|
||||
background-color: #f7f7f7;
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 813 B |
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<view v-if="isLoading" class="skeleton-container" style="padding: 10rpx 30rpx">
|
||||
<!-- 骨架屏记录项 -->
|
||||
<view class="skeleton-record-item" v-for="i in 3" :key="i">
|
||||
<!-- 标题骨架 -->
|
||||
<view class="skeleton-title"></view>
|
||||
|
||||
<!-- 金额区域骨架 -->
|
||||
<view class="skeleton-amount-section">
|
||||
<view class="skeleton-amount-line"></view>
|
||||
<view class="skeleton-amount-value"></view>
|
||||
</view>
|
||||
|
||||
<!-- 信息行骨架 -->
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多骨架 -->
|
||||
<view class="skeleton-loadmore"></view>
|
||||
</view>
|
||||
<view v-else style="padding: 10rpx 30rpx;">
|
||||
<view class="" v-for="(item,index) in withdrowList" :key="index"
|
||||
style="margin-top: 20rpx; gap: 20rpx; background-color: #fff; border-radius: 20rpx; padding: 30rpx; ">
|
||||
<view class="" style="font-weight: bold; border-bottom: 1rpx solid #f6f6f6; padding-bottom: 15rpx;">
|
||||
余额提现-{{ item.payway}}
|
||||
</view>
|
||||
<view class=""
|
||||
style="width: 100%; height: 200rpx; display: flex;flex-direction: column; justify-content: center; align-items: center; ">
|
||||
<view class="" style="">
|
||||
提现金额 {{ item.amount}} 元
|
||||
</view>
|
||||
<view class="" style="font-size: 32rpx; font-weight: bold; margin-top: 10rpx; ">
|
||||
实际到账 {{item.withAmount}} 元
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; ">
|
||||
<view class="" style="width: 120rpx;">
|
||||
收款人
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; margin-top: 10rpx; ">
|
||||
<view class="" style="width: 120rpx;">
|
||||
提现账号
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ item.account }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; margin-top: 10rpx;">
|
||||
<view class="" style="width: 120rpx;">
|
||||
提现时间
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ Service.formatDate(item.addTime,1) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad, onReachBottom } from "@dcloudio/uni-app";
|
||||
import { Service } from '@/Service/Service';
|
||||
import { ref } from "vue";
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let isLoading = ref(true)
|
||||
|
||||
let withdrowList = ref<Array<any>>([])
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
onReachBottom(() => {
|
||||
getList()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
withdrowList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderWithList(page.value).then(res => {
|
||||
isLoading.value = false
|
||||
if (res.data) {
|
||||
withdrowList.value = [...withdrowList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-record-item {
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
width: 200rpx;
|
||||
height: 32rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-amount-section {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-amount-line {
|
||||
width: 180rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-amount-value {
|
||||
width: 250rpx;
|
||||
height: 40rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-info-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-info-value {
|
||||
width: 300rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-loadmore {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-top: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: -100% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,625 @@
|
||||
<template>
|
||||
<view v-if="isLoading" class="rider-home-skeleton">
|
||||
<!-- 用户信息区域骨架 -->
|
||||
<view class="skeleton-user-info">
|
||||
<view class="skeleton-user-header">
|
||||
<view class="skeleton-avatar"></view>
|
||||
<view class="skeleton-user-details">
|
||||
<view class="skeleton-user-name"></view>
|
||||
<view class="skeleton-user-id"></view>
|
||||
</view>
|
||||
<view class="skeleton-setting-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 统计数据区域骨架 -->
|
||||
<view class="skeleton-stats-section">
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value income"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value completed"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value ongoing"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮骨架 -->
|
||||
<view class="skeleton-action-section">
|
||||
<view class="skeleton-accept-orders-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 附近高价单骨架 -->
|
||||
<view class="skeleton-high-price-orders">
|
||||
<view class="skeleton-section-title"></view>
|
||||
|
||||
<!-- 循环生成多个订单项骨架 -->
|
||||
<view class="skeleton-order-item" v-for="index in 3" :key="index">
|
||||
<view class="skeleton-order-header">
|
||||
<view class="skeleton-high-price-tag"></view>
|
||||
<view class="skeleton-order-price"></view>
|
||||
</view>
|
||||
<view class="skeleton-order-content">
|
||||
<view class="skeleton-restaurant-name"></view>
|
||||
<view class="skeleton-pickup-time">
|
||||
<view class="skeleton-clock-icon"></view>
|
||||
<view class="skeleton-pickup-time-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-distance"></view>
|
||||
<view class="skeleton-address"></view>
|
||||
<view class="skeleton-grab-order-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多骨架 -->
|
||||
<view class="skeleton-loadmore"></view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="rider-home">
|
||||
<!-- 用户信息区域 -->
|
||||
<view class="user-info">
|
||||
<view class="user-header">
|
||||
<image :src="Service.GetMateUrlByImg('/static/dele/home/test.jpeg')" mode="aspectFit" class="avatar">
|
||||
</image>
|
||||
<view class="user-details">
|
||||
<text class="user-name">大大怪将军</text>
|
||||
<text class="user-id">ID: LN007 · 已下线</text>
|
||||
</view>
|
||||
<up-icon @click="Service.GoPage('/pages/my/edit')" name="setting" size="32rpx" color="#333333"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥86.50</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">5单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">进行中</text>
|
||||
<text class="stat-value ongoing">6单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button type="primary" shape="circle" size="default" class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ userStatus === '已上线' ? '接单中 · 点击暂停' : '点击开始接单' }}</up-button>
|
||||
</view>
|
||||
|
||||
<!-- 附近高价单 -->
|
||||
<view class="high-price-orders">
|
||||
<view class="section-title">附近高价单</view>
|
||||
<view class="order-item" @click="Service.GoPage('/pages/order/grabOrder')" v-for="(order, index) in 3" :key="index">
|
||||
<view class="order-header">
|
||||
<view class="high-price-tag">高价单</view>
|
||||
<text class="order-price">¥20</text>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<text class="restaurant-name">王记炸酱面</text>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" size="24rpx" color="#FF9500"></up-icon>
|
||||
<text class="pickup-time-text">12:30 前取餐</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="distance">距您 0.8km</text>
|
||||
<text class="address">朝阳区三里屯路123号</text>
|
||||
<up-button shape="circle" type="primary" size="mini" class="grab-order-btn"
|
||||
:style="{backgroundColor: '#1890FF'}">立即抢单</up-button>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
|
||||
let userStatus = ref('已下线')
|
||||
let status = ref('nomore')
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
isLoading.value = false
|
||||
}, 1500)
|
||||
})
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
userStatus.value = userStatus.value === '已上线' ? '已下线' : '已上线';
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page{
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
/* 骨架屏通用样式 */
|
||||
.skeleton-user-info,
|
||||
.skeleton-stats-section,
|
||||
.skeleton-action-section,
|
||||
.skeleton-high-price-orders,
|
||||
.skeleton-order-item,
|
||||
.skeleton-order-header,
|
||||
.skeleton-order-content,
|
||||
.skeleton-pickup-time {
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 用户信息区域骨架 */
|
||||
.skeleton-user-info {
|
||||
background-color: #E6F7FF;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-avatar {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #d0d0d0;
|
||||
border: 1px solid #fff;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-user-details {
|
||||
margin-left: 20rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-user-name {
|
||||
width: 200rpx;
|
||||
height: 36rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
margin-bottom: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-user-id {
|
||||
width: 250rpx;
|
||||
height: 28rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-setting-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 统计数据区域骨架 */
|
||||
.skeleton-stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.skeleton-stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-stat-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-stat-value {
|
||||
width: 150rpx;
|
||||
height: 36rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 接单按钮骨架 */
|
||||
.skeleton-action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 45rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 附近高价单骨架 */
|
||||
.skeleton-high-price-orders {
|
||||
margin-top: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 200rpx;
|
||||
height: 32rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-order-item {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 25rpx;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skeleton-order-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-high-price-tag {
|
||||
width: 100rpx;
|
||||
height: 32rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 16rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-order-price {
|
||||
width: 80rpx;
|
||||
height: 32rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-order-content {
|
||||
margin-bottom: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.skeleton-restaurant-name {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 6rpx;
|
||||
margin-bottom: 12rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.skeleton-clock-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time-text {
|
||||
width: 200rpx;
|
||||
height: 26rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 150rpx;
|
||||
height: 26rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 12rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-address {
|
||||
width: 400rpx;
|
||||
height: 26rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-grab-order-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 30rpx;
|
||||
position: absolute;
|
||||
bottom: 25rpx;
|
||||
right: 25rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 加载更多骨架 */
|
||||
.skeleton-loadmore {
|
||||
margin: 0 250rpx;
|
||||
height: 40rpx;
|
||||
background-color: #d0d0d0;
|
||||
margin-bottom: 20rpx;
|
||||
opacity: 0.6;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 骨架屏加载动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置延迟,让骨架屏各部分加载动画错开 */
|
||||
.skeleton-user-info {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.skeleton-stats-section {
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.skeleton-action-section {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.skeleton-high-price-orders {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.skeleton-order-item:nth-child(2) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.skeleton-order-item:nth-child(3) {
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
.skeleton-order-item:nth-child(4) {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
// 骨架屏end
|
||||
|
||||
|
||||
|
||||
.rider-home {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 用户信息区域 */
|
||||
.user-info {
|
||||
background-color: #E6F7FF;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.user-details {
|
||||
margin-left: 20rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
/* 附近高价单 */
|
||||
.high-price-orders {
|
||||
margin-top: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 25rpx;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.high-price-tag {
|
||||
background-color: #FFF1F0;
|
||||
color: #FF4D4F;
|
||||
font-size: 24rpx;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.order-price {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #FF4D4F;
|
||||
}
|
||||
|
||||
.restaurant-name {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.pickup-time-text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.grab-order-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
position: absolute;
|
||||
bottom: 25rpx;
|
||||
right: 25rpx;
|
||||
}
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 278 B |
@@ -0,0 +1,727 @@
|
||||
/**
|
||||
* 图片编辑器-手势监听
|
||||
* 1. wxs 暂不支持 es6 语法
|
||||
* 2. 支持编译到微信小程序、QQ小程序、app-vue、H5上(uni-app 2.2.5及以上版本)
|
||||
*/
|
||||
/** 图片偏移量 */
|
||||
var offset = { x: 0, y: 0 };
|
||||
/** 图片缩放比例 */
|
||||
var scale = 1;
|
||||
/** 图片最小缩放比例 */
|
||||
var minScale = 1;
|
||||
/** 图片旋转角度 */
|
||||
var rotate = 0;
|
||||
/** 触摸点 */
|
||||
var touches = [];
|
||||
/** 图片布局信息 */
|
||||
var img = {};
|
||||
/** 系统信息 */
|
||||
var sys = {};
|
||||
/** 裁剪区域布局信息 */
|
||||
var area = {};
|
||||
/** 触摸行为类型 */
|
||||
var touchType = '';
|
||||
/** 操作角的位置 */
|
||||
var activeAngle = 0;
|
||||
/** 裁剪区域布局信息偏移量 */
|
||||
var areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
|
||||
/** 容错值 */
|
||||
var fault = 0.000001;
|
||||
/**
|
||||
* 获取a、b两数中的最小正数
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
function minimum(a, b) {
|
||||
if (a > 0 && b < 0) return a;
|
||||
if (a < 0 && b > 0) return b;
|
||||
if (a > 0 && b > 0) return Math.min(a, b);
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* 在容错访问内获取n近似值
|
||||
* @param n
|
||||
*/
|
||||
function num(n) {
|
||||
var m = parseFloat((n).toFixed(6));
|
||||
return m === fault || m === -fault ? 0 : m;
|
||||
}
|
||||
/**
|
||||
* 比较a值在容错值范围内是否等于b值
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
function equalsByFault(a, b) {
|
||||
return Math.abs(a - b) <= fault;
|
||||
}
|
||||
/**
|
||||
* 比较a值在容错值范围内是否小于b值
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
function lessThanByFault(a, b) {
|
||||
var c = a - b;
|
||||
return c < 0 ? c < -fault : c < fault;
|
||||
}
|
||||
/**
|
||||
* 验证并获取有效最大值
|
||||
* @param v
|
||||
* @param max
|
||||
* @param isInclude
|
||||
* @param x
|
||||
* @param y
|
||||
* @param rate
|
||||
* @returns
|
||||
*/
|
||||
function validMax(v, max, isInclude, x, y, rate) {
|
||||
if(typeof max === 'number') {
|
||||
if(isInclude && equalsByFault(max, y)) { // 宽高不等时,x轴用y轴值要做等比例转换
|
||||
var n = num(max * rate);
|
||||
if (n <= x) return n; // 转化后值在x轴最大值范围内
|
||||
return x; // 转化后值超出x轴最大值范围则用最大值
|
||||
}
|
||||
return max;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
/**
|
||||
* 计算两点间距
|
||||
* @param {Object} touches 触摸点信息
|
||||
*/
|
||||
function getDistanceByTouches(touches) {
|
||||
// 根据勾股定理求两点间距离
|
||||
var a = touches[1].pageX - touches[0].pageX;
|
||||
var b = touches[1].pageY - touches[0].pageY;
|
||||
var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
|
||||
// 求两点间的中点坐标
|
||||
// 1. a、b可能为负值
|
||||
// 2. 在求a、b时,如用touches[1]减touches[0],则求中点坐标也得用touches[1]减a/2、b/2
|
||||
// 3. 同理,在求a、b时,也可用touches[0]减touches[1],则求中点坐标也得用touches[0]减a/2、b/2
|
||||
var x = touches[1].pageX - a / 2;
|
||||
var y = touches[1].pageY - b / 2;
|
||||
return { c, x, y };
|
||||
};
|
||||
/**
|
||||
* 修正取值
|
||||
* @param {Object} a
|
||||
* @param {Object} b
|
||||
* @param {Object} c
|
||||
* @param {Object} reverse 是否反向
|
||||
*/
|
||||
function correctValue(a, b, c, reverse) {
|
||||
return num(reverse ? Math.max(Math.min(a, b), c) : Math.min(Math.max(a, b), c));
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转90°或270°时检查边界:限制 x、y 拖动范围,禁止滑出边界
|
||||
* @param {Object} e 点坐标
|
||||
* @param {Object} xReverse x是否反向
|
||||
* @param {Object} yReverse y是否反向
|
||||
*/
|
||||
function checkRotateRange(e, xReverse, yReverse) {
|
||||
var o = num((img.height - img.width) / 2); // 宽高差值一半
|
||||
return {
|
||||
x: correctValue(e.x, -img.height + o + area.width + area.left, area.left + o, xReverse),
|
||||
y: correctValue(e.y, -img.width - o + area.height + area.top, area.top - o, yReverse)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查边界:限制 x、y 拖动范围,禁止滑出边界
|
||||
* @param {Object} e 点坐标
|
||||
*/
|
||||
function checkRange(e) {
|
||||
var r = rotate / 90 % 2;
|
||||
if(r === 1) { // 因图片宽高可能不等,翻转 90° 或 270° 后图片宽高需反着计算,且左右和上下边界要根据差值做偏移
|
||||
if (area.width === area.height) {
|
||||
return checkRotateRange(e, img.height < area.height, img.width < area.width);
|
||||
}
|
||||
var isInclude = img.height < area.width && img.width < area.height; // 图片是否包含在裁剪区域内
|
||||
if (img.width < area.height || img.height < area.width) {
|
||||
if (area.width < area.height && img.width < img.height) {
|
||||
return isInclude
|
||||
? checkRotateRange(e, area.width < area.height, area.width < area.height)
|
||||
: checkRotateRange(e, false, true);
|
||||
}
|
||||
if (area.height < area.width && img.height < img.width) {
|
||||
return isInclude
|
||||
? checkRotateRange(e, area.height < area.width, area.height < area.width)
|
||||
: checkRotateRange(e, true, false);
|
||||
}
|
||||
}
|
||||
if (img.height >= area.width && img.width >= area.height) {
|
||||
return checkRotateRange(e, false, false);
|
||||
}
|
||||
if (isInclude) {
|
||||
return area.height < area.width
|
||||
? checkRotateRange(e, true, true)
|
||||
: checkRotateRange(e, area.width < area.height, area.width < area.height);
|
||||
}
|
||||
if (img.height < area.width && !img.width < area.height) {
|
||||
return checkRotateRange(e, true, false);
|
||||
}
|
||||
if (!img.height < area.width && img.width < area.height) {
|
||||
return checkRotateRange(e, false, true);
|
||||
}
|
||||
return checkRotateRange(e, img.height < area.height, img.width < area.width);
|
||||
}
|
||||
return {
|
||||
x: correctValue(e.x, -img.width + area.width + area.left, area.left, img.width < area.width),
|
||||
y: correctValue(e.y, -img.height + area.height + area.top, area.top, img.height < area.height)
|
||||
};
|
||||
};
|
||||
/**
|
||||
* 变更图片布局信息
|
||||
* @param {Object} e 布局信息
|
||||
*/
|
||||
function changeImageRect(e) {
|
||||
offset.x += e.x || 0;
|
||||
offset.y += e.y || 0;
|
||||
var image = e.instance.selectComponent('.crop-image');
|
||||
if(e.check && area.checkRange) { // 检查边界
|
||||
var point = checkRange(offset);
|
||||
if(offset.x !== point.x || offset.y !== point.y) {
|
||||
offset = point;
|
||||
}
|
||||
}
|
||||
// image.setStyle({
|
||||
// width: img.width + 'px',
|
||||
// height: img.height + 'px',
|
||||
// transform: 'translate(' + offset.x + 'px, ' + offset.y + 'px) rotate(' + rotate +'deg)'
|
||||
// });
|
||||
var ox = (img.width - img.oldWidth) / 2;
|
||||
var oy = (img.height - img.oldHeight) / 2;
|
||||
image.setStyle({
|
||||
width: img.oldWidth + 'px',
|
||||
height: img.oldHeight + 'px',
|
||||
transform: (img.gpu ? 'translateZ(0) ' : '') + 'translate(' + (offset.x + ox) + 'px, ' + (offset.y + oy) + 'px) rotate(' + rotate +'deg) scale(' + scale + ')'
|
||||
});
|
||||
|
||||
e.instance.callMethod('dataChange', {
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
x: offset.x,
|
||||
y: offset.y,
|
||||
rotate: rotate
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 变更裁剪区域布局信息
|
||||
* @param {Object} e 布局信息
|
||||
*/
|
||||
function changeAreaRect(e) {
|
||||
// 变更蒙版样式
|
||||
var masks = e.instance.selectAllComponents('.crop-mask-block');
|
||||
var maskStyles = [
|
||||
{
|
||||
left: 0,
|
||||
width: (area.left + areaOffset.left) + 'px',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
'z-index': area.zIndex + 2
|
||||
},
|
||||
{
|
||||
left: (area.right + areaOffset.right) + 'px',
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
'z-index': area.zIndex + 2
|
||||
},
|
||||
{
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
top: 0,
|
||||
height: (area.top + areaOffset.top) + 'px',
|
||||
'z-index': area.zIndex + 2
|
||||
},
|
||||
{
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
top: (area.bottom + areaOffset.bottom) + 'px',
|
||||
// height: (area.top - areaOffset.bottom + sys.offsetBottom) + 'px',
|
||||
bottom: 0,
|
||||
'z-index': area.zIndex + 2
|
||||
}
|
||||
];
|
||||
var len = masks.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
masks[i].setStyle(maskStyles[i]);
|
||||
}
|
||||
|
||||
// 变更边框样式
|
||||
if(area.showBorder) {
|
||||
var border = e.instance.selectComponent('.crop-border');
|
||||
border.setStyle({
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
top: (area.top + areaOffset.top) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
});
|
||||
}
|
||||
|
||||
// 变更参考线样式
|
||||
if(area.showGrid) {
|
||||
var grids = e.instance.selectAllComponents('.crop-grid');
|
||||
var gridStyles = [
|
||||
{
|
||||
'border-width': '1px 0 0 0',
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
right: (area.right + areaOffset.right) + 'px',
|
||||
top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) / 3 - 0.5) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': '1px 0 0 0',
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
right: (area.right + areaOffset.right) + 'px',
|
||||
top: (area.top + areaOffset.top + (area.height + areaOffset.bottom - areaOffset.top) * 2 / 3 - 0.5) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': '0 1px 0 0',
|
||||
top: (area.top + areaOffset.top) + 'px',
|
||||
bottom: (area.bottom + areaOffset.bottom) + 'px',
|
||||
left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) / 3 - 0.5) + 'px',
|
||||
height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': '0 1px 0 0',
|
||||
top: (area.top + areaOffset.top) + 'px',
|
||||
bottom: (area.bottom + areaOffset.bottom) + 'px',
|
||||
left: (area.left + areaOffset.left + (area.width + areaOffset.right - areaOffset.left) * 2 / 3 - 0.5) + 'px',
|
||||
height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
}
|
||||
];
|
||||
var len = grids.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
grids[i].setStyle(gridStyles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 变更四个伸缩角样式
|
||||
if(area.showAngle) {
|
||||
var angles = e.instance.selectAllComponents('.crop-angle');
|
||||
var angleStyles = [
|
||||
{
|
||||
'border-width': area.angleBorderWidth + 'px 0 0 ' + area.angleBorderWidth + 'px',
|
||||
left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
|
||||
top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0 0',
|
||||
left: (area.right + areaOffset.right - area.angleSize) + 'px',
|
||||
top: (area.top + areaOffset.top - area.angleBorderWidth) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': '0 0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px',
|
||||
left: (area.left + areaOffset.left - area.angleBorderWidth) + 'px',
|
||||
top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
},
|
||||
{
|
||||
'border-width': '0 ' + area.angleBorderWidth + 'px ' + area.angleBorderWidth + 'px 0',
|
||||
left: (area.right + areaOffset.right - area.angleSize) + 'px',
|
||||
top: (area.bottom + areaOffset.bottom - area.angleSize) + 'px',
|
||||
'z-index': area.zIndex + 3
|
||||
}
|
||||
];
|
||||
var len = angles.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
angles[i].setStyle(angleStyles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 变更圆角样式
|
||||
if(area.radius > 0) {
|
||||
var circleBox = e.instance.selectComponent('.crop-circle-box');
|
||||
var circle = e.instance.selectComponent('.crop-circle');
|
||||
var radius = area.radius;
|
||||
if(area.width === area.height && area.radius >= area.width / 2) { // 圆形
|
||||
radius = (area.width / 2);
|
||||
} else { // 圆角矩形
|
||||
if(area.width !== area.height) { // 限制圆角半径不能超过短边的一半
|
||||
radius = Math.min(area.width / 2, area.height / 2, radius);
|
||||
}
|
||||
}
|
||||
circleBox.setStyle({
|
||||
left: (area.left + areaOffset.left) + 'px',
|
||||
top: (area.top + areaOffset.top) + 'px',
|
||||
width: (area.width + areaOffset.right - areaOffset.left) + 'px',
|
||||
height: (area.height + areaOffset.bottom - areaOffset.top) + 'px',
|
||||
'z-index': area.zIndex + 2
|
||||
});
|
||||
circle.setStyle({
|
||||
'box-shadow': '0 0 0 ' + Math.max(area.width, area.height) + 'px rgba(51, 51, 51, 0.8)',
|
||||
'border-radius': radius + 'px'
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 缩放图片
|
||||
* @param {Object} e 布局信息
|
||||
*/
|
||||
function scaleImage(e) {
|
||||
var last = scale;
|
||||
scale = Math.min(Math.max(e.scale + scale, minScale), img.maxScale);
|
||||
if(last !== scale) {
|
||||
img.width = num(img.oldWidth * scale);
|
||||
img.height = num(img.oldHeight * scale);
|
||||
// 参考问题:有一个长4000px、宽4000px的四方形ABCD,A点的坐标固定在(-2000,-2000),
|
||||
// 该四边形上有一个点E,坐标为(-100,-300),将该四方形复制一份并缩小到90%后,
|
||||
// 新四边形的A点坐标为多少时可使新四边形的E点与原四边形的E点重合?
|
||||
// 预期效果:从图中选取某点(参照物)为中心点进行缩放,缩放时无论图像怎么变化,该点位置始终固定不变
|
||||
// 计算方法:以相同起点先计算缩放前后两点间的距离,再加上原图像偏移量即可
|
||||
e.x = num((e.x - offset.x) * (1 - scale / last));
|
||||
e.y = num((e.y - offset.y) * (1 - scale / last));
|
||||
changeImageRect(e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* 获取触摸点在哪个角
|
||||
* @param {number} x 触摸点x轴坐标
|
||||
* @param {number} y 触摸点y轴坐标
|
||||
* @return {number} 角的位置:0=无;1=左上;2=右上;3=左下;4=右下;
|
||||
*/
|
||||
function getToucheAngle(x, y) {
|
||||
// console.log('getToucheAngle', x, y, JSON.stringify(area))
|
||||
var o = area.angleBorderWidth; // 需扩大触发范围则把 o 值加大即可
|
||||
if(y >= area.top - o && y <= area.top + area.angleSize + o) {
|
||||
if(x >= area.left - o && x <= area.left + area.angleSize + o) {
|
||||
return 1; // 左上角
|
||||
} else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
|
||||
return 2; // 右上角
|
||||
}
|
||||
} else if(y >= area.bottom - area.angleSize - o && y <= area.bottom + o) {
|
||||
if(x >= area.left - o && x <= area.left + area.angleSize + o) {
|
||||
return 3; // 左下角
|
||||
} else if(x >= area.right - area.angleSize - o && x <= area.right + o) {
|
||||
return 4; // 右下角
|
||||
}
|
||||
}
|
||||
return 0; // 无触摸到角
|
||||
};
|
||||
/**
|
||||
* 重置数据
|
||||
*/
|
||||
function resetData() {
|
||||
offset = { x: 0, y: 0 };
|
||||
scale = 1;
|
||||
minScale = img.minScale;
|
||||
rotate = 0;
|
||||
};
|
||||
/**
|
||||
* 顺时针翻转图片90°
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
function rotateImage(e, o, r) {
|
||||
rotate = (rotate + r) % 360;
|
||||
if(img.minScale >= 1 && area.checkRange) {
|
||||
// 因图片宽高可能不等,翻转后图片宽高需足够填满裁剪区域
|
||||
minScale = 1;
|
||||
if(img.width < area.height) {
|
||||
minScale = area.height / img.oldWidth;
|
||||
} else if(img.height < area.width) {
|
||||
minScale = area.width / img.oldHeight;
|
||||
}
|
||||
if(minScale !== 1) {
|
||||
scaleImage({
|
||||
instance: o,
|
||||
scale: minScale - scale,
|
||||
x: sys.windowWidth / 2,
|
||||
y: (sys.windowHeight - sys.offsetBottom) / 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 由于拖动画布后会导致图片位置偏移,翻转时的旋转中心点需是图片区域+偏移区域的中心点
|
||||
// 翻转x轴中心点 = (超出裁剪区域右侧的图片宽度 - 超出裁剪区域左侧的图片宽度) / 2
|
||||
// 翻转y轴中心点 = (超出裁剪区域下方的图片宽度 - 超出裁剪区域上方的图片宽度) / 2
|
||||
var ox = ((offset.x + img.width - area.right) - (area.left - offset.x)) / 2;
|
||||
var oy = ((offset.y + img.height - area.bottom) - (area.top - offset.y)) / 2;
|
||||
changeImageRect({
|
||||
instance: o,
|
||||
check: true,
|
||||
x: -ox - oy,
|
||||
y: -oy + ox
|
||||
});
|
||||
};
|
||||
module.exports = {
|
||||
/**
|
||||
* 初始化:观察数据变更
|
||||
* @param {Object} newVal 新数据
|
||||
* @param {Object} oldVal 旧数据
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
initObserver: function(newVal, oldVal, o, i) {
|
||||
if(newVal) {
|
||||
img = newVal.img;
|
||||
sys = newVal.sys;
|
||||
area = newVal.area;
|
||||
minScale = img.minScale;
|
||||
resetData();
|
||||
img.src && changeImageRect({
|
||||
instance: o,
|
||||
x: (sys.windowWidth - img.width) / 2,
|
||||
y: (sys.windowHeight - sys.offsetBottom - img.height) / 2
|
||||
});
|
||||
changeAreaRect({
|
||||
instance: o
|
||||
});
|
||||
// console.log('initRect', JSON.stringify(newVal))
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 鼠标滚轮滚动
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
mousewheel: function(e, o) {
|
||||
if(!img.src) return;
|
||||
scaleImage({
|
||||
instance: o,
|
||||
check: true,
|
||||
// 鼠标向上滚动时,deltaY 固定 -100,鼠标向下滚动时,deltaY 固定 100
|
||||
scale: e.detail.deltaY > 0 ? -0.05 : 0.05,
|
||||
x: e.touches[0].pageX,
|
||||
y: e.touches[0].pageY
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 触摸开始
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
touchstart: function(e, o) {
|
||||
if(!img.src) return;
|
||||
touches = e.touches;
|
||||
activeAngle = area.showAngle ? getToucheAngle(touches[0].pageX, touches[0].pageY) : 0;
|
||||
if(touches.length === 1 && activeAngle !== 0) {
|
||||
touchType = 'stretch'; // 伸缩裁剪区域
|
||||
} else {
|
||||
touchType = '';
|
||||
}
|
||||
// console.log('touchstart', JSON.stringify(e), activeAngle)
|
||||
},
|
||||
/**
|
||||
* 触摸移动
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
touchmove: function(e, o) {
|
||||
if(!img.src) return;
|
||||
// console.log('touchmove', JSON.stringify(e), JSON.stringify(o))
|
||||
if(touchType === 'stretch') { // 触摸四个角进行拉伸
|
||||
var point = e.touches[0];
|
||||
var start = touches[0];
|
||||
var x = point.pageX - start.pageX;
|
||||
var y = point.pageY - start.pageY;
|
||||
if(x !== 0 || y !== 0) {
|
||||
var maxX = num(area.width * (1 - area.minScale));
|
||||
var maxY = num(area.height * (1 - area.minScale));
|
||||
// console.log(x, y, maxX, maxY, offset, area)
|
||||
touches[0] = point;
|
||||
var r = rotate / 90 % 2;
|
||||
var m = r === 1 ? num((img.height - img.width) / 2) : 0; // 宽高差值一半
|
||||
var xCompare = r === 1 ? lessThanByFault(img.height, area.width) : lessThanByFault(img.width, area.width);
|
||||
var yCompare = r === 1 ? lessThanByFault(img.width, area.height) : lessThanByFault(img.height, area.height)
|
||||
var isInclude = xCompare && yCompare;
|
||||
var isIntersect = area.checkRange && (xCompare || yCompare); // 图片是否包含在裁剪区域内
|
||||
var isReverse = !isInclude || num((offset.x - area.left) / area.width) <= num((offset.y - area.top) / area.height) || (area.width > area.height && img.width < img.height && r === 1);
|
||||
switch(activeAngle) {
|
||||
case 1: // 左上角
|
||||
x = num(x + areaOffset.left);
|
||||
y = num(y + areaOffset.top);
|
||||
if(x >= 0 && y >= 0) { // 有效滑动
|
||||
var t = num(offset.y + m - area.top);
|
||||
var l = num(offset.x - m - area.left);
|
||||
// && (offset.x + img.width < area.right || offset.y + img.height < area.bottom)
|
||||
var max = isIntersect && ((l >= 0) || (t >= 0))
|
||||
? minimum(t, l)
|
||||
: false;
|
||||
if(x > y && isReverse) { // 以x轴滑动距离为缩放基准
|
||||
maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
|
||||
if(x > maxX) x = maxX;
|
||||
y = num(x * area.height / area.width);
|
||||
} else { // 以y轴滑动距离为缩放基准
|
||||
maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
|
||||
if(y > maxY) y = maxY;
|
||||
x = num(y * area.width / area.height);
|
||||
}
|
||||
areaOffset.left = x;
|
||||
areaOffset.top = y;
|
||||
}
|
||||
break;
|
||||
case 2: // 右上角
|
||||
x = num(x + areaOffset.right);
|
||||
y = num(y + areaOffset.top);
|
||||
if(x <= 0 && y >= 0) { // 有效滑动
|
||||
var w = (r === 1 ? img.height : img.width);
|
||||
var t = num(offset.y + m - area.top);
|
||||
var l = num(area.right + m - offset.x - w);
|
||||
var max = isIntersect && ((t >= 0) || (l >= 0))
|
||||
? minimum(t, l)
|
||||
: false;
|
||||
// var max = isInclude && ((offset.x > 0 && offset.x + img.width <= area.right) || (offset.y > 0 && offset.y >= area.top))
|
||||
// ? minimum(offset.y - area.top, area.right - offset.x - img.width)
|
||||
// : false;
|
||||
// console.log(offset.x, offset.y, img.width, img.height, area.top, area.right, m, max)
|
||||
// console.log(offset.y + m - area.top, area.right + m - offset.x - w)
|
||||
if(-x > y && isReverse) { // 以x轴滑动距离为缩放基准
|
||||
maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
|
||||
if(-x > maxX) x = -maxX;
|
||||
y = num(-x * area.height / area.width);
|
||||
} else { // 以y轴滑动距离为缩放基准
|
||||
maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
|
||||
if(y > maxY) y = maxY;
|
||||
x = num(-y * area.width / area.height);
|
||||
}
|
||||
areaOffset.right = x;
|
||||
areaOffset.top = y;
|
||||
}
|
||||
break;
|
||||
case 3: // 左下角
|
||||
x += num(x + areaOffset.left);
|
||||
y += num(y + areaOffset.bottom);
|
||||
if(x >= 0 && y <= 0) { // 有效滑动
|
||||
var w = (r === 1 ? img.width : img.height);
|
||||
var t = num(area.bottom - m - offset.y - w);
|
||||
var l = num(offset.x - m - area.left);
|
||||
var max = isIntersect && ((l >= 0) || (t >= 0))
|
||||
? minimum(t, l)
|
||||
: false;
|
||||
if(x > -y && isReverse) { // 以x轴滑动距离为缩放基准
|
||||
maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
|
||||
if(x > maxX) x = maxX;
|
||||
y = num(-x * area.height / area.width);
|
||||
} else { // 以y轴滑动距离为缩放基准
|
||||
maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
|
||||
if(-y > maxY) y = -maxY;
|
||||
x = num(-y * area.width / area.height);
|
||||
}
|
||||
areaOffset.left = x;
|
||||
areaOffset.bottom = y;
|
||||
}
|
||||
break;
|
||||
case 4: // 右下角
|
||||
x = num(x + areaOffset.right);
|
||||
y = num(y + areaOffset.bottom);
|
||||
if(x <= 0 && y <= 0) { // 有效滑动
|
||||
var w = (r === 1 ? img.height : img.width);
|
||||
var h = (r === 1 ? img.width : img.height);
|
||||
var t = num(area.bottom - offset.y - h - m);
|
||||
var l = num(area.right + m - offset.x - w);
|
||||
var max = isIntersect && ((l >= 0) || (t >= 0))
|
||||
? minimum(t, l)
|
||||
: false;
|
||||
if(-x > -y && isReverse) { // 以x轴滑动距离为缩放基准
|
||||
maxX = validMax(maxX, max, isInclude, l, t, area.width / area.height);
|
||||
if(-x > maxX) x = -maxX;
|
||||
y = num(x * area.height / area.width);
|
||||
} else { // 以y轴滑动距离为缩放基准
|
||||
maxY = validMax(maxY, max, isInclude, t, l, area.height / area.width);
|
||||
if(-y > maxY) y = -maxY;
|
||||
x = num(y * area.width / area.height);
|
||||
}
|
||||
areaOffset.right = x;
|
||||
areaOffset.bottom = y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// console.log(x, y, JSON.stringify(areaOffset))
|
||||
changeAreaRect({
|
||||
instance: o,
|
||||
});
|
||||
// this.draw();
|
||||
}
|
||||
} else if (e.touches.length == 2) { // 双点触摸缩放
|
||||
var start = getDistanceByTouches(touches);
|
||||
var end = getDistanceByTouches(e.touches);
|
||||
scaleImage({
|
||||
instance: o,
|
||||
check: !area.bounce,
|
||||
scale: (end.c - start.c) / 100,
|
||||
x: end.x,
|
||||
y: end.y
|
||||
});
|
||||
touchType = 'scale';
|
||||
} else if(touchType === 'scale') {// 从双点触摸变成单点触摸 / 从缩放变成拖动
|
||||
touchType = 'move';
|
||||
} else {
|
||||
changeImageRect({
|
||||
instance: o,
|
||||
check: !area.bounce,
|
||||
x: e.touches[0].pageX - touches[0].pageX,
|
||||
y: e.touches[0].pageY - touches[0].pageY
|
||||
});
|
||||
touchType = 'move';
|
||||
}
|
||||
touches = e.touches;
|
||||
},
|
||||
/**
|
||||
* 触摸结束
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
touchend: function(e, o) {
|
||||
if(!img.src) return;
|
||||
if(touchType === 'stretch') { // 拉伸裁剪区域的四个角缩放
|
||||
// 裁剪区域宽度被缩放到多少
|
||||
var left = areaOffset.left;
|
||||
var right = areaOffset.right;
|
||||
var top = areaOffset.top;
|
||||
var bottom = areaOffset.bottom;
|
||||
var w = area.width + right - left;
|
||||
var h = area.height + bottom - top;
|
||||
// 图像放大倍数
|
||||
var p = scale * (area.width / w) - scale;
|
||||
// 复原裁剪区域
|
||||
areaOffset = { left: 0, right: 0, top: 0, bottom: 0 };
|
||||
changeAreaRect({
|
||||
instance: o,
|
||||
});
|
||||
scaleImage({
|
||||
instance: o,
|
||||
scale: p,
|
||||
x: area.left + left + (1 === activeAngle || 3 === activeAngle ? w : 0),
|
||||
y: area.top + top + (1 === activeAngle || 2 === activeAngle ? h : 0)
|
||||
});
|
||||
} else if (area.bounce) { // 检查边界并矫正,实现拖动到边界时有回弹效果
|
||||
changeImageRect({
|
||||
instance: o,
|
||||
check: true
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 顺时针翻转图片90°
|
||||
* @param {Object} e 事件对象
|
||||
* @param {Object} o 组件实例对象
|
||||
*/
|
||||
rotateImage: function(e, o) {
|
||||
rotateImage(e, o, 90);
|
||||
},
|
||||
rotateImage90: function(e, o) {
|
||||
rotateImage(e, o, 90)
|
||||
},
|
||||
rotateImage270: function(e, o) {
|
||||
rotateImage(e, o, 270)
|
||||
},
|
||||
// 此处只用于对齐其他平台端的样式参数,防止异常,无作用
|
||||
imageStyles: '',
|
||||
maskStylesList: ['', '', '', ''],
|
||||
borderStyles: '',
|
||||
gridStylesList: ['', '', '', ''],
|
||||
angleStylesList: ['', '', '', ''],
|
||||
circleBoxStyles: '',
|
||||
circleStyles: '',
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<!-- <UpApp :show="upShow" :url="url" /> -->
|
||||
<view class="borybac" v-if="upShow">
|
||||
<view class="up_box">
|
||||
|
||||
<view class="mt50">
|
||||
<view class="text">
|
||||
版本更新
|
||||
</view>
|
||||
<view class="text">
|
||||
{{remark}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="jdBox">
|
||||
<view class="jd">
|
||||
<view class="jdbfb">
|
||||
{{sum}}%
|
||||
</view>
|
||||
<view class="jdt">
|
||||
<view class="jdn" :style="'width:'+sum+'%'">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="jddx">
|
||||
{{datacl(beg)}}/{{datacl(downlog)}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" v-if="force==0" style="width: 95%; height: 60rpx; margin: 40rpx auto; display: flex; justify-content: space-between;">
|
||||
<view class="" style="width: 70rpx;" >
|
||||
|
||||
</view>
|
||||
<view class="" style="width: 240rpx; height: 60rpx; line-height: 60rpx; border-radius: 30rpx; text-align: center; color: #fff; font-size: 24rpx; background-color: var(--nav-mian);" @click="delUpApp">
|
||||
开始更新
|
||||
</view>
|
||||
<view class="" style="font-size: 22rpx; line-height: 80rpx; color: #999;" @click="goindex">
|
||||
暂不更新
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
let url = ref('')
|
||||
let force = ref('0')
|
||||
|
||||
// 控制热更新
|
||||
let upShow = ref(true)
|
||||
let sum = ref(0)
|
||||
let downlog = ref(0)
|
||||
let beg = ref(15642544)
|
||||
let remark = ref('')
|
||||
let type = ref('')
|
||||
|
||||
//模拟请求
|
||||
onLoad((data:any) => {
|
||||
// getdata()
|
||||
url.value=data.url
|
||||
});
|
||||
|
||||
const goindex = function () {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
|
||||
const getdata = function(){
|
||||
// RegisterService.GetNewVersion().then((res:any)=>{
|
||||
// url.value = res.data.path
|
||||
// downlog.value = res.data.size
|
||||
// force.value = res.data.force
|
||||
// remark.value = res.data.remark
|
||||
// type.value = res.data.type
|
||||
// if(res.data.force=='1'){
|
||||
// delUpApp()
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
|
||||
const datacl = function(e:any){
|
||||
if(e>1024){
|
||||
let sl = ((e/1024)/1024).toFixed(1)
|
||||
return sl+'MB'
|
||||
}else{
|
||||
return (e/1024).toFixed(1)+'KB'
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const delUpApp = function () {
|
||||
// 1.开始请求下载
|
||||
const downloadTask = uni.downloadFile({
|
||||
url: url.value,
|
||||
success: (downloadResult) => {
|
||||
if (downloadResult.statusCode === 200) {
|
||||
plus.runtime.install(downloadResult.tempFilePath, {
|
||||
force: false
|
||||
}, function() {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: "下载成功",
|
||||
complete() {
|
||||
if(type.value=='Bulking'){
|
||||
setTimeout(function() {
|
||||
plus.runtime.restart();
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
console.log('install success...');
|
||||
}, function(e) {
|
||||
uni.hideLoading()
|
||||
console.log(e,'失败')
|
||||
// uni.$u.toast('下载失败!')
|
||||
// console.error('install fail...');
|
||||
});
|
||||
}
|
||||
},
|
||||
fail(downloadResult) {
|
||||
console.log(downloadResult,'失败')
|
||||
// console.log('下载失败');
|
||||
// uni.$u.toast('下载失败')
|
||||
}
|
||||
});
|
||||
downloadTask.onProgressUpdate((res) => {
|
||||
downlog.value = res.totalBytesExpectedToWrite
|
||||
beg.value = res.totalBytesWritten
|
||||
sum.value =res.progress
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" setup>
|
||||
.borybac {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
.up_box {
|
||||
width: 513rpx;
|
||||
height: 680rpx;
|
||||
margin: 300rpx auto;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-image: url(@/static/index/system/upapphed.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
|
||||
.mt50 {
|
||||
display: block;
|
||||
margin-top: 200rpx;
|
||||
}
|
||||
|
||||
.jdBox {
|
||||
overflow: hidden;
|
||||
margin-top: 120rpx;
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
.jd {
|
||||
display: block;
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
|
||||
.jdbfb {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
font-size: 30rpx;
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.jdt {
|
||||
margin-top: 10rpx;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 23rpx;
|
||||
border-radius: 15rpx;
|
||||
background-color: #E5E5E5;
|
||||
|
||||
.jdn {
|
||||
display: block;
|
||||
height: 23rpx;
|
||||
border-radius: 15rpx;
|
||||
background: radial-gradient(#8370F8 0%, #455FF8 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.jddx {
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
margin-top: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 30rpx;
|
||||
width: 100%;
|
||||
height: 40rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,241 @@
|
||||
{
|
||||
"easycom": {
|
||||
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
|
||||
"custom": {
|
||||
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
|
||||
{
|
||||
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "门店运营",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/task",
|
||||
"style": {
|
||||
"navigationBarTitleText": "任务",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/income",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的收入",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/user",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "v派商家",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"backgroundColor": "#000"
|
||||
},
|
||||
"subPackages": [{
|
||||
"root": "pages/order",
|
||||
"pages": [{
|
||||
"path": "orderDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "navigation",
|
||||
"style": {
|
||||
"navigationBarTitleText": "导航",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "abnormal",
|
||||
"style": {
|
||||
"navigationBarTitleText": "上报异常"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "grabOrder",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "incomeDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "收入详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "withdraw",
|
||||
"style": {
|
||||
"navigationBarTitleText": "提现申请"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "finish",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单完成"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "upAbnormal",
|
||||
"style": {
|
||||
"navigationBarTitleText": "异常上报"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "orderMap",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单地图"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "orderChat",
|
||||
"style": {
|
||||
"navigationBarTitleText": "联系客户"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/my",
|
||||
"pages": [{
|
||||
"path": "edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑资料"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "statusContro",
|
||||
"style": {
|
||||
"navigationBarTitleText": "上线管理"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "myKF",
|
||||
"style": {
|
||||
"navigationBarTitleText": "联系客服"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "AbnormalList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "异常订单"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "check",
|
||||
"style": {
|
||||
"navigationBarTitleText": "签到奖励"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "abnormalDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "异常详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "security",
|
||||
"style": {
|
||||
"navigationBarTitleText": "账号与安全"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "authentication",
|
||||
"style": {
|
||||
"navigationBarTitleText": "实名认证"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "noticeList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "消息通知",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "setConnect",
|
||||
"style": {
|
||||
"navigationBarTitleText": "紧急联系人"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "evaluate",
|
||||
"style": {
|
||||
"navigationBarTitleText": "评价中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "completeData",
|
||||
"style": {
|
||||
"navigationBarTitleText": "完善信息"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "withDrowList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "提现列表"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
"tabBar": {
|
||||
"color": "#000",
|
||||
"selectedColor": "#000",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"list": [{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/tab/home.png",
|
||||
"selectedIconPath": "/static/tab/homed.png",
|
||||
"text": "主页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/income",
|
||||
"iconPath": "static/tab/income.png",
|
||||
"selectedIconPath": "static/tab/incomed.png",
|
||||
"text": "收入"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/user",
|
||||
"iconPath": "static/tab/user.png",
|
||||
"selectedIconPath": "static/tab/usered.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****代理端接口*****/
|
||||
class NvpAgentService {
|
||||
private static LoginPath: string = '/Agent/Login';
|
||||
/*****登录接口*****/
|
||||
static Login(name: string, pwd: string) {
|
||||
var result = Service.Request(this.LoginPath, "POST", { name, pwd });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetAgentAccInfoPath: string = '/Agent/GetAgentAccInfo';
|
||||
/*****账户接口*****/
|
||||
static GetAgentAccInfo() {
|
||||
var result = Service.Request(this.GetAgentAccInfoPath, "GET", "");
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetAgentAccLogPath: string = '/Agent/GetAgentAccLog';
|
||||
/*****账户记录*****/
|
||||
static GetAgentAccLog(code: string, page: number) {
|
||||
var result = Service.Request(this.GetAgentAccLogPath, "GET", { code, page });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetAgentMerchPath: string = '/Agent/GetAgentMerch';
|
||||
/*****获取代理开通商家*****/
|
||||
static GetAgentMerch(type: number, page: number) {
|
||||
var result = Service.Request(this.GetAgentMerchPath, "GET", { type, page });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetAgentHomePath: string = '/Agent/GetAgentHome';
|
||||
/*****代理主页*****/
|
||||
static GetAgentHome() {
|
||||
var result = Service.Request(this.GetAgentHomePath, "GET", { });
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
export {
|
||||
Service,
|
||||
NvpAgentService
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
@@ -0,0 +1,30 @@
|
||||
## 1.4.12(2024-09-21)
|
||||
- 修复 calendar在选择日期范围后重新选择日期需要点两次的Bug
|
||||
## 1.4.11(2024-01-10)
|
||||
- 修复 回到今天时,月份显示不一致问题
|
||||
## 1.4.10(2023-04-10)
|
||||
- 修复 某些情况 monthSwitch 未触发的Bug
|
||||
## 1.4.9(2023-02-02)
|
||||
- 修复 某些情况切换月份错误的Bug
|
||||
## 1.4.8(2023-01-30)
|
||||
- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
|
||||
## 1.4.7(2022-09-16)
|
||||
- 优化 支持使用 uni-scss 控制主题色
|
||||
## 1.4.6(2022-09-08)
|
||||
- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug
|
||||
## 1.4.5(2022-02-25)
|
||||
- 修复 条件编译 nvue 不支持的 css 样式的Bug
|
||||
## 1.4.4(2022-02-25)
|
||||
- 修复 条件编译 nvue 不支持的 css 样式的Bug
|
||||
## 1.4.3(2021-09-22)
|
||||
- 修复 startDate、 endDate 属性失效的Bug
|
||||
## 1.4.2(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.4.1(2021-08-05)
|
||||
- 修复 弹出层被 tabbar 遮盖的Bug
|
||||
## 1.4.0(2021-07-30)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.3.16(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.3.15(2021-02-04)
|
||||
- 调整为uni_modules目录规范
|
||||
@@ -0,0 +1,714 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style="padding:50rpx 20rpx 18rpx; box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: #fff; display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="">
|
||||
收入详情
|
||||
</view>
|
||||
<view class="" style="color: var(--nav-banbacor);">
|
||||
<image :src="Service.GetIconImg('/static/index/order/message.png')" style="width: 32rpx; height: 32rpx; "
|
||||
mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 100rpx; ">
|
||||
|
||||
</view>
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 标题骨架屏 -->
|
||||
<view class="skeleton-section-title"></view>
|
||||
|
||||
<!-- 收入卡片骨架屏 -->
|
||||
<view class="skeleton-card">
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-order-id"></view>
|
||||
<view class="skeleton-status"></view>
|
||||
</view>
|
||||
<view class="skeleton-row" v-for="item in 3" >
|
||||
<view class="skeleton-order-id" style="width: 30%;" ></view>
|
||||
<view class="skeleton-status"></view>
|
||||
</view>
|
||||
<view class="skeleton-total-row">
|
||||
<view class="skeleton-total-label"></view>
|
||||
<view class="skeleton-total-amount"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 配送信息标题骨架屏 -->
|
||||
<view class="skeleton-section-title"></view>
|
||||
|
||||
<!-- 订单信息卡片骨架屏 -->
|
||||
<view class="skeleton-card">
|
||||
<!-- 商家信息骨架屏 -->
|
||||
<view class="skeleton-address-item">
|
||||
<view class="skeleton-address-content">
|
||||
<view class="skeleton-address-text">
|
||||
<view class="skeleton-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
</view>
|
||||
<view class="skeleton-call-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 用户信息骨架屏 -->
|
||||
<view class="skeleton-address-item">
|
||||
<view class="skeleton-address-content">
|
||||
<view class="skeleton-address-text">
|
||||
<view class="skeleton-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
</view>
|
||||
<view class="skeleton-call-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 时间信息骨架屏 -->
|
||||
<view class="skeleton-time"></view>
|
||||
</view>
|
||||
|
||||
<!-- 底部提示骨架屏 -->
|
||||
<view class="skeleton-bottom-tip"></view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view class="order-detail-container">
|
||||
<view class="section-title" style="margin: 20rpx 0;" >订单信息</view>
|
||||
<!-- 订单收入信息卡片 -->
|
||||
<view class="income-card">
|
||||
<view class="income-header">
|
||||
<text class="order-id">订单 MT20251017123456</text>
|
||||
<text class="status">已到账</text>
|
||||
</view>
|
||||
|
||||
<view class="income-details">
|
||||
<view class="income-item">
|
||||
<text class="income-type">配送费</text>
|
||||
<text class="income-amount blue">+¥5.50</text>
|
||||
</view>
|
||||
<view class="income-item">
|
||||
<text class="income-type">冲单奖</text>
|
||||
<text class="income-amount orange">+¥3.00</text>
|
||||
</view>
|
||||
<view class="income-item">
|
||||
<text class="income-type">恶劣天气补贴</text>
|
||||
<text class="income-amount green">+¥2.00</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="total-income">
|
||||
<text class="total-label">总计收入</text>
|
||||
<text class="total-amount">¥10.50</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息卡片 -->
|
||||
<view class="section-title">配送信息</view>
|
||||
<view class="info-card">
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<view class="merchant-detail">
|
||||
<view class="merchant-text">
|
||||
<text class="merchant-name">张亮麻辣烫 (五道口店)</text>
|
||||
<text class="merchant-address">成府路28号</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="call-btn" @click="callMerchant">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="28rpx"></up-icon>
|
||||
<text class="call-text">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<view class="user-info">
|
||||
<view class="user-detail">
|
||||
<view class="user-text">
|
||||
<text class="user-name">张*</text>
|
||||
<text class="user-address">XX小区3栋502</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="call-btn" @click="callUser">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="28rpx"></up-icon>
|
||||
<text class="call-text">拨打用户</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单时间信息 -->
|
||||
<view class="order-time-info">
|
||||
<text class="time-text">2025-10-17 18:30 下单 · 19:15 送达</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部提示 -->
|
||||
<view class="bottom-tip">
|
||||
<text class="tip-text">收入明细如有疑问,请联系客服</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Service } from '@/Service/Service'
|
||||
// 加载状态
|
||||
const loading = ref(true)
|
||||
|
||||
|
||||
// 拨打商家电话
|
||||
const callMerchant = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: '13800138000'
|
||||
})
|
||||
}
|
||||
|
||||
// 拨打用户电话
|
||||
const callUser = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: '13900139000'
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 模拟数据加载
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1500)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
||||
/* 实际内容样式 */
|
||||
.order-detail-container {
|
||||
background-color: #f5f5f5;
|
||||
padding: 0 20rpx ;
|
||||
}
|
||||
|
||||
/* 订单收入信息卡片 */
|
||||
.income-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 28rpx;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.income-details {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-type {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.income-amount {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income-amount.blue {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.income-amount.orange {
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.income-amount.green {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.total-income {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 20rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.total-label {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.total-amount {
|
||||
font-size: 36rpx;
|
||||
color: #ff4d4f;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* 订单信息卡片 */
|
||||
.info-card {
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 34rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
/* 商家信息 */
|
||||
.merchant-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.merchant-detail {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.merchant-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.merchant-address {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 用户信息 */
|
||||
.user-info {
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.user-detail {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.user-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.user-address {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 拨打电话按钮 */
|
||||
.call-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.call-text {
|
||||
font-size: 24rpx;
|
||||
color: #1890ff;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
|
||||
/* 订单时间信息 */
|
||||
.time-text {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 底部提示 */
|
||||
.bottom-tip {
|
||||
text-align: center;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #faad14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding: 0 20rpx 60rpx;
|
||||
}
|
||||
|
||||
/* 标题骨架屏 */
|
||||
.skeleton-section-title {
|
||||
width: 160rpx;
|
||||
height: 34rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin: 30rpx 0;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 卡片骨架屏 */
|
||||
.skeleton-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 收入卡片骨架屏 */
|
||||
.skeleton-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-id {
|
||||
width: 60%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-status {
|
||||
width: 15%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
width: 100%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-total-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 20rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-total-label {
|
||||
width: 40%;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-total-amount {
|
||||
width: 25%;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 地址信息骨架屏 */
|
||||
.skeleton-address-item {
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-address-item:last-child {
|
||||
margin-bottom: 20rpx;
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.skeleton-address-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-name {
|
||||
width: 60%;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 10rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-address-line {
|
||||
width: 80%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-call-btn {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 时间信息骨架屏 */
|
||||
.skeleton-time {
|
||||
width: 70%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 底部提示骨架屏 */
|
||||
.skeleton-bottom-tip {
|
||||
margin: 0 100rpx;
|
||||
height: 24rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-top: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 为骨架屏元素添加渐变背景 */
|
||||
.skeleton-section-title,
|
||||
.skeleton-order-id,
|
||||
.skeleton-status,
|
||||
.skeleton-line,
|
||||
.skeleton-total-label,
|
||||
.skeleton-total-amount,
|
||||
.skeleton-name,
|
||||
.skeleton-address-line,
|
||||
.skeleton-call-btn,
|
||||
.skeleton-time,
|
||||
.skeleton-bottom-tip {
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 387 B |
@@ -0,0 +1,662 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style="padding:50rpx 20rpx 18rpx; box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: #fff; display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="">
|
||||
订单详情
|
||||
</view>
|
||||
<view class="" @click="Service.GoPage('/pages/my/myKF')" style="color: var(--nav-banbacor);">
|
||||
<image :src="Service.GetIconImg('/static/index/order/message.png')" style="width: 32rpx; height: 32rpx; "
|
||||
mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 88rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 骨架屏订单状态 -->
|
||||
<view class="skeleton-status"></view>
|
||||
|
||||
<!-- 骨架屏订单基本信息 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-half"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-third"></view>
|
||||
<view class="skeleton-info-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏物品清单 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;" >
|
||||
<view class="" style="background-color: #e6e6e6; width: 60%;height: 40rpx; " >
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-row" v-for="(item,index) in 3" :key="index" >
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;" >
|
||||
<view class="" style="background-color: #e6e6e6; width: 90%;height: 40rpx; " >
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-list-status"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏地图区域 -->
|
||||
<view class="skeleton-map"></view>
|
||||
|
||||
<!-- 骨架屏取餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-code"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏送餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-remark"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏底部按钮 -->
|
||||
<view class="skeleton-bottom">
|
||||
<view class="skeleton-bottom-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单状态 -->
|
||||
<view class="order-status"
|
||||
:style="{ 'background-color':orderStatus==0?'#E6F7FF':(orderStatus==1?'#FFFBE6':'#FFF2F0') }">
|
||||
<text :style="{ 'color':orderStatus==0?'#1890FF':(orderStatus==1?'#FAAD14':'#FF4D4F') }"
|
||||
style="font-size: 34rpx; font-weight: 600;">待取餐 · 请尽快到店取餐</text>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="info-item">
|
||||
<view class="label">剩余</view>
|
||||
<view class="value highlight">10分钟</view>
|
||||
<view class="label">(19:30前送达)</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥5.50</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">20251021123456</text>
|
||||
</view>
|
||||
<view class="info-item" style=" justify-content: space-between;">
|
||||
<view class="">
|
||||
<text class="label">物品明细 : </text>
|
||||
<text class="value">食物</text>
|
||||
</view>
|
||||
<view class="label">共3件商品</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">物品重量 : </text>
|
||||
<text class="value">0.5kg</text>
|
||||
</view>
|
||||
<view class="info-item" style="justify-content: space-between; ">
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="24rpx" class="clock-icon"></u-icon>
|
||||
2025-10-17 18:30下单
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<up-button @click.stop="Service.GoPage('/pages/order/abnormal')" type="warning"
|
||||
color='var(--nav-diluted)' shape='circle' size="mini">提交异常</up-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
5件
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
¥16
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'190rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in 5 " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
康师傅 大食桶红烧牛肉143g/桶 经典红烧酱香免洗桶装速食泡面
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×4
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥16
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 地图区域 -->
|
||||
<view class="map-section">
|
||||
<view class="map-placeholder">
|
||||
<text @click="Service.GoPage('/pages/order/navigation')" class="map-hint">点击查看完整导航</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">取餐地址</text>
|
||||
<view class="address-content">
|
||||
<text class="store-name">张亮麻辣烫(五道口店)</text>
|
||||
<text class="address">北京市海淀区成府路28号</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button icon="phone" type="primary" shape="circle" text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view class="pickup-code">
|
||||
<text class="code-label">取餐号:</text>
|
||||
<text class="code-value">A123</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 送餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">送餐地址</text>
|
||||
<view class="address-content">
|
||||
<text class="user-name">张*</text>
|
||||
<text class="address">XX小区3栋502室</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button icon="phone" type="primary" shape="circle" text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action">
|
||||
<up-button color="var(--nav-vice)" class="confirm-btn">我已取餐</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏导航栏 */
|
||||
.skeleton-nav {
|
||||
height: 88rpx;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.skeleton-nav-item {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-nav-title {
|
||||
width: 180rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单状态 */
|
||||
.skeleton-status {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-status::after {
|
||||
content: '';
|
||||
width: 350rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单基本信息 */
|
||||
.skeleton-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-info-half {
|
||||
width: 45%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-right {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-third {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-btn {
|
||||
width: 20%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 列表状态 */
|
||||
.skeleton-list-status {
|
||||
height: 60rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-list-status::after {
|
||||
content: '';
|
||||
width: 200rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏地图区域 */
|
||||
.skeleton-map {
|
||||
margin: 20rpx;
|
||||
height: 400rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-map::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, transparent 25%, rgba(255, 255, 255, 0.2) 25%, rgba(255, 255, 255, 0.2) 50%, transparent 50%, transparent 75%, rgba(255, 255, 255, 0.2) 75%, rgba(255, 255, 255, 0.2));
|
||||
background-size: 100rpx 100rpx;
|
||||
animation: shimmer 1.5s infinite linear;
|
||||
}
|
||||
|
||||
/* 骨架屏地址区域 */
|
||||
.skeleton-address {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-store-name {
|
||||
width: 70%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-address-line {
|
||||
width: 90%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
height: 70rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 35rpx;
|
||||
margin: 20rpx 0;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-code {
|
||||
width: 50%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-remark {
|
||||
width: 80%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏底部按钮 */
|
||||
.skeleton-bottom {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-bottom-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏滑动动画 */
|
||||
@keyframes shimmer-slide {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* end */
|
||||
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"name" : "骑手端",
|
||||
"appid" : "__UNI__06C2D6A",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.8",
|
||||
"versionCode" : 108,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"compatible" : {
|
||||
"ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : false,
|
||||
"waiting" : false,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"Barcode" : {},
|
||||
"Maps" : {},
|
||||
"Geolocation" : {},
|
||||
"Camera" : {},
|
||||
"Contacts" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
],
|
||||
"minSdkVersion" : 25,
|
||||
"targetSdkVersion" : 25,
|
||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {
|
||||
"idfa" : false,
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"ad" : {},
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"appkey_ios" : "3caf9e6f01b0085be1e75e0d0e281fe7",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
},
|
||||
"geolocation" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"__platform__" : [ "android" ],
|
||||
"appkey_ios" : "",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios" : {
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx6ef5a6a74620a3e8",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"qqmap" : {
|
||||
"key" : "7DIBZ-K4HCJ-ZR2FE-FOOOP-SALFT-RLFYW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****用户接口*****/
|
||||
class NvpApplyService {
|
||||
// private static WithDrawPath: string = '/With/WithDraw';
|
||||
// /*****佣金提现*****/
|
||||
// static WithDraw(money: number, name: string, account: string) {
|
||||
// var result = Service.Request(this.WithDrawPath, "POST", { money, name, account });
|
||||
// return result;
|
||||
// }
|
||||
|
||||
private static GetSiteMccCodeListPath: string = '/Apply/GetSiteMccCodeList';
|
||||
/*****获取mcc列表*****/
|
||||
static GetSiteMccCodeList(mercType:string, mchType: string) {
|
||||
var result = Service.Request(this.GetSiteMccCodeListPath, "GET", {mercType, mchType });
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static GetBankTypeListPath: string = '/Apply/GetBankTypeList';
|
||||
/*****获取银行列表*****/
|
||||
static GetBankTypeList(name:string) {
|
||||
var result = Service.Request(this.GetBankTypeListPath, "GET", {name});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetAreaListPath: string = '/Apply/GetAreaList';
|
||||
/*****获取银行地区列表*****/
|
||||
static GetAreaList(areaCode:string) {
|
||||
var result = Service.Request(this.GetAreaListPath, "GET", { areaCode});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static GetBankCodeListPath: string = '/Apply/GetBankCodeList';
|
||||
/*****获取银行代码列表*****/
|
||||
static GetBankCodeList(bankType:string,cityCode:string,name:string) {
|
||||
var result = Service.Request(this.GetBankCodeListPath, "GET", {bankType,cityCode,name});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static SendApplyMerchPath: string = '/Apply/SendApplyMerch';
|
||||
/*****进价提交*****/
|
||||
static SendApplyMerch(para:any) {
|
||||
var result = Service.Request(this.SendApplyMerchPath, "POST", para);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetAgentMerchLogPath: string = '/Apply/GetAgentMerchLog';
|
||||
/*****获取待审核*****/
|
||||
static GetAgentMerchLog() {
|
||||
var result = Service.Request(this.GetAgentMerchLogPath, "GET", {});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static AuditApplyPath: string = '/Apply/AuditApply';
|
||||
/*****确认资料*****/
|
||||
static AuditApply(outId:string) {
|
||||
var result = Service.Request(this.AuditApplyPath, "POST", {outId});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SetPayFeePath: string = '/Apply/SetPayFee';
|
||||
/*****确认资料*****/
|
||||
static SetPayFee(outId:string) {
|
||||
var result = Service.Request(this.SetPayFeePath, "POST", {outId});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetAssortListPath: string = '/Apply/GetAssortList';
|
||||
/*****获取v派分类*****/
|
||||
static GetAssortList(code:string) {
|
||||
var result = Service.Request(this.GetAssortListPath, "GET", {code,parent:'0'});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetAgentMerchPath: string = '/Agent/GetAgentMerch';
|
||||
/*****获取已开通商家*****/
|
||||
static GetAgentMerch(type:number,page:number) {
|
||||
var result = Service.Request(this.GetAgentMerchPath, "GET", {type,page});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetAppMerchInfoPath: string = '/Apply/GetAppMerchInfo';
|
||||
/*****获取银盛已填写信息*****/
|
||||
static GetAppMerchInfo(outId:string) {
|
||||
var result = Service.Request(this.GetAppMerchInfoPath, "GET", {outId});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static UpdateMerchPath: string = '/Apply/UpdateMerch';
|
||||
/*****修改银盛信息*****/
|
||||
static UpdateMerch(obj:any) {
|
||||
var result = Service.Request(this.UpdateMerchPath, "POST", obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static UploadImgPath: string = '/Apply/UploadImg';
|
||||
/*****修改银盛图片*****/
|
||||
static UploadImg(outId:string,picType:string,img:string) {
|
||||
var result = Service.Request(this.UploadImgPath, "POST", {outId,picType,img});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetAgentApplyPath: string = '/Apply/GetAgentApply';
|
||||
/*****获取添加的商家*****/
|
||||
static GetAgentApply(serch:string,page:number) {
|
||||
var result = Service.Request(this.GetAgentApplyPath, "GET", {serch,page});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetCategoryPath: string = '/Apply/GetCategory';
|
||||
/*****获取商家类型*****/
|
||||
static GetCategory() {
|
||||
var result = Service.Request(this.GetCategoryPath, "GET", {});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static AddMerchInfoPath: string = '/Apply/AddMerchInfo';
|
||||
/*****添加商户*****/
|
||||
static AddMerchInfo(obj:any) {
|
||||
var result = Service.Request(this.AddMerchInfoPath, "POST", obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static BandAppIdPath: string = '/Agent/BandAppId';
|
||||
/*****绑定appid*****/
|
||||
static BandAppId(merchId:string) {
|
||||
var result = Service.Request(this.BandAppIdPath, "POST", {merchId});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
export {
|
||||
Service,
|
||||
NvpApplyService
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
<template>
|
||||
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 成功提示区域骨架 -->
|
||||
<view class="success-section skeleton-success-section">
|
||||
<view class="skeleton-success-icon"></view>
|
||||
<view class="skeleton-line skeleton-success-title"></view>
|
||||
<view class="skeleton-line skeleton-success-desc"></view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息卡片骨架 -->
|
||||
<view class="order-card skeleton-order-card">
|
||||
<view class="order-item" v-for="i in 4" :key="i">
|
||||
<view class="skeleton-line skeleton-order-label"></view>
|
||||
<view class="skeleton-line skeleton-order-value"></view>
|
||||
</view>
|
||||
|
||||
<!-- 查看详情按钮骨架 -->
|
||||
<view class="skeleton-line skeleton-view-detail-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位 -->
|
||||
<view class="bottom-space"></view>
|
||||
|
||||
<!-- 底部按钮区域骨架 -->
|
||||
<view class="bottom-buttons skeleton-bottom-buttons">
|
||||
<view class="skeleton-line skeleton-continue-btn"></view>
|
||||
<view class="skeleton-line skeleton-view-progress-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="abnormal-reported-page">
|
||||
<!-- 成功提示区域 -->
|
||||
<view class="success-section">
|
||||
<view class="success-icon">
|
||||
<up-icon name="checkmark-circle-fill" size="80" color="#4CD964"></up-icon>
|
||||
</view>
|
||||
<view class="success-title">异常已上报!</view>
|
||||
<view class="success-desc">配送计时已暂停,不影响您的准时率</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息卡片 -->
|
||||
<view class="order-card">
|
||||
<view class="order-item">
|
||||
<text class="order-label">订单号</text>
|
||||
<text class="order-value" style="font-weight: 600;">MT20251017123456</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">商品信息</text>
|
||||
<text class="order-value">共3件商品</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">配送地址</text>
|
||||
<text class="order-value">XX小区3栋502室</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">用户备注</text>
|
||||
<text class="order-value remark-text">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
|
||||
<!-- 查看详情按钮 -->
|
||||
<view @click="Service.GoPage('/pages/my/abnormalDetail')" class="view-detail-btn">
|
||||
<text>查看详情</text>
|
||||
<up-icon name="arrow-right" size="20" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位 -->
|
||||
<view class="bottom-space"></view>
|
||||
|
||||
<!-- 底部按钮区域 -->
|
||||
<view class="bottom-buttons">
|
||||
<up-button @click="Service.GoPageTab('/pages/index/task')" type="primary" size="default" class="continue-btn">
|
||||
继续接单
|
||||
</up-button>
|
||||
<up-button @click="Service.GoPage('/pages/my/abnormalDetail')" type="default" size="default" class="view-progress-btn">
|
||||
查看异常进度
|
||||
</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
let loading = ref(true)
|
||||
// 页面加载时的逻辑
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
// 成功提示区域样式
|
||||
.success-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60rpx 30rpx;
|
||||
background-color: #F6FFFB;
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.success-desc {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
// 订单卡片样式
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0 30rpx;
|
||||
box-shadow: 0 0 10rpx 0 #e2e2e2;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.order-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.order-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
.remark-text {
|
||||
color: #FF6F00;
|
||||
}
|
||||
|
||||
// 查看详情按钮样式
|
||||
.view-detail-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
padding-top: 30rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
// 底部占位
|
||||
.bottom-space {
|
||||
height: 280rpx;
|
||||
}
|
||||
|
||||
// 底部按钮区域样式
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.continue-btn {
|
||||
border-radius: 50rpx;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #007AFF;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.view-progress-btn {
|
||||
border-radius: 50rpx;
|
||||
height: 100rpx;
|
||||
line-height: 98rpx;
|
||||
font-size: 32rpx;
|
||||
color: #007AFF;
|
||||
border: 1rpx solid #007AFF;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
// 骨架屏基础样式和动画
|
||||
.skeleton-line,
|
||||
.skeleton-success-icon,
|
||||
.skeleton-loading {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 骨架屏公共样式
|
||||
.skeleton-line {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
// 骨架屏容器
|
||||
.skeleton-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 成功提示区域骨架样式
|
||||
.skeleton-success-section {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.skeleton-success-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-success-title {
|
||||
width: 40%;
|
||||
height: 40rpx;
|
||||
margin-bottom: 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-success-desc {
|
||||
width: 70%;
|
||||
height: 30rpx;
|
||||
border-radius: 15rpx;
|
||||
}
|
||||
|
||||
// 订单卡片骨架样式
|
||||
.skeleton-order-card {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.skeleton-order-label {
|
||||
width: 20%;
|
||||
height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-value {
|
||||
width: 50%;
|
||||
height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-view-detail-btn {
|
||||
width: 25%;
|
||||
height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-top: 30rpx;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
// 底部按钮区域骨架样式
|
||||
.skeleton-bottom-buttons {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-continue-btn {
|
||||
width: 49%;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-view-progress-btn {
|
||||
width: 49%;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<view class="home">
|
||||
<view class=""
|
||||
style=" margin-top: 200rpx; display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||
<image :src="Service.GetIconImg('/static/index/logo/logo.png')" style="width: 150rpx; height: 150rpx; "
|
||||
mode="">
|
||||
</image>
|
||||
<view class="" style="font-size: 36rpx; font-weight: 800; margin-top: 20rpx;">
|
||||
确菜农·骑手端
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="margin: 30rpx 30rpx; margin-top: 150rpx;">
|
||||
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
欢迎登陆
|
||||
</view>
|
||||
|
||||
<view class="" style="font-size: 28rpx; margin-top: 20rpx; ">
|
||||
手机号登录,安全又便捷
|
||||
</view>
|
||||
|
||||
<view class="">
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.phone" type="number" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入手机号"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<view v-if="!type" class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.password" type="password" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入密码"
|
||||
clearable='true' border="surround"></up-input>
|
||||
</view>
|
||||
<view v-else class=""
|
||||
style=" display: flex; align-items: center; justify-content: space-between; margin-top: 30rpx; border: 1rpx solid #dadbde; box-sizing: border-box; padding: 20rpx 30rpx; border-radius: 200rpx; ">
|
||||
<view class="" style="">
|
||||
<up-code-input v-model="login.code" :maxlength="4" mode="line" size='24'></up-code-input>
|
||||
</view>
|
||||
<view class="wrap">
|
||||
<up-toast ref="uToastRef"></up-toast>
|
||||
<up-code :seconds="seconds" @end="end" @start="start" ref="uCodeRef"
|
||||
@change="codeChange"></up-code>
|
||||
<view @click="getCode">{{tips}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<view class=""
|
||||
style="margin-top: 40rpx; width: 100%; height: 80rpx; line-height: 80rpx; border-radius: 40rpx; background-color: #FFD700; color: #000; font-weight: bold; font-size: 30rpx; text-align: center;"
|
||||
@click="loginshop()">
|
||||
登录
|
||||
|
||||
</view>
|
||||
|
||||
<view class="" style="text-align: center; color: #637aff; margin: 50rpx 0; ">
|
||||
<text @click="type=!type,login.password='',login.code=''">{{ !type?'使用验证码登录':'使用密码登录' }}</text>
|
||||
</view>
|
||||
|
||||
<view class=""
|
||||
style="display: flex; justify-content: center; align-items: center;color: black; margin-top: 50rpx; "
|
||||
@click="isuser= !isuser">
|
||||
<view class="" style="margin-right: 10rpx;">
|
||||
<up-icon :name="!isuser?'checkmark-circle':'checkmark-circle-fill'"
|
||||
:color="!isuser?'#999':'var(--nav-mian)'" size="20"></up-icon>
|
||||
</view>
|
||||
我同意
|
||||
<a @click.stop style="color: #FF6B23; text-decoration: none; " :href="userUrl">《用户协议》</a>
|
||||
和
|
||||
<a @click.stop style="color: #FF6B23; text-decoration: none; " :href="userUrl">《隐私政策》</a>
|
||||
</view>
|
||||
<view class="" style="text-align: center; margin-top: 20rpx;">
|
||||
新用户?系统将自动为您注册
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service, CNRiderLoginService } from "@/Service/CN/CNRiderLoginService"
|
||||
import { ref } from "vue";
|
||||
import { WebSocket } from '@/Service/Comm/TwWebSocket';
|
||||
let qudPow = ref<string>('')
|
||||
|
||||
let login = ref({
|
||||
phone: '',
|
||||
code: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
const tips = ref('');
|
||||
const seconds = ref(60);
|
||||
const uCodeRef = ref(null);
|
||||
|
||||
let type = ref(false)
|
||||
|
||||
let isLogin = ref<boolean>(true)//登录注册状态
|
||||
|
||||
let isuser = ref<boolean>(false)//用户同意协议
|
||||
|
||||
let userUrl = ref('')
|
||||
let other = ref('')
|
||||
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderLoginService.GetPrivacy(1).then(res => {
|
||||
userUrl.value = res.data.url
|
||||
})
|
||||
|
||||
CNRiderLoginService.GetPrivacy(4).then(res => {
|
||||
other.value = res.data.url
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
//登录
|
||||
const loginshop = () => {
|
||||
if (login.value.phone == '') {
|
||||
return Service.Msg('请输入手机号/账号!')
|
||||
}
|
||||
|
||||
if (login.value.password == '' && !type.value) {
|
||||
return Service.Msg('请输入密码!')
|
||||
}
|
||||
|
||||
if (login.value.code == '' && type.value) {
|
||||
return Service.Msg('请输入验证码!')
|
||||
}
|
||||
|
||||
if (!isuser.value) {
|
||||
return Service.Msg('请勾选同意用户协议!')
|
||||
}
|
||||
|
||||
|
||||
|
||||
CNRiderLoginService.RiderLogin(login.value).then(res => {
|
||||
if (res.code == 0) {
|
||||
Service.Msg('登录成功!')
|
||||
Service.SetUserToken(res.data.accToken)
|
||||
uni.$emit('ImCom')
|
||||
setTimeout(() => {
|
||||
isuser.value = false
|
||||
Service.GoPageTab('/pages/index/index')
|
||||
}, 1000)
|
||||
|
||||
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const codeChange = (text) => {
|
||||
tips.value = text;
|
||||
};
|
||||
|
||||
|
||||
const getCode = () => {
|
||||
if (!login.value.phone) {
|
||||
Service.Msg('请输入手机号')
|
||||
return
|
||||
}
|
||||
if (uCodeRef.value.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
CNRiderLoginService.SendUserSms(login.value.phone, 'RiderReg').then(res => {
|
||||
|
||||
})
|
||||
uCodeRef.value.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
Service.Msg('倒计时结束后再发送')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const end = () => {
|
||||
console.log('倒计时结束');
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
console.log('倒计时开始');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.home {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: linear-gradient(to bottom, #FFD700, #fff 40%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chen {}
|
||||
</style>
|
||||
@@ -0,0 +1,369 @@
|
||||
<template>
|
||||
<view class="income-container">
|
||||
<!-- 收入概览区域 -->
|
||||
<view class="income-overview">
|
||||
<view class="income-header">
|
||||
<text class="income-title">今日已赚</text>
|
||||
<text class="income-amount">¥86.50</text>
|
||||
</view>
|
||||
|
||||
<!-- 时间选择标签 -->
|
||||
<view class="time-tabs">
|
||||
<text v-for="(item ,index) in timeList" :key="index" @click="changeTab(index)"
|
||||
:class="{ 'active':currentTime==index }" class="tab-item">{{item}}</text>
|
||||
</view>
|
||||
<text class="month-total">本月累计¥1,240.00</text>
|
||||
</view>
|
||||
|
||||
<!-- 收入构成区域 -->
|
||||
<view class="income-composition">
|
||||
<!-- 饼图占位区域 -->
|
||||
<view class="pie-chart-placeholder">
|
||||
<view id="cahrt" class="pie-chart">
|
||||
<!-- 黑边白底的饼图占位 -->
|
||||
</view>
|
||||
<view class="chart-legend">
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot blue"></view>
|
||||
<text class="legend-text">配送费¥60.50</text>
|
||||
</view>
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot orange"></view>
|
||||
<text class="legend-text">冲单奖¥20.00</text>
|
||||
</view>
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot green"></view>
|
||||
<text class="legend-text">恶劣天气补贴¥6.00</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 钱包区域 -->
|
||||
<view class="wallet-section">
|
||||
<view class="wallet-header">
|
||||
<text class="wallet-title">钱包余额</text>
|
||||
<text class="wallet-amount">¥86.50</text>
|
||||
</view>
|
||||
<u-button class="withdraw-button" type="primary">立即提现</u-button>
|
||||
<text class="withdraw-tip">提现到账时间: T+1工作日</text>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细区域 -->
|
||||
<view class="detail-header">
|
||||
<text class="detail-title">收入明细</text>
|
||||
</view>
|
||||
<view class="detail-list" v-for="(item, index) in 3" :key="index">
|
||||
<view class="detail-content">
|
||||
<view class="icon-placeholder">
|
||||
<image src="/static/index/income/order.png"
|
||||
style="width: 55rpx; height: 55rpx;" mode=""></image>
|
||||
</view>
|
||||
<view class="detail-info">
|
||||
<text class="order-id">订单 MT20251020123456</text>
|
||||
<text class="order-time">10-20 18:35</text>
|
||||
</view>
|
||||
<text class="order-amount">+¥5.50</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
let timeList = ref([
|
||||
'今日',
|
||||
'本周',
|
||||
'本月'
|
||||
])
|
||||
|
||||
let currentTime = ref(0)
|
||||
|
||||
let option = ref({
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: true,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: 1048 },
|
||||
{ value: 735 },
|
||||
{ value: 580 },
|
||||
{ value: 484},
|
||||
{ value: 300 }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
})
|
||||
onMounted(()=>{
|
||||
let chartDom =ref( document.getElementById('cahrt'))
|
||||
let myChart = ref(echarts.init(chartDom.value))
|
||||
myChart.value.setOption(option.value);
|
||||
})
|
||||
const changeTab = (index : number) => {
|
||||
currentTime.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.income-container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 收入概览区域 */
|
||||
.income-overview {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.income-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 时间标签 */
|
||||
.time-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-right: 40rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #1890ff;
|
||||
border-bottom: 3rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.month-total {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 收入构成区域 */
|
||||
.income-composition {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 饼图占位 */
|
||||
.pie-chart-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.chart-legend {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.legend-dot.blue {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.legend-dot.orange {
|
||||
background-color: #fa8c16;
|
||||
}
|
||||
|
||||
.legend-dot.green {
|
||||
background-color: #52c41a;
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 钱包区域 */
|
||||
.wallet-section {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wallet-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.withdraw-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.withdraw-tip {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 收入明细区域 */
|
||||
.income-detail {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
.detail-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-list {
|
||||
margin: 15rpx 0 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 图标占位符 - 黑边白底 */
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 没有更多记录 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 474 B |
@@ -0,0 +1,655 @@
|
||||
<template>
|
||||
|
||||
<!-- 骨架屏状态 -->
|
||||
<view v-if="loading" class="skeleton-loading">
|
||||
<!-- 收入概览骨架屏 -->
|
||||
<view class="skeleton-card income-overview">
|
||||
<view class="skeleton-income-title"></view>
|
||||
<view class="skeleton-income-amount"></view>
|
||||
<view class="skeleton-time-tabs">
|
||||
<view class="skeleton-tab-item"></view>
|
||||
<view class="skeleton-tab-item"></view>
|
||||
<view class="skeleton-tab-item"></view>
|
||||
</view>
|
||||
<view class="skeleton-month-total"></view>
|
||||
</view>
|
||||
|
||||
<!-- 收入构成骨架屏 -->
|
||||
<view class="skeleton-card income-composition">
|
||||
<view class="skeleton-pie-container">
|
||||
<view class="skeleton-pie-chart"></view>
|
||||
<view class="skeleton-legend-list">
|
||||
<view class="skeleton-legend-item" v-for="item in 3">
|
||||
<view class="skeleton-legend-dot"></view>
|
||||
<view class="skeleton-legend-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 钱包区域骨架屏 -->
|
||||
<view class="skeleton-card wallet-section">
|
||||
<view class="skeleton-wallet-header">
|
||||
<view class="skeleton-wallet-title"></view>
|
||||
<view class="skeleton-wallet-amount"></view>
|
||||
</view>
|
||||
<view class="skeleton-withdraw-button"></view>
|
||||
<view class="skeleton-withdraw-tip"></view>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细骨架屏 -->
|
||||
<view class="skeleton-card">
|
||||
<view class="skeleton-detail-title"></view>
|
||||
</view>
|
||||
|
||||
<!-- 明细项骨架屏 -->
|
||||
<view v-for="index in 3" :key="index" class="skeleton-card detail-list">
|
||||
<view class="skeleton-detail-content">
|
||||
<view class="skeleton-icon-placeholder"></view>
|
||||
<view class="skeleton-detail-info">
|
||||
<view class="skeleton-order-id"></view>
|
||||
<view class="skeleton-order-time"></view>
|
||||
</view>
|
||||
<view class="skeleton-order-amount"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 加载更多 -->
|
||||
<view class="skeleton-card" style="display: flex; justify-content: center; ">
|
||||
<view class="skeleton-detail-title"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收入概览区域 -->
|
||||
<view v-else class="income-container">
|
||||
<view class="income-overview">
|
||||
<view class="income-header">
|
||||
<text class="income-title">今日已赚</text>
|
||||
<text class="income-amount">¥86.50</text>
|
||||
</view>
|
||||
|
||||
<!-- 时间选择标签 -->
|
||||
<view class="time-tabs">
|
||||
<text v-for="(item ,index) in timeList" :key="index" @click="changeTab(index)"
|
||||
:class="{ 'active':currentTime==index }" class="tab-item">{{item}}</text>
|
||||
</view>
|
||||
<text class="month-total">本月累计¥1,240.00</text>
|
||||
</view>
|
||||
|
||||
<!-- 收入构成区域 -->
|
||||
<view class="income-composition">
|
||||
<!-- 饼图占位区域 -->
|
||||
<view class="pie-chart-placeholder">
|
||||
<view id="cahrt" class="pie-chart">
|
||||
<!-- 黑边白底的饼图占位 -->
|
||||
</view>
|
||||
<view class="chart-legend">
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot blue"></view>
|
||||
<text class="legend-text">配送费¥60.50</text>
|
||||
</view>
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot orange"></view>
|
||||
<text class="legend-text">冲单奖¥20.00</text>
|
||||
</view>
|
||||
<view class="legend-item">
|
||||
<view class="legend-dot green"></view>
|
||||
<text class="legend-text">恶劣天气补贴¥6.00</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 钱包区域 -->
|
||||
<view class="wallet-section">
|
||||
<view class="wallet-header">
|
||||
<text class="wallet-title">钱包余额</text>
|
||||
<text class="wallet-amount">¥86.50</text>
|
||||
</view>
|
||||
<u-button class="withdraw-button" @click="Service.GoPage('/pages/order/withdraw')" type="primary">立即提现</u-button>
|
||||
<text class="withdraw-tip">提现到账时间: T+1工作日</text>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细区域 -->
|
||||
<view class="detail-header">
|
||||
<text class="detail-title">收入明细</text>
|
||||
</view>
|
||||
<view class="detail-list" @click="Service.GoPage('/pages/order/incomeDetail')" v-for="(item, index) in 3"
|
||||
:key="index">
|
||||
<view class="detail-content">
|
||||
<view class="icon-placeholder">
|
||||
<image :src="Service.GetIconImg('/static/index/income/order.png')"
|
||||
style="width: 55rpx; height: 55rpx;" mode=""></image>
|
||||
</view>
|
||||
<view class="detail-info">
|
||||
<text class="order-id">订单 MT20251020123456</text>
|
||||
<text class="order-time">10-20 18:35</text>
|
||||
</view>
|
||||
<text class="order-amount">+¥5.50</text>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100vw; height: 100rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
let loading = ref(true)
|
||||
|
||||
let timeList = ref([
|
||||
'今日',
|
||||
'本周',
|
||||
'本月'
|
||||
])
|
||||
|
||||
let currentTime = ref(0)
|
||||
|
||||
let status = ref('nomore')
|
||||
|
||||
let test = ref(10)
|
||||
|
||||
let option = ref({
|
||||
tooltip: {
|
||||
'show': false
|
||||
},
|
||||
legend: {
|
||||
'show': false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: true,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: test.value, name: "配送奖", itemStyle: { color: '#1890FF' } },
|
||||
{ value: 735, name: "冲单奖", itemStyle: { color: '#52C41A' } },
|
||||
{ value: 580, name: "恶劣天气奖", itemStyle: { color: '#FF4D4F' } }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
setTimeout(() => {
|
||||
draw()
|
||||
}, 1000)
|
||||
}, 1000)
|
||||
})
|
||||
onMounted(() => {
|
||||
})
|
||||
|
||||
const draw = () => {
|
||||
let chartDom = ref(document.getElementById('cahrt'))
|
||||
let myChart = ref(echarts.init(chartDom.value))
|
||||
myChart.value.setOption(option.value)
|
||||
}
|
||||
|
||||
const changeTab = (index : number) => {
|
||||
currentTime.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.income-container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 收入概览区域 */
|
||||
.income-overview {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.income-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 时间标签 */
|
||||
.time-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-right: 40rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #1890ff;
|
||||
border-bottom: 3rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.month-total {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 收入构成区域 */
|
||||
.income-composition {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 饼图占位 */
|
||||
.pie-chart-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.chart-legend {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.legend-dot.blue {
|
||||
background-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
.legend-dot.orange {
|
||||
background-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.legend-dot.green {
|
||||
background-color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 钱包区域 */
|
||||
.wallet-section {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wallet-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.withdraw-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.withdraw-tip {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 收入明细区域 */
|
||||
.income-detail {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
.detail-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-list {
|
||||
margin: 15rpx 0 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 图标占位符 - 黑边白底 */
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 没有更多记录 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 收入概览骨架屏 */
|
||||
.skeleton-income-title {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-income-amount {
|
||||
width: 200rpx;
|
||||
height: 50rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-time-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
width: 80rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-month-total {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
/* 收入构成骨架屏 */
|
||||
.skeleton-pie-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-pie-chart {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 50%;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-legend-list {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-legend-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-legend-text {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
/* 钱包区域骨架屏 */
|
||||
.skeleton-wallet-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-wallet-title {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-wallet-amount {
|
||||
width: 150rpx;
|
||||
height: 40rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-withdraw-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 40rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-withdraw-tip {
|
||||
width: 300rpx;
|
||||
height: 24rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* 收入明细骨架屏 */
|
||||
.skeleton-detail-title {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-detail-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-detail-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-order-id {
|
||||
width: 300rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-time {
|
||||
width: 200rpx;
|
||||
height: 26rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-amount {
|
||||
width: 100rpx;
|
||||
height: 36rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-loading .skeleton-income-title::after,
|
||||
.skeleton-loading .skeleton-income-amount::after,
|
||||
.skeleton-loading .skeleton-tab-item::after,
|
||||
.skeleton-loading .skeleton-month-total::after,
|
||||
.skeleton-loading .skeleton-pie-chart::after,
|
||||
.skeleton-loading .skeleton-legend-dot::after,
|
||||
.skeleton-loading .skeleton-legend-text::after,
|
||||
.skeleton-loading .skeleton-wallet-title::after,
|
||||
.skeleton-loading .skeleton-wallet-amount::after,
|
||||
.skeleton-loading .skeleton-withdraw-button::after,
|
||||
.skeleton-loading .skeleton-withdraw-tip::after,
|
||||
.skeleton-loading .skeleton-detail-title::after,
|
||||
.skeleton-loading .skeleton-icon-placeholder::after,
|
||||
.skeleton-loading .skeleton-order-id::after,
|
||||
.skeleton-loading .skeleton-order-time::after,
|
||||
.skeleton-loading .skeleton-order-amount::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,445 @@
|
||||
<template>
|
||||
|
||||
<view v-if="loading" class="">
|
||||
<view class="tab-bar-skeleton">
|
||||
<view class="skeleton-slot skeleton-tab-item"></view>
|
||||
<view class="skeleton-slot skeleton-tab-item"></view>
|
||||
</view>
|
||||
<view class="skeleton-container">
|
||||
<view class="skeleton-order-item" v-for="index in 3" :key="'skeleton-' + index">
|
||||
<!-- 订单头部骨架 -->
|
||||
<view class="skeleton-header">
|
||||
<view class="skeleton-slot skeleton-order-number"></view>
|
||||
<view class="skeleton-slot skeleton-status-badge"></view>
|
||||
</view>
|
||||
|
||||
<!-- 异常类型骨架 -->
|
||||
<view class="skeleton-slot skeleton-type"></view>
|
||||
|
||||
<!-- 异常描述骨架 -->
|
||||
<view class="skeleton-slot skeleton-description"></view>
|
||||
|
||||
<!-- 底部信息骨架 -->
|
||||
<view class="skeleton-footer">
|
||||
<view class="skeleton-slot skeleton-time"></view>
|
||||
<view class="skeleton-actions">
|
||||
<view class="skeleton-slot skeleton-btn"></view>
|
||||
<view class="skeleton-slot skeleton-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; display: flex; justify-content: center; ">
|
||||
<view class="skeleton-slot " style="width: 160rpx; height: 30rpx; "></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="abnormal-orders-page">
|
||||
<!-- 选项卡 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
|
||||
<text class="tab-text" :class="{ active: activeTab === 0 }">待处理</text>
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
|
||||
<text class="tab-text" :class="{ active: activeTab === 1 }">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<view class="order-list">
|
||||
<view class="order-item" v-for="(orderItem,orederIndex) in dataList" :key="orederIndex">
|
||||
<!-- 订单头部 -->
|
||||
<view class="order-header">
|
||||
<text class="order-number">订单号: {{ orderItem.orderId}}</text>
|
||||
<view class="order-status pending">
|
||||
<text class="status-text">{{ orderItem.status===0?'待处理':'已处理' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单内容 -->
|
||||
<view class="">
|
||||
<text class="abnormal-type">{{orderItem.type }}</text>
|
||||
<text class="abnormal-description">{{ orderItem.remark }}</text>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<text class="order-time"
|
||||
style="font-size: 26rpx; color: #666;">{{ Service.formatDate(orderItem.addTime,1) }}</text>
|
||||
<!-- 操作按钮 -->
|
||||
<view class="order-actions">
|
||||
<text @click="Service.GoPage('/pages/my/abnormalDetail?orderId='+orderItem.orderId)"
|
||||
class="action-btn detail-btn">查看详情</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, computed } from 'vue';
|
||||
import { Service } from "@/Service/Service"
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
|
||||
let loading = ref(true)
|
||||
// 响应式数据
|
||||
const activeTab = ref(0);
|
||||
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
let dataList = ref<Array<any>>([])
|
||||
onLoad(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
dataList.value = []
|
||||
page.value = 1
|
||||
status.value = 'loadmore'
|
||||
getList()
|
||||
}
|
||||
|
||||
const getList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderOrderServiceList(activeTab.value, page.value).then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
dataList.value = [...dataList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 切换选项卡
|
||||
const switchTab = (tab : any) => {
|
||||
activeTab.value = tab;
|
||||
getData()
|
||||
};
|
||||
|
||||
|
||||
// 重新上报
|
||||
const reportAgain = (orderNo : string) => {
|
||||
uni.showModal({
|
||||
title: '重新上报',
|
||||
content: '确定要重新上报此订单异常吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 模拟重新上报
|
||||
uni.showToast({
|
||||
title: '已提交重新上报申请',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 页面基础样式 */
|
||||
.abnormal-orders-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
padding: 0 30rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-left,
|
||||
.nav-right {
|
||||
width: 60rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-center {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 选项卡 */
|
||||
.tab-bar {
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 50rpx;
|
||||
height: 6rpx;
|
||||
background-color: #1890ff;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tab-text.active {
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 订单列表 */
|
||||
.order-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 订单头部 */
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.order-number {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.order-status.pending {
|
||||
background-color: #fff2e8;
|
||||
}
|
||||
|
||||
.order-status.processed {
|
||||
background-color: #f6ffed;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.order-status.pending .status-text {
|
||||
color: #fa5151;
|
||||
}
|
||||
|
||||
.order-status.processed .status-text {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.abnormal-type {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.abnormal-description {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.order-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 26rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
.detail-btn {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.report-btn {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 - 纯CSS实现 */
|
||||
/* 选项卡骨架屏 */
|
||||
.tab-bar-skeleton {
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
height: 36rpx;
|
||||
align-self: center;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
|
||||
/* 订单列表骨架屏 */
|
||||
.skeleton-container {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
/* 订单项骨架 */
|
||||
.skeleton-order-item {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 订单头部布局 */
|
||||
.skeleton-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 底部布局 */
|
||||
.skeleton-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 操作按钮区域 */
|
||||
.skeleton-actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
/* 通用骨架占位元素 */
|
||||
.skeleton-slot {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
/* 特定元素尺寸 */
|
||||
.skeleton-order-number {
|
||||
width: 60%;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.skeleton-status-badge {
|
||||
width: 120rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-type {
|
||||
width: 30%;
|
||||
height: 36rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-description {
|
||||
width: 100%;
|
||||
height: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-time {
|
||||
width: 25%;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"id": "uni-calendar",
|
||||
"displayName": "uni-calendar 日历",
|
||||
"version": "1.4.12",
|
||||
"description": "日历组件",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"日历",
|
||||
"",
|
||||
"打卡",
|
||||
"日历选择"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 456 B |
@@ -0,0 +1,97 @@
|
||||
# qf-image-cropper
|
||||
## 图片裁剪插件
|
||||
uniapp微信小程序图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。
|
||||
|
||||
### 平台支持:
|
||||
1. 支持微信小程序:移动端、PC端、开发者工具
|
||||
2. 支持H5平台(2.1.0版本起)
|
||||
3. 支持APP平台(2.1.5版本起):Android、IOS
|
||||
4. 其他平台暂未测试兼容性未知
|
||||
|
||||
### 支持功能:
|
||||
1. 自定义裁剪尺寸
|
||||
2. 定点等比例缩放:移动端以双指触摸中心点为缩放中心点,PC端以鼠标所在点为缩放中心点
|
||||
3. 自由拖动:支持限制滑出边界,也支持回弹效果(滑动时可滑出边界,释放时回弹到边界)
|
||||
4. 图片翻转:在裁剪尺寸非 1:1 的情况下,翻转时宽高无法铺满裁剪区域时,图片会自动放大到合适尺寸
|
||||
5. 裁剪生成新图片
|
||||
6. 本地选择图片
|
||||
7. 可定制样式:可自由选择是否渲染裁剪边框、可伸缩裁剪顶角、参考线
|
||||
8. 裁剪圆角图片:圆形、圆角矩形
|
||||
|
||||
### 属性说明
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
|:---|:---|:---|:---|
|
||||
| src | String | | 图片资源地址 |
|
||||
| width | Number | 300 | 裁剪宽度 |
|
||||
| height | Number | 300 | 裁剪高度 |
|
||||
| showBorder | Boolean | true | 是否绘制裁剪区域边框 |
|
||||
| showGrid | Boolean | true | 是否绘制裁剪区域网格参考线 |
|
||||
| showAngle | Boolean | true | 是否展示四个支持伸缩的角 |
|
||||
| areaScale | Number | 0.3 | 裁剪区域最小缩放倍数 |
|
||||
| minScale | Number | 1 | 图片最小缩放倍数 |
|
||||
| maxScale | Number | 5 | 图片最大缩放倍数 |
|
||||
| checkRange | Boolean | true | 检查图片位置是否超出裁剪边界,如果超出则会矫正位置 |
|
||||
| backgroundColor | String | | 生成图片背景色:如果裁剪区域没有完全包含在图片中时,不设置该属性则生成图片存在一定的透明块 |
|
||||
| bounce | Boolean | true | 是否有回弹效果:当 checkRange 为 true 时有效,拖动时可以拖出边界,释放时会弹回边界 |
|
||||
| rotatable | Boolean | true | 是否支持翻转 |
|
||||
| reverseRotatable | Boolean | false | 是否支持逆向翻转 |
|
||||
| choosable | Boolean | true | 是否支持从本地选择素材 |
|
||||
| gpu | Boolean | false | 是否开启硬件加速,图片缩放过程中如果出现元素的“留影”或“重影”效果,可通过该方式解决或减轻这一问题 |
|
||||
| angleSize | Number | 20 | 四个角尺寸,单位px |
|
||||
| angleBorderWidth | Number | 2 | 四个角边框宽度,单位px |
|
||||
| zIndex | Number/String | | 调整组件层级 |
|
||||
| radius | Number | | 裁剪图片圆角半径,单位px |
|
||||
| fileType | String | png | 生成文件的类型,只支持 'jpg' 或 'png'。默认为 'png' |
|
||||
| delay | Number | 1000 | 图片从绘制到生成所需时间,单位ms<br>微信小程序平台使用 `Canvas 2D` 绘制时有效<br>如绘制大图或出现裁剪图片空白等情况应适当调大该值,因 `Canvas 2d` 采用同步绘制,需自己把控绘制完成时间 |
|
||||
| navigation | Boolean | true | 页面是否是原生标题栏:<br>H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 `"navigationStyle": "custom"` 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差。<br>注:因H5平台的窗口高度是包含标题栏的,而屏幕触摸点的坐标是不包含的 |
|
||||
| @crop | EventHandle | | 剪裁完成后触发,event = { tempFilePath }。在H5平台下,tempFilePath 为 base64 |
|
||||
|
||||
### 基本用法
|
||||
```
|
||||
<template>
|
||||
<div>
|
||||
<qf-image-cropper :width="500" :height="500" :radius="30" @crop="handleCrop"></qf-image-cropper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QfImageCropper from '@/components/qf-image-cropper/qf-image-cropper.vue';
|
||||
export default {
|
||||
components: {
|
||||
QfImageCropper
|
||||
},
|
||||
methods: {
|
||||
handleCrop(e) {
|
||||
uni.previewImage({
|
||||
urls: [e.tempFilePath],
|
||||
current: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
通过ref组件实例可在进入页面后直接打开相册选择图片
|
||||
```
|
||||
mounted() {
|
||||
this.$refs.qfImageCropper.chooseImage({ sourceType: ['album'] });
|
||||
}
|
||||
```
|
||||
### 使用说明
|
||||
1.建议在`pages.json`中将引用插件的页面添加一下配置禁止下拉刷新和禁止页面滑动,防止出现性能或页面抖动等问题。
|
||||
```
|
||||
{
|
||||
"enablePullDownRefresh": false,
|
||||
"disableScroll": true
|
||||
}
|
||||
```
|
||||
2.建议使用本插件不要设置过大宽高的目标图片尺寸,建议1365x1365以内,否则可能会导致如下问题:
|
||||
```
|
||||
1.界面卡顿,内存占用过高
|
||||
2.生成图片失真(模糊)
|
||||
3.确定裁剪后一直显示 `裁剪中...`,该问题是由 `uni.canvasToTempFilePath` 无法回调导致,不同平台不同设备限制可能有所不同。
|
||||
```
|
||||
3.如裁剪后的图片存在偏移的问题,请检查是否受自己项目中父组件或全局样式影响。
|
||||
4.src属性设置网络图片时,图片资源必须是能触发 `getImageInfo` API 的 success 回调才可用于插件裁剪。因此小程序平台获取网络图片信息需先配置download域名白名单才能生效。
|
||||
5.如果组件无法正常渲染且使用了 `v-if` 时,可尝试将 `v-if` 替换为 `v-show`
|
||||
6.如果App端导入组件后无法正常渲染,请尝试重新运行
|
||||
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"easycom": {
|
||||
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
|
||||
"custom": {
|
||||
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
|
||||
{
|
||||
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "门店运营",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/task",
|
||||
"style": {
|
||||
"navigationBarTitleText": "任务",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/income",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的收入",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/user",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "v派商家",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"backgroundColor": "#000"
|
||||
},
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages/order",
|
||||
"pages": [
|
||||
{
|
||||
"path": "orderDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "项目中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "navigation",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "导航",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "abnormal",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "上报异常",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "grabOrder",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "订单详情"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
"tabBar": {
|
||||
"color": "#000",
|
||||
"selectedColor": "#000",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"list": [{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/tab/home.png",
|
||||
"selectedIconPath": "/static/tab/homed.png",
|
||||
"text": "主页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/task",
|
||||
"iconPath": "static/tab/task.png",
|
||||
"selectedIconPath": "static/tab/tasked.png",
|
||||
"text": "任务"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/income",
|
||||
"iconPath": "static/tab/income.png",
|
||||
"selectedIconPath": "static/tab/incomed.png",
|
||||
"text": "收入"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/user",
|
||||
"iconPath": "static/tab/user.png",
|
||||
"selectedIconPath": "static/tab/usered.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
3912
.svn/pristine/12/12e3d1ab0fd1e1053a2010ad29a968c5bbb700a4.svn-base
Normal file
@@ -0,0 +1,380 @@
|
||||
<template>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view class="rider-home">
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥86.50</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">5单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">进行中</text>
|
||||
<text class="stat-value ongoing">6单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button type="primary" shape="circle" size="default" class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ userStatus === '已上线' ? '接单中 · 点击暂停' : '点击开始接单' }}</up-button>
|
||||
</view>
|
||||
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style="padding: 0 30rpx;">
|
||||
<view @click="gopage()" v-for="(orderItem,orderIndex) in 3 " :key="orderIndex" class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
|
||||
<view class="high-price-tag" :style="{'border':activeTab==0?'1rpx solid #52C41A':'1rpx solid #FAAD14','color':activeTab==0?'#52C41A':'#FAAD14' }" style="background-color: #fff;" >
|
||||
<text class="high-price-text">{{activeTab==0?'待取单':'配送中'}}</text>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">老北京炸酱面</text>
|
||||
<text v-if="activeTab==0" class="distance">500m</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text">北京市朝阳区三里屯SOHO</text>
|
||||
<text v-if="activeTab!==0" class="address-text">共3件商品</text>
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<view class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
<view class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==0" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">A121</text>
|
||||
</view>
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text class="address-text">据您1.2km</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" color="#FF9500" size="24rpx" />
|
||||
<text class="time-text" :style="{'color':activeTab==0?'#FAAD14':'#FF0000'}" >{{activeTab==0?'12:30 前取餐':'12:30 前送达'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
<up-button type="primary" :color="activeTab==0?'#1890FF':'#52C41A'" size="large" class="grab-btn">{{ activeTab==0?'我已取餐':'确认送达'}}</up-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
|
||||
let userStatus = ref('已下线')
|
||||
let status = ref('nomore')
|
||||
const tabs = ['待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
isLoading.value = false
|
||||
}, 1500)
|
||||
})
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
}
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
userStatus.value = userStatus.value === '已上线' ? '已下线' : '已上线';
|
||||
};
|
||||
|
||||
// 页面跳转
|
||||
const gopage = () => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder')
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,703 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style=" z-index: 100; padding:50rpx 20rpx 18rpx; box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: #fff; display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="">
|
||||
订单详情
|
||||
</view>
|
||||
<view class="" @click="Service.GoPage('/pages/my/myKF')" style="color: var(--nav-banbacor);">
|
||||
<image :src="Service.GetIconImg('/static/index/order/message.png')" style="width: 32rpx; height: 32rpx; "
|
||||
mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 88rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 骨架屏订单状态 -->
|
||||
<view class="skeleton-status"></view>
|
||||
|
||||
<!-- 骨架屏订单基本信息 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-half"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-third"></view>
|
||||
<view class="skeleton-info-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏物品清单 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;">
|
||||
<view class="" style="background-color: #e6e6e6; width: 60%;height: 40rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-row" v-for="(item,index) in 3" :key="index">
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;">
|
||||
<view class="" style="background-color: #e6e6e6; width: 90%;height: 40rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-list-status"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏地图区域 -->
|
||||
<view class="skeleton-map"></view>
|
||||
|
||||
<!-- 骨架屏取餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-code"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏送餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-remark"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏底部按钮 -->
|
||||
<view class="skeleton-bottom">
|
||||
<view class="skeleton-bottom-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单状态 -->
|
||||
<view class="order-status"
|
||||
:style="{ 'background-color':orderStatus==0?'#E6F7FF':(orderStatus==1?'#FFFBE6':'#FFF2F0') }">
|
||||
<text :style="{ 'color':orderStatus==0?'#1890FF':(orderStatus==1?'#FAAD14':'#FF4D4F') }"
|
||||
style="font-size: 34rpx; font-weight: 600;">待取餐 · 请尽快到店取餐</text>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="info-item">
|
||||
<view class="label" style="font-weight: 700; font-size: 30rpx;">
|
||||
{{ orderInfo.distribution=='预约订单'?'预计'+orderInfo.makeTime.split(' ')[1]+'送达':orderInfo.makeTime }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">{{ orderId }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item" style="justify-content: space-between;">
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="16" class="clock-icon"></u-icon>
|
||||
{{ Service.formatDate(orderInfo.addTime,1) }} 下单
|
||||
</view>
|
||||
<view class="">
|
||||
<button @click="Service.GoPage('/pages/order/abnormal?orderId='+orderInfo.orderId)" class=""
|
||||
style="padding: 0rpx 30rpx; height: 60rpx; font-size: 24rpx; border-radius: 40rpx; background-color: red; color: #fff; ">提交异常</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
数量
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
金额
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'110rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in JSON.parse(orderInfo.detail) " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
{{goodsItem.goodsName}}
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×{{ goodsItem.count }}
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥{{ goodsItem.count*goodsItem.price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class=""
|
||||
style="display: flex; align-items: center;justify-content: space-between; margin-top: 10rpx; ">
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥{{ Number(orderInfo.postage).toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-if="JSON.parse(orderInfo.detail).length>2" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">取餐地址</text>
|
||||
<view class="address-content">
|
||||
<view class="store-name">{{ storeInfo.name }}</view>
|
||||
<text class="address">{{ storeInfo.city }}{{storeInfo.region }}{{ storeInfo.address }}</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button @click="call(storeInfo.phone)" icon="phone" type="primary" shape="circle"
|
||||
text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view class="pickup-code">
|
||||
<text class="code-label">取餐号:</text>
|
||||
<text class="code-value">A123</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 送餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">送餐地址</text>
|
||||
<view class="address-content">
|
||||
<text class="user-name">{{ JSON.parse(orderInfo.address).realName }}</text>
|
||||
<text class="address">{{ JSON.parse(orderInfo.address).address }}</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button @click="call(JSON.parse(orderInfo.address).phone)" icon="phone" type="primary"
|
||||
shape="circle" text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view v-if="orderInfo.remark" class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">{{ orderInfo.remark }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action" style="display: flex; justify-content: space-between;'">
|
||||
<up-button @click="upGoods()" color="var(--nav-vice)" class="confirm-btn">{{type==1?'我已取货':'订单完成'}}</up-button>
|
||||
<view class="" style="width: 40rpx;">
|
||||
|
||||
</view>
|
||||
<up-button @click="Service.GoPage('/pages/order/orderChat?orderId='+orderId)" color="#6868ee" class="confirm-btn">联系商家</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
let deliveryTime = ref('')
|
||||
|
||||
let orderInfo = ref<any>({})
|
||||
let storeInfo = ref<any>({})
|
||||
let storeLocation = ref<any>({})
|
||||
|
||||
let type = ref(1)
|
||||
let orderId = ref('')
|
||||
onLoad((data : any) => {
|
||||
orderId.value = data.orderId
|
||||
type.value = data.type
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
deliveryTime.value = res.data.deliveryTime
|
||||
orderInfo.value = res.data.orderInfo
|
||||
storeInfo.value = res.data.storeInfo
|
||||
storeLocation.value = res.data.storeLocation
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const call = (phone : string) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone,
|
||||
fail(e) {
|
||||
console.log( e);
|
||||
},
|
||||
success(e) {
|
||||
console.log('1111', e);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const upGoods = () => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId.value, type.value).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('取餐成功!')
|
||||
setTimeout(() => {
|
||||
Service.GoPageBack()
|
||||
}, 1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏导航栏 */
|
||||
.skeleton-nav {
|
||||
height: 88rpx;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.skeleton-nav-item {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-nav-title {
|
||||
width: 180rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单状态 */
|
||||
.skeleton-status {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-status::after {
|
||||
content: '';
|
||||
width: 350rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单基本信息 */
|
||||
.skeleton-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-info-half {
|
||||
width: 45%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-right {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-third {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-btn {
|
||||
width: 20%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 列表状态 */
|
||||
.skeleton-list-status {
|
||||
height: 60rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-list-status::after {
|
||||
content: '';
|
||||
width: 200rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏地图区域 */
|
||||
.skeleton-map {
|
||||
margin: 20rpx;
|
||||
height: 400rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-map::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, transparent 25%, rgba(255, 255, 255, 0.2) 25%, rgba(255, 255, 255, 0.2) 50%, transparent 50%, transparent 75%, rgba(255, 255, 255, 0.2) 75%, rgba(255, 255, 255, 0.2));
|
||||
background-size: 100rpx 100rpx;
|
||||
animation: shimmer 1.5s infinite linear;
|
||||
}
|
||||
|
||||
/* 骨架屏地址区域 */
|
||||
.skeleton-address {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-store-name {
|
||||
width: 70%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-address-line {
|
||||
width: 90%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
height: 70rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 35rpx;
|
||||
margin: 20rpx 0;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-code {
|
||||
width: 50%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-remark {
|
||||
width: 80%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏底部按钮 */
|
||||
.skeleton-bottom {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-bottom-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏滑动动画 */
|
||||
@keyframes shimmer-slide {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* end */
|
||||
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin: 10rpx 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,506 @@
|
||||
<template>
|
||||
|
||||
<view class="skeleton-container" v-if="isLoading">
|
||||
<!-- 顶部提示栏骨架 -->
|
||||
<view class="skeleton-top-tip"></view>
|
||||
|
||||
<!-- 身份信息区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-upload-item"></view>
|
||||
<view class="skeleton-upload-item"></view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 协议勾选骨架 -->
|
||||
<view class="skeleton-agreement"></view>
|
||||
|
||||
<!-- 提交按钮骨架 -->
|
||||
<view class="skeleton-submit"></view>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="real-name-auth-container">
|
||||
<!-- 顶部提示栏 -->
|
||||
<view class="top-tip">
|
||||
<text class="tip-text">修改实名认证将重新审核,大约1~2工作日</text>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-content">
|
||||
<!-- 身份信息区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份信息</view>
|
||||
|
||||
<!-- 姓名输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">姓名</view>
|
||||
<u-input v-model="formData.nick" placeholder="请输入身份证姓名" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" />
|
||||
</view>
|
||||
|
||||
<!-- 身份证号输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">身份证号</view>
|
||||
<u-input v-model="formData.idenNumber" placeholder="请输入18位身份证号" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" maxlength="18" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份证照片</view>
|
||||
|
||||
<!-- 上传身份证正面 -->
|
||||
<view class="upload-item">
|
||||
<view @click="uploadFImg(1)" class="upload-area bordered-area">
|
||||
<view v-if="!formData.identityA" class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证正面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-else class="uploaded-placeholder">
|
||||
<image :src="Service.GetMateUrlByImg(formData.identityA)" style="width: 100%; height: 100%;" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上传身份证反面 -->
|
||||
<view class="upload-item">
|
||||
<view @click="uploadFImg(2)" class="upload-area bordered-area">
|
||||
<view v-if="!formData.identityB" class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证反面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-else class="uploaded-placeholder">
|
||||
<image :src="Service.GetMateUrlByImg(formData.identityB)" style="width: 100%; height: 100%;" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 协议勾选 -->
|
||||
<view class="agreement-section">
|
||||
<u-checkbox v-model="formData.agreed" shape="circle" class="checkbox" />
|
||||
<text class="agreement-text">我已阅读并同意</text>
|
||||
<text class="agreement-link" @click="handleAgreementClick">《骑手实名认证协议》</text>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<u-button @click="save()" type="primary" class="submit-btn" size="large">
|
||||
提交认证
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, computed } from 'vue';
|
||||
import { CNRiderDataService , Service } from "@/Service/CN/CNRiderDataService"
|
||||
|
||||
let isLoading = ref(true)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref<any>({});
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderInfo().then(res => {
|
||||
isLoading.value = false
|
||||
if(res.data){
|
||||
formData.value=res.data.riderInfo
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const uploadFImg = (index:number) => {
|
||||
uni.chooseImage({
|
||||
count: 1, // 最多选择3张图片
|
||||
sizeType: ['original', 'compressed'], // 支持原图和压缩图
|
||||
sourceType: ['album', 'camera'], // 可从相册选择或使用相机拍照
|
||||
success: function (res) {
|
||||
let path = res.tempFiles[0].path
|
||||
Service.uploadH5(path, 'Avatar', data => {
|
||||
if(index==1){
|
||||
formData.value.identityA=data
|
||||
}else{
|
||||
formData.value.identityB=data
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error('选择失败:', err.errMsg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 处理协议点击
|
||||
const handleAgreementClick = () => {
|
||||
// 打开协议详情
|
||||
console.log('打开协议详情');
|
||||
};
|
||||
|
||||
|
||||
const save=()=>{
|
||||
// if(!formData.value.agreed){
|
||||
// Service.Msg('请同意骑手实名认证协议')
|
||||
// return
|
||||
// }
|
||||
if(!formData.value.nick){
|
||||
Service.Msg('请输入姓名')
|
||||
return
|
||||
}
|
||||
if(!formData.value.idenNumber){
|
||||
Service.Msg('请输入身份证号')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
CNRiderDataService.UpdateRiderIdentity(formData.value.nick,formData.value.idenNumber,formData.value.identityA,formData.value.identityB).then(res=>{
|
||||
if(res.data){
|
||||
Service.Msg('上传成功!')
|
||||
}else{
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-top-tip {
|
||||
height: 70rpx;
|
||||
width: 100%;
|
||||
background-color: #e6f7ff;
|
||||
margin: 20rpx 0;
|
||||
border-radius: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
height: 32rpx;
|
||||
width: 160rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.skeleton-label {
|
||||
height: 28rpx;
|
||||
width: 120rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-input {
|
||||
height: 28rpx;
|
||||
width: calc(100% - 140rpx);
|
||||
background-color: #e6e6e6;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-upload-item {
|
||||
height: 200rpx;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 2rpx solid #000;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-face-area {
|
||||
height: 240rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-face-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-face-text {
|
||||
height: 28rpx;
|
||||
width: 200rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-agreement {
|
||||
height: 30rpx;
|
||||
width: 60%;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-submit {
|
||||
height: 92rpx;
|
||||
width: 100%;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 46rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.top-tip {
|
||||
background-color: #E6F7FF;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #1890ff;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 120rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
height: 350rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bordered-area {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 60rpx;
|
||||
color: #1890ff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.uploaded-placeholder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.face-verify-area {
|
||||
background-color: #fff;
|
||||
height: 240rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.face-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6f7ff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.face-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.agreement-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
font-size: 26rpx;
|
||||
color: #1890ff;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
margin-top: 60rpx;
|
||||
padding: 0 0rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 92rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 46rpx;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
background-color: #a0cfff;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,13 @@
|
||||
// import { createPinia, defineStore } from "pinia";
|
||||
// import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||
// export class StoreAssist{
|
||||
// private pinia:any=createPinia();
|
||||
// constructor() {
|
||||
// this.pinia.use(piniaPluginPersistedstate);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
<template>
|
||||
|
||||
<view v-if="loading" class="">
|
||||
<view class="tab-bar-skeleton">
|
||||
<view class="skeleton-slot skeleton-tab-item"></view>
|
||||
<view class="skeleton-slot skeleton-tab-item"></view>
|
||||
</view>
|
||||
<view class="skeleton-container">
|
||||
<view class="skeleton-order-item" v-for="index in 3" :key="'skeleton-' + index">
|
||||
<!-- 订单头部骨架 -->
|
||||
<view class="skeleton-header">
|
||||
<view class="skeleton-slot skeleton-order-number"></view>
|
||||
<view class="skeleton-slot skeleton-status-badge"></view>
|
||||
</view>
|
||||
|
||||
<!-- 异常类型骨架 -->
|
||||
<view class="skeleton-slot skeleton-type"></view>
|
||||
|
||||
<!-- 异常描述骨架 -->
|
||||
<view class="skeleton-slot skeleton-description"></view>
|
||||
|
||||
<!-- 底部信息骨架 -->
|
||||
<view class="skeleton-footer">
|
||||
<view class="skeleton-slot skeleton-time"></view>
|
||||
<view class="skeleton-actions">
|
||||
<view class="skeleton-slot skeleton-btn"></view>
|
||||
<view class="skeleton-slot skeleton-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; display: flex; justify-content: center; " >
|
||||
<view class="skeleton-slot " style="width: 160rpx; height: 30rpx; " ></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="abnormal-orders-page">
|
||||
<!-- 选项卡 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item" :class="{ active: activeTab === 'pending' }" @click="switchTab('pending')">
|
||||
<text class="tab-text" :class="{ active: activeTab === 'pending' }">待处理</text>
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 'processed' }" @click="switchTab('processed')">
|
||||
<text class="tab-text" :class="{ active: activeTab === 'processed' }">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<view class="order-list">
|
||||
<view class="order-item" v-for="(orderItem,orederIndex) in 3" :key="orederIndex">
|
||||
<!-- 订单头部 -->
|
||||
<view class="order-header">
|
||||
<text class="order-number">订单号: MT20251017123456</text>
|
||||
<view class="order-status pending">
|
||||
<text class="status-text">待处理</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单内容 -->
|
||||
<view class="">
|
||||
<text class="abnormal-type">配送超时</text>
|
||||
<text class="abnormal-description">订单配送时间超过预估时间25分钟</text>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<text class="order-time">今天14:30</text>
|
||||
<!-- 操作按钮 -->
|
||||
<view class="order-actions">
|
||||
<text @click="Service.GoPage('/pages/my/abnormalDetail')" class="action-btn detail-btn">查看详情</text>
|
||||
<text @click="Service.GoPage('/pages/order/abnormal')" class="action-btn report-btn">
|
||||
重新上报
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, computed } from 'vue';
|
||||
import { Service } from "@/Service/Service"
|
||||
|
||||
let loading = ref(true)
|
||||
// 响应式数据
|
||||
const activeTab = ref<'pending' | 'processed'>('pending');
|
||||
|
||||
let status=ref('nomore')
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(()=>{
|
||||
loading.value=false
|
||||
},1000)
|
||||
})
|
||||
|
||||
// 切换选项卡
|
||||
const switchTab = (tab : 'pending' | 'processed') => {
|
||||
activeTab.value = tab;
|
||||
};
|
||||
|
||||
|
||||
// 重新上报
|
||||
const reportAgain = (orderNo : string) => {
|
||||
uni.showModal({
|
||||
title: '重新上报',
|
||||
content: '确定要重新上报此订单异常吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 模拟重新上报
|
||||
uni.showToast({
|
||||
title: '已提交重新上报申请',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 页面基础样式 */
|
||||
.abnormal-orders-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
padding: 0 30rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-left,
|
||||
.nav-right {
|
||||
width: 60rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-center {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 选项卡 */
|
||||
.tab-bar {
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 50rpx;
|
||||
height: 6rpx;
|
||||
background-color: #1890ff;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tab-text.active {
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 订单列表 */
|
||||
.order-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 订单头部 */
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.order-number {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.order-status.pending {
|
||||
background-color: #fff2e8;
|
||||
}
|
||||
|
||||
.order-status.processed {
|
||||
background-color: #f6ffed;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.order-status.pending .status-text {
|
||||
color: #fa5151;
|
||||
}
|
||||
|
||||
.order-status.processed .status-text {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.abnormal-type {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.abnormal-description {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.order-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 26rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
.detail-btn {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.report-btn {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 - 纯CSS实现 */
|
||||
/* 选项卡骨架屏 */
|
||||
.tab-bar-skeleton {
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
height: 36rpx;
|
||||
align-self: center;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
|
||||
/* 订单列表骨架屏 */
|
||||
.skeleton-container {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
/* 订单项骨架 */
|
||||
.skeleton-order-item {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 订单头部布局 */
|
||||
.skeleton-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 底部布局 */
|
||||
.skeleton-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 操作按钮区域 */
|
||||
.skeleton-actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
/* 通用骨架占位元素 */
|
||||
.skeleton-slot {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
/* 特定元素尺寸 */
|
||||
.skeleton-order-number {
|
||||
width: 60%;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.skeleton-status-badge {
|
||||
width: 120rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-type {
|
||||
width: 30%;
|
||||
height: 36rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-description {
|
||||
width: 100%;
|
||||
height: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-time {
|
||||
width: 25%;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,261 @@
|
||||
{
|
||||
"easycom": {
|
||||
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
|
||||
"custom": {
|
||||
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
|
||||
{
|
||||
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "门店运营",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/task",
|
||||
"style": {
|
||||
"navigationBarTitleText": "任务",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/income",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的收入",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/user",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationBarBackgroundColor": "#36394D",
|
||||
"navigationStyle": "custom",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "v派商家",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"backgroundColor": "#000"
|
||||
},
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages/order",
|
||||
"pages": [
|
||||
{
|
||||
"path": "orderDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "项目中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "navigation",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "导航",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "abnormal",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "上报异常",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "grabOrder",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "订单详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "incomeDetail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "收入详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "withdraw",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "提现申请"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "finish",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "订单完成"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "upAbnormal",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "异常上报"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "orderMap",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单地图"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/my",
|
||||
"pages": [{
|
||||
"path" : "edit",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "编辑资料"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "statusContro",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "上线管理"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "myKF",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "联系客服",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "AbnormalList",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "异常订单"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "check",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "签到奖励"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "abnormalDetail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "异常详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "security",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "账号与安全"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "authentication",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "实名认证"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "login",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "登录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "noticeList",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "消息通知",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "setConnect",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "紧急联系人"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "evaluate",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "评价中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "completeData",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "完善信息"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "withDrowList",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "提现列表"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
"tabBar": {
|
||||
"color": "#000",
|
||||
"selectedColor": "#000",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"list": [{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/tab/home.png",
|
||||
"selectedIconPath": "/static/tab/homed.png",
|
||||
"text": "主页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/income",
|
||||
"iconPath": "static/tab/income.png",
|
||||
"selectedIconPath": "static/tab/incomed.png",
|
||||
"text": "收入"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/user",
|
||||
"iconPath": "static/tab/user.png",
|
||||
"selectedIconPath": "static/tab/usered.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export class UploadAssist {
|
||||
static Upload(url: string, path: string, fromData: any) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
uni.uploadFile({
|
||||
url: url, //仅为示例,非真实的接口地址
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
formData: fromData,
|
||||
success: (uploadFileRes) => {
|
||||
resolve(uploadFileRes);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
|
||||
},
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****腾讯云存储*****/
|
||||
class NvpTencentCosService {
|
||||
private static GetAuthorizationPath: string = '/TencentCos/GetAuthorization';
|
||||
/*****获取云存储配置*****/
|
||||
static GetAuthorization() {
|
||||
var result = Service.Request(this.GetAuthorizationPath, "GET", "");
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetUpLoadInfoPath: string = '/TencentCos/GetUpLoadInfo';
|
||||
/*****获取上传地址*****/
|
||||
static GetUpLoadInfo(code: string, fileName: string, desire: string) {
|
||||
var result = Service.Request(this.GetUpLoadInfoPath, "GET", { code, fileName, desire });
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
export {
|
||||
Service,
|
||||
NvpTencentCosService
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import {Service} from "@/Service/Service"
|
||||
export class EventHandler {
|
||||
//处理事件
|
||||
static Events(data: any) {
|
||||
var result = JSON.parse(data.data);
|
||||
if (result.code == 'msg') {
|
||||
this.ChatEnent(result);
|
||||
} else if (result.code == 'order') {
|
||||
uni.$emit('newOrder', data);
|
||||
}
|
||||
}
|
||||
|
||||
static ChatEnent(data: any) {
|
||||
console.log(data,'xxx')
|
||||
var eventName = `chat_${data.chanId}`;
|
||||
uni.$emit(eventName, data);
|
||||
}
|
||||
|
||||
static ChatUserEnent(data: any) {
|
||||
var eventUserName = `chatUser_${data.sendId}`;
|
||||
uni.$emit('UpdatePrivateMsg', data);
|
||||
uni.$emit(eventUserName, data);
|
||||
this.plusPush();
|
||||
}
|
||||
|
||||
static plusPush() {
|
||||
//#ifdef APP-PLUS
|
||||
if(!Service.getIsHede()){
|
||||
return
|
||||
}
|
||||
|
||||
let content = '您有一条新的消息~';
|
||||
let options = {
|
||||
cover: false,
|
||||
when: new Date(),
|
||||
title: '通知消息'
|
||||
};
|
||||
let body = {
|
||||
id: 'id',
|
||||
key: 'key'
|
||||
};
|
||||
let payload = JSON.stringify(body);
|
||||
plus.push.createMessage(content, payload, options);
|
||||
//#endif
|
||||
}
|
||||
|
||||
static SystemEnent(data: any) {
|
||||
let obj = JSON.parse(data.data);
|
||||
if (obj.code == 'Like' || obj.code == 'Aite' || obj.code == 'Comment' || obj.code == 'Notice') {
|
||||
uni.$emit('MegEvent', obj);
|
||||
} else if (obj.code == 'Off') {
|
||||
uni.$emit('ImComOff', 'user');
|
||||
} else if (obj.code == 'UpdateUserInfo') {
|
||||
uni.$emit('UpdateUserInfo');
|
||||
} else if (obj.code == 'Friend') {
|
||||
uni.$emit('Friend');
|
||||
}
|
||||
}
|
||||
|
||||
static ConnectBus() {
|
||||
uni.$emit('UpdateChat');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide, onError } from '@dcloudio/uni-app'
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
|
||||
// 全局定时器引用
|
||||
let globalTimer = null
|
||||
|
||||
// 每分钟要执行的方法
|
||||
const minuteTask = () => {
|
||||
console.log('每分钟执行一次的任务', new Date().toLocaleTimeString())
|
||||
}
|
||||
|
||||
// 启动全局定时器
|
||||
const startGlobalTimer = () => {
|
||||
if (globalTimer) {
|
||||
clearInterval(globalTimer)
|
||||
}
|
||||
|
||||
// 立即执行一次
|
||||
minuteTask()
|
||||
|
||||
// 设置每分钟执行一次(60000毫秒 = 1分钟)
|
||||
globalTimer = setInterval(() => {
|
||||
minuteTask()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
// 停止全局定时器
|
||||
const stopGlobalTimer = () => {
|
||||
if (globalTimer) {
|
||||
clearInterval(globalTimer)
|
||||
globalTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
onLaunch(() => {
|
||||
console.log('App Launch')
|
||||
// 应用启动时开始定时器
|
||||
startGlobalTimer()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
console.log('App Show')
|
||||
// 应用回到前台时重新开始定时器
|
||||
startGlobalTimer()
|
||||
})
|
||||
|
||||
onHide(() => {
|
||||
console.log('App Hide')
|
||||
// 应用进入后台时停止定时器,节省资源
|
||||
stopGlobalTimer()
|
||||
})
|
||||
|
||||
// Vue组件卸载时清理定时器
|
||||
onUnmounted(() => {
|
||||
stopGlobalTimer()
|
||||
})
|
||||
|
||||
// 全局错误处理
|
||||
onError((err) => {
|
||||
console.error('App Error:', err)
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "uview-plus/index.scss";
|
||||
@import "colorui/main.css";
|
||||
@import "colorui/icon.css";
|
||||
|
||||
page {
|
||||
--nav-mian: #1890FF; //全局颜色
|
||||
--nav-vice: #52C41A; //副颜色
|
||||
--nav-diluted: #FF4D4F; //次颜色
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,511 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 余额区域骨架屏 -->
|
||||
<view class="skeleton-balance-section">
|
||||
<div class="skeleton-balance-label"></div>
|
||||
<div class="skeleton-balance-amount"></div>
|
||||
<div class="skeleton-balance-current"></div>
|
||||
</view>
|
||||
|
||||
<!-- 账户选择区域骨架屏 -->
|
||||
<view class="skeleton-account-section">
|
||||
<div class="skeleton-section-title"></div>
|
||||
<div class="skeleton-account-item">
|
||||
<div class="skeleton-account-icon"></div>
|
||||
<div class="skeleton-account-name"></div>
|
||||
<div class="skeleton-account-radio"></div>
|
||||
</div>
|
||||
<div class="skeleton-account-item">
|
||||
<div class="skeleton-account-icon"></div>
|
||||
<div class="skeleton-account-name"></div>
|
||||
<div class="skeleton-account-radio"></div>
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息骨架屏 -->
|
||||
<view class="skeleton-tip-section">
|
||||
<div class="skeleton-tip-icon"></div>
|
||||
<div class="skeleton-tip-content">
|
||||
<div class="skeleton-tip-line"></div>
|
||||
<div class="skeleton-tip-line-small"></div>
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮骨架屏 -->
|
||||
<view class="skeleton-confirm-section">
|
||||
<div class="skeleton-confirm-button"></div>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 真实内容 -->
|
||||
<view v-else class="withdraw-container">
|
||||
<!-- 可提现金额 -->
|
||||
<view class="balance-section">
|
||||
<text class="balance-label">可提现金额</text>
|
||||
<text class="balance-amount">¥86.50</text>
|
||||
<text class="current-balance">当前钱包余额</text>
|
||||
</view>
|
||||
|
||||
<!-- 提现账户选择 -->
|
||||
<view class="account-section">
|
||||
<text class="section-title">提现账户</text>
|
||||
<view class=""
|
||||
style="display: flex;align-items: center; border-bottom: 4rpx solid #e2e2e2;padding-bottom: 10px; margin-bottom: 10px;">
|
||||
<up-icon name="zhifubao-circle-fill" size="30" color="#1890ff"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
支付宝
|
||||
</view>
|
||||
<view @click="changePay(0)" class="">
|
||||
<view v-if="current==0" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex;align-items: center;">
|
||||
<up-icon name="weixin-circle-fill" size="30" color="#28C445"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
微信
|
||||
</view>
|
||||
<view @click="changePay(1)" class="">
|
||||
<view v-if="current==1" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tip-section">
|
||||
<up-icon name="clock" size="18" color="#1890ff"></up-icon>
|
||||
<view class="" style="margin-left: 10rpx;">
|
||||
<view class="tip-text">预计 T+1 工作日到账</view>
|
||||
<view class="tip-text" style="color: #666666; font-size: 24rpx; margin-top: 10rpx; ">无手续费</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-section">
|
||||
<button class="confirm-button" @click="confirmWithdraw">确认提现 ¥86.50</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
|
||||
let current = ref(null)
|
||||
let loading=ref(true)
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(()=>{
|
||||
loading.value=false
|
||||
},1000)
|
||||
})
|
||||
|
||||
const changePay = (item : any) => {
|
||||
current.value = item
|
||||
}
|
||||
|
||||
// 确认提现
|
||||
const confirmWithdraw = () => {
|
||||
// 这里可以添加提现逻辑
|
||||
uni.showToast({
|
||||
title: '提现申请已提交',
|
||||
icon: 'success'
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.withdraw-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 选择 */
|
||||
|
||||
.radio-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.radio-inner {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.radio-no-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid #dadada;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* 余额显示区域 */
|
||||
.balance-section {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.balance-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4757;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.current-balance {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 账户选择区域 */
|
||||
.account-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.account-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #1677ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
border: 2rpx solid #000;
|
||||
}
|
||||
|
||||
.account-icon.wechat {
|
||||
background-color: #07c160;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 提示信息区域 */
|
||||
.tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 确认按钮区域 */
|
||||
.confirm-section {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #1677ff;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 45rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.confirm-button:active {
|
||||
background-color: #0958d9;
|
||||
}
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏通用样式 */
|
||||
.skeleton-balance-section,
|
||||
.skeleton-account-section,
|
||||
.skeleton-tip-section {
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 余额区域骨架屏 */
|
||||
.skeleton-balance-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-balance-label {
|
||||
width: 30%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-amount {
|
||||
width: 40%;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-current {
|
||||
width: 25%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 账户选择区域骨架屏 */
|
||||
.skeleton-account-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 25%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 4rpx solid #e2e2e2;
|
||||
}
|
||||
|
||||
.skeleton-account-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.skeleton-account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-name {
|
||||
flex: 1;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-radio {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 提示信息骨架屏 */
|
||||
.skeleton-tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-tip-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
margin-right: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-tip-line {
|
||||
width: 70%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 15rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-line-small {
|
||||
width: 50%;
|
||||
height: 24rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 确认按钮骨架屏 */
|
||||
.skeleton-confirm-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,335 @@
|
||||
<template>
|
||||
<view class="review-management-page">
|
||||
<!-- 全新方案:纯 CSS 手动构建的骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-wrapper">
|
||||
<view class="skeleton-card" style="height: 150rpx;"></view>
|
||||
<view class="skeleton-tabs">
|
||||
<view class="skeleton-item skeleton-text" style="width: 100%; height: 44rpx;"></view>
|
||||
</view>
|
||||
<view v-for="i in 3" :key="i" class="skeleton-card">
|
||||
<view class="skeleton-item skeleton-text" style="width: 100%; height: 300rpx;"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 页面实际内容 -->
|
||||
<view v-else class="page-content" >
|
||||
|
||||
<!-- 1. 数据看板 -->
|
||||
<view class="summary-card">
|
||||
<view class="data-item">
|
||||
<view class="value"><text class="score">{{ satisfaction }}%</text><up-icon name="star-fill"
|
||||
color="#ff9900" size="20"></up-icon></view>
|
||||
<text class="label">满意度</text>
|
||||
</view>
|
||||
<view class="data-item">
|
||||
<text class="value">{{total}}</text>
|
||||
<text class="label">总评价数</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 2. Tabs 切换 -->
|
||||
<view class="sticky-tabs-wrapper">
|
||||
<up-tabs :list="reviewTabs" :current="currentTab" @change="onTabChange" lineColor="#fa6400"
|
||||
:activeStyle="{ color: '#fa6400', fontWeight: 'bold' }" :inactiveStyle="{ color: '#666' }">
|
||||
</up-tabs>
|
||||
</view>
|
||||
|
||||
<view class="review-list">
|
||||
<view class="review-card" v-for="review in reviewList" :key="review">
|
||||
<view class="reviewer-info">
|
||||
<text class="name" style="font-weight: bold;" >{{ review.nick }}</text>
|
||||
<up-rate v-model="review.source" readonly activeColor="#ff9900" size="16"></up-rate>
|
||||
<text class="time">{{ Service.formatDate(review.addTime,1) }}</text>
|
||||
</view>
|
||||
<text class="review-text">{{ review.sign }}</text>
|
||||
</view>
|
||||
|
||||
<up-loadmore status="nomore" nomoreText="没有更多评价了"></up-loadmore>
|
||||
<view class="" style="width: 100%; height: 20rpx;" >
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onShow } from '@dcloudio/uni-app';
|
||||
import { Service } from "@/Service/Service";
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
|
||||
|
||||
const loading = ref<boolean>(true);
|
||||
const currentTab = ref<number>(0);
|
||||
|
||||
|
||||
let satisfaction = ref(0)
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
|
||||
let review = ref('')
|
||||
|
||||
let storeInfo = ref<any>()
|
||||
let total = ref(0)
|
||||
|
||||
const reviewTabs = ref([
|
||||
{ name: '全部' }, { name: '好评' }, { name: '差评' }
|
||||
]);
|
||||
|
||||
const reviewList = ref<Array<any>>([]);
|
||||
|
||||
let currentId = ref('')
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
onShow(() => { });
|
||||
|
||||
onReachBottom(()=>{
|
||||
getList()
|
||||
})
|
||||
|
||||
// 获取数据
|
||||
const getData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
reviewList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
|
||||
const getList = () => {
|
||||
if (status.value == 'loading' || status.value == 'nomore') {
|
||||
return
|
||||
}
|
||||
status.value = 'loading'
|
||||
CNRiderDataService.GetRiderEvaluate(currentTab.value, page.value).then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
satisfaction.value = res.data.satisfaction
|
||||
total.value=res.data.total
|
||||
reviewList.value = [...reviewList.value, ...res.data.evaluateList]
|
||||
page.value++
|
||||
status.value = res.data.evaluateList == 10 ? 'loadmore' : 'nomore'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onTabChange = (e : { index : number }) => {
|
||||
currentTab.value = e.index;
|
||||
getData()
|
||||
};
|
||||
|
||||
const replyTo = () => {
|
||||
|
||||
if (review.value == '') {
|
||||
return
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
page{
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
@keyframes skeleton-blink {
|
||||
0% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-item {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-blink 1.5s infinite linear;
|
||||
}
|
||||
|
||||
.skeleton-rect {
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.skeleton-text {
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-wrapper {
|
||||
padding: 24rpx;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.skeleton-tabs {
|
||||
padding: 20rpx 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-card {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.review-management-page {
|
||||
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
text-align: center;
|
||||
background-color: #fff8f5;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin: 24rpx;
|
||||
|
||||
.data-item {
|
||||
.value {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.text-red {
|
||||
color: #fa5151;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sticky-tabs-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background-color: #fff;
|
||||
|
||||
:deep(.up-tabs__wrapper__nav__item) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.up-tabs__wrapper__nav) {
|
||||
position: relative;
|
||||
|
||||
.unread-badge {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
right: 20rpx;
|
||||
background-color: #fa5151;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
min-width: 32rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-list {
|
||||
padding: 24rpx;
|
||||
|
||||
.review-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&.bad-review {
|
||||
border: 1rpx solid #fef0f0;
|
||||
}
|
||||
|
||||
.reviewer-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
|
||||
.name {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.review-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin: 20rpx 0;
|
||||
display: block;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.review-images {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
|
||||
.image-placeholder {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.merchant-reply {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
.reply-label {
|
||||
color: #fa6400;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.reply-text {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.reply-action {
|
||||
text-align: right;
|
||||
margin-top: 20rpx;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
border: 1rpx solid #fa6400;
|
||||
color: #fa6400;
|
||||
font-size: 26rpx;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"id": "qf-image-cropper",
|
||||
"displayName": "图片裁剪插件",
|
||||
"version": "2.2.5",
|
||||
"description": "图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。",
|
||||
"keywords": [
|
||||
"qf-image-cropper",
|
||||
"图片裁剪",
|
||||
"图片编辑",
|
||||
"头像裁剪",
|
||||
"小程序"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "n",
|
||||
"百度": "n",
|
||||
"字节跳动": "n",
|
||||
"QQ": "u",
|
||||
"钉钉": "n",
|
||||
"快手": "n",
|
||||
"飞书": "n",
|
||||
"京东": "n"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "n",
|
||||
"联盟": "n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
<template>
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 收入概览区域骨架 -->
|
||||
<view class="income-container" style="padding-top: 80rpx">
|
||||
<view class="income-overview">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between">
|
||||
<view class="">
|
||||
<view class="skeleton-income-title"></view>
|
||||
<view class="" style="display: flex; align-items: center">
|
||||
<view class="skeleton-income-amount"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-withdraw-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细区域骨架 -->
|
||||
<view class="detail-header">
|
||||
<view class="skeleton-detail-title"></view>
|
||||
</view>
|
||||
<!-- 时间选择标签骨架 -->
|
||||
<view class="time-tabs">
|
||||
<view class="skeleton-tab-item" v-for="(item, index) in 4" :key="index"></view>
|
||||
</view>
|
||||
<!-- 明细列表骨架 -->
|
||||
<view class="detail-list" v-for="(item, index) in 3" :key="index">
|
||||
<view class="detail-content">
|
||||
<view class="skeleton-icon-placeholder"></view>
|
||||
<view class="detail-info">
|
||||
<view class="skeleton-order-id"></view>
|
||||
<view class="skeleton-order-time"></view>
|
||||
</view>
|
||||
<view class="">
|
||||
<view class="skeleton-order-amount"></view>
|
||||
<view class="skeleton-order-balance"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 加载更多骨架 -->
|
||||
<view class="skeleton-load-more"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收入概览区域 -->
|
||||
<view v-else class="income-container" style="padding-top: 80rpx">
|
||||
<view v-if="!istrought" class="">
|
||||
<view class="income-overview">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between">
|
||||
<view class="">
|
||||
<text class="income-title">账户余额</text>
|
||||
<view class="" style="display: flex; align-items: center">
|
||||
<text class="income-amount">¥{{ riderAcc.account }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-button class="withdraw-button" @click="Service.GoPage('/pages/order/withdraw')"
|
||||
type="primary">立即提现</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细区域 -->
|
||||
<view class="detail-header">
|
||||
<text class="detail-title">收支明细</text>
|
||||
</view>
|
||||
<!-- 时间选择标签 -->
|
||||
<view class="time-tabs">
|
||||
<text v-for="(item, index) in timeList" :key="index" @click="changeTab(index)"
|
||||
:class="{ active: currentTime == index }" class="tab-item">{{
|
||||
item
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="detail-list" v-for="(item, index) in accList" :key="index">
|
||||
<view class="detail-content">
|
||||
<view class="icon-placeholder">
|
||||
<image :src="Service.GetIconImg('/static/index/income/order.png')"
|
||||
style="width: 55rpx; height: 55rpx" mode=""></image>
|
||||
</view>
|
||||
<view class="detail-info">
|
||||
<text class="order-id">{{ item.name }}</text>
|
||||
<text class="order-time">{{ Service.formatDate(item.addTime, 1) }}</text>
|
||||
</view>
|
||||
<view class="" style="">
|
||||
<view class="order-amount" style="text-align: right">
|
||||
{{ item.code == '收入' ? '+' : '-' }}{{ item.amount }}
|
||||
</view>
|
||||
<view class="order-time"> 账户余额 {{ item.balance }} </view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="istrought" style=" margin-top: 20rpx; text-align: center; font-weight: bold; font-size: 34rpx;"
|
||||
class="">
|
||||
信息审核中·请等待审核
|
||||
</view>
|
||||
|
||||
<calender ref="calendar" :range="true" :insert="false" @confirm="dataConfirm" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { Service } from '@/Service/Service'
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
import calender from '@/uni_modules/uni-calendar/components/uni-calendar/uni-calendar'
|
||||
|
||||
let loading = ref(true)
|
||||
let calendar = ref(null)
|
||||
let timeList = ref(['今日', '本周', '本月', '自定义'])
|
||||
|
||||
let currentTime = ref(0)
|
||||
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
let riderAcc = ref<any>({})
|
||||
|
||||
let accList = ref<Array<any>>([])
|
||||
|
||||
let timeString = ref('')
|
||||
|
||||
let istrought = ref(false)
|
||||
|
||||
onLoad(() => { })
|
||||
|
||||
onShow(() => {
|
||||
getData()
|
||||
getIncome()
|
||||
})
|
||||
|
||||
onMounted(() => { })
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderAccInfo().then((res) => {
|
||||
loading.value = false
|
||||
if (res.code == 0) {
|
||||
riderAcc.value = res.data.riderAcc
|
||||
istrought.value = false
|
||||
}
|
||||
else if (res.code == 1008) {
|
||||
istrought.value = true
|
||||
}
|
||||
else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 收入列表
|
||||
const getIncome = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
accList.value = []
|
||||
getIncomeList()
|
||||
}
|
||||
|
||||
const getIncomeList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderAccLog(
|
||||
currentTime.value == 0 ? '' : currentTime.value == 3 ? timeString.value : String(currentTime.value),
|
||||
page.value
|
||||
).then((res) => {
|
||||
accList.value = [...accList.value, ...res.data.accLog]
|
||||
status.value = res.data.accLog == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
|
||||
const changeTab = (index : number) => {
|
||||
currentTime.value = index
|
||||
if (index == 3) {
|
||||
calendar.value.open()
|
||||
return
|
||||
}
|
||||
getIncome()
|
||||
}
|
||||
|
||||
const dataConfirm = (e) => {
|
||||
timeString.value = e.range.data[0] + '_' + e.range.data.slice(-1)
|
||||
if (e.range.data.length == 0) {
|
||||
timeString.value = e.fulldate
|
||||
getIncome()
|
||||
return
|
||||
}
|
||||
getIncome()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.income-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 收入概览区域 */
|
||||
.income-overview {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.income-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.income-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 时间标签 */
|
||||
.time-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-right: 40rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #1890ff;
|
||||
border-bottom: 3rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.month-total {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 收入构成区域 */
|
||||
.income-composition {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 饼图占位 */
|
||||
.pie-chart-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chart-legend {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.legend-dot.blue {
|
||||
background-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
.legend-dot.orange {
|
||||
background-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.legend-dot.green {
|
||||
background-color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 钱包区域 */
|
||||
.wallet-section {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wallet-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.withdraw-button {
|
||||
margin: 0;
|
||||
width: fit-content;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.withdraw-tip {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 收入明细区域 */
|
||||
.income-detail {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-list {
|
||||
margin: 15rpx 0 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 图标占位符 - 黑边白底 */
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #e6f7ff;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 没有更多记录 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 收入概览骨架 */
|
||||
.skeleton-income-title {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-income-amount {
|
||||
width: 240rpx;
|
||||
height: 48rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-withdraw-button {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 30rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 明细标题骨架 */
|
||||
.skeleton-detail-title {
|
||||
width: 150rpx;
|
||||
height: 34rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 时间标签骨架 */
|
||||
.skeleton-tab-item {
|
||||
width: 80rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
/* 明细列表骨架 */
|
||||
.skeleton-icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-id {
|
||||
width: 200rpx;
|
||||
height: 26rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.skeleton-order-time {
|
||||
width: 150rpx;
|
||||
height: 24rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-order-amount {
|
||||
width: 120rpx;
|
||||
height: 32rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.skeleton-order-balance {
|
||||
width: 180rpx;
|
||||
height: 24rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
text-align: right;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
|
||||
/* 加载更多骨架 */
|
||||
.skeleton-load-more {
|
||||
height: 80rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: -100% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,355 @@
|
||||
import { HttpRequest, StoreAssist, UploadAssist, ResultData } from '@/common/Common';
|
||||
import { BaseConfig } from './BaseConfig';
|
||||
export class Service extends BaseConfig {
|
||||
|
||||
|
||||
// 获取是否后台
|
||||
static getIsHede () {
|
||||
let isHede = this.GetStorageCache('isHede')
|
||||
if (isHede == null || isHede == '') {
|
||||
return false;
|
||||
} else {
|
||||
return isHede;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//获取API地址
|
||||
static ApiUrl(path : string) {
|
||||
return `${this.servesUrl}${path}`;
|
||||
}
|
||||
|
||||
//获取图片地址
|
||||
static GetpayImg(path : string) {
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.payuploadUrl}${path}`;
|
||||
}
|
||||
}
|
||||
|
||||
//获取图标地址
|
||||
static GetIconImg(path : string) {
|
||||
return path
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.imgUrl}${path}`;
|
||||
}
|
||||
}
|
||||
|
||||
//获取图片地址
|
||||
static GetMateUrlByImg(path : string) {
|
||||
return path
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.imgUrl}${path}`;
|
||||
}
|
||||
}
|
||||
//获取音视频地址
|
||||
static GetMateUrlByMedia(path : string) {
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.mediaUrl}${path}`;
|
||||
}
|
||||
}
|
||||
//获取登录账号token
|
||||
static GetUserToken() {
|
||||
return Service.GetStorageCache('token');
|
||||
}
|
||||
// 获取登录状态
|
||||
static GetUserIsLogin() {
|
||||
var token = this.GetUserToken();
|
||||
if (token == null || token == '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//设置登录账户Token
|
||||
static SetUserToken(token : string) {
|
||||
this.SetStorageCache('token', token);
|
||||
}
|
||||
//清理登录账户Token
|
||||
static OffUserToken() {
|
||||
Service.DelStorageCache('token');
|
||||
uni.$emit('ImComOff', 'user');
|
||||
this.ClearUserStateData();
|
||||
}
|
||||
//获取登录账号状态信息
|
||||
static GetUserStateData() {
|
||||
return Service.GetStorageCache('StateDomain');
|
||||
}
|
||||
//设置当前登录账号状态信息
|
||||
static SetUserStateData() {
|
||||
return Service.GetStorageCache('StateDomain');
|
||||
}
|
||||
//清理当前登录账号状态信息
|
||||
static ClearUserStateData() {
|
||||
Service.DelStorageCache('StateDomain');
|
||||
}
|
||||
|
||||
|
||||
//获取当前客户端ID
|
||||
static GetUserClientId() {
|
||||
return this.GetStorageCache('ClientId');
|
||||
}
|
||||
//保存当前客户端ID
|
||||
static SetUserClientId(clientId: string) {
|
||||
this.SetStorageCache('ClientId', clientId);
|
||||
}
|
||||
|
||||
|
||||
//获取缓存
|
||||
static GetStorageCache(key : string) {
|
||||
return StoreAssist.Get(key);
|
||||
}
|
||||
//删除缓存
|
||||
static DelStorageCache(key : string) {
|
||||
StoreAssist.Delete(key);
|
||||
}
|
||||
//设置缓存
|
||||
static SetStorageCache(key : string, data : any) {
|
||||
StoreAssist.Set(key, data);
|
||||
}
|
||||
|
||||
/*****以下是基础方法调用与拦截器*****/
|
||||
|
||||
static Request(url : string, method : 'GET' | 'POST' | 'PUT' | undefined, data : object | any) {
|
||||
const token = Service.GetUserToken();
|
||||
|
||||
const _url = Service.ApiUrl(url);
|
||||
var result = HttpRequest.RequestWithToken(_url, method, token, data).then((retResult : any) => {
|
||||
if (retResult.statusCode == '200') {
|
||||
var obj = retResult.data;
|
||||
if (obj.code == 401) {
|
||||
//过期
|
||||
this.OffUserToken();
|
||||
this.Msg('登录过期,请重新登录')
|
||||
this.GoPage('/pages/my/login')
|
||||
return Promise.reject();
|
||||
} else if (obj.code == 40101) {
|
||||
//失效
|
||||
this.OffUserToken();
|
||||
this.GoPageDelse('/pages/mine/login/login');
|
||||
return Promise.reject();
|
||||
} else if (obj.code == 1004) {
|
||||
//资源不存在
|
||||
this.GoPageDelse('/pages/AppSet/404/404');
|
||||
return Promise.reject();
|
||||
// return new ResultData(-1, '', '');
|
||||
} else if (obj.code == 40188) {
|
||||
//无权限
|
||||
|
||||
this.GoPageDelse('/pages/AppSet/40188/40188');
|
||||
return Promise.reject();
|
||||
// return new ResultData(-1, '', '');
|
||||
} else if (obj.code == 1008) {
|
||||
//业务提示
|
||||
return new ResultData(obj.code, obj.msg, obj.data);
|
||||
} else {
|
||||
return new ResultData(obj.code, obj.msg, obj.data);
|
||||
}
|
||||
} else {
|
||||
return new ResultData(-1, '', '');
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/*****以下是腾讯云oss上传*****/
|
||||
static UpLoadMedia(code : string, fileName : string, desire : string, path : string) {
|
||||
var result = this.Request(this.uploadUrl, 'GET', { code, fileName, desire }).then((retResult) => {
|
||||
if (retResult.code == 0) {
|
||||
var upOk = UploadAssist.Upload(retResult.data.url, path, retResult.data.cosData).then((upRet : any) => {
|
||||
if (upRet.statusCode == 200) {
|
||||
const retData : any = { code: retResult.data.code, file: retResult.data.file, cache: retResult.data.cache };
|
||||
return new ResultData(0, '上传成功!', retData);
|
||||
} else {
|
||||
this.Msg('上传失败!');
|
||||
return new ResultData(-1, '', '');
|
||||
}
|
||||
});
|
||||
return upOk;
|
||||
} else {
|
||||
this.Msg('上传失败!');
|
||||
return new ResultData(-1, retResult.msg,retResult.data);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********消息操作**************/
|
||||
static Msg(message : any, icon ?: any) : void {
|
||||
if (icon != null) {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: icon
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static Alert(msg : string, cb ?: any) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: msg,
|
||||
showCancel: false,
|
||||
cancelText: '取消',
|
||||
confirmText: '确定',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
cb && cb();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static LoadIng(text : any) : void {
|
||||
uni.showLoading({
|
||||
title: text,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
static LoadClose() : void {
|
||||
uni.hideLoading();
|
||||
}
|
||||
|
||||
/**********跳转操作*********/
|
||||
|
||||
|
||||
static GoPageTab(path : string) : void {
|
||||
uni.switchTab({
|
||||
url: path
|
||||
});
|
||||
}
|
||||
|
||||
/**********跳转操作*********/
|
||||
static GoPage(path : string) : void {
|
||||
uni.navigateTo({
|
||||
url: path, //跳转的页面
|
||||
success: function (res) {
|
||||
// 通过eventChannel向被打开页面传送数据
|
||||
}
|
||||
});
|
||||
}
|
||||
/**********跳转并删除当前页面操作*********/
|
||||
static GoPageDelse(path : string) : void {
|
||||
uni.redirectTo({
|
||||
url: path //跳转的页面
|
||||
});
|
||||
}
|
||||
|
||||
/**********返回上一页*********/
|
||||
static GoPageBack() : void {
|
||||
uni.navigateBack({ delta: 1 });
|
||||
}
|
||||
|
||||
/*****获取图片base64*****/
|
||||
static UpLoadMediaBase64(path : string) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
uni.uploadFile({
|
||||
url: 'http://cloud.pccsh.com/DefUp/UploadFileImgBase64', //仅为示例,非真实的接口地址
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
success: (uploadFileRes) => {
|
||||
resolve(uploadFileRes);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/*****获取图片位置信息*****/
|
||||
//获取时间戳
|
||||
static GetTimeSpan(milliSecond : number) {
|
||||
return Date.now() + milliSecond;
|
||||
}
|
||||
|
||||
// 时间戳处理
|
||||
static formatDate(time : any, type : number) : string {
|
||||
const date = new Date(time);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以加1,并用0填充
|
||||
const day = String(date.getDate()).padStart(2, '0'); // 用0填充
|
||||
const hours = String(date.getHours()).padStart(2, '0'); // 用0填充
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0'); // 用0填充
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0'); // 用0填充
|
||||
if (type == 0) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
else if (type == 1) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
} else if (type == 2) {
|
||||
return `${year}-${month}-${day}`;
|
||||
} else if (type == 3) {
|
||||
return `${hours}:${minutes}`;
|
||||
} else if (type == 4) {
|
||||
return `${year}${month}${day}`;
|
||||
}
|
||||
|
||||
else {
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
}
|
||||
|
||||
/*****节流*****/
|
||||
static throttle(fn: () => void, time: number) {
|
||||
let canRun: boolean = true;
|
||||
return function () {
|
||||
if (!canRun) return;
|
||||
canRun = false;
|
||||
setTimeout(() => {
|
||||
fn(); //可以不执行
|
||||
canRun = true;
|
||||
}, time);
|
||||
};
|
||||
}
|
||||
/*****防抖*****/
|
||||
static debounce<T extends (...args: any[]) => void>(fn: T, time: number): (...args: Parameters<T>) => void {
|
||||
let timerId: NodeJS.Timeout | null = null;
|
||||
|
||||
return (...args: Parameters<T>) => {
|
||||
if (timerId) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
|
||||
timerId = setTimeout(() => {
|
||||
fn(...args); // 执行传入的函数
|
||||
timerId = null; // 清除定时器ID
|
||||
}, time);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 普通图片上传
|
||||
static uploadH5(path, dic, callback) {
|
||||
console.log(this.payuploadUrl,'xxx')
|
||||
uni.uploadFile({
|
||||
url: this.payuploadUrl+'/Upload/Upload',
|
||||
method: "POST",
|
||||
header: {
|
||||
'Authorization': 'Bearer ' + Service.GetUserToken(),
|
||||
},
|
||||
formData: {
|
||||
"path": dic,
|
||||
},
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
success: (data) => {
|
||||
let info = data.data
|
||||
callback(info)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
<template>
|
||||
<!-- <UpApp :show="upShow" :url="url" /> -->
|
||||
<view class="borybac" v-if="upShow">
|
||||
<view class="up_box">
|
||||
|
||||
<view class="mt50">
|
||||
<view class="" style="margin: 0 60rpx;" >
|
||||
1.优化布局细节,优化购物体验,优化产品体验
|
||||
</view>
|
||||
<view class="" style="margin: 0 60rpx;" >
|
||||
2.修复已知问题,修复一些BUG
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="jdBox">
|
||||
<view class="jd">
|
||||
<view class="jdbfb">
|
||||
{{sum}}%
|
||||
</view>
|
||||
<view class="jdt">
|
||||
<view class="jdn" :style="'width:'+sum+'%'">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="buttonContro" class="jddx">
|
||||
{{datacl(beg)}}/{{datacl(downlog)}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" v-if="force==0"
|
||||
style="width: 100%; padding: 0 20rpx; height: 60rpx; margin: 40rpx auto; display: flex; justify-content: space-between;">
|
||||
<view class="" style="width: 70rpx;">
|
||||
|
||||
</view>
|
||||
<view class=""
|
||||
style="width: 240rpx; height: 60rpx; line-height: 60rpx; border-radius: 30rpx; text-align: center; color: #fff; font-size: 24rpx; background-color: #FFD700;"
|
||||
@click="delUpApp">
|
||||
开始更新
|
||||
</view>
|
||||
<view class="" style="font-size: 22rpx; line-height: 80rpx; color: #999;" @click="goindex">
|
||||
暂不更新
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
|
||||
let buttonContro = ref(false)
|
||||
|
||||
let url = ref('')
|
||||
let force = ref('0')
|
||||
|
||||
// 控制热更新
|
||||
let upShow = ref(true)
|
||||
let sum = ref(0)
|
||||
let downlog = ref(0)
|
||||
let beg = ref(0)
|
||||
let remark = ref('')
|
||||
let type = ref('')
|
||||
|
||||
//模拟请求
|
||||
onLoad((data : any) => {
|
||||
// getdata()
|
||||
url.value = data.url
|
||||
});
|
||||
|
||||
const goindex = function () {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
|
||||
const getdata = function () {
|
||||
// RegisterService.GetNewVersion().then((res:any)=>{
|
||||
// url.value = res.data.path
|
||||
// downlog.value = res.data.size
|
||||
// force.value = res.data.force
|
||||
// remark.value = res.data.remark
|
||||
// type.value = res.data.type
|
||||
// if(res.data.force=='1'){
|
||||
// delUpApp()
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
|
||||
const datacl = function (e : any) {
|
||||
if (e > 1024) {
|
||||
let sl = ((e / 1024) / 1024).toFixed(1)
|
||||
return sl + 'MB'
|
||||
} else {
|
||||
return (e / 1024).toFixed(1) + 'KB'
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const delUpApp = function () {
|
||||
|
||||
if (buttonContro.value) {
|
||||
return
|
||||
}
|
||||
buttonContro.value = true
|
||||
// 1.开始请求下载
|
||||
const downloadTask = uni.downloadFile({
|
||||
url: url.value,
|
||||
success: (downloadResult) => {
|
||||
if (downloadResult.statusCode === 200) {
|
||||
plus.runtime.install(downloadResult.tempFilePath, {
|
||||
force: false
|
||||
}, function () {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: "下载成功",
|
||||
complete() {
|
||||
if (type.value == 'Bulking') {
|
||||
setTimeout(function () {
|
||||
plus.runtime.restart();
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
console.log('install success...');
|
||||
}, function (e) {
|
||||
uni.hideLoading()
|
||||
console.log(e, '失败')
|
||||
// uni.$u.toast('下载失败!')
|
||||
// console.error('install fail...');
|
||||
});
|
||||
}
|
||||
},
|
||||
fail(downloadResult) {
|
||||
console.log(downloadResult, '失败')
|
||||
// console.log('下载失败');
|
||||
// uni.$u.toast('下载失败')
|
||||
}
|
||||
});
|
||||
downloadTask.onProgressUpdate((res) => {
|
||||
downlog.value = res.totalBytesExpectedToWrite
|
||||
beg.value = res.totalBytesWritten
|
||||
sum.value = res.progress
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" setup>
|
||||
.borybac {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #f6f6f6;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
.up_box {
|
||||
width: 650rpx;
|
||||
height: 1000rpx;
|
||||
margin: 200rpx auto;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-image: url(@/static/index/system/updata.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
|
||||
.mt50 {
|
||||
display: block;
|
||||
margin-top: 570rpx;
|
||||
}
|
||||
|
||||
.jdBox {
|
||||
overflow: hidden;
|
||||
margin-top: 70rpx;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.jd {
|
||||
display: block;
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
|
||||
.jdbfb {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
font-size: 30rpx;
|
||||
color: #FFD700;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.jdt {
|
||||
margin-top: 10rpx;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 23rpx;
|
||||
border-radius: 15rpx;
|
||||
background-color: #E5E5E5;
|
||||
|
||||
.jdn {
|
||||
display: block;
|
||||
height: 23rpx;
|
||||
border-radius: 15rpx;
|
||||
background: radial-gradient(#8370F8 0%, #455FF8 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.jddx {
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
margin-top: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 30rpx;
|
||||
width: 100%;
|
||||
height: 40rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
## 1.1.7(2024-10-29)
|
||||
修复底部露出部分组件bug
|
||||
## 1.1.6(2024-08-20)
|
||||
更新本地数据源为最新数据源
|
||||
## 1.1.5(2024-06-12)
|
||||
使用说明文档优化
|
||||
## 1.1.4(2024-06-12)
|
||||
增加问题反馈描述
|
||||
## 1.1.3(2024-02-29)
|
||||
更新使用文档
|
||||
## 1.1.2(2024-01-16)
|
||||
解决Vue3项目导入导出报错问题
|
||||
## 1.1.1(2023-12-06)
|
||||
defaultValue可以传入defaultValue:['河北省','唐山市','丰南区']数组类型以及defaultValue: '420103'地区编码字符串类型
|
||||
## 1.1.0(2023-12-05)
|
||||
即默认值传入地区编码,也支持传入中文省市区数组
|
||||
## 1.0.9(2023-12-04)
|
||||
优化
|
||||
## 1.0.8(2023-10-24)
|
||||
修复东菀市和中山市下各镇的行政编码错误问题
|
||||
## 1.0.4(2023-09-15)
|
||||
改为uni_modules规范
|
||||
|
After Width: | Height: | Size: 594 B |
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<web-view ref="webviewRef" v-if="isshow" :src="url" @message="handleMessage" @logData = "logData"></web-view>
|
||||
|
||||
<!-- ✅ 新增:一个绝对定位的遮罩层,用于在刷新时覆盖 web-view -->
|
||||
<view v-else class="reloading-mask">
|
||||
<up-loading-icon text="正在获取订单状态..." v-if="orderOver" textSize="16"></up-loading-icon>
|
||||
|
||||
<up-loading-icon text="订单已完成" v-else textSize="16"></up-loading-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { Service } from "@/Service/Service";
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let orderId = ref<string>('')
|
||||
let url = ref<string>('')
|
||||
let isshow = ref<false>(false)
|
||||
|
||||
let orderInfo = ref<any>({
|
||||
isFood: 0
|
||||
})
|
||||
|
||||
let riderOrder = ref<any>({
|
||||
status:0
|
||||
})
|
||||
|
||||
let orderOver = ref<true>(false)
|
||||
|
||||
onLoad((data) => {
|
||||
if (data.orderId) {
|
||||
orderId.value = data.orderId
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg('为获取到订单ID')
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化url
|
||||
const getUrl = () => {
|
||||
isshow.value = false
|
||||
url.value = 'https://hmjz.327gzs.top?orderId=' + orderId.value + '&isFood=' + riderOrder.value.status
|
||||
isshow.value = true
|
||||
}
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
if (res.code==0) {
|
||||
orderInfo.value = res.data.orderInfo
|
||||
riderOrder.value = res.data.riderOrder
|
||||
getUrl()
|
||||
|
||||
}else{
|
||||
Service.Msg(res.mgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 点击完成送餐取餐调用
|
||||
const handleMessage = (data) => {
|
||||
|
||||
let preat = data.detail.data[0]
|
||||
if(preat.action =='message'){
|
||||
if (riderOrder.value.status == 0) {
|
||||
// 去商家、取餐
|
||||
pickFood(1)
|
||||
} else {
|
||||
// 去用户,送餐
|
||||
pickFood(2)
|
||||
}
|
||||
}else if(preat.action =='logData'){
|
||||
CNRiderOrderService.UpdateRiderLocation(preat.data[0],preat.data[1]).then(res=>{
|
||||
if(res.code==0){
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// 骑手定位
|
||||
const logData = (data) =>{
|
||||
console.log(data,'骑手定位')
|
||||
}
|
||||
|
||||
// 取餐
|
||||
const pickFood = ( type:number) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId.value, type).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg(type==1?'取餐成功':'订单完成')
|
||||
if(type==2){
|
||||
setTimeout(()=>{Service.GoPageTab('/pages/index/index')},500)
|
||||
}
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.reloading-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #f7f7f7; // 使用页面底色
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****订单接口*****/
|
||||
class CNRiderOrderService {
|
||||
private static GetRiderOrderListPath : string = '/Rider/GetRiderOrderList';
|
||||
/*****首页新订单*****/
|
||||
static GetRiderOrderList(page : number) {
|
||||
var result = Service.Request(this.GetRiderOrderListPath, "GET", {page});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static RiderTakeOrderPath : string = '/Rider/RiderTakeOrder';
|
||||
/*****骑手接单*****/
|
||||
static RiderTakeOrder(orderId : string) {
|
||||
var result = Service.Request(this.RiderTakeOrderPath, "POST", {orderId});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetRiderTakeOrderListPath : string = '/Rider/GetRiderTakeOrderList';
|
||||
/*****首页 待取餐/配送中*****/
|
||||
static GetRiderTakeOrderList(status: number,page : number) {
|
||||
var result = Service.Request(this.GetRiderTakeOrderListPath, "GET", {status,page});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetUnitOrderInfoPath : string = '/Order/GetUnitOrderInfo';
|
||||
/*****获取订单详情*****/
|
||||
static GetUnitOrderInfo(orderId: string) {
|
||||
var result = Service.Request(this.GetUnitOrderInfoPath, "GET", {orderId});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static UpdateRiderOrderTakePath : string = '/Rider/UpdateRiderOrderTake';
|
||||
/*****取餐*****/
|
||||
static UpdateRiderOrderTake(orderId: string,status:number) {
|
||||
var result = Service.Request(this.UpdateRiderOrderTakePath, "POST", {orderId,status});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetRiderAccLogPath : string = '/Rider/GetRiderAccLog';
|
||||
/*****收入列表*****/
|
||||
static GetRiderAccLog(time: string,page:number) {
|
||||
var result = Service.Request(this.GetRiderAccLogPath, "GET", {time,page});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AddRiderWithPath : string = '/Rider/AddRiderWith';
|
||||
/*****骑手提现*****/
|
||||
static AddRiderWith(amount: number,payway:string,name:string,account:string) {
|
||||
var result = Service.Request(this.AddRiderWithPath, "POST", {amount,payway,name,account});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static GetRiderWithListPath : string = '/Rider/GetRiderWithList';
|
||||
/*****骑手提现列表*****/
|
||||
static GetRiderWithList(page:number) {
|
||||
var result = Service.Request(this.GetRiderWithListPath, "GET", {page});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
export {
|
||||
Service,
|
||||
CNRiderOrderService
|
||||
}
|
||||
|
After Width: | Height: | Size: 632 B |
@@ -0,0 +1,332 @@
|
||||
<template>
|
||||
<view class="review-management-page">
|
||||
<!-- 全新方案:纯 CSS 手动构建的骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-wrapper">
|
||||
<view class="skeleton-card" style="height: 150rpx;"></view>
|
||||
<view class="skeleton-tabs">
|
||||
<view class="skeleton-item skeleton-text" style="width: 100%; height: 44rpx;"></view>
|
||||
</view>
|
||||
<view v-for="i in 3" :key="i" class="skeleton-card">
|
||||
<view class="skeleton-item skeleton-text" style="width: 100%; height: 300rpx;"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 页面实际内容 -->
|
||||
<view v-else class="page-content" :class="{'height-pre':showReview}">
|
||||
|
||||
<!-- 1. 数据看板 -->
|
||||
<view class="summary-card">
|
||||
<view class="data-item">
|
||||
<view class="value"><text class="score">{{ satisfaction }}</text><up-icon name="star-fill"
|
||||
color="#ff9900" size="20"></up-icon></view>
|
||||
<text class="label">满意度</text>
|
||||
</view>
|
||||
<view class="data-item">
|
||||
<text class="value">{{total}}</text>
|
||||
<text class="label">总评价数</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 2. Tabs 切换 -->
|
||||
<view class="sticky-tabs-wrapper">
|
||||
<up-tabs :list="reviewTabs" :current="currentTab" @change="onTabChange" lineColor="#fa6400"
|
||||
:activeStyle="{ color: '#fa6400', fontWeight: 'bold' }" :inactiveStyle="{ color: '#666' }">
|
||||
</up-tabs>
|
||||
</view>
|
||||
|
||||
<view class="review-list">
|
||||
<view class="review-card" v-for="review in reviewList" :key="review">
|
||||
<view class="reviewer-info">
|
||||
<text class="name" style="font-weight: bold;" >{{ review.nick }}</text>
|
||||
<up-rate v-model="review.source" readonly activeColor="#ff9900" size="16"></up-rate>
|
||||
<text class="time">{{ Service.formatDate(review.addTime,1) }}</text>
|
||||
</view>
|
||||
<text class="review-text">{{ review.sign }}</text>
|
||||
</view>
|
||||
|
||||
<up-loadmore status="nomore" nomoreText="没有更多评价了"></up-loadmore>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { Service } from "@/Service/Service";
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
|
||||
|
||||
const loading = ref<boolean>(true);
|
||||
const currentTab = ref<number>(0);
|
||||
|
||||
|
||||
let satisfaction = ref(0)
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
let showReview = ref(false)
|
||||
let review = ref('')
|
||||
|
||||
let storeInfo = ref<any>()
|
||||
let total = ref(0)
|
||||
|
||||
const reviewTabs = ref([
|
||||
{ name: '全部' }, { name: '好评' }, { name: '差评' }
|
||||
]);
|
||||
|
||||
const reviewList = ref<Array<any>>([]);
|
||||
|
||||
let currentId = ref('')
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
onShow(() => { });
|
||||
|
||||
|
||||
|
||||
// 获取数据
|
||||
const getData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
reviewList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
|
||||
const getList = () => {
|
||||
if (status.value == 'loading' || status.value == 'nomore') {
|
||||
return
|
||||
}
|
||||
status.value = 'loading'
|
||||
CNRiderDataService.GetRiderEvaluate(currentTab.value, page.value).then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
satisfaction.value = res.data.satisfaction
|
||||
total.value=res.data.total.value
|
||||
reviewList.value = [...reviewList.value, ...res.data.evaluateList]
|
||||
page.value++
|
||||
status.value = res.data.evaluateList == 10 ? 'loadmore' : 'nomore'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onTabChange = (e : { index : number }) => {
|
||||
currentTab.value = e.index;
|
||||
getData()
|
||||
};
|
||||
|
||||
const replyTo = () => {
|
||||
|
||||
if (review.value == '') {
|
||||
return
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.height-pre {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
@keyframes skeleton-blink {
|
||||
0% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-item {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-blink 1.5s infinite linear;
|
||||
}
|
||||
|
||||
.skeleton-rect {
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.skeleton-text {
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-wrapper {
|
||||
padding: 24rpx;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.skeleton-tabs {
|
||||
padding: 20rpx 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-card {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.review-management-page {
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
text-align: center;
|
||||
background-color: #fff8f5;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin: 24rpx;
|
||||
|
||||
.data-item {
|
||||
.value {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.text-red {
|
||||
color: #fa5151;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sticky-tabs-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background-color: #fff;
|
||||
|
||||
:deep(.up-tabs__wrapper__nav__item) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.up-tabs__wrapper__nav) {
|
||||
position: relative;
|
||||
|
||||
.unread-badge {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
right: 20rpx;
|
||||
background-color: #fa5151;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
min-width: 32rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-list {
|
||||
padding: 24rpx;
|
||||
|
||||
.review-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&.bad-review {
|
||||
border: 1rpx solid #fef0f0;
|
||||
}
|
||||
|
||||
.reviewer-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
|
||||
.name {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.review-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin: 20rpx 0;
|
||||
display: block;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.review-images {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
|
||||
.image-placeholder {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.merchant-reply {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
.reply-label {
|
||||
color: #fa6400;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.reply-text {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.reply-action {
|
||||
text-align: right;
|
||||
margin-top: 20rpx;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
border: 1rpx solid #fa6400;
|
||||
color: #fa6400;
|
||||
font-size: 26rpx;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,423 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="order-detail skeleton-loading">
|
||||
<!-- 订单基本信息骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view class="" style="display: flex; justify-content: space-between;align-items: center; " >
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;" >
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<!-- 物品清单骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view v-for="item in 4" class="skeleton-block" style="width: 100%; height: 40rpx; " ></view>
|
||||
|
||||
<view class="" style="display: flex; justify-content: center;" >
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地图区域骨架屏 -->
|
||||
<view class="map-section skeleton-section">
|
||||
<view class="map-placeholder skeleton-map"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址区域骨架屏 -->
|
||||
<view class="address-section skeleton-section">
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-padding"></view>
|
||||
|
||||
<!-- 底部按钮骨架屏 -->
|
||||
<view class="bottom-action">
|
||||
<view class="skeleton-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: baseline; justify-content: space-between;">
|
||||
<view class="info-item">
|
||||
<view class="label" style="font-weight: 700; font-size: 30rpx;">30分钟内送达</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥5.50</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">20251021123456</text>
|
||||
</view>
|
||||
<view class="info-item" style=" justify-content: space-between;">
|
||||
<view class="">
|
||||
<text class="label">物品明细 : </text>
|
||||
<text class="value">食物</text>
|
||||
</view>
|
||||
<view class="label">共3件商品</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">物品重量 : </text>
|
||||
<text class="value">0.5kg</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="24rpx" class="clock-icon"></u-icon>
|
||||
2025-10-17 18:30下单
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
5件
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
¥16
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'190rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in 5 " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
康师傅 大食桶红烧牛肉143g/桶 经典红烧酱香免洗桶装速食泡面
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×4
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥16
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地图区域 -->
|
||||
<view class="map-section">
|
||||
<view class="map-placeholder">
|
||||
<text @click="Service.GoPage('/pages/order/navigation')" class="map-hint">点击查看完整导航</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<view class="" style=" border-bottom: 4rpx solid #e2e2e2; ">
|
||||
<text class="section-title">取餐地址 : </text>
|
||||
<view class="address-content">
|
||||
<text class="store-name">张亮麻辣烫(五道口店)</text>
|
||||
<text class="address">北京市海淀区成府路28号</text>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top: 20rpx; font-size: 30rpx;font-weight: 800;color: #333;">送餐地址 : </view>
|
||||
<view class="address-content">
|
||||
<text class="user-name">张*</text>
|
||||
<text class="address">XX小区3栋502室</text>
|
||||
<view class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action">
|
||||
<up-button color="var(--nav-mian)" class="confirm-btn">立即接单</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-section {
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-block {
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-short {
|
||||
height: 40rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-medium {
|
||||
height: 30rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-long {
|
||||
height: 30rpx;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.skeleton-map {
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 20rpx;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.skeleton-button {
|
||||
height: 90rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.bottom-padding {
|
||||
height: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-block::after,
|
||||
.skeleton-map::after,
|
||||
.skeleton-button::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,494 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="task-list-container skeleton-loading">
|
||||
<!-- 顶部标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; height: 120rpx"> </view>
|
||||
|
||||
<!-- 骨架屏订单列表 -->
|
||||
<view class="order-list">
|
||||
<!-- 骨架屏任务卡片 1 -->
|
||||
<view v-for="item in 3" class="task-section skeleton-card">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;" >
|
||||
<view class="skeleton-tag"></view>
|
||||
<view class="skeleton-time-group">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-time-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
<view class="skeleton-address-info">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-price"></view>
|
||||
<view class="skeleton-time-group">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-time-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; display: flex; justify-content: center; margin-top: 20rpx; " >
|
||||
<view class="" style="width: 200rpx; height: 40rpx; background-color: #fff; border-radius: 4rpx; " >
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="task-list-container">
|
||||
<!-- 顶部标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; height: 120rpx; ">
|
||||
|
||||
</view>
|
||||
<!-- 订单列表 -->
|
||||
<view class="order-list">
|
||||
<view @click="gopage()" v-for="(orderItem,orderIndex) in 3 " :key="orderIndex" class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<view v-if="activeTab==0" class="high-price-tag" style="border-radius: 8rpx;" >
|
||||
<image :src="Service.GetIconImg('/static/index/task/fire.png')" style="width: 24rpx; height: 24rpx;" mode=""></image>
|
||||
<text class="high-price-text" style="margin-left: 4rpx;" >高价单</text>
|
||||
</view>
|
||||
<view v-else class="high-price-tag" :style="{'border':activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14','color':activeTab==1?'#52C41A':'#FAAD14' }" style="background-color: #fff;" >
|
||||
<text class="high-price-text">{{activeTab==1?'待取单':'配送中'}}</text>
|
||||
</view>
|
||||
<view class="" v-if="activeTab!==0" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">老北京炸酱面</text>
|
||||
<text class="distance">500m</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text">北京市朝阳区三里屯SOHO</text>
|
||||
<text v-if="activeTab!==0" class="address-text">共3件商品</text>
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<view v-if="activeTab==1" class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==0" class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">A121</text>
|
||||
</view>
|
||||
<view v-if="activeTab==2" class="">
|
||||
<text class="address-text">据您1.2km</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" color="#FF9500" size="24rpx" />
|
||||
<text class="time-text" :style="{'color':activeTab==0?'#FAAD14':'#FF0000'}" >{{activeTab==0?'12:30 前取餐':'12:30 前送达'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
<up-button type="primary" @click="buttonClick()" :color="activeTab==0?'#1890FF':(activeTab==1?'#52C41A':'#52C41A')" size="large" class="grab-btn">{{ activeTab==0?'立即抢单':(activeTab==1?'我已取餐':'确认送达') }}</up-button>
|
||||
</view>
|
||||
|
||||
<!-- 没有更多任务提示 -->
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100vw; height: 60rpx; " ></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue'
|
||||
import { Service } from '@/Service/Service'
|
||||
|
||||
let loading = ref(true)
|
||||
// 标签数据
|
||||
const tabs = ['新任务', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let status = ref('nomore')
|
||||
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
// 页面跳转
|
||||
const gopage = () => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder')
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const buttonClick=()=>{
|
||||
|
||||
if(activeTab.value==2){
|
||||
Service.GoPage('/pages/order/finish')
|
||||
}
|
||||
}
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* 订单列表 */
|
||||
.order-list {
|
||||
padding: 0rpx 30rpx;
|
||||
}
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
/* 没有更多任务 */
|
||||
.no-more-tasks {
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 80rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-tag {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-merchant-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 60rpx;
|
||||
height: 28rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 400rpx;
|
||||
height: 28rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-price-time-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.skeleton-price {
|
||||
width: 80rpx;
|
||||
height: 36rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-time-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-time-text {
|
||||
width: 150rpx;
|
||||
height: 26rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-card .skeleton-tag::after,
|
||||
.skeleton-card .skeleton-merchant-name::after,
|
||||
.skeleton-card .skeleton-distance::after,
|
||||
.skeleton-card .skeleton-address-text::after,
|
||||
.skeleton-card .icon-placeholder::after,
|
||||
.skeleton-card .skeleton-price::after,
|
||||
.skeleton-card .skeleton-time-text::after,
|
||||
.skeleton-card .skeleton-button::after,
|
||||
.skeleton-loading .skeleton-tab-text::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,476 @@
|
||||
<template>
|
||||
|
||||
<view class="skeleton-container" v-if="isLoading">
|
||||
<!-- 顶部提示栏骨架 -->
|
||||
<view class="skeleton-top-tip"></view>
|
||||
|
||||
<!-- 身份信息区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-upload-item"></view>
|
||||
<view class="skeleton-upload-item"></view>
|
||||
</view>
|
||||
|
||||
<!-- 人脸识别区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-face-area">
|
||||
<view class="skeleton-face-icon"></view>
|
||||
<view class="skeleton-face-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 协议勾选骨架 -->
|
||||
<view class="skeleton-agreement"></view>
|
||||
|
||||
<!-- 提交按钮骨架 -->
|
||||
<view class="skeleton-submit"></view>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="real-name-auth-container">
|
||||
<!-- 顶部提示栏 -->
|
||||
<view class="top-tip">
|
||||
<text class="tip-text">请完成实名认证,保障您的接单权益</text>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-content">
|
||||
<!-- 身份信息区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份信息</view>
|
||||
|
||||
<!-- 姓名输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">姓名</view>
|
||||
<u-input v-model="formData.name" placeholder="请输入身份证姓名" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" />
|
||||
</view>
|
||||
|
||||
<!-- 身份证号输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">身份证号</view>
|
||||
<u-input v-model="formData.idCard" placeholder="请输入18位身份证号" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" maxlength="18" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份证照片</view>
|
||||
|
||||
<!-- 上传身份证正面 -->
|
||||
<view class="upload-item">
|
||||
<view class="upload-area bordered-area">
|
||||
<view class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证正面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-if="formData.frontImage" class="uploaded-placeholder">
|
||||
<text>身份证正面</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上传身份证反面 -->
|
||||
<view class="upload-item">
|
||||
<view class="upload-area bordered-area">
|
||||
<view class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证反面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-if="formData.backImage" class="uploaded-placeholder">
|
||||
<text>身份证反面</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 人脸识别区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">人脸验证</view>
|
||||
|
||||
<view class="face-verify-area" @click="handleFaceVerify">
|
||||
<view class="face-icon">
|
||||
<up-icon name="account" size="60" color="#1890ff"></up-icon>
|
||||
</view>
|
||||
<view class="face-text">点击进行人脸识别</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 协议勾选 -->
|
||||
<view class="agreement-section">
|
||||
<u-checkbox v-model="formData.agreed" shape="circle" class="checkbox" />
|
||||
<text class="agreement-text">我已阅读并同意</text>
|
||||
<text class="agreement-link" @click="handleAgreementClick">《骑手实名认证协议》</text>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<u-button type="primary" class="submit-btn" size="large">
|
||||
提交认证
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
let isLoading = ref(true)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
name: '',
|
||||
idCard: '',
|
||||
frontImage: '',
|
||||
backImage: '',
|
||||
agreed: false
|
||||
});
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
isLoading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
// 处理人脸识别
|
||||
const handleFaceVerify = () => {
|
||||
// 在实际应用中,这里会调用人脸识别相关API
|
||||
console.log('开始人脸识别');
|
||||
};
|
||||
|
||||
// 处理协议点击
|
||||
const handleAgreementClick = () => {
|
||||
// 打开协议详情
|
||||
console.log('打开协议详情');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-top-tip {
|
||||
height: 70rpx;
|
||||
width: 100%;
|
||||
background-color: #e6f7ff;
|
||||
margin: 20rpx 0;
|
||||
border-radius: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
height: 32rpx;
|
||||
width: 160rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.skeleton-label {
|
||||
height: 28rpx;
|
||||
width: 120rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-input {
|
||||
height: 28rpx;
|
||||
width: calc(100% - 140rpx);
|
||||
background-color: #e6e6e6;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-upload-item {
|
||||
height: 200rpx;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 2rpx solid #000;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-face-area {
|
||||
height: 240rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-face-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-face-text {
|
||||
height: 28rpx;
|
||||
width: 200rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 14rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-agreement {
|
||||
height: 30rpx;
|
||||
width: 60%;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-submit {
|
||||
height: 92rpx;
|
||||
width: 100%;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 46rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.top-tip {
|
||||
background-color: #E6F7FF;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #1890ff;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 120rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bordered-area {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 60rpx;
|
||||
color: #1890ff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.uploaded-placeholder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid #000;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.face-verify-area {
|
||||
background-color: #fff;
|
||||
height: 240rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.face-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6f7ff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.face-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.agreement-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
font-size: 26rpx;
|
||||
color: #1890ff;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
margin-top: 60rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 92rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 46rpx;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
background-color: #a0cfff;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
13938
.svn/pristine/1f/1ffed74b02329a3cddec4cb05b3f8203ebe54f3b.svn-base
Normal file
@@ -0,0 +1,808 @@
|
||||
<template>
|
||||
|
||||
<view v-if="isLoading" class="skeleton-container" style="padding-top: 80rpx;" >
|
||||
<!-- 统计数据区域骨架 -->
|
||||
<view class="skeleton-stats-section">
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮骨架 -->
|
||||
<view class="skeleton-action-section">
|
||||
<view class="skeleton-accept-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 标签栏骨架 -->
|
||||
<view class="skeleton-tab-bar">
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任务列表骨架 -->
|
||||
<view class="skeleton-task-list">
|
||||
<!-- 任务卡片骨架 -->
|
||||
<view class="skeleton-task-section" v-for="i in 3" :key="i">
|
||||
<!-- 高价单标签骨架 -->
|
||||
<view class="skeleton-tag-row">
|
||||
<view class="skeleton-high-price-tag"></view>
|
||||
<view class="skeleton-phone-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息骨架 -->
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息骨架 -->
|
||||
<view class="skeleton-address-info">
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间骨架 -->
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-pickup-code"></view>
|
||||
<view class="skeleton-pickup-time"></view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮骨架 -->
|
||||
<view class="skeleton-grab-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="rider-home" style="padding-top: 60rpx;" >
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥{{userData.dayAmount.toFixed(2)}}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">{{userData.dayOrderCount}}单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">配送中</text>
|
||||
<text class="stat-value ongoing">{{ userData.takeOrderCount }}单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button :disabled='riderInfo.status===0' type="primary" shape="circle" size="default"
|
||||
class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ riderInfo.status==0?'审核中':(riderInfo.isOnline == 0 ? '已下线' : '已上线') }}</up-button>
|
||||
</view>
|
||||
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status==1" class="" style="padding: 0 30rpx;">
|
||||
<!-- -->
|
||||
<view v-for="(orderItem,orderIndex) in orderList " @click="gopage(orderItem.orderId)" :key="orderIndex"
|
||||
class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
|
||||
<view class="high-price-tag"
|
||||
:style="{'border':activeTab==0?'1rpx solid #FF7875':(activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14'),'color':activeTab==0?'#FF7875':(activeTab==1?'#52C41A':'#FAAD14') }"
|
||||
style="background-color: #fff;">
|
||||
<text class="high-price-text">{{activeTab==0? '新订单':(activeTab==1? '待取单':'配送中')}}</text>
|
||||
</view>
|
||||
<view class="" @click.stop="call(orderItem.phone)" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">{{ orderItem.storeName }}</text>
|
||||
<text v-if="activeTab==1" class="distance">{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text"> {{orderItem.address }}</text>
|
||||
<!-- <text v-if="activeTab!==0" class="address-text">共3件商品</text> -->
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<!-- <view class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
<view class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">{{orderItem.pickCode }}</text>
|
||||
</view>
|
||||
<view v-if="activeTab!==1" class="">
|
||||
<text class="address-text">据您{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" :color="activeTab==0?'#FAAD14':'#FF0000'" size="16" />
|
||||
<text class="time-text"
|
||||
:style="{'color':activeTab==0?'#FAAD14':'#FF0000'}">{{ orderItem.makeTime.split(' ').length==2?'预计'+orderItem.makeTime.split(' ')[1]+'送达':orderItem.makeTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
|
||||
<view class="" style="display: flex; ">
|
||||
<view class="" style="width: 100%;"
|
||||
@click.stop="activeTab==0?takeOrder(orderItem.orderId):pickFood(orderItem.orderId)">
|
||||
<button type="primary" :color="activeTab==0?'#1890FF':'#52C41A'" size="large"
|
||||
class="grab-btn">{{ activeTab==0?'立即接单':(activeTab==1?'我已取餐':'确认送达')}}</button>
|
||||
</view>
|
||||
<view class="" style="width: 20rpx;" v-if="activeTab!=0">
|
||||
|
||||
</view>
|
||||
<view style="width: 100%;" v-if="activeTab!=0" @click.stop="Service.GoPage('/pages/order/orderMap?orderId='+orderItem.orderId)" class="">
|
||||
<button type="primary" color="#1890FF"
|
||||
class="grab-btn">{{activeTab==1?'导航取餐':'导航送餐'}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status==0" style=" margin-top: 20rpx; text-align: center; font-weight: bold; font-size: 34rpx;" class="">
|
||||
信息审核中·请等待审核
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
let userData = ref({
|
||||
dayAmount: 0,
|
||||
dayOrderCount: 0,
|
||||
takeOrderCount: 0
|
||||
})
|
||||
|
||||
const tabs = ['新订单', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let riderInfo = ref<any>({})
|
||||
|
||||
let orderList = ref<Array<any>>([])
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
uni.$on(`newOrder`, (data) => {
|
||||
newOrder()
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
onShow(() => {
|
||||
getData()
|
||||
getOrderData()
|
||||
})
|
||||
|
||||
// 有新订单
|
||||
const newOrder = () =>{
|
||||
if(activeTab.value==0){
|
||||
getOrderData()
|
||||
}
|
||||
|
||||
audioPlay()
|
||||
}
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderHomeInfo().then(res => {
|
||||
isLoading.value = false
|
||||
riderInfo.value = res.data.riderInfo
|
||||
userData.value = res.data
|
||||
if (res.data.riderInfo.status === -1) {
|
||||
Service.GoPage('/pages/my/completeData')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getOrderData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
orderList.value = []
|
||||
getOrderList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getOrderList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
|
||||
if (activeTab.value == 0) {
|
||||
CNRiderOrderService.GetRiderOrderList(page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
} else {
|
||||
CNRiderOrderService.GetRiderTakeOrderList(activeTab.value == 1 ? 0 : 1, page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 接单
|
||||
const takeOrder = (orderId : string) => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId).then(res => {
|
||||
if (res.data) {
|
||||
activeTab.value=1
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 取餐
|
||||
const pickFood = (orderId : string) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId, activeTab.value).then(res => {
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
getOrderData()
|
||||
}
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
CNRiderDataService.UpdateRiderOnline().then(res => {
|
||||
if (res.data) {
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// 距离计算
|
||||
const distance = (item : any) => {
|
||||
if (item < 0) {
|
||||
return Number(item * 100).toFixed(2) + 'm'
|
||||
} else {
|
||||
return Number(item).toFixed(2) + 'km'
|
||||
}
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
const call = (e : string) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: e
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 页面跳转
|
||||
const gopage = (id) => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder?orderId=' + id)
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail?orderId=' + id+'&type='+activeTab.value)
|
||||
}
|
||||
}
|
||||
|
||||
const audioPlay = () => {
|
||||
const innerAudioContext = uni.createInnerAudioContext();
|
||||
innerAudioContext.autoplay = true;
|
||||
innerAudioContext.src = '/static/order.mp3';
|
||||
innerAudioContext.onPlay(() => {
|
||||
console.log('开始播放');
|
||||
});
|
||||
innerAudioContext.onError((res) => {
|
||||
console.log(res.errMsg);
|
||||
console.log(res.errCode);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 统计数据区域骨架 */
|
||||
.skeleton-stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.skeleton-stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-stat-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-stat-value {
|
||||
width: 150rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 接单按钮骨架 */
|
||||
.skeleton-action-section {
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-accept-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 标签栏骨架 */
|
||||
.skeleton-tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 100rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 任务列表骨架 */
|
||||
.skeleton-task-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 标签骨架 */
|
||||
.skeleton-tag-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.skeleton-high-price-tag {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-phone-btn {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 商家信息骨架 */
|
||||
.skeleton-merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 80rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 地址信息骨架 */
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 100%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 价格和时间骨架 */
|
||||
.skeleton-price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-pickup-code {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 按钮骨架 */
|
||||
.skeleton-grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,799 @@
|
||||
<template>
|
||||
|
||||
<view v-if="isLoading" class="skeleton-container" style="padding-top: 80rpx;">
|
||||
<!-- 统计数据区域骨架 -->
|
||||
<view class="skeleton-stats-section">
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮骨架 -->
|
||||
<view class="skeleton-action-section">
|
||||
<view class="skeleton-accept-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 标签栏骨架 -->
|
||||
<view class="skeleton-tab-bar">
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任务列表骨架 -->
|
||||
<view class="skeleton-task-list">
|
||||
<!-- 任务卡片骨架 -->
|
||||
<view class="skeleton-task-section" v-for="i in 3" :key="i">
|
||||
<!-- 高价单标签骨架 -->
|
||||
<view class="skeleton-tag-row">
|
||||
<view class="skeleton-high-price-tag"></view>
|
||||
<view class="skeleton-phone-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息骨架 -->
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息骨架 -->
|
||||
<view class="skeleton-address-info">
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间骨架 -->
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-pickup-code"></view>
|
||||
<view class="skeleton-pickup-time"></view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮骨架 -->
|
||||
<view class="skeleton-grab-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="rider-home" style="padding-top: 60rpx;">
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥{{userData.dayAmount.toFixed(2)}}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">{{userData.dayOrderCount}}单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">配送中</text>
|
||||
<text class="stat-value ongoing">{{ userData.takeOrderCount }}单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button :disabled='riderInfo.status===0' type="primary" shape="circle" size="default"
|
||||
class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ riderInfo.status==0?'审核中':(riderInfo.isOnline == 0 ? '已下线' : '已上线') }}</up-button>
|
||||
</view>
|
||||
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status==1" class="" style="padding: 0 30rpx;">
|
||||
<!-- -->
|
||||
<view v-for="(orderItem,orderIndex) in orderList " @click="gopage(orderItem.orderId)" :key="orderIndex"
|
||||
class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
|
||||
<view class="high-price-tag"
|
||||
:style="{'border':activeTab==0?'1rpx solid #FF7875':(activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14'),'color':activeTab==0?'#FF7875':(activeTab==1?'#52C41A':'#FAAD14') }"
|
||||
style="background-color: #fff;">
|
||||
<text class="high-price-text">{{activeTab==0? '新订单':(activeTab==1? '待取单':'配送中')}}</text>
|
||||
</view>
|
||||
<view class="" @click.stop="call(orderItem.phone)" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">{{ orderItem.storeName }}</text>
|
||||
<text v-if="activeTab==1" class="distance">{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text"> {{orderItem.address }}</text>
|
||||
<!-- <text v-if="activeTab!==0" class="address-text">共3件商品</text> -->
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<!-- <view class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
<view class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text
|
||||
style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">{{orderItem.pickCode }}</text>
|
||||
</view>
|
||||
<view v-if="activeTab!==1" class="">
|
||||
<text class="address-text">据您{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" :color="activeTab==0?'#FAAD14':'#FF0000'" size="16" />
|
||||
<text class="time-text"
|
||||
:style="{'color':activeTab==0?'#FAAD14':'#FF0000'}">{{ orderItem.makeTime.split(' ').length==2?'预计'+orderItem.makeTime.split(' ')[1]+'送达':orderItem.makeTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
|
||||
<view class="" style="display: flex; ">
|
||||
<view class="" style="width: 100%;"
|
||||
@click.stop="activeTab==0?takeOrder(orderItem.orderId):pickFood(orderItem.orderId)">
|
||||
<button type="primary" :color="activeTab==0?'#1890FF':'#52C41A'" size="large"
|
||||
class="grab-btn">{{ activeTab==0?'立即接单':(activeTab==1?'我已取餐':'确认送达')}}</button>
|
||||
</view>
|
||||
<view class="" style="width: 20rpx;" v-if="activeTab!=0">
|
||||
|
||||
</view>
|
||||
<view style="width: 100%;" v-if="activeTab!=0"
|
||||
@click.stop="Service.GoPage('/pages/order/orderMap?orderId='+orderItem.orderId)" class="">
|
||||
<button type="primary" color="#1890FF" class="grab-btn">{{activeTab==1?'导航取餐':'导航送餐'}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status==0"
|
||||
style=" margin-top: 20rpx; text-align: center; font-weight: bold; font-size: 34rpx;" class="">
|
||||
信息审核中·请等待审核
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
let userData = ref({
|
||||
dayAmount: 0,
|
||||
dayOrderCount: 0,
|
||||
takeOrderCount: 0
|
||||
})
|
||||
|
||||
const tabs = ['新订单', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let riderInfo = ref<any>({})
|
||||
|
||||
let orderList = ref<Array<any>>([])
|
||||
|
||||
let a = ref(1)
|
||||
|
||||
onLoad(() => {
|
||||
uni.$on(`newOrder`, (data) => {
|
||||
a.value++
|
||||
console.log('消息推送1', a.value);
|
||||
newOrder()
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
onShow(() => {
|
||||
getData()
|
||||
getOrderData()
|
||||
})
|
||||
|
||||
// 有新订单
|
||||
const newOrder = () => {
|
||||
if (activeTab.value == 0) {
|
||||
getOrderData()
|
||||
}
|
||||
}
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderHomeInfo().then(res => {
|
||||
isLoading.value = false
|
||||
riderInfo.value = res.data.riderInfo
|
||||
userData.value = res.data
|
||||
if (res.data.riderInfo.status === -1) {
|
||||
Service.GoPage('/pages/my/completeData')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getOrderData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
orderList.value = []
|
||||
getOrderList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getOrderList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
|
||||
if (activeTab.value == 0) {
|
||||
CNRiderOrderService.GetRiderOrderList(page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
} else {
|
||||
CNRiderOrderService.GetRiderTakeOrderList(activeTab.value == 1 ? 0 : 1, page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 接单
|
||||
const takeOrder = (orderId : string) => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId).then(res => {
|
||||
if (res.data) {
|
||||
activeTab.value = 1
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 取餐
|
||||
const pickFood = (orderId : string) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId, activeTab.value).then(res => {
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
getOrderData()
|
||||
}
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
CNRiderDataService.UpdateRiderOnline().then(res => {
|
||||
if (res.data) {
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// 距离计算
|
||||
const distance = (item : any) => {
|
||||
if (item < 0) {
|
||||
return Number(item * 100).toFixed(2) + 'm'
|
||||
} else {
|
||||
return Number(item).toFixed(2) + 'km'
|
||||
}
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
const call = (e : string) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: e
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 页面跳转
|
||||
const gopage = (id) => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder?orderId=' + id)
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail?orderId=' + id + '&type=' + activeTab.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 统计数据区域骨架 */
|
||||
.skeleton-stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.skeleton-stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-stat-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-stat-value {
|
||||
width: 150rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 接单按钮骨架 */
|
||||
.skeleton-action-section {
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-accept-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 标签栏骨架 */
|
||||
.skeleton-tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 100rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 任务列表骨架 */
|
||||
.skeleton-task-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 标签骨架 */
|
||||
.skeleton-tag-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.skeleton-high-price-tag {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-phone-btn {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 商家信息骨架 */
|
||||
.skeleton-merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 80rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 地址信息骨架 */
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 100%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 价格和时间骨架 */
|
||||
.skeleton-price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-pickup-code {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 按钮骨架 */
|
||||
.skeleton-grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
@import 'uview-plus/theme.scss';
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color: #333; // 基本色
|
||||
$uni-text-color-inverse: #fff; // 反色
|
||||
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable: #c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color: #fff;
|
||||
$uni-bg-color-grey: #f8f8f8;
|
||||
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
|
||||
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color: #c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm: 12px;
|
||||
$uni-font-size-base: 14px;
|
||||
$uni-font-size-lg: 16;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm: 20px;
|
||||
$uni-img-size-base: 26px;
|
||||
$uni-img-size-lg: 40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2c405a; // 文章标题颜色
|
||||
$uni-font-size-title: 20px;
|
||||
$uni-color-subtitle: #555; // 二级标题颜色
|
||||
$uni-font-size-subtitle: 18px;
|
||||
$uni-color-paragraph: #3f536e; // 文章段落颜色
|
||||
$uni-font-size-paragraph: 15px;
|
||||
@@ -0,0 +1,119 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { WebSocket } from '@/Service/Comm/TwWebSocket';
|
||||
import { Service } from "@/Service/Service"
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let isios = ref(false)
|
||||
|
||||
const currentLatitude = ref(0);
|
||||
const currentLongitude = ref(0);
|
||||
|
||||
let locationTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
|
||||
onLaunch(() => {
|
||||
isios.value = uni.getSystemInfoSync().platform != 'ios'//是否为ios
|
||||
//#ifdef APP-PLUS//app
|
||||
if (isios.value) {
|
||||
// getVersion()//更新
|
||||
}
|
||||
//#endif
|
||||
// 在 App 启动时,立即初始化并建立 WebSocket 连接
|
||||
WebSocket.ConnectSocketInit();
|
||||
// 打开调用
|
||||
uni.$on("ImCom", () => {
|
||||
WebSocket.ConnectSocketInit();
|
||||
})
|
||||
// 关闭调用
|
||||
uni.$on("ImComOff", () => {
|
||||
WebSocket.CloseSocket();
|
||||
})
|
||||
|
||||
});
|
||||
onShow(() => {
|
||||
WebSocket.ConnectSocketInit();
|
||||
|
||||
});
|
||||
onHide(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
const startFetchingLocation = () => {
|
||||
// 安全检查:如果定时器已存在,先清除,防止重复启动
|
||||
if (locationTimer) {
|
||||
clearInterval(locationTimer);
|
||||
}
|
||||
|
||||
console.log("开始定时获取位置,间隔1分钟...");
|
||||
|
||||
// 1. 立即执行第一次获取
|
||||
getLocationNow();
|
||||
|
||||
// 2. 设置定时器,每 60000 毫秒 (1分钟) 执行一次
|
||||
locationTimer = setInterval(() => {
|
||||
getLocationNow();
|
||||
}, 60000);
|
||||
};
|
||||
|
||||
const getLocationNow = () => {
|
||||
uni.getLocation({
|
||||
type: 'wgs84',
|
||||
isHighAccuracy: true,
|
||||
success: (res) => {
|
||||
|
||||
if(Service.GetUserIsLogin()){
|
||||
CNRiderOrderService.UpdateRiderLocation(res.longitude,res.latitude).then(res=>{})
|
||||
}
|
||||
|
||||
},
|
||||
fail: (err) => {
|
||||
// console.error('获取经纬度失败:', err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 停止定时获取位置
|
||||
*/
|
||||
const stopFetchingLocation = () => {
|
||||
if (locationTimer) {
|
||||
clearInterval(locationTimer);
|
||||
locationTimer = null; // 清理 ID
|
||||
}
|
||||
};
|
||||
|
||||
const getUpData = () => {
|
||||
// #ifdef APP
|
||||
// plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
|
||||
// NvpMerchService.GetAppVersion().then(res=>{
|
||||
// console.log('wgtinfo.versionCode',wgtinfo.versionCode);
|
||||
// if (res.data.version > wgtinfo.versionCode) {
|
||||
// setTimeout(function() {
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/upData/upData?info=" +
|
||||
// encodeURIComponent(
|
||||
// JSON.stringify(res.data))
|
||||
// })
|
||||
// }, 1000)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// #endif
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "uview-plus/index.scss";
|
||||
@import "colorui/main.css";
|
||||
@import "colorui/icon.css";
|
||||
|
||||
page {
|
||||
--nav-mian: #1890FF; //全局颜色
|
||||
--nav-vice: #52C41A; //副颜色
|
||||
--nav-diluted: #FF4D4F; //次颜色
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****登录接口*****/
|
||||
class CNRiderLoginService {
|
||||
private static RiderLoginPath : string = '/Login/RiderLogin';
|
||||
/*****登录注册*****/
|
||||
static RiderLogin(login : any) {
|
||||
var result = Service.Request(this.RiderLoginPath, "POST", login);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetKefuInfoPath: string = '/Home/GetKefuInfo';
|
||||
/*****获取客服电话*****/
|
||||
static GetKefuInfo() {
|
||||
var result = Service.Request(this.GetKefuInfoPath, "GET", {});
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
export {
|
||||
Service,
|
||||
CNRiderLoginService
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style="padding:50rpx 20rpx 18rpx; box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: space-between; ">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" color="#fff" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="" style="color: #fff; ">
|
||||
配送中 · 2单
|
||||
</view>
|
||||
<image :src="Service.GetIconImg('/static/index/order/voice.png')"
|
||||
style="width: 32rpx; height: 32rpx; " mode=""></image>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 88rpx; ">
|
||||
|
||||
</view>
|
||||
<view>
|
||||
1111
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service } from "@/Service/Service"
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,494 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="task-list-container skeleton-loading">
|
||||
<!-- 顶部标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; height: 120rpx"> </view>
|
||||
|
||||
<!-- 骨架屏订单列表 -->
|
||||
<view class="order-list">
|
||||
<!-- 骨架屏任务卡片 1 -->
|
||||
<view v-for="item in 3" class="task-section skeleton-card">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;" >
|
||||
<view class="skeleton-tag"></view>
|
||||
<view class="skeleton-time-group">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-time-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
<view class="skeleton-address-info">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-price"></view>
|
||||
<view class="skeleton-time-group">
|
||||
<view class="icon-placeholder"></view>
|
||||
<view class="skeleton-time-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; display: flex; justify-content: center; margin-top: 20rpx; " >
|
||||
<view class="" style="width: 200rpx; height: 40rpx; background-color: #fff; border-radius: 4rpx; " >
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="task-list-container" style="padding-top: 60rpx;" >
|
||||
<!-- 顶部标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100vw; height: 120rpx; ">
|
||||
|
||||
</view>
|
||||
<!-- 订单列表 -->
|
||||
<view class="order-list">
|
||||
<view @click="gopage()" v-for="(orderItem,orderIndex) in 3 " :key="orderIndex" class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<view v-if="activeTab==0" class="high-price-tag" style="border-radius: 8rpx;" >
|
||||
<image :src="Service.GetIconImg('/static/index/task/fire.png')" style="width: 24rpx; height: 24rpx;" mode=""></image>
|
||||
<text class="high-price-text" style="margin-left: 4rpx;" >高价单</text>
|
||||
</view>
|
||||
<view v-else class="high-price-tag" :style="{'border':activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14','color':activeTab==1?'#52C41A':'#FAAD14' }" style="background-color: #fff;" >
|
||||
<text class="high-price-text">{{activeTab==1?'待取单':'配送中'}}</text>
|
||||
</view>
|
||||
<view class="" v-if="activeTab!==0" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">老北京炸酱面</text>
|
||||
<text class="distance">500m</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text">北京市朝阳区三里屯SOHO</text>
|
||||
<text v-if="activeTab!==0" class="address-text">共3件商品</text>
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<view v-if="activeTab==1" class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==0" class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">A121</text>
|
||||
</view>
|
||||
<view v-if="activeTab==2" class="">
|
||||
<text class="address-text">据您1.2km</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" color="#FF9500" size="24rpx" />
|
||||
<text class="time-text" :style="{'color':activeTab==0?'#FAAD14':'#FF0000'}" >{{activeTab==0?'12:30 前取餐':'12:30 前送达'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
<up-button type="primary" @click="buttonClick()" :color="activeTab==0?'#1890FF':(activeTab==1?'#52C41A':'#52C41A')" size="large" class="grab-btn">{{ activeTab==0?'立即抢单':(activeTab==1?'我已取餐':'确认送达') }}</up-button>
|
||||
</view>
|
||||
|
||||
<!-- 没有更多任务提示 -->
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100vw; height: 60rpx; " ></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue'
|
||||
import { Service } from '@/Service/Service'
|
||||
|
||||
let loading = ref(true)
|
||||
// 标签数据
|
||||
const tabs = ['新任务', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let status = ref('nomore')
|
||||
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
// 页面跳转
|
||||
const gopage = () => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder')
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const buttonClick=()=>{
|
||||
|
||||
if(activeTab.value==2){
|
||||
Service.GoPage('/pages/order/finish')
|
||||
}
|
||||
}
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* 订单列表 */
|
||||
.order-list {
|
||||
padding: 0rpx 30rpx;
|
||||
}
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
/* 没有更多任务 */
|
||||
.no-more-tasks {
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 80rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-tag {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-merchant-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 60rpx;
|
||||
height: 28rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 400rpx;
|
||||
height: 28rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-price-time-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.skeleton-price {
|
||||
width: 80rpx;
|
||||
height: 36rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-time-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-time-text {
|
||||
width: 150rpx;
|
||||
height: 26rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-card .skeleton-tag::after,
|
||||
.skeleton-card .skeleton-merchant-name::after,
|
||||
.skeleton-card .skeleton-distance::after,
|
||||
.skeleton-card .skeleton-address-text::after,
|
||||
.skeleton-card .icon-placeholder::after,
|
||||
.skeleton-card .skeleton-price::after,
|
||||
.skeleton-card .skeleton-time-text::after,
|
||||
.skeleton-card .skeleton-button::after,
|
||||
.skeleton-loading .skeleton-tab-text::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,443 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="order-detail skeleton-loading">
|
||||
<!-- 订单基本信息骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view class="" style="display: flex; justify-content: space-between;align-items: center; ">
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<!-- 物品清单骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view v-for="item in 4" class="skeleton-block" style="width: 100%; height: 40rpx; "></view>
|
||||
|
||||
<view class="" style="display: flex; justify-content: center;">
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地图区域骨架屏 -->
|
||||
<view class="map-section skeleton-section">
|
||||
<view class="map-placeholder skeleton-map"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址区域骨架屏 -->
|
||||
<view class="address-section skeleton-section">
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-padding"></view>
|
||||
|
||||
<!-- 底部按钮骨架屏 -->
|
||||
<view class="bottom-action">
|
||||
<view class="skeleton-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="info-item">
|
||||
<view class="label" style="font-weight: 700; font-size: 30rpx;"> {{ orderInfo.distribution=='预约订单'?'预计'+orderInfo.makeTime.split(' ')[1]+'送达':orderInfo.makeTime }} </view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">{{ orderId }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="16" class="clock-icon"></u-icon>
|
||||
{{ Service.formatDate(orderInfo.addTime,1) }} 下单
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
数量
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
金额
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'110rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in JSON.parse(orderInfo.detail) " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
{{goodsItem.goodsName}}
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×{{ goodsItem.count }}
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥{{ goodsItem.count*goodsItem.price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;" >
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥{{ Number(orderInfo.postage).toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-if="JSON.parse(orderInfo.detail).length>2" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<view class="" style=" border-bottom: 4rpx solid #e2e2e2; ">
|
||||
<view class="section-title">取餐地址 : </view>
|
||||
<view class="address-content">
|
||||
<text class="store-name">{{ storeInfo.name }}</text>
|
||||
<text class="address"> {{ storeInfo.city }}{{storeInfo.region }}{{ storeInfo.address }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin: 10rpx 0; font-size: 30rpx;font-weight: 800;color: #333;">送餐地址 : </view>
|
||||
<view class="address-content">
|
||||
<text class="user-name">{{ JSON.parse(orderInfo.address).realName }}</text>
|
||||
<text class="address">{{ JSON.parse(orderInfo.address).address }}</text>
|
||||
<view v-if="orderInfo.remark" class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action">
|
||||
<up-button @click="placeOrder()" color="var(--nav-mian)" class="confirm-btn">立即接单</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
let deliveryTime = ref('')
|
||||
|
||||
let orderInfo = ref<any>({})
|
||||
let storeInfo = ref<any>({})
|
||||
let storeLocation = ref<any>({})
|
||||
|
||||
let orderId = ref('')
|
||||
onLoad((data : any) => {
|
||||
orderId.value = data.orderId
|
||||
getData()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
loading.value = false
|
||||
|
||||
if (res.data) {
|
||||
deliveryTime.value = res.data.deliveryTime
|
||||
orderInfo.value = res.data.orderInfo
|
||||
storeInfo.value = res.data.storeInfo
|
||||
storeLocation.value = res.data.storeLocation
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const placeOrder = () => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId.value).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('接单成功!')
|
||||
setTimeout(() => {
|
||||
Service.GoPageBack()
|
||||
},1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-section {
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-block {
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-short {
|
||||
height: 40rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-medium {
|
||||
height: 30rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-long {
|
||||
height: 30rpx;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.skeleton-map {
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 20rpx;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.skeleton-button {
|
||||
height: 90rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.bottom-padding {
|
||||
height: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-block::after,
|
||||
.skeleton-map::after,
|
||||
.skeleton-button::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"name" : "骑手端",
|
||||
"appid" : "__UNI__06C2D6A",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.2",
|
||||
"versionCode" : 102,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"compatible" : {
|
||||
"ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : false,
|
||||
"waiting" : false,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"Barcode" : {},
|
||||
"Maps" : {},
|
||||
"Geolocation" : {},
|
||||
"Camera" : {},
|
||||
"Contacts" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>"
|
||||
],
|
||||
"minSdkVersion" : 25,
|
||||
"targetSdkVersion" : 25,
|
||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {
|
||||
"idfa" : false,
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"ad" : {},
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"appkey_ios" : "3caf9e6f01b0085be1e75e0d0e281fe7",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
},
|
||||
"geolocation" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"__platform__" : [ "android" ],
|
||||
"appkey_ios" : "",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios" : {
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx6ef5a6a74620a3e8",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"qqmap" : {
|
||||
"key" : "7DIBZ-K4HCJ-ZR2FE-FOOOP-SALFT-RLFYW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"name" : "骑手端",
|
||||
"appid" : "__UNI__06C2D6A",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.6",
|
||||
"versionCode" : 106,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"compatible" : {
|
||||
"ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : false,
|
||||
"waiting" : false,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"Barcode" : {},
|
||||
"Maps" : {},
|
||||
"Geolocation" : {},
|
||||
"Camera" : {},
|
||||
"Contacts" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>"
|
||||
],
|
||||
"minSdkVersion" : 25,
|
||||
"targetSdkVersion" : 25,
|
||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {
|
||||
"idfa" : false,
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"ad" : {},
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"appkey_ios" : "3caf9e6f01b0085be1e75e0d0e281fe7",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
},
|
||||
"geolocation" : {
|
||||
"amap" : {
|
||||
"name" : "amapZAvZjTHj",
|
||||
"__platform__" : [ "android" ],
|
||||
"appkey_ios" : "",
|
||||
"appkey_android" : "3caf9e6f01b0085be1e75e0d0e281fe7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios" : {
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx6ef5a6a74620a3e8",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"qqmap" : {
|
||||
"key" : "7DIBZ-K4HCJ-ZR2FE-FOOOP-SALFT-RLFYW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<view class="contact-support-page">
|
||||
<!-- 全新方案:纯 CSS 手动构建的骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-wrapper">
|
||||
<view class="skeleton-card">
|
||||
<view style="padding: 40rpx 0; ">
|
||||
<view class="skeleton-item skeleton-text" style="width: 100%; height: 60rpx;"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 页面实际内容 -->
|
||||
<view v-else class="page-content">
|
||||
|
||||
<view class="page-container">
|
||||
<view class="card emergency-card" @click="callEmergency">
|
||||
<view class="emergency-title">
|
||||
<up-icon name="phone-fill" color="#fa6400" size="18"></up-icon>
|
||||
<text>紧急问题?直接拨打人工客服</text>
|
||||
</view>
|
||||
<text class="phone-number">{{ phone }}</text>
|
||||
<text class="service-time">9:00-22:00</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { Service, CNRiderLoginService } from "@/Service/CN/CNRiderLoginService";
|
||||
const loading = ref<boolean>(true);
|
||||
|
||||
let phone=ref('')
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
onShow(() => { });
|
||||
|
||||
const getData=()=>{
|
||||
|
||||
CNRiderLoginService.GetKefuInfo().then(res=>{
|
||||
loading.value = false;
|
||||
|
||||
if(res.code==0){
|
||||
phone.value=res.data.phone
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const callEmergency = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone.value
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@keyframes skeleton-blink {
|
||||
0% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.skeleton-item {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-blink 1.5s infinite linear;
|
||||
}
|
||||
|
||||
.skeleton-rect {
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.skeleton-text {
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-wrapper {
|
||||
padding: 24rpx;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.skeleton-card {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-support-page {
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
&.info-box {
|
||||
background-color: #ecf5ff;
|
||||
color: #40a9ff;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
padding: 0 30rpx;
|
||||
|
||||
:deep(.up-cell-group) {
|
||||
.up-cell {
|
||||
.up-cell__body {
|
||||
padding: 28rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cell-title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emergency-card {
|
||||
background-color: #ffffff;
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
|
||||
.emergency-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #fa6400;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.phone-number {
|
||||
display: block;
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin: 16rpx 0;
|
||||
}
|
||||
|
||||
.service-time {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,743 @@
|
||||
<template>
|
||||
<view class="image-cropper" :style="{ zIndex }" @wheel="cropper.mousewheel">
|
||||
<canvas v-if="use2d" type="2d" id="imgCanvas" class="img-canvas" :style="{
|
||||
width: `${canvansWidth}px`,
|
||||
height: `${canvansHeight}px`
|
||||
}"></canvas>
|
||||
<canvas v-else id="imgCanvas" canvas-id="imgCanvas" class="img-canvas" :style="{
|
||||
width: `${canvansWidth}px`,
|
||||
height: `${canvansHeight}px`
|
||||
}"></canvas>
|
||||
<view id="pic-preview" class="pic-preview" :change:init="cropper.initObserver" :init="initData" @touchstart="cropper.touchstart" @touchmove="cropper.touchmove" @touchend="cropper.touchend">
|
||||
<image v-if="imgSrc" id="crop-image" class="crop-image" :style="cropper.imageStyles" :src="imgSrc" webp></image>
|
||||
<view v-for="(item, index) in maskList" :key="item.id" :id="item.id" class="crop-mask-block" :style="cropper.maskStylesList[index]"></view>
|
||||
<view v-if="showBorder" id="crop-border" class="crop-border" :style="cropper.borderStyles"></view>
|
||||
<view v-if="radius > 0" id="crop-circle-box" class="crop-circle-box" :style="cropper.circleBoxStyles">
|
||||
<view class="crop-circle" id="crop-circle" :style="cropper.circleStyles"></view>
|
||||
</view>
|
||||
<block v-if="showGrid">
|
||||
<view v-for="(item, index) in gridList" :key="item.id" :id="item.id" class="crop-grid" :style="cropper.gridStylesList[index]"></view>
|
||||
</block>
|
||||
<block v-if="showAngle">
|
||||
<view v-for="(item, index) in angleList" :key="item.id" :id="item.id" class="crop-angle" :style="cropper.angleStylesList[index]">
|
||||
<view :style="[{
|
||||
width: `${angleSize}px`,
|
||||
height: `${angleSize}px`
|
||||
}]"></view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<slot />
|
||||
<view class="fixed-bottom safe-area-inset-bottom" :style="{ zIndex: initData.area.zIndex + 99 }">
|
||||
<view v-if="(rotatable || reverseRotatable) && !!imgSrc" class="action-bar">
|
||||
<view v-if="reverseRotatable" class="rotate-icon" @click="cropper.rotateImage270"></view>
|
||||
<view v-if="rotatable" class="rotate-icon is-reverse" @click="cropper.rotateImage90"></view>
|
||||
</view>
|
||||
<view v-if="!choosable" class="choose-btn" @click="cropClick">确定</view>
|
||||
<block v-else-if="!!imgSrc">
|
||||
<view class="rechoose" @click="chooseImage">重选</view>
|
||||
<button class="button" size="mini" @click="cropClick">确定</button>
|
||||
</block>
|
||||
<view v-else class="choose-btn" @click="chooseImage">选择图片</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- #ifdef APP-VUE -->
|
||||
<script module="cropper" lang="renderjs">
|
||||
import cropper from './qf-image-cropper.render.js';
|
||||
// vue3 app renderjs中条件编译无效
|
||||
cropper.setPlatform('APP');
|
||||
export default {
|
||||
mixins: [ cropper ]
|
||||
}
|
||||
</script>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<script module="cropper" lang="renderjs">
|
||||
import cropper from './qf-image-cropper.render.js';
|
||||
export default {
|
||||
mixins: [ cropper ]
|
||||
}
|
||||
</script>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ -->
|
||||
<script module="cropper" lang="wxs" src="./qf-image-cropper.wxs"></script>
|
||||
<!-- #endif -->
|
||||
<script>
|
||||
/** 裁剪区域最大宽高所占屏幕宽度百分比 */
|
||||
const AREA_SIZE = 75;
|
||||
/** 图片默认宽高 */
|
||||
const IMG_SIZE = 300;
|
||||
|
||||
export default {
|
||||
name:"qf-image-cropper",
|
||||
// #ifdef MP-WEIXIN
|
||||
options: {
|
||||
// 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响
|
||||
styleIsolation: "isolated"
|
||||
},
|
||||
// #endif
|
||||
props: {
|
||||
/** 图片资源地址 */
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/** 裁剪宽度,有些平台或设备对于canvas的尺寸有限制,过大可能会导致无法正常绘制 */
|
||||
width: {
|
||||
type: Number,
|
||||
default: IMG_SIZE
|
||||
},
|
||||
/** 裁剪高度,有些平台或设备对于canvas的尺寸有限制,过大可能会导致无法正常绘制 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: IMG_SIZE
|
||||
},
|
||||
/** 是否绘制裁剪区域边框 */
|
||||
showBorder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 是否绘制裁剪区域网格参考线 */
|
||||
showGrid: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 是否展示四个支持伸缩的角 */
|
||||
showAngle: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 裁剪区域最小缩放倍数 */
|
||||
areaScale: {
|
||||
type: Number,
|
||||
default: 0.3
|
||||
},
|
||||
/** 图片最小缩放倍数 */
|
||||
minScale: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
/** 图片最大缩放倍数 */
|
||||
maxScale: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
/** 检查图片位置是否超出裁剪边界,如果超出则会矫正位置 */
|
||||
checkRange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 生成图片背景色:如果裁剪区域没有完全包含在图片中时,不设置该属性生成图片存在一定的透明块 */
|
||||
backgroundColor: {
|
||||
type: String
|
||||
},
|
||||
/** 是否有回弹效果:当 checkRange 为 true 时有效,拖动时可以拖出边界,释放时会弹回边界 */
|
||||
bounce: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 是否支持翻转 */
|
||||
rotatable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 是否支持逆向翻转 */
|
||||
reverseRotatable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/** 是否支持从本地选择素材 */
|
||||
choosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/** 是否开启硬件加速,图片缩放过程中如果出现元素的“留影”或“重影”效果,可通过该方式解决或减轻这一问题 */
|
||||
gpu: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/** 四个角尺寸,单位px */
|
||||
angleSize: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
/** 四个角边框宽度,单位px */
|
||||
angleBorderWidth: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
zIndex: {
|
||||
type: [Number, String]
|
||||
},
|
||||
/** 裁剪图片圆角半径,单位px */
|
||||
radius: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/** 生成文件的类型,只支持 'jpg' 或 'png'。默认为 'png' */
|
||||
fileType: {
|
||||
type: String,
|
||||
default: 'png'
|
||||
},
|
||||
/**
|
||||
* 图片从绘制到生成所需时间,单位ms
|
||||
* 微信小程序平台使用 `Canvas 2D` 绘制时有效
|
||||
* 如绘制大图或出现裁剪图片空白等情况应适当调大该值,因 `Canvas 2d` 采用同步绘制,需自己把控绘制完成时间
|
||||
*/
|
||||
delay: {
|
||||
type: Number,
|
||||
default: 1000
|
||||
},
|
||||
// #ifdef H5
|
||||
/**
|
||||
* 页面是否是原生标题栏
|
||||
* H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 "navigationStyle": "custom" 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差。
|
||||
* 注:因H5平台的窗口高度是包含标题栏的,而屏幕触摸点的坐标是不包含的
|
||||
*/
|
||||
navigation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
emits: ["crop"],
|
||||
data() {
|
||||
return {
|
||||
// 用不同 id 使 v-for key 不重复
|
||||
maskList: [
|
||||
{ id: 'crop-mask-block-1' },
|
||||
{ id: 'crop-mask-block-2' },
|
||||
{ id: 'crop-mask-block-3' },
|
||||
{ id: 'crop-mask-block-4' },
|
||||
],
|
||||
gridList: [
|
||||
{ id: 'crop-grid-1' },
|
||||
{ id: 'crop-grid-2' },
|
||||
{ id: 'crop-grid-3' },
|
||||
{ id: 'crop-grid-4' },
|
||||
],
|
||||
angleList: [
|
||||
{ id: 'crop-angle-1' },
|
||||
{ id: 'crop-angle-2' },
|
||||
{ id: 'crop-angle-3' },
|
||||
{ id: 'crop-angle-4' },
|
||||
],
|
||||
/** 本地缓存的图片路径 */
|
||||
imgSrc: '',
|
||||
/** 图片的裁剪宽度 */
|
||||
imgWidth: IMG_SIZE,
|
||||
/** 图片的裁剪高度 */
|
||||
imgHeight: IMG_SIZE,
|
||||
/** 裁剪区域最大宽度所占屏幕宽度百分比 */
|
||||
widthPercent: AREA_SIZE,
|
||||
/** 裁剪区域最大高度所占屏幕宽度百分比 */
|
||||
heightPercent: AREA_SIZE,
|
||||
/** 裁剪区域布局信息 */
|
||||
area: {},
|
||||
/** 未被缩放过的图片宽 */
|
||||
oldWidth: 0,
|
||||
/** 未被缩放过的图片高 */
|
||||
oldHeight: 0,
|
||||
/** 系统信息 */
|
||||
sys: uni.getSystemInfoSync(),
|
||||
scaleWidth: 0,
|
||||
scaleHeight: 0,
|
||||
rotate: 0,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
use2d: false,
|
||||
canvansWidth: 0,
|
||||
canvansHeight: 0,
|
||||
// imageStyles: {},
|
||||
// maskStylesList: [{}, {}, {}, {}],
|
||||
// borderStyles: {},
|
||||
// gridStylesList: [{}, {}, {}, {}],
|
||||
// angleStylesList: [{}, {}, {}, {}],
|
||||
// circleBoxStyles: {},
|
||||
// circleStyles: {},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
initData() {
|
||||
// console.log('initData')
|
||||
return {
|
||||
timestamp: new Date().getTime(),
|
||||
area: {
|
||||
...this.area,
|
||||
bounce: this.bounce,
|
||||
showBorder: this.showBorder,
|
||||
showGrid: this.showGrid,
|
||||
showAngle: this.showAngle,
|
||||
angleSize: this.angleSize,
|
||||
angleBorderWidth: this.angleBorderWidth,
|
||||
minScale: this.areaScale,
|
||||
widthPercent: this.widthPercent,
|
||||
heightPercent: this.heightPercent,
|
||||
radius: this.radius,
|
||||
checkRange: this.checkRange,
|
||||
zIndex: +this.zIndex || 0,
|
||||
},
|
||||
sys: this.sys,
|
||||
img: {
|
||||
minScale: this.minScale,
|
||||
maxScale: this.maxScale,
|
||||
src: this.imgSrc,
|
||||
width: this.oldWidth,
|
||||
height: this.oldHeight,
|
||||
oldWidth: this.oldWidth,
|
||||
oldHeight: this.oldHeight,
|
||||
gpu: this.gpu,
|
||||
}
|
||||
}
|
||||
},
|
||||
imgProps() {
|
||||
return {
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
src: this.src,
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
imgProps: {
|
||||
handler(val, oldVal) {
|
||||
// 自定义裁剪尺,示例如下:
|
||||
this.imgWidth = Number(val.width) || IMG_SIZE;
|
||||
this.imgHeight = Number(val.height) || IMG_SIZE;
|
||||
let use2d = true;
|
||||
// #ifndef MP-WEIXIN
|
||||
use2d = false;
|
||||
// #endif
|
||||
// if(use2d && (this.imgWidth > 1365 || this.imgHeight > 1365)) {
|
||||
// use2d = false;
|
||||
// }
|
||||
let canvansWidth = this.imgWidth;
|
||||
let canvansHeight = this.imgHeight;
|
||||
let size = Math.max(canvansWidth, canvansHeight)
|
||||
let scalc = 1;
|
||||
if(size > 1365) {
|
||||
scalc = 1365 / size;
|
||||
}
|
||||
this.canvansWidth = canvansWidth * scalc;
|
||||
this.canvansHeight = canvansHeight * scalc;
|
||||
this.use2d = use2d;
|
||||
this.initArea();
|
||||
const src = val.src || this.imgSrc;
|
||||
src && this.initImage(src, oldVal === undefined);
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/** 提供给wxs调用,用来接收图片变更数据 */
|
||||
dataChange(e) {
|
||||
// console.log('dataChange', e)
|
||||
this.scaleWidth = e.width;
|
||||
this.scaleHeight = e.height;
|
||||
this.rotate = e.rotate;
|
||||
this.offsetX = e.x;
|
||||
this.offsetY = e.y;
|
||||
},
|
||||
/** 初始化裁剪区域布局信息 */
|
||||
initArea() {
|
||||
// 底部操作栏高度 = 底部底部操作栏内容高度 + 设备底部安全区域高度
|
||||
this.sys.offsetBottom = uni.upx2px(100) + this.sys.safeAreaInsets.bottom;
|
||||
// #ifndef H5
|
||||
this.sys.windowTop = 0;
|
||||
this.sys.navigation = true;
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
// h5平台的窗口高度是包含标题栏的
|
||||
this.sys.windowTop = this.sys.windowTop || 44;
|
||||
this.sys.navigation = this.navigation;
|
||||
// #endif
|
||||
let wp = this.widthPercent;
|
||||
let hp = this.heightPercent;
|
||||
if (this.imgWidth > this.imgHeight) {
|
||||
hp = hp * this.imgHeight / this.imgWidth;
|
||||
} else if (this.imgWidth < this.imgHeight) {
|
||||
wp = wp * this.imgWidth / this.imgHeight;
|
||||
}
|
||||
const size = this.sys.windowWidth > this.sys.windowHeight ? this.sys.windowHeight : this.sys.windowWidth;
|
||||
const width = size * wp / 100;
|
||||
const height = size * hp / 100;
|
||||
const left = (this.sys.windowWidth - width) / 2;
|
||||
const right = left + width;
|
||||
const top = (this.sys.windowHeight + this.sys.windowTop - this.sys.offsetBottom - height) / 2;
|
||||
const bottom = this.sys.windowHeight + this.sys.windowTop - this.sys.offsetBottom - top;
|
||||
this.area = { width, height, left, right, top, bottom };
|
||||
this.scaleWidth = width;
|
||||
this.scaleHeight = height;
|
||||
},
|
||||
/** 从本地选取图片 */
|
||||
chooseImage(options) {
|
||||
// #ifdef MP-WEIXIN || MP-JD
|
||||
if(uni.chooseMedia) {
|
||||
uni.chooseMedia({
|
||||
...options,
|
||||
count: 1,
|
||||
mediaType: ['image'],
|
||||
success: (res) => {
|
||||
this.resetData();
|
||||
this.initImage(res.tempFiles[0].tempFilePath);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
// #endif
|
||||
uni.chooseImage({
|
||||
...options,
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
this.resetData();
|
||||
this.initImage(res.tempFiles[0].path);
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 重置数据 */
|
||||
resetData() {
|
||||
this.imgSrc = '';
|
||||
this.rotate = 0;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.initArea();
|
||||
},
|
||||
/**
|
||||
* 初始化图片信息
|
||||
* @param {String} url 图片链接
|
||||
*/
|
||||
initImage(url, isFirst) {
|
||||
uni.getImageInfo({
|
||||
src: url,
|
||||
success: async (res) => {
|
||||
if (isFirst && this.src === url) await (new Promise((resolve) => setTimeout(resolve, 50)));
|
||||
this.imgSrc = res.path;
|
||||
let scale = res.width / res.height;
|
||||
let areaScale = this.area.width / this.area.height;
|
||||
if (scale > 1) { // 横向图片
|
||||
if (scale >= areaScale) { // 图片宽不小于目标宽,则高固定,宽自适应
|
||||
this.scaleWidth = (this.scaleHeight / res.height) * this.scaleWidth * (res.width / this.scaleWidth);
|
||||
} else { // 否则宽固定、高自适应
|
||||
this.scaleHeight = res.height * this.scaleWidth / res.width;
|
||||
}
|
||||
} else { // 纵向图片
|
||||
if (scale <= areaScale) { // 图片高不小于目标高,宽固定,高自适应
|
||||
this.scaleHeight = (this.scaleWidth / res.width) * this.scaleHeight / (this.scaleHeight / res.height);
|
||||
} else { // 否则高固定,宽自适应
|
||||
this.scaleWidth = res.width * this.scaleHeight / res.height;
|
||||
}
|
||||
}
|
||||
// 记录原始宽高,为缩放比列做限制
|
||||
this.oldWidth = +this.scaleWidth.toFixed(2);
|
||||
this.oldHeight = +this.scaleHeight.toFixed(2);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error(err)
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 剪切图片圆角
|
||||
* @param {Object} ctx canvas 的绘图上下文对象
|
||||
* @param {Number} radius 圆角半径
|
||||
* @param {Number} scale 生成图片的实际尺寸与截取区域比
|
||||
* @param {Function} drawImage 执行剪切时所调用的绘图方法,入参为是否执行了剪切
|
||||
*/
|
||||
drawClipImage(ctx, radius, scale, drawImage) {
|
||||
if(radius > 0) {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
const w = this.canvansWidth;
|
||||
const h = this.canvansHeight;
|
||||
if(w === h && radius >= w / 2) { // 圆形
|
||||
ctx.arc(w / 2, h / 2, w / 2, 0, 2 * Math.PI);
|
||||
} else { // 圆角矩形
|
||||
if(w !== h) { // 限制圆角半径不能超过短边的一半
|
||||
radius = Math.min(w / 2, h / 2, radius);
|
||||
// radius = Math.min(Math.max(w, h) / 2, radius);
|
||||
}
|
||||
ctx.moveTo(radius, 0);
|
||||
ctx.arcTo(w, 0, w, h, radius);
|
||||
ctx.arcTo(w, h, 0, h, radius);
|
||||
ctx.arcTo(0, h, 0, 0, radius);
|
||||
ctx.arcTo(0, 0, w, 0, radius);
|
||||
ctx.closePath();
|
||||
}
|
||||
ctx.clip();
|
||||
drawImage && drawImage(true);
|
||||
ctx.restore();
|
||||
} else {
|
||||
drawImage && drawImage(false);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 旋转图片
|
||||
* @param {Object} ctx canvas 的绘图上下文对象
|
||||
* @param {Number} rotate 旋转角度
|
||||
* @param {Number} scale 生成图片的实际尺寸与截取区域比
|
||||
*/
|
||||
drawRotateImage(ctx, rotate, scale) {
|
||||
if(rotate !== 0) {
|
||||
// 1. 以图片中心点为旋转中心点
|
||||
const x = this.scaleWidth * scale / 2;
|
||||
const y = this.scaleHeight * scale / 2;
|
||||
ctx.translate(x, y);
|
||||
// 2. 旋转画布
|
||||
ctx.rotate(rotate * Math.PI / 180);
|
||||
// 3. 旋转完画布后恢复设置旋转中心时所做的偏移
|
||||
ctx.translate(-x, -y);
|
||||
}
|
||||
},
|
||||
drawImage(ctx, image, callback) {
|
||||
// 生成图片的实际尺寸与截取区域比
|
||||
const scale = this.canvansWidth / this.area.width;
|
||||
if(this.backgroundColor) {
|
||||
if(ctx.setFillStyle) ctx.setFillStyle(this.backgroundColor);
|
||||
else ctx.fillStyle = this.backgroundColor;
|
||||
ctx.fillRect(0, 0, this.canvansWidth, this.canvansHeight);
|
||||
}
|
||||
this.drawClipImage(ctx, this.radius, scale, () => {
|
||||
this.drawRotateImage(ctx, this.rotate, scale);
|
||||
const r = this.rotate / 90;
|
||||
ctx.drawImage(
|
||||
image,
|
||||
[
|
||||
(this.offsetX - this.area.left),
|
||||
(this.offsetY - this.area.top),
|
||||
-(this.offsetX - this.area.left),
|
||||
-(this.offsetY - this.area.top)
|
||||
][r] * scale,
|
||||
[
|
||||
(this.offsetY - this.area.top),
|
||||
-(this.offsetX - this.area.left),
|
||||
-(this.offsetY - this.area.top),
|
||||
(this.offsetX - this.area.left)
|
||||
][r] * scale,
|
||||
this.scaleWidth * scale,
|
||||
this.scaleHeight * scale
|
||||
);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 绘图
|
||||
* @param {Object} canvas
|
||||
* @param {Object} ctx canvas 的绘图上下文对象
|
||||
* @param {String} src 图片路径
|
||||
* @param {Function} callback 开始绘制时回调
|
||||
*/
|
||||
draw2DImage(canvas, ctx, src, callback) {
|
||||
// console.log('draw2DImage', canvas, ctx, src, callback)
|
||||
if(canvas) {
|
||||
const image = canvas.createImage();
|
||||
image.onload = () => {
|
||||
this.drawImage(ctx, image);
|
||||
// 如果觉得`生成时间过长`或`出现生成图片空白`可尝试调整延迟时间
|
||||
callback && setTimeout(callback, this.delay);
|
||||
};
|
||||
image.onerror = (err) => {
|
||||
console.error(err)
|
||||
uni.hideLoading();
|
||||
};
|
||||
image.src = src;
|
||||
} else {
|
||||
this.drawImage(ctx, src);
|
||||
setTimeout(() => {
|
||||
ctx.draw(false, callback);
|
||||
}, 200);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 画布转图片到本地缓存
|
||||
* @param {Object} canvas
|
||||
* @param {String} canvasId
|
||||
*/
|
||||
canvasToTempFilePath(canvas, canvasId) {
|
||||
// console.log('canvasToTempFilePath', canvas, canvasId)
|
||||
uni.canvasToTempFilePath({
|
||||
canvas,
|
||||
canvasId,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.canvansWidth,
|
||||
height: this.canvansHeight,
|
||||
destWidth: this.imgWidth, // 必要,保证生成图片宽度不受设备分辨率影响
|
||||
destHeight: this.imgHeight, // 必要,保证生成图片高度不受设备分辨率影响
|
||||
fileType: this.fileType, // 目标文件的类型,默认png
|
||||
success: (res) => {
|
||||
// 生成的图片临时文件路径
|
||||
this.handleImage(res.tempFilePath);
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: '裁剪失败,生成图片异常!', icon: 'none' });
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
/** 确认裁剪 */
|
||||
cropClick() {
|
||||
uni.showLoading({ title: '裁剪中...', mask: true });
|
||||
if(!this.use2d) {
|
||||
const ctx = uni.createCanvasContext('imgCanvas', this);
|
||||
ctx.clearRect(0, 0, this.canvansWidth, this.canvansHeight);
|
||||
this.draw2DImage(null, ctx, this.imgSrc, () => {
|
||||
this.canvasToTempFilePath(null, 'imgCanvas');
|
||||
});
|
||||
return;
|
||||
}
|
||||
// #ifdef MP-WEIXIN
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('#imgCanvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec((res) => {
|
||||
const canvas = res[0].node;
|
||||
|
||||
const dpr = uni.getSystemInfoSync().pixelRatio;
|
||||
canvas.width = res[0].width * dpr;
|
||||
canvas.height = res[0].height * dpr;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(dpr, dpr);
|
||||
ctx.clearRect(0, 0, this.canvansWidth, this.canvansHeight);
|
||||
|
||||
this.draw2DImage(canvas, ctx, this.imgSrc, () => {
|
||||
this.canvasToTempFilePath(canvas);
|
||||
});
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
handleImage(tempFilePath){
|
||||
// 在H5平台下,tempFilePath 为 base64
|
||||
// console.log(tempFilePath)
|
||||
uni.hideLoading();
|
||||
this.$emit('crop', { tempFilePath });
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.image-cropper {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #000;
|
||||
.img-canvas {
|
||||
position: absolute !important;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.pic-preview {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.crop-mask-block {
|
||||
background-color: rgba(51, 51, 51, 0.8);
|
||||
z-index: 2;
|
||||
position: fixed;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
}
|
||||
.crop-circle-box {
|
||||
position: fixed;
|
||||
box-sizing: border-box;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
.crop-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.crop-image {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
display: block !important;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
.crop-border {
|
||||
position: fixed;
|
||||
border: 1px solid #fff;
|
||||
box-sizing: border-box;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
}
|
||||
.crop-grid {
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
border-style: dashed;
|
||||
border-color: #fff;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.crop-angle {
|
||||
position: fixed;
|
||||
z-index: 3;
|
||||
border-style: solid;
|
||||
border-color: #fff;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fixed-bottom {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: $uni-bg-color-grey;
|
||||
|
||||
.action-bar {
|
||||
position: absolute;
|
||||
top: -90rpx;
|
||||
left: 10rpx;
|
||||
display: flex;
|
||||
.rotate-icon {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABCFJREFUaEPtml3IpVMUx3//ko/ChTIyiGFSMyhllI8bc4F85yuNC2FCqLmQC1+FZORiEkUMNW7UjKjJULgxV+NzSkxDhEkZgwsyigv119J63p7zvOc8z37OmXdOb51dz82711r7/99r7bXXXucVi3xokeNnRqCvB20fDmwAlgK/5bcD+FTSr33tHXQP2H4MeHQE0A+B5yRtLiUyDQJrgVc6AAaBpyV93kXkoBMIQLbfBS5NcK8BRwDXNcD+AdwnaVMbiWkRCPBBohpxHuK7M7865sclRdgNHVMhkF6IMIpwirFEUhzo8M7lwIvASTXEqyVtH8ZgagQSbOzsDknv18HZXpHn5IL8+94IOUm7miSmSqAttjPdbgGuTrnNktYsGgLpoYuAD2qg1zRTbG8P2D4SOC6/Q7vSHPALsE/S7wWy80RsPw/ckxMfSTq/LtRJwPbxwF3ASiCUTxwHCPAnEBfVF8AWSTtL7Ng+LfWOTfmlkn6udFsJ5K15R6a4kvX6yGyUFBvTOWzHXXFzCt4g6c1OArYj9iIGh43YgR+BvztXh1PSa4cMkd0jaVmXDduPAE+k3HpJD7cSGFKvfAc8FQUX8IOk/V2L1udtB/hTgdOBW4Aba/M7Ja1qs2f7euCNlHlZUlx4/495IWQ7Jl+qGbxX0gt9AHfJ2o6zFBVoNVrDKe+F3Sm8VdK1bQQ+A85JgXckXdkFaJx527cC9TpnVdvBtl3h2iapuhsGPdBw1b9xnUvaNw7AEh3bnwDnpuwGSfeP0rN9NvAMELXRXFkxEEK2nwQeSiOtRVQJwC4Z29cAW1Nuu6TVXTrN+SaBt4ErUug2Sa/2NdhH3vZy4NvU2S/p6D768w5xI3WOrAD7LtISFpGdIhVXKfaYvjd20wP13L9M0p4DBbaFRKToSLExVkr6qs+aIwlI6iwz+izUQqC+ab29PiMwqRcmPXczD8w8MFj1zg7xXEqbpdHCw7FgWSjafZL+KcQxtpjteCeflwYulFR/J3TabSslVkj6utPChAK2f6q9uZdLitKieLQRuExSvX9ZbLRUMFs09efpUZL+KtUfVo1GW/umNHC3pOhRLtiwfSbwZS6wV9IJfRdreuBBYH0a2STp9r4G+8jbXgc8mzoDT8VSO00ClwDv1ZR7XyylC4ec7ejaLUmdsV6Aw7oSbwFXpdFdks7qA6pU1na0aR6owgeIR/1cx63UzjAC0YXYVjMQHlkn6ZtSo21ytuPZGKFagQ/xsXZ/3iGuFrYdjafXG0DiQMeBi47c9/GV3BO247UV38n5o0UAP6xmu7jFOGxjRr66On5NPBDOCBsDTapxjHY1dyOcolNXnYlx1himE53p2PmNkxosevfavhg4Izt2k7TXPwZ2S6p6QZPin/2rwcQ7OKmBohCadJGF1P8PG6aaQBKVX/8AAAAASUVORK5CYII=');
|
||||
background-size: 60% 60%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
&.is-reverse {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rechoose {
|
||||
color: $uni-color-primary;
|
||||
padding: 0 $uni-spacing-row-lg;
|
||||
line-height: 100rpx;
|
||||
}
|
||||
|
||||
.choose-btn {
|
||||
color: $uni-color-primary;
|
||||
text-align: center;
|
||||
line-height: 100rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin: auto $uni-spacing-row-lg auto auto;
|
||||
background-color: $uni-color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.safe-area-inset-bottom {
|
||||
padding-bottom: 0;
|
||||
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
|
||||
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>=11.2
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<view class="abnormal-reported-page">
|
||||
<!-- 成功提示区域 -->
|
||||
<view class="success-section">
|
||||
<view class="success-icon">
|
||||
<up-icon name="checkmark-circle-fill" size="80" color="#4CD964"></up-icon>
|
||||
</view>
|
||||
<view class="success-title">异常已上报!</view>
|
||||
<view class="success-desc">配送计时已暂停,不影响您的准时率</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息卡片 -->
|
||||
<view class="order-card">
|
||||
<view class="order-item">
|
||||
<text class="order-label">订单号</text>
|
||||
<text class="order-value" style="font-weight: 600;" >MT20251017123456</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">商品信息</text>
|
||||
<text class="order-value">共3件商品</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">配送地址</text>
|
||||
<text class="order-value">XX小区3栋502室</text>
|
||||
</view>
|
||||
<view class="order-item">
|
||||
<text class="order-label">用户备注</text>
|
||||
<text class="order-value remark-text">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
|
||||
<!-- 查看详情按钮 -->
|
||||
<view class="view-detail-btn">
|
||||
<text>查看详情</text>
|
||||
<up-icon name="arrow-right" size="20" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位 -->
|
||||
<view class="bottom-space"></view>
|
||||
|
||||
<!-- 底部按钮区域 -->
|
||||
<view class="bottom-buttons">
|
||||
<up-button type="primary" size="default" class="continue-btn">
|
||||
继续接单
|
||||
</up-button>
|
||||
<up-button type="default" size="default" class="view-progress-btn">
|
||||
查看异常进度
|
||||
</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
// 页面加载时的逻辑
|
||||
onLoad(() => {
|
||||
console.log('异常上报成功页面加载')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page{
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
// 成功提示区域样式
|
||||
.success-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60rpx 30rpx;
|
||||
background-color: #F6FFFB;
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.success-desc {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
// 订单卡片样式
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0 30rpx;
|
||||
box-shadow: 0 0 10rpx 0 #e2e2e2;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.order-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.order-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
.remark-text {
|
||||
color: #FF6F00;
|
||||
}
|
||||
|
||||
// 查看详情按钮样式
|
||||
.view-detail-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
padding-top: 30rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
// 底部占位
|
||||
.bottom-space {
|
||||
height: 280rpx;
|
||||
}
|
||||
|
||||
// 底部按钮区域样式
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.continue-btn {
|
||||
border-radius: 50rpx;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #007AFF;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.view-progress-btn {
|
||||
border-radius: 50rpx;
|
||||
height: 100rpx;
|
||||
line-height: 98rpx;
|
||||
font-size: 32rpx;
|
||||
color: #007AFF;
|
||||
border: 1rpx solid #007AFF;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
|
||||
## Calendar 日历
|
||||
> **组件名:uni-calendar**
|
||||
> 代码块: `uCalendar`
|
||||
|
||||
|
||||
日历组件
|
||||
|
||||
> **注意事项**
|
||||
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
|
||||
> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)
|
||||
> - 仅支持自定义组件模式
|
||||
> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
|
||||
> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
|
||||
> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
|
||||
|
||||
|
||||
### 安装方式
|
||||
|
||||
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
|
||||
|
||||
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
|
||||
|
||||
### 基本用法
|
||||
|
||||
在 ``template`` 中使用组件
|
||||
|
||||
```html
|
||||
<view>
|
||||
<uni-calendar
|
||||
:insert="true"
|
||||
:lunar="true"
|
||||
:start-date="'2019-3-2'"
|
||||
:end-date="'2019-5-20'"
|
||||
@change="change"
|
||||
/>
|
||||
</view>
|
||||
```
|
||||
|
||||
### 通过方法打开日历
|
||||
|
||||
需要设置 `insert` 为 `false`
|
||||
|
||||
```html
|
||||
<view>
|
||||
<uni-calendar
|
||||
ref="calendar"
|
||||
:insert="false"
|
||||
@confirm="confirm"
|
||||
/>
|
||||
<button @click="open">打开日历</button>
|
||||
</view>
|
||||
```
|
||||
|
||||
```javascript
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
open(){
|
||||
this.$refs.calendar.open();
|
||||
},
|
||||
confirm(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Calendar Props
|
||||
|
||||
| 属性名 | 类型 | 默认值| 说明 |
|
||||
| - | - | - | - |
|
||||
| date | String |- | 自定义当前时间,默认为今天 |
|
||||
| lunar | Boolean | false | 显示农历 |
|
||||
| startDate | String |- | 日期选择范围-开始日期 |
|
||||
| endDate | String |- | 日期选择范围-结束日期 |
|
||||
| range | Boolean | false | 范围选择 |
|
||||
| insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 |
|
||||
|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 |
|
||||
| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
|
||||
|showMonth | Boolean | true | 是否显示月份为背景 |
|
||||
|
||||
### Calendar Events
|
||||
|
||||
| 事件名 | 说明 |返回值|
|
||||
| - | - | - |
|
||||
| open | 弹出日历组件,`insert :false` 时生效|- |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 组件示例
|
||||
|
||||
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)
|
||||
@@ -0,0 +1,588 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 余额区域骨架屏 -->
|
||||
<view class="skeleton-balance-section">
|
||||
<view class="skeleton-balance-label"></view>
|
||||
<view class="skeleton-balance-amount"></view>
|
||||
<view class="skeleton-balance-current"></view>
|
||||
</view>
|
||||
|
||||
<!-- 账户选择区域骨架屏 -->
|
||||
<view class="skeleton-account-section">
|
||||
<view class="skeleton-section-title"></view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息骨架屏 -->
|
||||
<view class="skeleton-tip-section">
|
||||
<view class="skeleton-tip-icon"></view>
|
||||
<view class="skeleton-tip-content">
|
||||
<view class="skeleton-tip-line"></view>
|
||||
<view class="skeleton-tip-line-small"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮骨架屏 -->
|
||||
<view class="skeleton-confirm-section">
|
||||
<view class="skeleton-confirm-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 真实内容 -->
|
||||
<view v-else class="withdraw-container">
|
||||
<!-- 可提现金额 -->
|
||||
<view class="balance-section">
|
||||
<text class="balance-label">可提现金额</text>
|
||||
<text class="balance-amount">¥{{ riderAcc.account }}</text>
|
||||
<text class="current-balance">当前钱包余额</text>
|
||||
</view>
|
||||
|
||||
<!-- 提现账户选择 -->
|
||||
<view class="account-section">
|
||||
<text class="section-title">提现账户</text>
|
||||
<view class=""
|
||||
style="display: flex;align-items: center; border-bottom: 4rpx solid #e2e2e2;padding-bottom: 10px; margin-bottom: 10px;">
|
||||
<up-icon name="zhifubao-circle-fill" size="30" color="#1890ff"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
支付宝
|
||||
</view>
|
||||
<view @click="changePay(0)" class="">
|
||||
<view v-if="current==0" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex;align-items: center;">
|
||||
<up-icon name="weixin-circle-fill" size="30" color="#28C445"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
微信
|
||||
</view>
|
||||
<view @click="changePay(1)" class="">
|
||||
<view v-if="current==1" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提现账号 -->
|
||||
<view class="" v-if="current!=null" style="margin: 20rpx 30rpx; ">
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
账号信息
|
||||
</view>
|
||||
|
||||
<up-form labelPosition="top" label-width="200" :model="account" ref="form1">
|
||||
<up-form-item label="姓名" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.name" @change="changePrice" placeholder="请输入姓名" border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item :label="current==0? '支付宝账号':'微信账号'" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.id" :placeholder="current==0? '请输入支付宝账号':'请输入微信账号'"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="提现金额" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.price" type="digit" placeholder="请输入提现金额" border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tip-section">
|
||||
<up-icon name="clock" size="18" color="#1890ff"></up-icon>
|
||||
<view class="" style="margin-left: 10rpx;">
|
||||
<view class="tip-text">预计 T+1 工作日到账</view>
|
||||
<view class="tip-text" style="color: #666666; font-size: 24rpx; margin-top: 10rpx; ">无手续费</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-section">
|
||||
<button class="confirm-button" @click="confirmWithdraw">确认提现</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
|
||||
let current = ref(null)
|
||||
let loading = ref(true)
|
||||
|
||||
|
||||
let account = ref({
|
||||
id: '',
|
||||
price: "",
|
||||
name: ''
|
||||
})
|
||||
|
||||
let riderAcc = ref<any>({})
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderAccInfo().then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
riderAcc.value = res.data.riderAcc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const changePay = (item : any) => {
|
||||
current.value = item
|
||||
}
|
||||
|
||||
const changePrice = (e : string) => {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
|
||||
// 确认提现
|
||||
const confirmWithdraw = () => {
|
||||
if (!account.value.name) {
|
||||
Service.Msg('请输入姓名!')
|
||||
return
|
||||
}
|
||||
if (!account.value.price) {
|
||||
Service.Msg('请输入提现金额!')
|
||||
return
|
||||
}
|
||||
if (!account.value.id) {
|
||||
Service.Msg('请输入账户号!')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '请仔细确认身份信息?',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
CNRiderOrderService.AddRiderWith(Number(account.value.price), current.value == 0 ? '支付宝' : '微信', account.value.name, account.value.id).then(res => {
|
||||
if (res.code == 0) {
|
||||
Service.Msg('提现成功')
|
||||
setTimeout(() => {
|
||||
Service.GoPage('/pages/my/withDrowList')
|
||||
}, 1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
// 用户点击取消后的操作
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.withdraw-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 选择 */
|
||||
|
||||
.radio-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.radio-inner {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.radio-no-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid #dadada;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* 余额显示区域 */
|
||||
.balance-section {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.balance-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4757;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.current-balance {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 账户选择区域 */
|
||||
.account-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.account-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #1677ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
border: 2rpx solid #000;
|
||||
}
|
||||
|
||||
.account-icon.wechat {
|
||||
background-color: #07c160;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 提示信息区域 */
|
||||
.tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 确认按钮区域 */
|
||||
.confirm-section {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #1677ff;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 45rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.confirm-button:active {
|
||||
background-color: #0958d9;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏通用样式 */
|
||||
.skeleton-balance-section,
|
||||
.skeleton-account-section,
|
||||
.skeleton-tip-section {
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 余额区域骨架屏 */
|
||||
.skeleton-balance-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-balance-label {
|
||||
width: 30%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-amount {
|
||||
width: 40%;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-current {
|
||||
width: 25%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 账户选择区域骨架屏 */
|
||||
.skeleton-account-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 25%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 4rpx solid #e2e2e2;
|
||||
}
|
||||
|
||||
.skeleton-account-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.skeleton-account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-name {
|
||||
flex: 1;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-radio {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 提示信息骨架屏 */
|
||||
.skeleton-tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-tip-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
margin-right: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-tip-line {
|
||||
width: 70%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 15rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-line-small {
|
||||
width: 50%;
|
||||
height: 24rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 确认按钮骨架屏 */
|
||||
.skeleton-confirm-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<view class="home">
|
||||
<view class=""
|
||||
style=" margin-top: 300rpx; display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||
<image :src="Service.GetIconImg('/static/dele/logo.png')" style="width: 150rpx; height: 150rpx; "
|
||||
mode=""></image>
|
||||
<view class="" style="font-size: 36rpx; font-weight: 600; ">
|
||||
美味到家
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="margin: 30rpx 30rpx;">
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
欢迎登陆
|
||||
</view>
|
||||
<view class="" style="font-size: 28rpx; margin-top: 20rpx; ">
|
||||
手机号登录,安全又便捷
|
||||
</view>
|
||||
|
||||
<view class="" style="margin-top: 30rpx;">
|
||||
<up-input v-model="login.phone" type="number" shape='circle'
|
||||
:customStyle="{'padding':'20rpx 30rpx','font-size':'32rpx'}" placeholder="请输入手机号" clearable='true'
|
||||
border="surround"></up-input>
|
||||
</view>
|
||||
|
||||
<view class=""
|
||||
style=" display: flex; align-items: center; justify-content: space-between; margin-top: 30rpx; border: 1rpx solid #dadbde; box-sizing: border-box; padding: 20rpx 30rpx; border-radius: 200rpx; ">
|
||||
<up-code-input v-model="login.code" mode="line" size='24'></up-code-input>
|
||||
<view class="wrap">
|
||||
<up-toast ref="uToastRef"></up-toast>
|
||||
<up-code :seconds="seconds" @end="end" @start="start" ref="uCodeRef" @change="codeChange"></up-code>
|
||||
<view @click="getCode">{{tips}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style="text-align: center; color: #888; margin-top: 30rpx; ">
|
||||
登录即代表同意
|
||||
<text style="color: var(--nav-banbacor);">《用户协议》</text>
|
||||
和
|
||||
<text style="color: var(--nav-banbacor);">《隐私政策》</text>
|
||||
</view>
|
||||
<view class="" style="text-align: center; margin-top: 20rpx;">
|
||||
新用户?系统将自动为您注册
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service } from "@/Service/Service"
|
||||
import { ref } from "vue";
|
||||
|
||||
let login = ref({
|
||||
phone: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
const tips = ref('');
|
||||
const seconds = ref(60);
|
||||
const uCodeRef = ref(null);
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
const codeChange = (text) => {
|
||||
tips.value = text;
|
||||
};
|
||||
|
||||
|
||||
const getCode = () => {
|
||||
if (uCodeRef.value.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被start()方法中的提示覆盖
|
||||
Service.Msg('验证码已发送')
|
||||
// 通知验证码组件内部开始倒计时
|
||||
uCodeRef.value.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
Service.Msg('倒计时结束后再发送')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const end = () => {
|
||||
console.log('倒计时结束');
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
console.log('倒计时开始');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.home {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: linear-gradient(to bottom, var(--nav-mian), #fff 40%);
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,807 @@
|
||||
<template>
|
||||
|
||||
<view v-if="isLoading" class="skeleton-container" style="padding-top: 80rpx;" >
|
||||
<!-- 统计数据区域骨架 -->
|
||||
<view class="skeleton-stats-section">
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮骨架 -->
|
||||
<view class="skeleton-action-section">
|
||||
<view class="skeleton-accept-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 标签栏骨架 -->
|
||||
<view class="skeleton-tab-bar">
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任务列表骨架 -->
|
||||
<view class="skeleton-task-list">
|
||||
<!-- 任务卡片骨架 -->
|
||||
<view class="skeleton-task-section" v-for="i in 3" :key="i">
|
||||
<!-- 高价单标签骨架 -->
|
||||
<view class="skeleton-tag-row">
|
||||
<view class="skeleton-high-price-tag"></view>
|
||||
<view class="skeleton-phone-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息骨架 -->
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息骨架 -->
|
||||
<view class="skeleton-address-info">
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间骨架 -->
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-pickup-code"></view>
|
||||
<view class="skeleton-pickup-time"></view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮骨架 -->
|
||||
<view class="skeleton-grab-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="rider-home" style="padding-top: 60rpx;" >
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥{{userData.dayAmount.toFixed(2)}}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">{{userData.dayOrderCount}}单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">配送中</text>
|
||||
<text class="stat-value ongoing">{{ userData.takeOrderCount }}单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button :disabled='riderInfo.status===0' type="primary" shape="circle" size="default"
|
||||
class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ riderInfo.status==0?'审核中':(riderInfo.isOnline == 0 ? '已下线' : '已上线') }}</up-button>
|
||||
</view>
|
||||
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status===1" class="" style="padding: 0 30rpx;">
|
||||
<!-- -->
|
||||
<view v-for="(orderItem,orderIndex) in orderList " @click="gopage(orderItem.orderId)" :key="orderIndex"
|
||||
class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
|
||||
<view class="high-price-tag"
|
||||
:style="{'border':activeTab==0?'1rpx solid #FF7875':(activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14'),'color':activeTab==0?'#FF7875':(activeTab==1?'#52C41A':'#FAAD14') }"
|
||||
style="background-color: #fff;">
|
||||
<text class="high-price-text">{{activeTab==0? '新订单':(activeTab==1? '待取单':'配送中')}}</text>
|
||||
</view>
|
||||
<view class="" @click.stop="call(orderItem.phone)" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">{{ orderItem.storeName }}</text>
|
||||
<text v-if="activeTab==1" class="distance">{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text"> {{orderItem.address }}</text>
|
||||
<!-- <text v-if="activeTab!==0" class="address-text">共3件商品</text> -->
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<!-- <view class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
<view class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">A121</text>
|
||||
</view>
|
||||
<view v-if="activeTab!==1" class="">
|
||||
<text class="address-text">据您{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" :color="activeTab==0?'#FAAD14':'#FF0000'" size="16" />
|
||||
<text class="time-text"
|
||||
:style="{'color':activeTab==0?'#FAAD14':'#FF0000'}">{{ orderItem.makeTime.split(' ').length==2?'预计'+orderItem.makeTime.split(' ')[1]+'送达':orderItem.makeTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
|
||||
<view class="" style="display: flex; ">
|
||||
<view class="" style="width: 100%;"
|
||||
@click.stop="activeTab==0?takeOrder(orderItem.orderId):pickFood(orderItem.orderId)">
|
||||
<button type="primary" :color="activeTab==0?'#1890FF':'#52C41A'" size="large"
|
||||
class="grab-btn">{{ activeTab==0?'立即接单':(activeTab==1?'我已取餐':'确认送达')}}</button>
|
||||
</view>
|
||||
<view class="" style="width: 20rpx;" v-if="activeTab!=0">
|
||||
|
||||
</view>
|
||||
<view style="width: 100%;" v-if="activeTab!=0" @click.stop="Service.GoPage('/pages/order/orderMap?orderId='+orderItem.orderId)" class="">
|
||||
<button type="primary" color="#1890FF"
|
||||
class="grab-btn">{{activeTab==1?'导航取餐':'导航送餐'}}</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="" style="font-weight: bold; text-align: center; font-size: 32rpx; margin-top: 100rpx; ">
|
||||
信息审核中·暂时无法接单
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
let userData = ref({
|
||||
dayAmount: 0,
|
||||
dayOrderCount: 0,
|
||||
takeOrderCount: 0
|
||||
})
|
||||
|
||||
const tabs = ['新订单', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let riderInfo = ref<any>({})
|
||||
|
||||
let orderList = ref<Array<any>>([])
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
uni.$on(`newOrder`, (data) => {
|
||||
newOrder()
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
onShow(() => {
|
||||
getData()
|
||||
getOrderData()
|
||||
})
|
||||
|
||||
// 有新订单
|
||||
const newOrder = () =>{
|
||||
audioPlay()
|
||||
}
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderHomeInfo().then(res => {
|
||||
isLoading.value = false
|
||||
riderInfo.value = res.data.riderInfo
|
||||
userData.value = res.data
|
||||
if (res.data.riderInfo.status === -1) {
|
||||
Service.GoPage('/pages/my/completeData')
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getOrderData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
orderList.value = []
|
||||
getOrderList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getOrderList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
|
||||
if (activeTab.value == 0) {
|
||||
CNRiderOrderService.GetRiderOrderList(page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
} else {
|
||||
CNRiderOrderService.GetRiderTakeOrderList(activeTab.value == 1 ? 0 : 1, page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 接单
|
||||
const takeOrder = (orderId : string) => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId).then(res => {
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 取餐
|
||||
const pickFood = (orderId : string) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId, activeTab.value).then(res => {
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
getOrderData()
|
||||
}
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
CNRiderDataService.UpdateRiderOnline().then(res => {
|
||||
if (res.data) {
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// 距离计算
|
||||
const distance = (item : any) => {
|
||||
if (item < 0) {
|
||||
return Number(item * 100).toFixed(2) + 'm'
|
||||
} else {
|
||||
return Number(item).toFixed(2) + 'km'
|
||||
}
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
const call = (e : string) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: e
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 页面跳转
|
||||
const gopage = (id) => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder?orderId=' + id)
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail?orderId=' + id+'&type='+activeTab.value)
|
||||
}
|
||||
}
|
||||
|
||||
const audioPlay = () => {
|
||||
const innerAudioContext = uni.createInnerAudioContext();
|
||||
innerAudioContext.autoplay = true;
|
||||
innerAudioContext.src = '/static/order.mp3';
|
||||
innerAudioContext.onPlay(() => {
|
||||
console.log('开始播放');
|
||||
});
|
||||
innerAudioContext.onError((res) => {
|
||||
console.log(res.errMsg);
|
||||
console.log(res.errCode);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 统计数据区域骨架 */
|
||||
.skeleton-stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.skeleton-stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-stat-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-stat-value {
|
||||
width: 150rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 接单按钮骨架 */
|
||||
.skeleton-action-section {
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-accept-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 标签栏骨架 */
|
||||
.skeleton-tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 100rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 任务列表骨架 */
|
||||
.skeleton-task-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 标签骨架 */
|
||||
.skeleton-tag-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.skeleton-high-price-tag {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-phone-btn {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 商家信息骨架 */
|
||||
.skeleton-merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 80rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 地址信息骨架 */
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 100%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 价格和时间骨架 */
|
||||
.skeleton-price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-pickup-code {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 按钮骨架 */
|
||||
.skeleton-grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 566 B |
@@ -0,0 +1,580 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 余额区域骨架屏 -->
|
||||
<view class="skeleton-balance-section">
|
||||
<view class="skeleton-balance-label"></view>
|
||||
<view class="skeleton-balance-amount"></view>
|
||||
<view class="skeleton-balance-current"></view>
|
||||
</view>
|
||||
|
||||
<!-- 账户选择区域骨架屏 -->
|
||||
<view class="skeleton-account-section">
|
||||
<view class="skeleton-section-title"></view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息骨架屏 -->
|
||||
<view class="skeleton-tip-section">
|
||||
<view class="skeleton-tip-icon"></view>
|
||||
<view class="skeleton-tip-content">
|
||||
<view class="skeleton-tip-line"></view>
|
||||
<view class="skeleton-tip-line-small"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮骨架屏 -->
|
||||
<view class="skeleton-confirm-section">
|
||||
<view class="skeleton-confirm-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 真实内容 -->
|
||||
<view v-else class="withdraw-container">
|
||||
<!-- 可提现金额 -->
|
||||
<view class="balance-section">
|
||||
<text class="balance-label">可提现金额</text>
|
||||
<text class="balance-amount">¥{{ riderAcc.account }}</text>
|
||||
<text class="current-balance">当前钱包余额</text>
|
||||
</view>
|
||||
|
||||
<!-- 提现账户选择 -->
|
||||
<view class="account-section">
|
||||
<text class="section-title">提现账户</text>
|
||||
<view class=""
|
||||
style="display: flex;align-items: center; border-bottom: 4rpx solid #e2e2e2;padding-bottom: 10px; margin-bottom: 10px;">
|
||||
<up-icon name="zhifubao-circle-fill" size="30" color="#1890ff"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
支付宝
|
||||
</view>
|
||||
<view @click="changePay(0)" class="">
|
||||
<view v-if="current==0" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex;align-items: center;">
|
||||
<up-icon name="weixin-circle-fill" size="30" color="#28C445"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
微信
|
||||
</view>
|
||||
<view @click="changePay(1)" class="">
|
||||
<view v-if="current==1" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提现账号 -->
|
||||
<view class="" v-if="current!=null" style="margin: 20rpx 30rpx; ">
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
支付宝账号信息
|
||||
</view>
|
||||
|
||||
<up-form labelPosition="top" label-width="200" :model="account" ref="form1">
|
||||
<up-form-item label="姓名" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.name" @change="changePrice" placeholder="请输入姓名" border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item :label="current==0? '支付宝账号':'微信账号'" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.id" :placeholder="current==0? '请输入支付宝账号':'请输入微信账号'"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="提现金额" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.price" type="digit" placeholder="请输入提现金额" border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tip-section">
|
||||
<up-icon name="clock" size="18" color="#1890ff"></up-icon>
|
||||
<view class="" style="margin-left: 10rpx;">
|
||||
<view class="tip-text">预计 T+1 工作日到账</view>
|
||||
<view class="tip-text" style="color: #666666; font-size: 24rpx; margin-top: 10rpx; ">无手续费</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-section">
|
||||
<button class="confirm-button" @click="confirmWithdraw">确认提现</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
|
||||
let current = ref(null)
|
||||
let loading = ref(true)
|
||||
|
||||
|
||||
let account = ref({
|
||||
id: '',
|
||||
price: "",
|
||||
name: ''
|
||||
})
|
||||
|
||||
let riderAcc=ref<any>({})
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData=()=>{
|
||||
CNRiderDataService.GetRiderAccInfo().then(res=>{
|
||||
loading.value = false
|
||||
if(res.data){
|
||||
riderAcc.value=res.data.riderAcc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const changePay = (item : any) => {
|
||||
current.value = item
|
||||
}
|
||||
|
||||
const changePrice = (e : string) => {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
|
||||
// 确认提现
|
||||
const confirmWithdraw = () => {
|
||||
if(!account.value.name){
|
||||
Service.Msg('请输入姓名!')
|
||||
return
|
||||
}
|
||||
if(!account.value.price){
|
||||
Service.Msg('请输入提现金额!')
|
||||
return
|
||||
}
|
||||
if(!account.value.id){
|
||||
Service.Msg('请输入账户号!')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '请仔细确认身份信息?',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
CNRiderOrderService.AddRiderWith(Number(account.value.price),current.value==0?'支付宝':'微信',account.value.name,account.value.id).then(res=>{
|
||||
|
||||
})
|
||||
} else {
|
||||
// 用户点击取消后的操作
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.withdraw-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 选择 */
|
||||
|
||||
.radio-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.radio-inner {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.radio-no-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid #dadada;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* 余额显示区域 */
|
||||
.balance-section {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.balance-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4757;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.current-balance {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 账户选择区域 */
|
||||
.account-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.account-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #1677ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
border: 2rpx solid #000;
|
||||
}
|
||||
|
||||
.account-icon.wechat {
|
||||
background-color: #07c160;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 提示信息区域 */
|
||||
.tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 确认按钮区域 */
|
||||
.confirm-section {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #1677ff;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 45rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.confirm-button:active {
|
||||
background-color: #0958d9;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏通用样式 */
|
||||
.skeleton-balance-section,
|
||||
.skeleton-account-section,
|
||||
.skeleton-tip-section {
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 余额区域骨架屏 */
|
||||
.skeleton-balance-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-balance-label {
|
||||
width: 30%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-amount {
|
||||
width: 40%;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-current {
|
||||
width: 25%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 账户选择区域骨架屏 */
|
||||
.skeleton-account-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 25%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 4rpx solid #e2e2e2;
|
||||
}
|
||||
|
||||
.skeleton-account-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.skeleton-account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-name {
|
||||
flex: 1;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-radio {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 提示信息骨架屏 */
|
||||
.skeleton-tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-tip-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
margin-right: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-tip-line {
|
||||
width: 70%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 15rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-line-small {
|
||||
width: 50%;
|
||||
height: 24rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 确认按钮骨架屏 */
|
||||
.skeleton-confirm-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,661 @@
|
||||
<template>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="isLoading" class="skeleton-container">
|
||||
<!-- 顶部提示栏骨架 -->
|
||||
<view class="skeleton-top-tip"></view>
|
||||
|
||||
<!-- 头像上传区域骨架 -->
|
||||
<view class="skeleton-avatar-section">
|
||||
<view class="skeleton-avatar"></view>
|
||||
<view class="skeleton-avatar-text"></view>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容骨架 -->
|
||||
<view class="skeleton-form-content">
|
||||
<!-- 身份信息区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-section-title"></view>
|
||||
|
||||
<!-- 姓名输入骨架 -->
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证号输入骨架 -->
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
|
||||
<!-- 年龄输入骨架 -->
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-input"></view>
|
||||
</view>
|
||||
|
||||
<!-- 性别选择骨架 -->
|
||||
<view class="skeleton-form-item">
|
||||
<view class="skeleton-label"></view>
|
||||
<view class="skeleton-radio-group">
|
||||
<view class="skeleton-radio-item"></view>
|
||||
<view class="skeleton-radio-item"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域骨架 -->
|
||||
<view class="skeleton-section">
|
||||
<view class="skeleton-section-title"></view>
|
||||
|
||||
<!-- 身份证正面上传骨架 -->
|
||||
<view class="skeleton-upload-item">
|
||||
<view class="skeleton-upload-area"></view>
|
||||
</view>
|
||||
|
||||
<!-- 身份证反面上传骨架 -->
|
||||
<view class="skeleton-upload-item">
|
||||
<view class="skeleton-upload-area"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 占位空间骨架 -->
|
||||
<view class="skeleton-placeholder"></view>
|
||||
|
||||
<!-- 提交按钮骨架 -->
|
||||
<view class="skeleton-submit-section">
|
||||
<view class="skeleton-submit-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="real-name-auth-container">
|
||||
<!-- 顶部提示栏 -->
|
||||
<view class="top-tip">
|
||||
<text class="tip-text">请完成实名认证,保障您的接单权益</text>
|
||||
</view>
|
||||
<view @click="uploadFImg(1)" class=""
|
||||
style=" display: flex; flex-direction: column; justify-content: center; align-items: center; ">
|
||||
<img v-if="formData.headImg!=''" :src="Service.GetMateUrlByImg(formData.headImg)"
|
||||
style="width: 140rpx; height: 140rpx; border-radius: 50%; " alt="" />
|
||||
<view v-else class=""
|
||||
style="background-color: #EBEBEB; width: 140rpx; height: 140rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; ">
|
||||
<image :src="Service.GetIconImg('/static/index/my/edit/photo.png')"
|
||||
style="width: 50rpx; height: 50rpx; " alt=""> </image>
|
||||
</view>
|
||||
<view class="" style="margin-top: 15rpx; font-size: 26rpx; color: #999999; ">
|
||||
点击更换头像
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-content">
|
||||
<!-- 身份信息区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份信息</view>
|
||||
|
||||
<!-- 姓名输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">姓名</view>
|
||||
<u-input v-model="formData.name" placeholder="请输入真实姓名" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" />
|
||||
</view>
|
||||
<!-- 身份证号输入 -->
|
||||
<view class="form-item">
|
||||
<view class="label">身份证号</view>
|
||||
<u-input v-model="formData.idCard" placeholder="请输入18位身份证号" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" maxlength="18" />
|
||||
</view>
|
||||
<!-- 年龄 -->
|
||||
<view class="form-item">
|
||||
<view class="label">年龄</view>
|
||||
<u-input v-model="formData.age" placeholder="请输入年龄" placeholder-color="#999" border="none"
|
||||
class="input" input-align="right" maxlength="18" />
|
||||
</view>
|
||||
<view class="form-item" style="justify-content: space-between;">
|
||||
<view class="label">性别</view>
|
||||
<view class="" style="">
|
||||
<up-radio-group v-model="formData.sex" placement="row">
|
||||
<up-radio v-for="(item, index) in radiolist1" activeColor='#FF6A00' :key="index"
|
||||
iconPlacement="right" :label="item.name" :name="item.name">
|
||||
</up-radio>
|
||||
</up-radio-group>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 身份证照片区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">身份证照片</view>
|
||||
|
||||
<!-- 上传身份证正面 -->
|
||||
<view @click="uploadFImg(2)" class="upload-item">
|
||||
<view class="upload-area bordered-area">
|
||||
<view v-if="!formData.frontImage" class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证正面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-else class="uploaded-placeholder">
|
||||
<image :src="Service.GetMateUrlByImg(formData.frontImage)"
|
||||
style="width: 100%; height: 100%; " mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上传身份证反面 -->
|
||||
<view @click="uploadFImg(3)" class="upload-item">
|
||||
<view class="upload-area bordered-area">
|
||||
<view v-if="!formData.backImage" class="upload-content">
|
||||
<view class="upload-icon">+</view>
|
||||
<view class="upload-text">上传身份证反面</view>
|
||||
</view>
|
||||
<!-- 显示上传后的占位图 -->
|
||||
<view v-else class="uploaded-placeholder">
|
||||
<image :src="Service.GetMateUrlByImg(formData.backImage)"
|
||||
style="width: 100%; height: 100%; " mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" style="width: 100vw; height: 180rpx;">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<button @click="save()" type="primary" class="submit-btn">
|
||||
提交信息
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, computed } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService';
|
||||
|
||||
|
||||
let isLoading = ref(true)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
name: '',
|
||||
idCard: '',
|
||||
sex: '男',
|
||||
frontImage: '',
|
||||
backImage: '',
|
||||
agreed: false,
|
||||
headImg: '',
|
||||
age: '',
|
||||
phone: ''
|
||||
});
|
||||
|
||||
const radiolist1 = ref([
|
||||
{
|
||||
name: '男',
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
disabled: false,
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
let addressInfo = ref({
|
||||
province: '',
|
||||
city: '',
|
||||
region: '',
|
||||
lat: 0,
|
||||
lon: 0
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
getLocation()
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
const getLocation = () => {
|
||||
console.log('开始定位');
|
||||
uni.getLocation({
|
||||
type: 'wgs84',
|
||||
success: function (res) {
|
||||
addressInfo.value.lat = res.latitude
|
||||
addressInfo.value.lon = res.longitude
|
||||
CNRiderDataService.GetAddressInfo(res.latitude, res.longitude).then(data => {
|
||||
console.log(1111);
|
||||
isLoading.value = false
|
||||
addressInfo.value.province = data.data.addrInfo.province
|
||||
addressInfo.value.city = data.data.addrInfo.city
|
||||
addressInfo.value.region = data.data.addrInfo.district
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const uploadFImg = (index : number) => {
|
||||
uni.chooseImage({
|
||||
count: 1, // 最多选择3张图片
|
||||
sizeType: ['original', 'compressed'], // 支持原图和压缩图
|
||||
sourceType: ['album', 'camera'], // 可从相册选择或使用相机拍照
|
||||
success: function (res) {
|
||||
let path = res.tempFiles[0].path
|
||||
Service.uploadH5(path, 'Avatar', data => {
|
||||
|
||||
if (index === 1) {
|
||||
formData.value.headImg = data
|
||||
} else if (index === 2) {
|
||||
formData.value.frontImage = data
|
||||
} else {
|
||||
formData.value.backImage = data
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error('选择失败:', err.errMsg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const save = () => {
|
||||
if (rules() === 1) {
|
||||
return
|
||||
}
|
||||
CNRiderDataService.CompleteRider(formData.value.name, formData.value.headImg, formData.value.idCard, formData.value.sex, Number(formData.value.age), formData.value.frontImage, formData.value.backImage, addressInfo.value.province, addressInfo.value.city, addressInfo.value.region, addressInfo.value.lat, addressInfo.value.lon).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('提交成功')
|
||||
setTimeout(()=>{
|
||||
Service.GoPageTab('/pages/index/index')
|
||||
},1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const rules = () => {
|
||||
if (!formData.value.headImg) {
|
||||
Service.Msg('请上传头像!')
|
||||
return 1
|
||||
}
|
||||
if (!formData.value.name) {
|
||||
Service.Msg('请输入真实姓名!')
|
||||
return 1
|
||||
}
|
||||
|
||||
if (formData.value.idCard.split('').length !== 18) {
|
||||
Service.Msg('请输入正确身份证号!')
|
||||
return 1
|
||||
}
|
||||
|
||||
if (!formData.value.idCard) {
|
||||
Service.Msg('请输入身份证号!')
|
||||
return 1
|
||||
}
|
||||
if (!formData.value.age) {
|
||||
Service.Msg('请输入年龄!')
|
||||
return 1
|
||||
}
|
||||
|
||||
if (!formData.value.frontImage) {
|
||||
Service.Msg('请输入身份证正面!')
|
||||
return 1
|
||||
}
|
||||
if (!formData.value.backImage) {
|
||||
Service.Msg('请输入身份证背面!')
|
||||
return 1
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-top-tip {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: #e6f7ff;
|
||||
border-radius: 20rpx;
|
||||
margin: 20rpx 0;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-avatar-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-avatar {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-avatar-text {
|
||||
width: 200rpx;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-form-content {
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 150rpx;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-form-item {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.skeleton-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-input {
|
||||
flex: 1;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-radio-group {
|
||||
display: flex;
|
||||
gap: 40rpx;
|
||||
}
|
||||
|
||||
.skeleton-radio-item {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-upload-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-upload-area {
|
||||
width: 100%;
|
||||
height: 250rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-placeholder {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
}
|
||||
|
||||
.skeleton-submit-section {
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
margin-top: 60rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.skeleton-submit-btn {
|
||||
width: 100%;
|
||||
height: 92rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 46rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
50% {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
100% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
|
||||
.top-tip {
|
||||
background-color: #E6F7FF;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #1890ff;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 120rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
height: 250rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 6rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bordered-area {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 60rpx;
|
||||
color: #1890ff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.uploaded-placeholder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.face-verify-area {
|
||||
background-color: #fff;
|
||||
height: 240rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.face-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e6f7ff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.face-text {
|
||||
font-size: 28rpx;
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.agreement-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
font-size: 26rpx;
|
||||
color: #1890ff;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
margin-top: 60rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 92rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 46rpx;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
background-color: #a0cfff;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,770 @@
|
||||
<template>
|
||||
|
||||
<view v-if="isLoading" class="skeleton-container">
|
||||
<!-- 统计数据区域骨架 -->
|
||||
<view class="skeleton-stats-section">
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
<view class="skeleton-stat-item">
|
||||
<view class="skeleton-stat-label"></view>
|
||||
<view class="skeleton-stat-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮骨架 -->
|
||||
<view class="skeleton-action-section">
|
||||
<view class="skeleton-accept-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 标签栏骨架 -->
|
||||
<view class="skeleton-tab-bar">
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
<view class="skeleton-tab-item">
|
||||
<view class="skeleton-tab-text"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任务列表骨架 -->
|
||||
<view class="skeleton-task-list">
|
||||
<!-- 任务卡片骨架 -->
|
||||
<view class="skeleton-task-section" v-for="i in 3" :key="i">
|
||||
<!-- 高价单标签骨架 -->
|
||||
<view class="skeleton-tag-row">
|
||||
<view class="skeleton-high-price-tag"></view>
|
||||
<view class="skeleton-phone-btn"></view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息骨架 -->
|
||||
<view class="skeleton-merchant-info">
|
||||
<view class="skeleton-merchant-name"></view>
|
||||
<view class="skeleton-distance"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息骨架 -->
|
||||
<view class="skeleton-address-info">
|
||||
<view class="skeleton-address-text"></view>
|
||||
</view>
|
||||
|
||||
<!-- 价格和取餐时间骨架 -->
|
||||
<view class="skeleton-price-time-row">
|
||||
<view class="skeleton-pickup-code"></view>
|
||||
<view class="skeleton-pickup-time"></view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮骨架 -->
|
||||
<view class="skeleton-grab-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="rider-home">
|
||||
<!-- 统计数据区域 -->
|
||||
<view class="stats-section">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">今日收入</text>
|
||||
<text class="stat-value income">¥{{userData.dayAmount.toFixed(2)}}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">已完成</text>
|
||||
<text class="stat-value completed">{{userData.dayOrderCount}}单</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">配送中</text>
|
||||
<text class="stat-value ongoing">{{ userData.takeOrderCount }}单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="action-section">
|
||||
<up-button :disabled='riderInfo.status===0' type="primary" shape="circle" size="default"
|
||||
class="accept-orders-btn"
|
||||
@click="toggleAcceptOrders">{{ riderInfo.status==0?'审核中':(riderInfo.isOnline == 0 ? '已下线' : '已上线') }}</up-button>
|
||||
</view>
|
||||
|
||||
<view class="tab-bar">
|
||||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab }}</text>
|
||||
<view v-if="activeTab === index" class="active-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="riderInfo.status===1" class="" style="padding: 0 30rpx;">
|
||||
<view @click="gopage(orderItem.orderId)" v-for="(orderItem,orderIndex) in orderList " :key="orderIndex"
|
||||
class="task-section">
|
||||
<!-- 高价单标签 -->
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
|
||||
<view class="high-price-tag"
|
||||
:style="{'border':activeTab==0?'1rpx solid #FF7875':(activeTab==1?'1rpx solid #52C41A':'1rpx solid #FAAD14'),'color':activeTab==0?'#FF7875':(activeTab==1?'#52C41A':'#FAAD14') }"
|
||||
style="background-color: #fff;">
|
||||
<text class="high-price-text">{{activeTab==0? '新订单':(activeTab==1? '待取单':'配送中')}}</text>
|
||||
</view>
|
||||
<view class="" @click.stop="call(orderItem.phone)" style="display: flex; align-items: baseline;">
|
||||
<up-icon name="phone" color="var(--nav-mian)" size="20"></up-icon>
|
||||
<text style="margin-left: 10rpx; color: var(--nav-mian); ">拨打商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商家信息 -->
|
||||
<view class="merchant-info">
|
||||
<text class="merchant-name">{{ orderItem.storeName }}</text>
|
||||
<text v-if="activeTab==1" class="distance">{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="address-info">
|
||||
<up-icon name="map" color="#999" size="24rpx" />
|
||||
<text class="address-text"> {{orderItem.address }}</text>
|
||||
<!-- <text v-if="activeTab!==0" class="address-text">共3件商品</text> -->
|
||||
</view>
|
||||
<!-- 商品次数-->
|
||||
<!-- <view class="address-info">
|
||||
<text class="address-text">共3件商品</text>
|
||||
<view class="">
|
||||
<text class="price">¥5.50</text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">/单</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 价格和取餐时间 -->
|
||||
<view class="price-time-row">
|
||||
<view v-if="activeTab==1" class="">
|
||||
<text style="font-size: 30rpx; font-weight: 600; color: #1890FF; ">取件码: </text>
|
||||
<text style="color: var(--nav-mian); font-weight: 600; margin-left: 10rpx; ">A121</text>
|
||||
</view>
|
||||
<view v-if="activeTab!==1" class="">
|
||||
<text class="address-text">据您{{ distance(orderItem.distance) }}</text>
|
||||
</view>
|
||||
<view class="pickup-time">
|
||||
<up-icon name="clock" :color="activeTab==0?'#FAAD14':'#FF0000'" size="16" />
|
||||
<text class="time-text"
|
||||
:style="{'color':activeTab==0?'#FAAD14':'#FF0000'}">{{ orderItem.makeTime.split(' ').length==2?'预计'+orderItem.makeTime.split(' ')[1]+'送达':orderItem.makeTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即抢单按钮 -->
|
||||
<up-button type="primary"
|
||||
@click="activeTab==0?takeOrder(orderItem.orderId):pickFood(orderItem.orderId)"
|
||||
:color="activeTab==0?'#1890FF':'#52C41A'" size="large"
|
||||
class="grab-btn">{{ activeTab==0?'立即接单':(activeTab==1?'我已取餐':'确认送达')}}</up-button>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
|
||||
|
||||
<view v-else class="" style="font-weight: bold; text-align: center; font-size: 32rpx; margin-top: 100rpx; ">
|
||||
信息审核中·暂时无法接单
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" style="width: 100%; height: 60rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const isLoading = ref(true);
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
let userData = ref({
|
||||
dayAmount: 0,
|
||||
dayOrderCount: 0,
|
||||
takeOrderCount: 0
|
||||
})
|
||||
|
||||
const tabs = ['新订单', '待取货', '配送中']
|
||||
const activeTab = ref(0)
|
||||
let riderInfo = ref<any>({})
|
||||
|
||||
let orderList = ref<Array<any>>([])
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
|
||||
})
|
||||
|
||||
|
||||
onShow(() => {
|
||||
getOrderData()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderHomeInfo().then(res => {
|
||||
isLoading.value = false
|
||||
riderInfo.value = res.data.riderInfo
|
||||
userData.value=res.data
|
||||
if (res.data.riderInfo.status === -1) {
|
||||
Service.GoPage('/pages/my/completeData')
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getOrderData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
orderList.value = []
|
||||
getOrderList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getOrderList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
|
||||
if (activeTab.value == 0) {
|
||||
CNRiderOrderService.GetRiderOrderList(page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
} else {
|
||||
CNRiderOrderService.GetRiderTakeOrderList(activeTab.value == 1 ? 0 : 1, page.value).then(res => {
|
||||
orderList.value = [...orderList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 接单
|
||||
const takeOrder = (orderId : string) => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId).then(res => {
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 取餐
|
||||
const pickFood = (orderId : string) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId,activeTab.value).then(res=>{
|
||||
if (res.data) {
|
||||
getOrderData()
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (index : number) => {
|
||||
activeTab.value = index
|
||||
getOrderData()
|
||||
}
|
||||
|
||||
// 切换接单状态
|
||||
const toggleAcceptOrders = () => {
|
||||
CNRiderDataService.UpdateRiderOnline().then(res => {
|
||||
if (res.data) {
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// 距离计算
|
||||
const distance = (item : any) => {
|
||||
if (item < 0) {
|
||||
return Number(item * 100).toFixed(2) + 'm'
|
||||
} else {
|
||||
return Number(item).toFixed(2) + 'km'
|
||||
}
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
const call = (e : string) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: e
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 页面跳转
|
||||
const gopage = (id) => {
|
||||
if (activeTab.value == 0) {
|
||||
Service.GoPage('/pages/order/grabOrder?orderId=' + id)
|
||||
} else {
|
||||
Service.GoPage('/pages/order/orderDetail?orderId=' + id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
page {
|
||||
background-color: #F6f6f6;
|
||||
}
|
||||
|
||||
|
||||
/* 统计数据区域 */
|
||||
.stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.income {
|
||||
color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.completed {
|
||||
color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.ongoing {
|
||||
color: #FF9500;
|
||||
}
|
||||
|
||||
/* 接单按钮 */
|
||||
.action-section {
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.accept-orders-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
background-color: #52C41A;
|
||||
}
|
||||
|
||||
|
||||
/* 顶部标签栏 */
|
||||
.tab-bar {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #E5E5E5;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 110rpx;
|
||||
height: 6rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
|
||||
.task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 标签样式 */
|
||||
.high-price-tag {
|
||||
width: fit-content;
|
||||
background-color: #FF7875;
|
||||
color: #FFFFFF;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 20rpx;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.status-tag.pending {
|
||||
background-color: #4CD964;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status-tag.delivering {
|
||||
background-color: #FF9500;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* 右侧操作按钮 */
|
||||
.right-action {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.call-btn {
|
||||
padding: 5rpx 15rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
/* 信息展示 */
|
||||
.merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.distance {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.address-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 价格和时间 */
|
||||
.price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.pickup-code {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pickup-time {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
margin-left: 8rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.grab-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* uview组件样式覆盖 */
|
||||
::v-deep .u-button--primary {
|
||||
background-color: var(--nav-vice);
|
||||
border-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
::v-deep .u-button--mini {
|
||||
background-color: var(--nav-mian);
|
||||
border-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 统计数据区域骨架 */
|
||||
.skeleton-stats-section {
|
||||
background-color: #ffffff;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.skeleton-stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-stat-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-stat-value {
|
||||
width: 150rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 接单按钮骨架 */
|
||||
.skeleton-action-section {
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-accept-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 标签栏骨架 */
|
||||
.skeleton-tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
padding: 20rpx 0 0;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skeleton-tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skeleton-tab-text {
|
||||
width: 100rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 任务列表骨架 */
|
||||
.skeleton-task-list {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-task-section {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 标签骨架 */
|
||||
.skeleton-tag-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.skeleton-high-price-tag {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-phone-btn {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 商家信息骨架 */
|
||||
.skeleton-merchant-info {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-merchant-name {
|
||||
width: 200rpx;
|
||||
height: 34rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-distance {
|
||||
width: 80rpx;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 地址信息骨架 */
|
||||
.skeleton-address-info {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.skeleton-address-text {
|
||||
width: 100%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 价格和时间骨架 */
|
||||
.skeleton-price-time-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.skeleton-pickup-code {
|
||||
width: 150rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-pickup-time {
|
||||
width: 200rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 按钮骨架 */
|
||||
.skeleton-grab-btn {
|
||||
margin-top: 25rpx;
|
||||
height: 80rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 40rpx;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 690 B |
@@ -0,0 +1,46 @@
|
||||
import { Service } from '@/Service/Service';
|
||||
/*****连接*****/
|
||||
class ImConnectService {
|
||||
private static GetConnectPath: string = '/Im/GetConnect';
|
||||
/*****获取连接*****/
|
||||
static GetConnect() {
|
||||
var result = Service.Request(this.GetConnectPath, 'POST', {type:3});
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IsOnlinePath: string = '/Im/IsOnline';
|
||||
/*****判断是否在线*****/
|
||||
static IsOnline(id:number) {
|
||||
var result = Service.Request(this.IsOnlinePath, 'POST', id);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JoinChatPath: string = '/Im/JoinChat';
|
||||
/*****加入聊天室*****/
|
||||
static JoinChat(id: number,chan:number) {
|
||||
var result = Service.Request(this.JoinChatPath, 'POST', { id,chan });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SendChanMsgPath: string = '/Im/SendChanMsg';
|
||||
/*****发送聊天室消息*****/
|
||||
static SendChanMsg(id: number, user: string, chan: string, type: string,msg:string,media:string) {
|
||||
var result = Service.Request(this.SendChanMsgPath, 'POST', { id, user, chan, type , msg , media });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ExitChatPath: string = '/Im/ExitChat';
|
||||
/*****离开聊天室*****/
|
||||
static ExitChat(id:number, chan: string) {
|
||||
var result = Service.Request(this.ExitChatPath, 'POST', {id, chan });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetOrderMessagePath: string = '/Order/GetOrderMessage';
|
||||
/*****聊天记录*****/
|
||||
static GetOrderMessage(orderId:string) {
|
||||
var result = Service.Request(this.GetOrderMessagePath, 'GET', {orderId });
|
||||
return result;
|
||||
}
|
||||
}
|
||||
export { Service, ImConnectService };
|
||||
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<view style=" padding: 20rpx 40rpx; background-color: #fff; ">
|
||||
<up-form v-if="type!=='1'" labelPosition="left" labelWidth='90' :model="userData" ref="form1">
|
||||
<up-form-item label="姓名:" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input inputAlign='right' v-model="userData.name" clearable='true' placeholder="请输入联系人姓名"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="手机号:" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input inputAlign='right' v-model="userData.phone" clearable='true' placeholder="请输入手机号"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
<up-form v-else labelPosition="left" labelWidth='90' :model="password" ref="form1">
|
||||
|
||||
<up-form-item label="手机号:" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input clearable='true' v-model="password.phone" placeholder="请输入手机号" border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="验证码:" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input clearable='true' v-model="password.code" placeholder="请输入验证码" border="none">
|
||||
<template #suffix>
|
||||
<up-code :seconds="seconds" @end="end" @start="start" ref="uCodeRef"
|
||||
@change="codeChange"></up-code>
|
||||
<up-button @tap="getCode">{{tips}}</up-button>
|
||||
</template>
|
||||
</up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
</view>
|
||||
<view class="" style=" position: fixed; bottom: 0; left: 0; width: 100%; padding: 20rpx; ">
|
||||
<button @click="save()" class="logout-btn">确认修改</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { ref } from "vue";
|
||||
import { Service } from "../../Service/Service";
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
import { CNRiderLoginService } from '@/Service/CN/CNRiderLoginService'
|
||||
|
||||
const tips = ref('');
|
||||
const seconds = ref(60);
|
||||
const uCodeRef = ref(null);
|
||||
|
||||
let password = ref({
|
||||
phone: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
let userData = ref({
|
||||
name: '',
|
||||
phone: ''
|
||||
})
|
||||
|
||||
let type = ref('')
|
||||
onLoad((data : any) => {
|
||||
if (data.type === '1') {
|
||||
uni.setNavigationBarTitle({
|
||||
title: '修改手机号'
|
||||
})
|
||||
}
|
||||
type.value = data.type
|
||||
console.log(type.value);
|
||||
getData()
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderExigency().then(res => {
|
||||
if (res.code == 0) {
|
||||
if (res.data.info) {
|
||||
userData.value = res.data.info
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const save = () => {
|
||||
if (type.value === '0') {
|
||||
if (!userData.value.name) {
|
||||
Service.Msg('请输入联系人姓名!')
|
||||
return
|
||||
}
|
||||
if (!userData.value.phone) {
|
||||
Service.Msg('请输入联系人手机号!')
|
||||
return
|
||||
}
|
||||
if (userData.value.phone.split('').length !== 11) {
|
||||
Service.Msg('请输入正确手机号!')
|
||||
return
|
||||
}
|
||||
|
||||
CNRiderDataService.AddRiderExigency(userData.value.name, userData.value.phone).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('添加成功!')
|
||||
setTimeout(() => {
|
||||
Service.GoPageBack()
|
||||
}, 1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (!password.value.phone) {
|
||||
Service.Msg('请输入手机号!')
|
||||
return
|
||||
}
|
||||
if (password.value.phone.split('').length !== 11) {
|
||||
Service.Msg('请输入正确手机号!')
|
||||
return
|
||||
}
|
||||
if (!password.value.code) {
|
||||
Service.Msg('请输入验证码!')
|
||||
return
|
||||
}
|
||||
CNRiderLoginService.UpdateRiderPhone(password.value.phone, password.value.code).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('修改成功!')
|
||||
setTimeout(() => {
|
||||
Service.GoPageBack()
|
||||
}, 1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const codeChange = (text) => {
|
||||
tips.value = text;
|
||||
};
|
||||
|
||||
const getCode = () => {
|
||||
|
||||
if (uCodeRef.value.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码',
|
||||
});
|
||||
CNRiderLoginService.SendUserSms(password.value.phone, 'RiderUpPhone').then(res => {
|
||||
if (res.code == 0) {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被start()方法中的提示覆盖
|
||||
Service.Msg('验证码已发送')
|
||||
uCodeRef.value.start();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Service.Msg('倒计时结束后再发送')
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const end = () => {
|
||||
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
background-color: var(--nav-mian);
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
border-radius: 60rpx;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
font-size: 30rpx;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<web-view ref="webviewRef" v-if="isshow" :src="url" @message="handleMessage" @logData = "logData"></web-view>
|
||||
|
||||
<!-- ✅ 新增:一个绝对定位的遮罩层,用于在刷新时覆盖 web-view -->
|
||||
<view v-else class="reloading-mask">
|
||||
<up-loading-icon text="正在获取订单状态..." v-if="orderOver" textSize="16"></up-loading-icon>
|
||||
|
||||
<up-loading-icon text="订单已完成" v-else textSize="16"></up-loading-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { Service } from "@/Service/Service";
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let orderId = ref<string>('')
|
||||
let url = ref<string>('')
|
||||
let isshow = ref<false>(false)
|
||||
|
||||
let orderInfo = ref<any>({
|
||||
isFood: 0
|
||||
})
|
||||
|
||||
let riderOrder = ref<any>({
|
||||
status:0
|
||||
})
|
||||
|
||||
let orderOver = ref<true>(false)
|
||||
|
||||
onLoad((data) => {
|
||||
if (data.orderId) {
|
||||
orderId.value = data.orderId
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg('为获取到订单ID')
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化url
|
||||
const getUrl = () => {
|
||||
isshow.value = false
|
||||
url.value = 'https://hmjz.327gzs.top?orderId=' + orderId.value + '&isFood=' + riderOrder.value.status
|
||||
isshow.value = true
|
||||
}
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
if (res.code==0) {
|
||||
orderInfo.value = res.data.orderInfo
|
||||
riderOrder.value = res.data.riderOrder
|
||||
getUrl()
|
||||
|
||||
}else{
|
||||
Service.Msg(res.mgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 点击完成送餐取餐调用
|
||||
const handleMessage = (data) => {
|
||||
|
||||
let preat = data.detail.data[0]
|
||||
if(preat.action =='message'){
|
||||
if (riderOrder.value.status == 0) {
|
||||
// 去商家、取餐
|
||||
pickFood(1)
|
||||
} else {
|
||||
// 去用户,送餐
|
||||
pickFood(2)
|
||||
}
|
||||
}else if(preat.action =='logData'){
|
||||
CNRiderOrderService.UpdateRiderLocation(preat.data[0],preat.data[1]).then(res=>{
|
||||
if(res.code==0){
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// 骑手定位
|
||||
const logData = (data) =>{
|
||||
console.log(data,'骑手定位')
|
||||
}
|
||||
|
||||
// 取餐
|
||||
const pickFood = ( type:number) => {
|
||||
CNRiderOrderService.UpdateRiderOrderTake(orderId.value, type).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg(type==1?'取餐成功':'订单完成')
|
||||
setTimeout(()=>{Service.GoPageTab('/pages/index/index')},500)
|
||||
getData()
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.reloading-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #f7f7f7; // 使用页面底色
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
10661
.svn/pristine/39/39b8e7d2b5fa559692b43fcaf6bcae3ac88317ea.svn-base
Normal file
@@ -0,0 +1,331 @@
|
||||
import { HttpRequest, StoreAssist, UploadAssist, ResultData } from '@/common/Common';
|
||||
import { BaseConfig } from './BaseConfig';
|
||||
export class Service extends BaseConfig {
|
||||
//获取API地址
|
||||
static ApiUrl(path : string) {
|
||||
return `${this.servesUrl}${path}`;
|
||||
}
|
||||
|
||||
//获取图片地址
|
||||
static GetpayImg(path : string) {
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.payuploadUrl}${path}`;
|
||||
}
|
||||
}
|
||||
|
||||
//获取图标地址
|
||||
static GetIconImg(path : string) {
|
||||
return path
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.imgUrl}${path}`;
|
||||
}
|
||||
}
|
||||
|
||||
//获取图片地址
|
||||
static GetMateUrlByImg(path : string) {
|
||||
return path
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.imgUrl}${path}`;
|
||||
}
|
||||
}
|
||||
//获取音视频地址
|
||||
static GetMateUrlByMedia(path : string) {
|
||||
if (path.startsWith('http') || path.startsWith('https')) {
|
||||
return path;
|
||||
} else {
|
||||
return `${this.mediaUrl}${path}`;
|
||||
}
|
||||
}
|
||||
//获取登录账号token
|
||||
static GetUserToken() {
|
||||
return Service.GetStorageCache('token');
|
||||
}
|
||||
// 获取登录状态
|
||||
static GetUserIsLogin() {
|
||||
var token = this.GetUserToken();
|
||||
if (token == null || token == '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//设置登录账户Token
|
||||
static SetUserToken(token : string) {
|
||||
this.SetStorageCache('token', token);
|
||||
}
|
||||
//清理登录账户Token
|
||||
static OffUserToken() {
|
||||
Service.DelStorageCache('token');
|
||||
uni.$emit('ImComOff', 'user');
|
||||
this.ClearUserStateData();
|
||||
}
|
||||
//获取登录账号状态信息
|
||||
static GetUserStateData() {
|
||||
return Service.GetStorageCache('StateDomain');
|
||||
}
|
||||
//设置当前登录账号状态信息
|
||||
static SetUserStateData() {
|
||||
return Service.GetStorageCache('StateDomain');
|
||||
}
|
||||
//清理当前登录账号状态信息
|
||||
static ClearUserStateData() {
|
||||
Service.DelStorageCache('StateDomain');
|
||||
}
|
||||
|
||||
//获取缓存
|
||||
static GetStorageCache(key : string) {
|
||||
return StoreAssist.Get(key);
|
||||
}
|
||||
//删除缓存
|
||||
static DelStorageCache(key : string) {
|
||||
StoreAssist.Delete(key);
|
||||
}
|
||||
//设置缓存
|
||||
static SetStorageCache(key : string, data : any) {
|
||||
StoreAssist.Set(key, data);
|
||||
}
|
||||
|
||||
/*****以下是基础方法调用与拦截器*****/
|
||||
|
||||
static Request(url : string, method : 'GET' | 'POST' | 'PUT' | undefined, data : object | any) {
|
||||
const token = Service.GetUserToken();
|
||||
|
||||
const _url = Service.ApiUrl(url);
|
||||
var result = HttpRequest.RequestWithToken(_url, method, token, data).then((retResult : any) => {
|
||||
if (retResult.statusCode == '200') {
|
||||
var obj = retResult.data;
|
||||
if (obj.code == 401) {
|
||||
//过期
|
||||
this.OffUserToken();
|
||||
this.Msg('登录过期,请重新登录')
|
||||
this.GoPage('/pages/login/login')
|
||||
return Promise.reject();
|
||||
} else if (obj.code == 40101) {
|
||||
//失效
|
||||
this.OffUserToken();
|
||||
this.GoPageDelse('/pages/mine/login/login');
|
||||
return Promise.reject();
|
||||
} else if (obj.code == 1004) {
|
||||
//资源不存在
|
||||
this.GoPageDelse('/pages/AppSet/404/404');
|
||||
return Promise.reject();
|
||||
// return new ResultData(-1, '', '');
|
||||
} else if (obj.code == 40188) {
|
||||
//无权限
|
||||
|
||||
this.GoPageDelse('/pages/AppSet/40188/40188');
|
||||
return Promise.reject();
|
||||
// return new ResultData(-1, '', '');
|
||||
} else if (obj.code == 1008) {
|
||||
//业务提示
|
||||
return new ResultData(obj.code, obj.msg, obj.data);
|
||||
} else {
|
||||
return new ResultData(obj.code, obj.msg, obj.data);
|
||||
}
|
||||
} else {
|
||||
return new ResultData(-1, '', '');
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/*****以下是腾讯云oss上传*****/
|
||||
static UpLoadMedia(code : string, fileName : string, desire : string, path : string) {
|
||||
var result = this.Request(this.uploadUrl, 'GET', { code, fileName, desire }).then((retResult) => {
|
||||
if (retResult.code == 0) {
|
||||
var upOk = UploadAssist.Upload(retResult.data.url, path, retResult.data.cosData).then((upRet : any) => {
|
||||
if (upRet.statusCode == 200) {
|
||||
const retData : any = { code: retResult.data.code, file: retResult.data.file, cache: retResult.data.cache };
|
||||
return new ResultData(0, '上传成功!', retData);
|
||||
} else {
|
||||
this.Msg('上传失败!');
|
||||
return new ResultData(-1, '', '');
|
||||
}
|
||||
});
|
||||
return upOk;
|
||||
} else {
|
||||
this.Msg('上传失败!');
|
||||
return new ResultData(-1, retResult.msg,retResult.data);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********消息操作**************/
|
||||
static Msg(message : any, icon ?: any) : void {
|
||||
if (icon != null) {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: icon
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static Alert(msg : string, cb ?: any) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: msg,
|
||||
showCancel: false,
|
||||
cancelText: '取消',
|
||||
confirmText: '确定',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
cb && cb();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static LoadIng(text : any) : void {
|
||||
uni.showLoading({
|
||||
title: text,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
static LoadClose() : void {
|
||||
uni.hideLoading();
|
||||
}
|
||||
|
||||
/**********跳转操作*********/
|
||||
|
||||
|
||||
static GoPageTab(path : string) : void {
|
||||
uni.switchTab({
|
||||
url: path
|
||||
});
|
||||
}
|
||||
|
||||
/**********跳转操作*********/
|
||||
static GoPage(path : string) : void {
|
||||
uni.navigateTo({
|
||||
url: path, //跳转的页面
|
||||
success: function (res) {
|
||||
// 通过eventChannel向被打开页面传送数据
|
||||
}
|
||||
});
|
||||
}
|
||||
/**********跳转并删除当前页面操作*********/
|
||||
static GoPageDelse(path : string) : void {
|
||||
uni.redirectTo({
|
||||
url: path //跳转的页面
|
||||
});
|
||||
}
|
||||
|
||||
/**********返回上一页*********/
|
||||
static GoPageBack() : void {
|
||||
uni.navigateBack({ delta: 1 });
|
||||
}
|
||||
|
||||
/*****获取图片base64*****/
|
||||
static UpLoadMediaBase64(path : string) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
uni.uploadFile({
|
||||
url: 'http://cloud.pccsh.com/DefUp/UploadFileImgBase64', //仅为示例,非真实的接口地址
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
success: (uploadFileRes) => {
|
||||
resolve(uploadFileRes);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/*****获取图片位置信息*****/
|
||||
//获取时间戳
|
||||
static GetTimeSpan(milliSecond : number) {
|
||||
return Date.now() + milliSecond;
|
||||
}
|
||||
|
||||
// 时间戳处理
|
||||
static formatDate(time : any, type : number) : string {
|
||||
const date = new Date(time);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以加1,并用0填充
|
||||
const day = String(date.getDate()).padStart(2, '0'); // 用0填充
|
||||
const hours = String(date.getHours()).padStart(2, '0'); // 用0填充
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0'); // 用0填充
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0'); // 用0填充
|
||||
if (type == 0) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
else if (type == 1) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
} else if (type == 2) {
|
||||
return `${year}-${month}-${day}`;
|
||||
} else if (type == 3) {
|
||||
return `${hours}:${minutes}`;
|
||||
} else if (type == 4) {
|
||||
return `${year}${month}${day}`;
|
||||
}
|
||||
|
||||
else {
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
}
|
||||
|
||||
/*****节流*****/
|
||||
static throttle(fn: () => void, time: number) {
|
||||
let canRun: boolean = true;
|
||||
return function () {
|
||||
if (!canRun) return;
|
||||
canRun = false;
|
||||
setTimeout(() => {
|
||||
fn(); //可以不执行
|
||||
canRun = true;
|
||||
}, time);
|
||||
};
|
||||
}
|
||||
/*****防抖*****/
|
||||
static debounce<T extends (...args: any[]) => void>(fn: T, time: number): (...args: Parameters<T>) => void {
|
||||
let timerId: NodeJS.Timeout | null = null;
|
||||
|
||||
return (...args: Parameters<T>) => {
|
||||
if (timerId) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
|
||||
timerId = setTimeout(() => {
|
||||
fn(...args); // 执行传入的函数
|
||||
timerId = null; // 清除定时器ID
|
||||
}, time);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 普通图片上传
|
||||
static uploadH5(path, dic, callback) {
|
||||
console.log(this.payuploadUrl,'xxx')
|
||||
uni.uploadFile({
|
||||
url: this.payuploadUrl+'/Upload/UploadFile',
|
||||
method: "POST",
|
||||
header: {
|
||||
'Authorization': 'Bearer ' + Service.GetUserToken(),
|
||||
},
|
||||
formData: {
|
||||
"path": dic,
|
||||
},
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
success: (data) => {
|
||||
let info = data.data
|
||||
callback(info)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
<template>
|
||||
<!-- 收入概览区域 -->
|
||||
<view class="income-container">
|
||||
<view class="income-overview">
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between; ">
|
||||
<view class="">
|
||||
<text class="income-title">账户余额</text>
|
||||
<view class="" style="display: flex; align-items: center;">
|
||||
<text class="income-amount">¥{{riderAcc.account}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-button class="withdraw-button" @click="Service.GoPage('/pages/order/withdraw')"
|
||||
type="primary">立即提现</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收入明细区域 -->
|
||||
<view class="detail-header">
|
||||
<text class="detail-title">收支明细</text>
|
||||
</view>
|
||||
<!-- 时间选择标签 -->
|
||||
<view class="time-tabs">
|
||||
<text v-for="(item ,index) in timeList" :key="index" @click="changeTab(index)"
|
||||
:class="{ 'active':currentTime==index }" class="tab-item">{{item}}</text>
|
||||
</view>
|
||||
<view class="detail-list" v-for="(item, index) in accList" :key="index">
|
||||
<view class="detail-content">
|
||||
<view class="icon-placeholder">
|
||||
<image :src="Service.GetIconImg('/static/index/income/order.png')"
|
||||
style="width: 55rpx; height: 55rpx;" mode=""></image>
|
||||
</view>
|
||||
<view class="detail-info">
|
||||
<text class="order-id">{{item.name}}</text>
|
||||
<text class="order-time">{{ Service.formatDate(item.addTime,1) }}</text>
|
||||
</view>
|
||||
<view class="" style="" >
|
||||
<view class="order-amount" style="text-align: right;" >{{ item.code=='收入'?'+':'-' }}{{item.amount}}</view>
|
||||
<view class="order-time" >
|
||||
账户余额 {{ item.balance }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
<view class="" style="width: 100vw; height: 100rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<calender ref="calendar" :range='true' :insert="false" @confirm='dataConfirm' />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderDataService } from "@/Service/CN/CNRiderDataService"
|
||||
import { CNRiderOrderService } from "@/Service/CN/CNRiderOrderService"
|
||||
import calender from "@/uni_modules/uni-calendar/components/uni-calendar/uni-calendar"
|
||||
|
||||
let loading = ref(true)
|
||||
let calendar = ref(null)
|
||||
let timeList = ref([
|
||||
'今日',
|
||||
'本周',
|
||||
'本月',
|
||||
'自定义'
|
||||
])
|
||||
|
||||
let currentTime = ref(0)
|
||||
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
let riderAcc = ref<any>({})
|
||||
|
||||
let accList = ref<Array<any>>([])
|
||||
|
||||
let timeString=ref('')
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
getIncome()
|
||||
})
|
||||
onMounted(() => {
|
||||
})
|
||||
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderAccInfo().then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
riderAcc.value = res.data.riderAcc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 收入列表
|
||||
|
||||
const getIncome = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
accList.value=[]
|
||||
getIncomeList()
|
||||
}
|
||||
|
||||
const getIncomeList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderAccLog(currentTime.value==0?'0':(currentTime.value==3?timeString.value:String(currentTime.value)), page.value).then(res => {
|
||||
accList.value = [...accList.value, ...res.data.accLog]
|
||||
status.value = res.data.accLog == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
}
|
||||
|
||||
const changeTab = (index : number) => {
|
||||
currentTime.value = index
|
||||
if (index == 3) {
|
||||
calendar.value.open()
|
||||
return
|
||||
}
|
||||
getIncome()
|
||||
}
|
||||
|
||||
const dataConfirm = (e) => {
|
||||
timeString.value = e.range.data[0] + '_' + e.range.data.slice(-1)
|
||||
if(e.range.data.length==0){
|
||||
timeString.value=e.fulldate+'_'
|
||||
getIncome()
|
||||
return
|
||||
}
|
||||
getIncome()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
.income-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 收入概览区域 */
|
||||
.income-overview {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.income-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.income-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 时间标签 */
|
||||
.time-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-right: 40rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #1890ff;
|
||||
border-bottom: 3rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.month-total {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 收入构成区域 */
|
||||
.income-composition {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 饼图占位 */
|
||||
.pie-chart-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.chart-legend {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.legend-dot.blue {
|
||||
background-color: var(--nav-mian);
|
||||
}
|
||||
|
||||
.legend-dot.orange {
|
||||
background-color: var(--nav-vice);
|
||||
}
|
||||
|
||||
.legend-dot.green {
|
||||
background-color: var(--nav-diluted);
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 钱包区域 */
|
||||
.wallet-section {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wallet-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.withdraw-button {
|
||||
margin: 0;
|
||||
width: fit-content;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.withdraw-tip {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 收入明细区域 */
|
||||
.income-detail {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
.detail-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-list {
|
||||
margin: 15rpx 0 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 图标占位符 - 黑边白底 */
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* 没有更多记录 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<view style="padding: 10rpx 30rpx;">
|
||||
<view class="" v-for="(item,index) in withdrowList" :key="index"
|
||||
style="margin-top: 20rpx; gap: 20rpx; background-color: #fff; border-radius: 20rpx; padding: 30rpx; display: flex; align-items: center; justify-content: space-between; ">
|
||||
<view class="icon-placeholder">
|
||||
<image :src="Service.GetIconImg('/static/index/income/order.png')" style="width: 55rpx; height: 55rpx;"
|
||||
mode=""></image>
|
||||
</view>
|
||||
<view class="" style="flex: 1;">
|
||||
<view class="" style="font-weight: bold;">
|
||||
余额提现-到{{item.payway}}
|
||||
</view>
|
||||
|
||||
<view style=" margin-top: 4rpx; color: #999; font-size: 24rpx;">2025-12-15</view>
|
||||
</view>
|
||||
<view class="" style="color: red; font-weight: bold; ">
|
||||
+15.6
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service } from '@/Service/Service';
|
||||
import { ref } from "vue";
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let withdrowList = ref<Array<any>>([])
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
const getData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
withdrowList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderWithList(page.value).then(res => {
|
||||
withdrowList.value = [...withdrowList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,680 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style=" z-index: 100; padding:50rpx 20rpx 18rpx; box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: #fff; display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="">
|
||||
订单详情
|
||||
</view>
|
||||
<view class="" @click="Service.GoPage('/pages/my/myKF')" style="color: var(--nav-banbacor);">
|
||||
<image :src="Service.GetIconImg('/static/index/order/message.png')" style="width: 32rpx; height: 32rpx; "
|
||||
mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 88rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 骨架屏订单状态 -->
|
||||
<view class="skeleton-status"></view>
|
||||
|
||||
<!-- 骨架屏订单基本信息 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-half"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-line"></view>
|
||||
<view class="skeleton-row">
|
||||
<view class="skeleton-info-third"></view>
|
||||
<view class="skeleton-info-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏物品清单 -->
|
||||
<view class="skeleton-basic-info">
|
||||
<view class="skeleton-row">
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;">
|
||||
<view class="" style="background-color: #e6e6e6; width: 60%;height: 40rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-row" v-for="(item,index) in 3" :key="index">
|
||||
<view class="" style="width: 45%;height: 40rpx;border-radius: 4rpx;animation: shimmer 1.5s infinite;">
|
||||
<view class="" style="background-color: #e6e6e6; width: 90%;height: 40rpx; ">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
<view class="skeleton-info-half skeleton-right"></view>
|
||||
</view>
|
||||
<view class="skeleton-list-status"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏地图区域 -->
|
||||
<view class="skeleton-map"></view>
|
||||
|
||||
<!-- 骨架屏取餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-code"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏送餐地址 -->
|
||||
<view class="skeleton-address">
|
||||
<view class="skeleton-title"></view>
|
||||
<view class="skeleton-store-name"></view>
|
||||
<view class="skeleton-address-line"></view>
|
||||
<view class="skeleton-btn"></view>
|
||||
<view class="skeleton-remark"></view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏底部按钮 -->
|
||||
<view class="skeleton-bottom">
|
||||
<view class="skeleton-bottom-btn"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单状态 -->
|
||||
<view class="order-status"
|
||||
:style="{ 'background-color':orderStatus==0?'#E6F7FF':(orderStatus==1?'#FFFBE6':'#FFF2F0') }">
|
||||
<text :style="{ 'color':orderStatus==0?'#1890FF':(orderStatus==1?'#FAAD14':'#FF4D4F') }"
|
||||
style="font-size: 34rpx; font-weight: 600;">待取餐 · 请尽快到店取餐</text>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="info-item">
|
||||
<view class="label" style="font-weight: 700; font-size: 30rpx;"> {{ orderInfo.distribution=='预约订单'?'预计'+orderInfo.makeTime.split(' ')[1]+'送达':orderInfo.makeTime }} </view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">{{ orderId }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item" style="justify-content: space-between;" >
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="16" class="clock-icon"></u-icon>
|
||||
{{ Service.formatDate(orderInfo.addTime,1) }} 下单
|
||||
</view>
|
||||
<view class="">
|
||||
<button @click="Service.GoPage('/pages/order/abnormal')" class="" style="padding: 0rpx 30rpx; height: 60rpx; font-size: 24rpx; border-radius: 40rpx; background-color: red; color: #fff; " >提交异常</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
数量
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
金额
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'110rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in JSON.parse(orderInfo.detail) " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
{{goodsItem.goodsName}}
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×{{ goodsItem.count }}
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥{{ goodsItem.count*goodsItem.price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center;justify-content: space-between; margin-top: 10rpx; " >
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥{{ Number(orderInfo.postage).toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-if="JSON.parse(orderInfo.detail).length>2" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 地图区域 -->
|
||||
<view class="map-section">
|
||||
<view class="map-placeholder">
|
||||
<text @click="Service.GoPage('/pages/order/navigation')" class="map-hint">点击查看完整导航</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">取餐地址</text>
|
||||
<view class="address-content">
|
||||
<view class="store-name">{{ storeInfo.name }}</view>
|
||||
<text class="address">{{ storeInfo.city }}{{storeInfo.region }}{{ storeInfo.address }}</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button @click="call(storeInfo.phone)" icon="phone" type="primary" shape="circle" text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view class="pickup-code">
|
||||
<text class="code-label">取餐号:</text>
|
||||
<text class="code-value">A123</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 送餐地址 -->
|
||||
<view class="address-section">
|
||||
<text class="section-title">送餐地址</text>
|
||||
<view class="address-content">
|
||||
<text class="user-name">{{ JSON.parse(orderInfo.address).realName }}</text>
|
||||
<text class="address">{{ JSON.parse(orderInfo.address).address }}</text>
|
||||
<view class="" style="margin-bottom: 20rpx;">
|
||||
<up-button @click="call(JSON.parse(orderInfo.address).phone)" icon="phone" type="primary" shape="circle" text="拨打商家"></up-button>
|
||||
</view>
|
||||
<view v-if="orderInfo.remark" class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">{{ orderInfo.remark }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action">
|
||||
<up-button color="var(--nav-vice)" class="confirm-btn">我已取餐</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
let deliveryTime = ref('')
|
||||
|
||||
let orderInfo = ref<any>({})
|
||||
let storeInfo = ref<any>({})
|
||||
let storeLocation = ref<any>({})
|
||||
|
||||
let orderId = ref('')
|
||||
onLoad((data : any) => {
|
||||
orderId.value = data.orderId
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
deliveryTime.value = res.data.deliveryTime
|
||||
orderInfo.value = res.data.orderInfo
|
||||
storeInfo.value = res.data.storeInfo
|
||||
storeLocation.value = res.data.storeLocation
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const call=(phone:string)=>{
|
||||
uni.makePhoneCall({
|
||||
phoneNumber:phone
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏导航栏 */
|
||||
.skeleton-nav {
|
||||
height: 88rpx;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.skeleton-nav-item {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-nav-title {
|
||||
width: 180rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单状态 */
|
||||
.skeleton-status {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-status::after {
|
||||
content: '';
|
||||
width: 350rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏订单基本信息 */
|
||||
.skeleton-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-info-half {
|
||||
width: 45%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-right {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-third {
|
||||
width: 60%;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-info-btn {
|
||||
width: 20%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 列表状态 */
|
||||
.skeleton-list-status {
|
||||
height: 60rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.skeleton-list-status::after {
|
||||
content: '';
|
||||
width: 200rpx;
|
||||
height: 45rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏地图区域 */
|
||||
.skeleton-map {
|
||||
margin: 20rpx;
|
||||
height: 400rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-map::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, transparent 25%, rgba(255, 255, 255, 0.2) 25%, rgba(255, 255, 255, 0.2) 50%, transparent 50%, transparent 75%, rgba(255, 255, 255, 0.2) 75%, rgba(255, 255, 255, 0.2));
|
||||
background-size: 100rpx 100rpx;
|
||||
animation: shimmer 1.5s infinite linear;
|
||||
}
|
||||
|
||||
/* 骨架屏地址区域 */
|
||||
.skeleton-address {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
width: 120rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 25rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-store-name {
|
||||
width: 70%;
|
||||
height: 50rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-address-line {
|
||||
width: 90%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
height: 70rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 35rpx;
|
||||
margin: 20rpx 0;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-code {
|
||||
width: 50%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-remark {
|
||||
width: 80%;
|
||||
height: 26rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏底部按钮 */
|
||||
.skeleton-bottom {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-bottom-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏滑动动画 */
|
||||
@keyframes shimmer-slide {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* end */
|
||||
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin: 10rpx 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,14 @@
|
||||
export class StoreAssist{
|
||||
static Get(key:string):any
|
||||
{
|
||||
return uni.getStorageSync(key);
|
||||
}
|
||||
static Set(key:string,value:any):void
|
||||
{
|
||||
uni.setStorageSync(key, value);
|
||||
}
|
||||
static Delete(key:string):void
|
||||
{
|
||||
uni.removeStorageSync(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
|
||||
<view v-if="loading" class="pure-css-skeleton">
|
||||
<view style=" margin: 20rpx 0; padding: 20rpx; background-color: #fff; border-radius: 10rpx;">
|
||||
<!-- 头像区域骨架 -->
|
||||
<view class="avatar-skeleton-wrapper"
|
||||
style="display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||
<view class="skeleton-circle animate-pulse"></view>
|
||||
<view class="skeleton-text animate-pulse" style="margin-top: 15rpx;"></view>
|
||||
</view>
|
||||
|
||||
<!-- 表单区域骨架 -->
|
||||
<view class="form-skeleton-wrapper" style="margin-top: 30rpx;">
|
||||
<!-- 昵称 -->
|
||||
<view class="form-item-skeleton">
|
||||
<view class="form-label-skeleton animate-pulse"></view>
|
||||
<view class="form-input-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
<!-- 性别 -->
|
||||
<view class="form-item-skeleton">
|
||||
<view class="form-label-skeleton animate-pulse"></view>
|
||||
<view class="form-radio-skeleton">
|
||||
<view class="radio-item-skeleton animate-pulse"></view>
|
||||
<view class="radio-item-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 生日 -->
|
||||
<view class="form-item-skeleton">
|
||||
<view class="form-label-skeleton animate-pulse"></view>
|
||||
<view class="form-input-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
<!-- 手机号 -->
|
||||
<view class="form-item-skeleton">
|
||||
<view class="form-label-skeleton animate-pulse"></view>
|
||||
<view class="form-input-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
<!-- 邮箱 -->
|
||||
<view class="form-item-skeleton">
|
||||
<view class="form-label-skeleton animate-pulse"></view>
|
||||
<view class="form-input-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部空间占位 -->
|
||||
<view style="width: 100%; height: 200rpx;"></view>
|
||||
</view>
|
||||
|
||||
<!-- 底部保存按钮骨架 -->
|
||||
<view class="bottom-button-skeleton animate-pulse"></view>
|
||||
</view>
|
||||
|
||||
<view v-else style=" margin: 20rpx; padding: 20rpx;">
|
||||
<view @click="uploadFImg()" class=""
|
||||
style=" display: flex; flex-direction: column; justify-content: center; align-items: center; ">
|
||||
<img v-if="userInfo.headImg!=''" :src="Service.GetMateUrlByImg(userInfo.headImg)"
|
||||
style="width: 140rpx; height: 140rpx; border-radius: 50%; " alt="" />
|
||||
<view v-else class=""
|
||||
style="background-color: #EBEBEB; width: 140rpx; height: 140rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; ">
|
||||
<image :src="Service.GetIconImg('/static/index/my/edit/photo.png')"
|
||||
style="width: 50rpx; height: 50rpx; " alt=""> </image>
|
||||
</view>
|
||||
<view class="" style="margin-top: 15rpx; font-size: 26rpx; color: #999999; ">
|
||||
点击更换头像
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="" style=" margin-top: 30rpx; ">
|
||||
<up-form labelWidth='90' labelPosition="left" :borderBottom="true" :model="userInfo" ref="form1">
|
||||
<up-form-item label="昵称" prop="userInfo.name" ref="item1" :borderBottom="true">
|
||||
<up-input inputAlign='right' v-model="userInfo.nick" border="none"></up-input>
|
||||
</up-form-item>
|
||||
|
||||
<up-form-item label="性别" :borderBottom="true" style="position: relative;" prop="userInfo.sex">
|
||||
<view class="" style=" position: absolute; top: 10rpx; right: 0; ">
|
||||
<up-radio-group v-model="userInfo.sex" placement="row">
|
||||
<up-radio v-for="(item, index) in radiolist1" activeColor='#FF6A00' :key="index"
|
||||
iconPlacement="right" :label="item.name" :name="item.name">
|
||||
</up-radio>
|
||||
</up-radio-group>
|
||||
</view>
|
||||
</up-form-item>
|
||||
<up-form-item label="生日" :borderBottom="true" prop="userInfo.sex" style="position: relative;">
|
||||
<view @click="showDate=true" class=""
|
||||
style=" position: absolute; top: 25rpx; right: 0; display: flex; align-items: center; ">
|
||||
{{Service.formatDate(userInfo.date,2)}}
|
||||
<u-icon name="arrow-right" size="24rpx" color="#000"></u-icon>
|
||||
</view>
|
||||
</up-form-item>
|
||||
<up-form-item label="手机号" :borderBottom="true" prop="userInfo.sex">
|
||||
<up-input inputAlign='right' v-model="userInfo.phone" border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
</view>
|
||||
|
||||
<up-datetime-picker :maxDate="nowDate" :minDate="631123200000" :show="showDate" @cancel="showDate=!showDate"
|
||||
@confirm="dateConfirm" v-model="userInfo.date" mode="date"></up-datetime-picker>
|
||||
<view class="" style="width: 100%; height: 200rpx;">
|
||||
|
||||
</view>
|
||||
<view class="" style=" width: 100% ; background-color: #fff; position: fixed; bottom: 15rpx; left: 0; ">
|
||||
<view class=""
|
||||
style=" margin: 0 20rpx; padding: 26rpx 0; color: #fff; display: flex; align-items: center; justify-content: center; border-radius: 60rpx; background-color: var(--nav-mian);">
|
||||
保存信息
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Service } from '@/Service/Service';
|
||||
import { ref } from "vue";
|
||||
|
||||
|
||||
let loading = ref(true)
|
||||
|
||||
let showDate = ref(false)
|
||||
const userInfo = ref({
|
||||
headImg: '',
|
||||
age: '1',
|
||||
sex: '',
|
||||
phone: '1',
|
||||
date: Date.now(),
|
||||
nick: '大大怪将军'
|
||||
})
|
||||
|
||||
let nowDate = ref()
|
||||
|
||||
const radiolist1 = ref([
|
||||
{
|
||||
name: '男',
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
disabled: false,
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
nowDate.value = new Date()
|
||||
});
|
||||
|
||||
const dateConfirm = (e) => {
|
||||
showDate.value = !showDate.value
|
||||
userInfo.value.date = e.value
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const uploadFImg = () => {
|
||||
uni.chooseImage({
|
||||
count: 1, // 最多选择3张图片
|
||||
sizeType: ['original', 'compressed'], // 支持原图和压缩图
|
||||
sourceType: ['album', 'camera'], // 可从相册选择或使用相机拍照
|
||||
success: function (res) {
|
||||
let path = res.tempFiles[0].path
|
||||
userInfo.value.headImg = path
|
||||
// Service.uploadH5(path, 'Avatar', data => {
|
||||
// userInfo.value.headImg = data.split(',')[2].split(':')[1].split('"')[1]
|
||||
// })
|
||||
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error('选择失败:', err.errMsg);
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.pure-css-skeleton {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* 骨架屏基础样式 */
|
||||
.skeleton-circle {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.skeleton-text {
|
||||
width: 120rpx;
|
||||
height: 26rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.form-item-skeleton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-item-skeleton:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.form-label-skeleton {
|
||||
width: 90rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.form-input-skeleton {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
height: 30rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.form-radio-skeleton {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.radio-item-skeleton {
|
||||
width: 100rpx;
|
||||
height: 30rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.bottom-button-skeleton {
|
||||
position: fixed;
|
||||
bottom: 15rpx;
|
||||
left: 20rpx;
|
||||
right: 20rpx;
|
||||
height: 90rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 60rpx;
|
||||
}
|
||||
|
||||
/* 动画效果 - 不使用组件,纯CSS实现 */
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,361 @@
|
||||
<template>
|
||||
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 安全等级卡片骨架 -->
|
||||
<view class="security-level-card skeleton-card">
|
||||
<view class="security-level-header">
|
||||
<view class="skeleton-line skeleton-line-sm"></view>
|
||||
</view>
|
||||
<view class="progress-bar skeleton-progress"></view>
|
||||
<view class="skeleton-line skeleton-line-xs"></view>
|
||||
</view>
|
||||
|
||||
<!-- 安全设置列表骨架 -->
|
||||
<view class="security-settings skeleton-settings">
|
||||
<view class="security-item skeleton-item" v-for="i in 3" :key="i">
|
||||
<view class="item-left">
|
||||
<view class="item-icon skeleton-icon"></view>
|
||||
<view class="skeleton-line skeleton-line-md"></view>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<view class="skeleton-line skeleton-line-sm"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 安全提示卡片骨架 -->
|
||||
<view class="security-tip-card skeleton-tip-card">
|
||||
<view class="tip-content">
|
||||
<view class="skeleton-circle"></view>
|
||||
<view class="skeleton-line skeleton-line-full"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="account-security-page" style="overflow: hidden;" >
|
||||
<!-- 安全等级卡片 -->
|
||||
<view class="security-level-card">
|
||||
<view class="security-level-header">
|
||||
<text class="security-level-label">账号安全等级:</text>
|
||||
<text class="security-level-value">高</text>
|
||||
</view>
|
||||
<view class="progress-bar">
|
||||
<view class="progress-fill"></view>
|
||||
</view>
|
||||
<view class="security-desc">您已完成所有安全设置</view>
|
||||
</view>
|
||||
|
||||
<!-- 安全设置列表 -->
|
||||
<view class="security-settings">
|
||||
<!-- 实名认证 -->
|
||||
<view class="security-item" @click="Service.GoPage(item.path)" v-for="(item,index) in funcList" :key="index">
|
||||
<view class="item-left">
|
||||
<view class="item-icon">
|
||||
<image :src="Service.GetIconImg(item.icon)" style="width: 100%; height: 100%; " mode=""></image>
|
||||
</view>
|
||||
<text class="item-label">{{item.name}}</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<text class="item-status">{{ item.des }}</text>
|
||||
<up-icon name="arrow-right" size="19" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 安全提示卡片 -->
|
||||
<view class="security-tip-card">
|
||||
<view class="tip-content">
|
||||
<up-icon name="info-circle-fill" size="24" color="#999"></up-icon>
|
||||
<text class="tip-text">为保障您的账号安全,请勿泄露验证码,定期更新密码。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { Service } from "@/Service/Service"
|
||||
import { ref } from 'vue'
|
||||
import { CNRiderDataService } from "@/Service/CN/CNRiderDataService"
|
||||
|
||||
let loading = ref(true)
|
||||
|
||||
let riderInfo=ref<any>({})
|
||||
|
||||
|
||||
const funcList = ref([
|
||||
{
|
||||
name: '实名认证',
|
||||
icon: '/static/index/my/security/security.png',
|
||||
des: "已认证",
|
||||
path:'/pages/my/authentication'
|
||||
},
|
||||
{
|
||||
name: '手机号绑定',
|
||||
icon: '/static/index/my/security/phone.png',
|
||||
des: "",
|
||||
path:'/pages/my/setConnect?type=1'
|
||||
},
|
||||
{
|
||||
name: '紧急联系人',
|
||||
icon: '/static/index/my/security/user.png',
|
||||
des: "",
|
||||
path:'/pages/my/setConnect?type=0'
|
||||
},
|
||||
{
|
||||
name: '修改密码',
|
||||
icon: '/static/index/my/security/mima.png',
|
||||
des: "",
|
||||
path:'/pages/my/editPasssword'
|
||||
}
|
||||
|
||||
])
|
||||
|
||||
// 页面加载时的逻辑
|
||||
onLoad(() => {
|
||||
|
||||
})
|
||||
|
||||
onShow(()=>{
|
||||
getData()
|
||||
getConnect()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderInfo().then(res => {
|
||||
loading.value = false
|
||||
if(res.data){
|
||||
riderInfo.value=res.data.riderInfo
|
||||
funcList.value[0].des=riderInfo.value.status===-1?'未认证':(riderInfo.value.status===0?'审核中':'已认证')
|
||||
funcList.value[1].des='已绑定'+' '+riderInfo.value.phone.slice(0,3)+'****'+riderInfo.value.phone.slice(-4)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const getConnect=()=>{
|
||||
CNRiderDataService.GetRiderExigency().then(res=>{
|
||||
if(res.data){
|
||||
funcList.value[2].des= res.data.info? res.data.info.phone : '未绑定'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
// 安全等级卡片样式
|
||||
.security-level-card {
|
||||
background-color: #E6F7FF;
|
||||
margin: 30rpx 30rpx 30rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.security-level-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.security-level-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.security-level-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8rpx;
|
||||
background-color: #B3D8FF;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #007AFF;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.security-desc {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
// 安全设置列表样式
|
||||
.security-settings {
|
||||
background-color: #fff;
|
||||
margin: 0 30rpx 30rpx;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.security-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.security-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.item-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-status {
|
||||
font-size: 28rpx;
|
||||
color: #4CD964;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
// 安全提示卡片样式
|
||||
.security-tip-card {
|
||||
background-color: #FFF8E8;
|
||||
margin: 0 30rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.tip-content {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: 36rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
// 骨架屏基础样式
|
||||
.skeleton-line {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.skeleton-icon {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.skeleton-circle {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
border-radius: 50%;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-progress {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-loading 1.5s infinite;
|
||||
}
|
||||
|
||||
// 骨架屏线条尺寸
|
||||
.skeleton-line-xs {
|
||||
height: 28rpx;
|
||||
width: 200rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.skeleton-line-sm {
|
||||
height: 32rpx;
|
||||
width: 300rpx;
|
||||
}
|
||||
|
||||
.skeleton-line-md {
|
||||
height: 36rpx;
|
||||
width: 240rpx;
|
||||
}
|
||||
|
||||
.skeleton-line-full {
|
||||
height: 36rpx;
|
||||
width: calc(100% - 60rpx);
|
||||
}
|
||||
|
||||
// 骨架屏动画
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 骨架屏容器样式
|
||||
.skeleton-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 骨架屏卡片样式
|
||||
.skeleton-card {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-settings {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-item {
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.skeleton-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.skeleton-tip-card {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,600 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="skeleton-container">
|
||||
<!-- 余额区域骨架屏 -->
|
||||
<view class="skeleton-balance-section">
|
||||
<view class="skeleton-balance-label"></view>
|
||||
<view class="skeleton-balance-amount"></view>
|
||||
<view class="skeleton-balance-current"></view>
|
||||
</view>
|
||||
|
||||
<!-- 账户选择区域骨架屏 -->
|
||||
<view class="skeleton-account-section">
|
||||
<view class="skeleton-section-title"></view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
<view class="skeleton-account-item">
|
||||
<view class="skeleton-account-icon"></view>
|
||||
<view class="skeleton-account-name"></view>
|
||||
<view class="skeleton-account-radio"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息骨架屏 -->
|
||||
<view class="skeleton-tip-section">
|
||||
<view class="skeleton-tip-icon"></view>
|
||||
<view class="skeleton-tip-content">
|
||||
<view class="skeleton-tip-line"></view>
|
||||
<view class="skeleton-tip-line-small"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮骨架屏 -->
|
||||
<view class="skeleton-confirm-section">
|
||||
<view class="skeleton-confirm-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 真实内容 -->
|
||||
<view v-else class="withdraw-container">
|
||||
<!-- 可提现金额 -->
|
||||
<view class="balance-section">
|
||||
<text class="balance-label">可提现金额</text>
|
||||
<text class="balance-amount">¥{{ riderAcc.account }}</text>
|
||||
<text class="current-balance">当前钱包余额</text>
|
||||
</view>
|
||||
|
||||
<!-- 提现账户选择 -->
|
||||
<view class="account-section">
|
||||
<text class="section-title">提现账户</text>
|
||||
<view class=""
|
||||
style="display: flex;align-items: center; border-bottom: 4rpx solid #e2e2e2;padding-bottom: 10px; margin-bottom: 10px;">
|
||||
<up-icon name="zhifubao-circle-fill" size="30" color="#1890ff"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
支付宝
|
||||
</view>
|
||||
<view @click="changePay(0)" class="">
|
||||
<view v-if="current==0" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex;align-items: center;">
|
||||
<up-icon name="weixin-circle-fill" size="30" color="#28C445"></up-icon>
|
||||
<view style="flex: 1; margin-left: 30rpx; " class="">
|
||||
微信
|
||||
</view>
|
||||
<view @click="changePay(1)" class="">
|
||||
<view v-if="current==1" class="radio-circle">
|
||||
<view class="radio-inner"></view>
|
||||
</view>
|
||||
<view v-else class="radio-no-circle">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提现账号 -->
|
||||
<view class="" v-if="current!=null" style="margin: 20rpx 30rpx; ">
|
||||
<view class="" style="font-size: 34rpx; font-weight: 600; ">
|
||||
账号信息
|
||||
</view>
|
||||
|
||||
<up-form labelPosition="top" label-width="200" :model="account" ref="form1">
|
||||
<up-form-item label="姓名" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.name" @change="changePrice" placeholder="请输入姓名" border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item :label="current==0? '支付宝账号':'微信账号'" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.id" :placeholder="current==0? '请输入支付宝账号':'请输入微信账号'"
|
||||
border="none"></up-input>
|
||||
</up-form-item>
|
||||
<up-form-item label="提现金额" prop="userInfo.name" :borderBottom="true" ref="item1">
|
||||
<up-input v-model="account.price" type="digit" placeholder="请输入提现金额" border="none"></up-input>
|
||||
</up-form-item>
|
||||
</up-form>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tip-section">
|
||||
<up-icon name="clock" size="18" color="#1890ff"></up-icon>
|
||||
<view class="" style="margin-left: 10rpx;">
|
||||
<view class="tip-text">预计 T+1 工作日到账</view>
|
||||
<view class="tip-text" style="color: #666666; font-size: 24rpx; margin-top: 10rpx; ">无手续费</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-section">
|
||||
<button class="confirm-button" @click="confirmWithdraw">确认提现</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
import { CNRiderDataService } from '@/Service/CN/CNRiderDataService'
|
||||
|
||||
let current = ref(null)
|
||||
let loading = ref(true)
|
||||
|
||||
|
||||
let account = ref({
|
||||
id: '',
|
||||
price: "",
|
||||
name: ''
|
||||
})
|
||||
|
||||
let riderAcc = ref<any>({})
|
||||
|
||||
onLoad(() => {
|
||||
|
||||
})
|
||||
|
||||
onShow(()=>{
|
||||
getData()
|
||||
})
|
||||
|
||||
|
||||
const getData = () => {
|
||||
CNRiderDataService.GetRiderAccInfo().then(res => {
|
||||
loading.value = false
|
||||
if (res.data) {
|
||||
riderAcc.value = res.data.riderAcc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const changePay = (item : any) => {
|
||||
current.value = item
|
||||
}
|
||||
|
||||
const changePrice = (e : string) => {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
|
||||
// 确认提现
|
||||
const confirmWithdraw = () => {
|
||||
if(!current.value){
|
||||
Service.Msg('请选择提现方式!')
|
||||
return
|
||||
}
|
||||
|
||||
if (!account.value.name) {
|
||||
Service.Msg('请输入姓名!')
|
||||
return
|
||||
}
|
||||
if (!account.value.price) {
|
||||
Service.Msg('请输入提现金额!')
|
||||
return
|
||||
}
|
||||
if (!account.value.id) {
|
||||
Service.Msg('请输入账户号!')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '请仔细确认身份信息?',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
CNRiderOrderService.AddRiderWith(Number(account.value.price), current.value == 0 ? '支付宝' : '微信', account.value.name, account.value.id).then(res => {
|
||||
if (res.code == 0) {
|
||||
Service.Msg('提现成功')
|
||||
account.value.name=''
|
||||
account.value.price=null
|
||||
account.value.id=''
|
||||
setTimeout(() => {
|
||||
Service.GoPage('/pages/my/withDrowList')
|
||||
}, 1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
// 用户点击取消后的操作
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.withdraw-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 选择 */
|
||||
|
||||
.radio-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.radio-inner {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: var(--nav-mian);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.radio-no-circle {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 2rpx solid #dadada;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* 余额显示区域 */
|
||||
.balance-section {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.balance-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4757;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.current-balance {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 账户选择区域 */
|
||||
.account-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.account-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #1677ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
border: 2rpx solid #000;
|
||||
}
|
||||
|
||||
.account-icon.wechat {
|
||||
background-color: #07c160;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 提示信息区域 */
|
||||
.tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 确认按钮区域 */
|
||||
.confirm-section {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #1677ff;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 45rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.confirm-button:active {
|
||||
background-color: #0958d9;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏通用样式 */
|
||||
.skeleton-balance-section,
|
||||
.skeleton-account-section,
|
||||
.skeleton-tip-section {
|
||||
padding: 40rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 余额区域骨架屏 */
|
||||
.skeleton-balance-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-balance-label {
|
||||
width: 30%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-amount {
|
||||
width: 40%;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-balance-current {
|
||||
width: 25%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 账户选择区域骨架屏 */
|
||||
.skeleton-account-section {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.skeleton-section-title {
|
||||
width: 25%;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 4rpx solid #e2e2e2;
|
||||
}
|
||||
|
||||
.skeleton-account-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.skeleton-account-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-name {
|
||||
flex: 1;
|
||||
height: 32rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 20rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-account-radio {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 提示信息骨架屏 */
|
||||
.skeleton-tip-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #e6f7ff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 30rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-tip-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 50%;
|
||||
margin-right: 15rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-tip-line {
|
||||
width: 70%;
|
||||
height: 28rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin-bottom: 15rpx;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
.skeleton-tip-line-small {
|
||||
width: 50%;
|
||||
height: 24rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
|
||||
/* 确认按钮骨架屏 */
|
||||
.skeleton-confirm-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.skeleton-confirm-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 45rpx;
|
||||
animation: shimmer 1.5s infinite;
|
||||
background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 1000px 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,451 @@
|
||||
<template>
|
||||
<!-- 骨架屏 -->
|
||||
<view v-if="loading" class="order-detail skeleton-loading">
|
||||
<!-- 订单基本信息骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view class="" style="display: flex; justify-content: space-between;align-items: center; ">
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
</view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<!-- 物品清单骨架屏 -->
|
||||
<view class="order-basic-info skeleton-section">
|
||||
<view v-for="item in 4" class="skeleton-block" style="width: 100%; height: 40rpx; "></view>
|
||||
|
||||
<view class="" style="display: flex; justify-content: center;">
|
||||
<view class="skeleton-block skeleton-short"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地图区域骨架屏 -->
|
||||
<view class="map-section skeleton-section">
|
||||
<view class="map-placeholder skeleton-map"></view>
|
||||
</view>
|
||||
|
||||
<!-- 地址区域骨架屏 -->
|
||||
<view class="address-section skeleton-section">
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-medium"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
<view class="skeleton-block skeleton-long"></view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-padding"></view>
|
||||
|
||||
<!-- 底部按钮骨架屏 -->
|
||||
<view class="bottom-action">
|
||||
<view class="skeleton-button"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 实际内容 -->
|
||||
<view v-else class="order-detail">
|
||||
<!-- 订单基本信息 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="info-item">
|
||||
<view class="label" style="font-weight: 700; font-size: 30rpx;"> {{ orderInfo.distribution=='预约订单'?'预计'+orderInfo.makeTime.split(' ')[1]+'送达':orderInfo.makeTime }} </view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单编号 : </text>
|
||||
<text class="value">{{ orderId }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="label" style="display: flex; align-items: baseline;">
|
||||
<u-icon name="clock" size="16" class="clock-icon"></u-icon>
|
||||
{{ Service.formatDate(orderInfo.addTime,1) }} 下单
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 物品清单 -->
|
||||
<view class="order-basic-info">
|
||||
<view class="" style="display: flex; align-items: center; ">
|
||||
<view class="" style="flex: 1; font-size: 34rpx; font-weight: 600; ">
|
||||
物品清单
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; font-size: 30rpx; ">
|
||||
数量
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; font-size: 30rpx; ">
|
||||
金额
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<view class="" :style="{'height':isShow?'110rpx':'fit-content' }" style="overflow: hidden;">
|
||||
<view class="" v-for="(goodsItem,goodsIndex) in JSON.parse(orderInfo.detail) " :key="goodsIndex"
|
||||
style="display: flex; align-items: center; margin-top: 15rpx; ">
|
||||
<view class="" style="flex: 1; ">
|
||||
{{goodsItem.goodsName}}
|
||||
</view>
|
||||
<view class="" style="width: 100rpx; text-align: right; ">
|
||||
×{{ goodsItem.count }}
|
||||
</view>
|
||||
<view class="" style="width: 120rpx; text-align: right; ">
|
||||
¥{{ goodsItem.count*goodsItem.price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; justify-content: space-between;" >
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label" style="font-weight: 700;">配送费</text>
|
||||
<text class="value price">¥{{ Number(orderInfo.postage).toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-if="JSON.parse(orderInfo.detail).length>2" @click="isShow=!isShow"
|
||||
style=" margin-top: 20rpx; display: flex; align-items: center; justify-content: center; color: #666; ">
|
||||
<up-icon :name="isShow?'arrow-down':'arrow-up'" color="#666" size="18"></up-icon>
|
||||
{{isShow?'展开':'收入'}}
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 地图区域 -->
|
||||
<view class="map-section">
|
||||
<view class="map-placeholder">
|
||||
<text @click="Service.GoPage('/pages/order/navigation')" class="map-hint">点击查看完整导航</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 取餐地址 -->
|
||||
<view class="address-section">
|
||||
<view class="" style=" border-bottom: 4rpx solid #e2e2e2; ">
|
||||
<view class="section-title">取餐地址 : </view>
|
||||
<view class="address-content">
|
||||
<text class="store-name">{{ storeInfo.name }}</text>
|
||||
<text class="address"> {{ storeInfo.city }}{{storeInfo.region }}{{ storeInfo.address }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin: 10rpx 0; font-size: 30rpx;font-weight: 800;color: #333;">送餐地址 : </view>
|
||||
<view class="address-content">
|
||||
<text class="user-name">{{ JSON.parse(orderInfo.address).realName }}</text>
|
||||
<text class="address">{{ JSON.parse(orderInfo.address).address }}</text>
|
||||
<view v-if="orderInfo.remark" class="remark">
|
||||
<text class="remark-label">备注:</text>
|
||||
<text class="remark-content">请放门口,勿按门铃</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="" style="width: 100vw; height: 140rpx; ">
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-action">
|
||||
<up-button @click="placeOrder()" color="var(--nav-mian)" class="confirm-btn">立即接单</up-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Service } from '@/Service/Service';
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
let orderStatus = ref(0)
|
||||
|
||||
let isShow = ref(true)
|
||||
|
||||
let deliveryTime = ref('')
|
||||
|
||||
let orderInfo = ref<any>({})
|
||||
let storeInfo = ref<any>({})
|
||||
let storeLocation = ref<any>({})
|
||||
|
||||
let orderId = ref('')
|
||||
onLoad((data : any) => {
|
||||
orderId.value = data.orderId
|
||||
getData()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
CNRiderOrderService.GetUnitOrderInfo(orderId.value).then(res => {
|
||||
loading.value = false
|
||||
|
||||
if (res.data) {
|
||||
deliveryTime.value = res.data.deliveryTime
|
||||
orderInfo.value = res.data.orderInfo
|
||||
storeInfo.value = res.data.storeInfo
|
||||
storeLocation.value = res.data.storeLocation
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const placeOrder = () => {
|
||||
CNRiderOrderService.RiderTakeOrder(orderId.value).then(res => {
|
||||
if (res.data) {
|
||||
Service.Msg('接单成功!')
|
||||
setTimeout(() => {
|
||||
Service.GoPageBack()
|
||||
},1000)
|
||||
} else {
|
||||
Service.Msg(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 订单状态样式 */
|
||||
.order-status {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* 订单基本信息样式 */
|
||||
.order-basic-info {
|
||||
background-color: #fff;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value.highlight {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value.price {
|
||||
color: var(--nav-diluted);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
color: #666;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
/* 地图区域样式 */
|
||||
.map-section {
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-placeholder {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
}
|
||||
|
||||
.map-placeholder::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #f5f5f5 25%, #e6e6e6 25%, #e6e6e6 50%, #f5f5f5 50%, #f5f5f5 75%, #e6e6e6 75%, #e6e6e6 100%);
|
||||
background-size: 20rpx 20rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.map-hint {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 地址区域样式 */
|
||||
.address-section {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #333;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
.address-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.store-name,
|
||||
.user-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 25rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pickup-code,
|
||||
.remark {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.code-label,
|
||||
.code-value {
|
||||
color: var(--nav-mian);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.remark-label,
|
||||
.remark-content {
|
||||
color: #FAAD14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部按钮样式 */
|
||||
.bottom-action {
|
||||
background-color: #fff;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-loading .skeleton-section {
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-block {
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.skeleton-short {
|
||||
height: 40rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-medium {
|
||||
height: 30rpx;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.skeleton-long {
|
||||
height: 30rpx;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.skeleton-map {
|
||||
height: 400rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 20rpx;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.skeleton-button {
|
||||
height: 90rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.bottom-padding {
|
||||
height: 140rpx;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
.skeleton-block::after,
|
||||
.skeleton-map::after,
|
||||
.skeleton-button::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,131 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { WebSocket } from "@/Service/Comm/TwWebSocket";
|
||||
import { Service } from "@/Service/Service"
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let isios = ref(false)
|
||||
var socket = new WebSocket();
|
||||
|
||||
const currentLatitude = ref(0);
|
||||
const currentLongitude = ref(0);
|
||||
|
||||
let locationTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
|
||||
onLaunch(() => {
|
||||
isios.value = uni.getSystemInfoSync().platform != 'ios'//是否为ios
|
||||
//#ifdef APP-PLUS//app
|
||||
if (isios.value) {
|
||||
// getVersion()//更新
|
||||
}
|
||||
//#endif
|
||||
|
||||
//链接服务器
|
||||
uni.$on("ImCom", () => {
|
||||
socket.ConnectSocketInit();
|
||||
})
|
||||
uni.$on("ImComOff", function (data) {
|
||||
socket.CloseSocket(data);
|
||||
})
|
||||
startFetchingLocation();
|
||||
});
|
||||
onShow(() => {
|
||||
Service.SetStorageCache('isHede',false)
|
||||
//链接服务器
|
||||
if (Service.GetUserIsLogin()) {
|
||||
uni.$emit('ImCom')
|
||||
}
|
||||
|
||||
});
|
||||
onHide(() => {
|
||||
Service.SetStorageCache('isHede',true)
|
||||
});
|
||||
|
||||
|
||||
const startFetchingLocation = () => {
|
||||
// 安全检查:如果定时器已存在,先清除,防止重复启动
|
||||
if (locationTimer) {
|
||||
clearInterval(locationTimer);
|
||||
}
|
||||
|
||||
console.log("开始定时获取位置,间隔1分钟...");
|
||||
|
||||
// 1. 立即执行第一次获取
|
||||
getLocationNow();
|
||||
|
||||
// 2. 设置定时器,每 60000 毫秒 (1分钟) 执行一次
|
||||
locationTimer = setInterval(() => {
|
||||
getLocationNow();
|
||||
}, 60000);
|
||||
};
|
||||
|
||||
const getLocationNow = () => {
|
||||
console.log("正在获取当前经纬度...");
|
||||
|
||||
uni.getLocation({
|
||||
type: 'wgs84',
|
||||
isHighAccuracy: true,
|
||||
success: (res) => {
|
||||
console.log('成功获取到新位置:', res);
|
||||
|
||||
// 更新页面上的数据显示
|
||||
|
||||
console.log(res.latitude,res.longitude,'===')
|
||||
|
||||
if(Service.GetUserIsLogin()){
|
||||
CNRiderOrderService.UpdateRiderLocation(res.longitude,res.latitude).then(res=>{})
|
||||
}
|
||||
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('获取经纬度失败:', err);
|
||||
// (可选) 可以在这里添加失败提示
|
||||
// uni.showToast({ title: '获取位置失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 停止定时获取位置
|
||||
*/
|
||||
const stopFetchingLocation = () => {
|
||||
if (locationTimer) {
|
||||
clearInterval(locationTimer);
|
||||
locationTimer = null; // 清理 ID
|
||||
}
|
||||
};
|
||||
|
||||
const getUpData = () => {
|
||||
// #ifdef APP
|
||||
// plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
|
||||
// NvpMerchService.GetAppVersion().then(res=>{
|
||||
// console.log('wgtinfo.versionCode',wgtinfo.versionCode);
|
||||
// if (res.data.version > wgtinfo.versionCode) {
|
||||
// setTimeout(function() {
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/upData/upData?info=" +
|
||||
// encodeURIComponent(
|
||||
// JSON.stringify(res.data))
|
||||
// })
|
||||
// }, 1000)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// #endif
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "uview-plus/index.scss";
|
||||
@import "colorui/main.css";
|
||||
@import "colorui/icon.css";
|
||||
|
||||
page {
|
||||
--nav-mian: #1890FF; //全局颜色
|
||||
--nav-vice: #52C41A; //副颜色
|
||||
--nav-diluted: #FF4D4F; //次颜色
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<view class=""
|
||||
style=" z-index: 100; padding:50rpx 20rpx 18rpx;box-sizing: border-box; position: fixed;top: 0; left: 0; width: 100vw; background-color: #fff; display: flex; align-items: center; justify-content: space-between; ">
|
||||
<view class="" @click="Service.GoPageBack()">
|
||||
<up-icon name="arrow-left" size="32rpx"></up-icon>
|
||||
</view>
|
||||
<view class="">
|
||||
消息通知
|
||||
</view>
|
||||
<view class="" style="font-size: 22rpx; color: #999999; " >
|
||||
全部已读
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="width: 100%; height: 108rpx; ">
|
||||
|
||||
</view>
|
||||
<view v-if="loading" class="">
|
||||
<!-- 消息列表骨架 -->
|
||||
<view class="skeleton-list">
|
||||
<!-- 模拟4条消息 -->
|
||||
<view v-for="index in 4" :key="index" class="skeleton-message-item">
|
||||
<view class="skeleton-message-icon">
|
||||
<view class="skeleton-icon-container"></view>
|
||||
<view class="skeleton-unread-dot"></view>
|
||||
</view>
|
||||
<view class="skeleton-message-content">
|
||||
<view class="skeleton-message-header">
|
||||
<view class="skeleton-message-title"></view>
|
||||
<view class="skeleton-message-time"></view>
|
||||
</view>
|
||||
<view class="skeleton-message-desc">
|
||||
<view class="skeleton-desc-line"></view>
|
||||
<view class="skeleton-desc-line short"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多骨架 -->
|
||||
<view class="skeleton-load-more"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="message-center-container">
|
||||
<!-- 标签页 -->
|
||||
<up-tabs :list="tabList" :current="currentTab" @change="handleTabChange" lineWidth='60' :scrollable="false"
|
||||
lineColor="var(--nav-mian)"
|
||||
:activeStyle="{ color: 'var(--nav-mian)', fontWeight: 'bold', transform: 'scale(1.05)'}"
|
||||
:inactiveStyle="{color: '#606266', transform: 'scale(1)'}"></up-tabs>
|
||||
<!-- 消息列表 -->
|
||||
<scroll-view scroll-y class="message-list" :show-scrollbar="false">
|
||||
<!-- 根据不同标签显示不同的消息 -->
|
||||
<view v-for="(message, index) in 4" :key="index" class="message-item">
|
||||
<view class="message-icon">
|
||||
<view class="icon-container">
|
||||
<image v-if="currentTab === 1" style="width: 100%; height: 100%;"
|
||||
:src=" Service.GetIconImg('/static/index/home/shop.png')" mode=""></image>
|
||||
<image v-if="currentTab === 2" style="width: 100%; height: 100%;"
|
||||
:src=" Service.GetIconImg('/static/index/home/custom.png')" mode=""></image>
|
||||
<image v-if="currentTab === 3" style="width: 100%; height: 100%;"
|
||||
:src=" Service.GetIconImg('/static/index/home/system.png')" mode=""></image>
|
||||
</view>
|
||||
<view class="unread-dot"></view>
|
||||
</view>
|
||||
<view class="message-content">
|
||||
<view class="message-header">
|
||||
<text class="message-title">系统维护通知</text>
|
||||
<text class="message-time">10分钟前</text>
|
||||
</view>
|
||||
<text class="message-desc">为了给您提供更好的服务体验,系统将于今晚24:00-次日凌晨2:00进行例行维护</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-loadmore :status="status" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { Service } from "@/Service/Service"
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
// 标签页数据
|
||||
const tabList = ref([
|
||||
{ name: '全部' },
|
||||
{ name: '订单通知' },
|
||||
{ name: '客户消息' },
|
||||
{ name: '系统通知' }
|
||||
]);
|
||||
// 当前选中标签
|
||||
const currentTab = ref(0);
|
||||
|
||||
// 加载状态
|
||||
let loading = ref(true);
|
||||
let status = ref('nomore')
|
||||
|
||||
onLoad(() => {
|
||||
setTimeout(() => { loading.value = false; }, 1500);
|
||||
})
|
||||
|
||||
// 处理标签切换
|
||||
const handleTabChange = (e) => {
|
||||
currentTab.value = e.index;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 消息列表骨架 */
|
||||
.skeleton-list {
|
||||
padding: 30rpx;
|
||||
height: calc(100vh - 220rpx);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeleton-message-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-message-icon {
|
||||
position: relative;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.skeleton-icon-container {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 16rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-unread-dot {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 50%;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-message-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-message-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.skeleton-message-title {
|
||||
width: 200rpx;
|
||||
height: 44rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-message-time {
|
||||
width: 100rpx;
|
||||
height: 32rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 6rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-message-desc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-desc-line {
|
||||
height: 40rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 8rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-desc-line.short {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.skeleton-load-more {
|
||||
height: 60rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 骨架屏加载动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置延迟,让骨架屏各部分加载动画错开 */
|
||||
.skeleton-tab:nth-child(1) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.skeleton-tab:nth-child(2) {
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.skeleton-tab:nth-child(3) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.skeleton-tab:nth-child(4) {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.skeleton-message-item:nth-child(1) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.skeleton-message-item:nth-child(2) {
|
||||
animation-delay: 0.15s;
|
||||
}
|
||||
|
||||
.skeleton-message-item:nth-child(3) {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.skeleton-message-item:nth-child(4) {
|
||||
animation-delay: 0.45s;
|
||||
}
|
||||
|
||||
// end
|
||||
|
||||
.message-center-container {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.read-all-btn {
|
||||
position: absolute;
|
||||
top: 88rpx;
|
||||
right: 30rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.message-list {
|
||||
padding: 30rpx;
|
||||
height: calc(100vh - 220rpx);
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
transition: transform 0.2s;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
position: relative;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.unread-dot {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #FF4444;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #ffffff;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.message-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.message-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.message-desc {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 40rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 120rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<view v-if="isLoading" class="skeleton-container" style="padding: 10rpx 30rpx">
|
||||
<!-- 骨架屏记录项 -->
|
||||
<view class="skeleton-record-item" v-for="i in 3" :key="i">
|
||||
<!-- 标题骨架 -->
|
||||
<view class="skeleton-title"></view>
|
||||
|
||||
<!-- 金额区域骨架 -->
|
||||
<view class="skeleton-amount-section">
|
||||
<view class="skeleton-amount-line"></view>
|
||||
<view class="skeleton-amount-value"></view>
|
||||
</view>
|
||||
|
||||
<!-- 信息行骨架 -->
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
|
||||
<view class="skeleton-info-row">
|
||||
<view class="skeleton-info-label"></view>
|
||||
<view class="skeleton-info-value"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多骨架 -->
|
||||
<view class="skeleton-loadmore"></view>
|
||||
</view>
|
||||
<view v-else style="padding: 10rpx 30rpx;">
|
||||
<view class="" v-for="(item,index) in withdrowList" :key="index"
|
||||
style="margin-top: 20rpx; gap: 20rpx; background-color: #fff; border-radius: 20rpx; padding: 30rpx; ">
|
||||
<view class="" style=" display: flex; align-items: center; justify-content: space-between; font-weight: bold; border-bottom: 1rpx solid #f6f6f6; padding-bottom: 15rpx;">
|
||||
余额提现-{{ item.payway}}
|
||||
<view class="" :style="{ 'color': item.status==0?'#1890FF':(item.status==1?'#52C41A':'#FF4D4F') }" >
|
||||
{{ item.status==0?'待审核':(item.status==1?'已通过':'已拒绝') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class=""
|
||||
style="width: 100%; height: 200rpx; display: flex;flex-direction: column; justify-content: center; align-items: center; ">
|
||||
<view class="" style="">
|
||||
提现金额 {{ item.amount}} 元
|
||||
</view>
|
||||
<view class="" style="font-size: 32rpx; font-weight: bold; margin-top: 10rpx; ">
|
||||
实际到账 {{item.withAmount}} 元
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; ">
|
||||
<view class="" style="width: 120rpx;">
|
||||
收款人
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; margin-top: 10rpx; ">
|
||||
<view class="" style="width: 120rpx;">
|
||||
提现账号
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ item.account }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="display: flex; align-items: center; gap: 30rpx; margin-top: 10rpx;">
|
||||
<view class="" style="width: 120rpx;">
|
||||
提现时间
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ Service.formatDate(item.addTime,1) }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="item.reply && item.status==2" class="" style="display: flex; align-items: center; gap: 30rpx; margin-top: 10rpx;">
|
||||
<view class="" style="width: 120rpx;">
|
||||
拒绝通知
|
||||
</view>
|
||||
<view class="" style="">
|
||||
{{ item.reply }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<up-loadmore :status="status" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow, onLoad, onReachBottom } from "@dcloudio/uni-app";
|
||||
import { Service } from '@/Service/Service';
|
||||
import { ref } from "vue";
|
||||
import { CNRiderOrderService } from '@/Service/CN/CNRiderOrderService'
|
||||
|
||||
let isLoading = ref(true)
|
||||
|
||||
let withdrowList = ref<Array<any>>([])
|
||||
let status = ref('nomore')
|
||||
let page = ref(1)
|
||||
|
||||
onLoad(() => {
|
||||
getData()
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
onReachBottom(() => {
|
||||
getList()
|
||||
})
|
||||
|
||||
const getData = () => {
|
||||
status.value = 'loadmore'
|
||||
page.value = 1
|
||||
withdrowList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
|
||||
//获取订单
|
||||
const getList = () => {
|
||||
if (status.value == 'nomore' || status.value == 'loading') {
|
||||
return
|
||||
}
|
||||
status.value == 'loadmore'
|
||||
CNRiderOrderService.GetRiderWithList(page.value).then(res => {
|
||||
isLoading.value = false
|
||||
if (res.data) {
|
||||
withdrowList.value = [...withdrowList.value, ...res.data.list]
|
||||
status.value = res.data.list == 10 ? 'loadmore' : 'nomore'
|
||||
page.value++
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-placeholder {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #E6F7FF;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 骨架屏样式 */
|
||||
.skeleton-record-item {
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
width: 200rpx;
|
||||
height: 32rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-amount-section {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.skeleton-amount-line {
|
||||
width: 180rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 10rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-amount-value {
|
||||
width: 250rpx;
|
||||
height: 40rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.skeleton-info-label {
|
||||
width: 120rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-info-value {
|
||||
width: 300rpx;
|
||||
height: 28rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.skeleton-loadmore {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e6e6e6 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4rpx;
|
||||
margin-top: 20rpx;
|
||||
animation: skeleton-loading 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* 骨架屏动画 */
|
||||
@keyframes skeleton-loading {
|
||||
0% {
|
||||
background-position: -100% 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||