骑手端app代码仓库创建
This commit is contained in:
463
pages/index/user.vue
Normal file
463
pages/index/user.vue
Normal file
@@ -0,0 +1,463 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- header -->
|
||||
<view class="header-wrap" :style="headerStyle">
|
||||
<view class="header-bg"></view>
|
||||
<view class="header-inner">
|
||||
<image class="avatar" :src="user.avatar || defautAvatar"></image>
|
||||
<view class="user-meta">
|
||||
<view class="user-name">{{ user.nickName || '姓名(账号)' }}</view>
|
||||
<view class="user-status" @click="handleStatusToggle">
|
||||
{{ user.isOnline ? '在线' : '离线' }}<uni-icons style="margin-left:10rpx;" type="right" size="13" color="#fff"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- stats card -->
|
||||
<view class="stats-card">
|
||||
<view class="stats-row">
|
||||
<view class="stats-item">
|
||||
<text class="stats-title">今日预计收入(元)</text>
|
||||
<text class="stats-value"> {{ formatMoney(todayIncome) }} </text>
|
||||
<view class="stats-link" @click="openAccount">
|
||||
我的账户 <uni-icons type="right" size="13"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stats-item">
|
||||
<text class="stats-title">今日完成单量(单)</text>
|
||||
<text class="stats-value"> {{ todayOrders }} </text>
|
||||
<view class="stats-link" @click="openOrders">
|
||||
订单统计 <uni-icons type="right" size="13"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- shortcuts -->
|
||||
<view class="shortcuts">
|
||||
<view class="shortcut" @click="openAttendance">
|
||||
<image class="shortcut-icon" src="/static/img/order1.png" mode="aspectFit" />
|
||||
<text class="shortcut-text">考勤排班</text>
|
||||
</view>
|
||||
<view class="shortcut" @click="openSalary">
|
||||
<image class="shortcut-icon" src="/static/img/order2.png" mode="aspectFit" />
|
||||
<text class="shortcut-text">薪资助手</text>
|
||||
</view>
|
||||
<view class="shortcut" @click="openSetting">
|
||||
<!-- <image class="shortcut-icon" src="/static/img/edit.png" mode="aspectFit" /> -->
|
||||
<view class="shortcut-icon">
|
||||
<uni-icons type="gear" size="43"></uni-icons>
|
||||
</view>
|
||||
<text class="shortcut-text">设置</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<s-auth-modal />
|
||||
|
||||
<su-popup type="center" :show="showStatusPopup" round="14" :showClose="false">
|
||||
<view class="modal-box">
|
||||
<view class="modal-body">
|
||||
<text class="modal-title">{{ modalTitle }}</text>
|
||||
<text v-if="modalMsg" class="modal-msg">{{ modalMsg }}</text>
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel" @click="cancelConfirm">取消</view>
|
||||
<view class="modal-btn confirm" @click="confirmAction">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onShow,
|
||||
onPageScroll,
|
||||
onPullDownRefresh
|
||||
} from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// 现有 store / 模板数据
|
||||
const template = computed(() => sheep.$store('app').template.user);
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
|
||||
const user = ref({});
|
||||
const todayIncome = ref(0);
|
||||
const todayOrders = ref(0);
|
||||
const showBind = ref(false);
|
||||
// 动态 header 内联样式,用于兼容不同平台的状态栏高度
|
||||
const headerStyle = ref({});
|
||||
const defautAvatar =
|
||||
'https://huichibao.oss-cn-guangzhou.aliyuncs.com/1/material/348b8223-8d03-46aa-8836-6757e8beebd2.png';
|
||||
|
||||
// 格式化金额显示
|
||||
function formatMoney(val) {
|
||||
if (val == null) return '0';
|
||||
return (Number(val) || 0).toFixed(1);
|
||||
}
|
||||
|
||||
// 微信小程序的“手机号快速验证”
|
||||
const getPhoneNumber = async (e) => {
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
sheep.$helper.toast('快捷登录失败');
|
||||
return;
|
||||
}
|
||||
let result = await sheep.$platform.useProvider().mobileLogin(e.detail);
|
||||
if (result) {
|
||||
showBind.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 页面显示时拉取用户信息并填充统计数据(从 store 获取或使用占位)
|
||||
onShow(async () => {
|
||||
const data = await sheep.$store('user').getInfo();
|
||||
if (data) {
|
||||
user.value = data;
|
||||
// 兼容后端字段名,优先使用 data.todayIncome / data.income / placeholder
|
||||
todayIncome.value = data.todayIncome ?? data.income ?? 137.9;
|
||||
todayOrders.value = data.todayOrders ?? data.orders ?? 39;
|
||||
if (data?.status == 1) {
|
||||
console.log("清空缓存");
|
||||
uni.clearStorageSync();
|
||||
}
|
||||
}
|
||||
// 兼容处理:读取原生状态栏高度并设置 header 的 padding-top(px)与 CSS 变量 --statusbar(rpx)
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
const statusBarHeightPx = sys?.statusBarHeight || 0;
|
||||
const windowWidth = sys?.windowWidth || 375;
|
||||
// 将 px 转为 rpx: rpx = px / windowWidth * 750
|
||||
const statusBarHeightRpx = Math.round((statusBarHeightPx / windowWidth) * 750);
|
||||
headerStyle.value = {
|
||||
paddingTop: statusBarHeightPx + 'px',
|
||||
'--statusbar': statusBarHeightRpx + 'rpx'
|
||||
};
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
// 确认弹框状态(上线/下线/禁止)
|
||||
const showStatusPopup = ref(false);
|
||||
const confirmType = ref(''); // 'online' | 'offline' | 'forbidden'
|
||||
const modalTitle = ref('');
|
||||
const modalMsg = ref('');
|
||||
|
||||
// 判断用户是否被禁止接单(兼容多种字段)
|
||||
function isUserForbidden() {
|
||||
const u = user.value || {};
|
||||
return !!(u.forbidden || u.isForbidden || u.forbid || u.forbidReceive || u.disableReceive || u.receive === false);
|
||||
}
|
||||
|
||||
// 点击状态:根据当前状态弹不同的确认框
|
||||
function handleStatusToggle() {
|
||||
if (user.value.isOnline) {
|
||||
confirmType.value = 'offline';
|
||||
modalTitle.value = '确认下线?';
|
||||
modalMsg.value = '下线需平台进行核准\n此时正常接单请留意核准信息';
|
||||
showStatusPopup.value = true;
|
||||
return;
|
||||
}
|
||||
// 如果被禁止接单
|
||||
if (isUserForbidden()) {
|
||||
confirmType.value = 'forbidden';
|
||||
modalTitle.value = '您处于禁止接单状态';
|
||||
modalMsg.value = '暂无法上线上线';
|
||||
showStatusPopup.value = true;
|
||||
return;
|
||||
}
|
||||
// 普通从离线 -> 上线
|
||||
confirmType.value = 'online';
|
||||
modalTitle.value = '确认上线?';
|
||||
modalMsg.value = '';
|
||||
showStatusPopup.value = true;
|
||||
}
|
||||
|
||||
function cancelConfirm() {
|
||||
showStatusPopup.value = false;
|
||||
}
|
||||
|
||||
async function confirmAction() {
|
||||
const type = confirmType.value;
|
||||
showStatusPopup.value = false;
|
||||
if (type === 'online') {
|
||||
// TODO: 调用后端接口变更上线状态
|
||||
user.value.isOnline = true;
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已上线');
|
||||
} else if (type === 'offline') {
|
||||
user.value.isOnline = false;
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已下线');
|
||||
} else if (type === 'forbidden') {
|
||||
// 仅展示信息,无操作
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('无法上线(禁止接单)');
|
||||
}
|
||||
// 可在此处调用 store 或 API 同步服务端状态,例如:
|
||||
// await sheep.$store('user').setOnline(user.value.isOnline);
|
||||
}
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
sheep.$store('user').updateUserData();
|
||||
setTimeout(function() {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
|
||||
onPageScroll(() => {});
|
||||
|
||||
// 跳转/交互方法(保留路由调用位置,用户可按需实现)
|
||||
function goBack() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
function openAccount() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/webview?type=account'
|
||||
});
|
||||
}
|
||||
|
||||
function openOrders() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/order-list'
|
||||
});
|
||||
}
|
||||
|
||||
function openAttendance() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/faq'
|
||||
});
|
||||
}
|
||||
|
||||
function openSalary() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/richtext'
|
||||
});
|
||||
}
|
||||
|
||||
function openSetting() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/setting'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
background: #ffffff;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* header */
|
||||
.header-wrap {
|
||||
position: relative;
|
||||
/* 适配刘海屏安全区:优先使用 constant/env,兼容小程序与 iOS/Android 安全区 */
|
||||
padding-top: constant(safe-area-inset-top);
|
||||
padding-top: env(safe-area-inset-top);
|
||||
}
|
||||
|
||||
.header-bg {
|
||||
/* 背景放置为绝对定位以覆盖安全区(兼容 env/constant 回退与 JS 动态 --statusbar) */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* 背景高度需要包含安全区高度,优先使用 env/constant;最后一行为回退值 */
|
||||
height: 250rpx;
|
||||
height: calc(250rpx + constant(safe-area-inset-top));
|
||||
height: calc(250rpx + env(safe-area-inset-top));
|
||||
/* JS 动态变量回退(当 env/constant 不可用时,使用 --statusbar,单位 rpx) */
|
||||
height: calc(250rpx + var(--statusbar, 0rpx));
|
||||
background: #9ad6f0;
|
||||
/* 浅蓝 */
|
||||
border-bottom-left-radius: 24rpx;
|
||||
border-bottom-right-radius: 24rpx;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
/* 使用 CSS 变量保证当我们通过 JS 设置 --statusbar 时,内容会相对下移(单位 rpx) */
|
||||
top: calc(var(--statusbar, 0rpx) + 40rpx);
|
||||
z-index: 1;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.user-meta {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-status {
|
||||
margin-top: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.back {
|
||||
position: absolute;
|
||||
left: 18rpx;
|
||||
top: calc(var(--statusbar, 0rpx) + 12rpx);
|
||||
z-index: 2;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
/* stats card */
|
||||
.stats-card {
|
||||
padding: 0 24rpx;
|
||||
margin-top: 190rpx;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
background: #f6c98b;
|
||||
/* 浅橙色 */
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.stats-title {
|
||||
font-size: 24rpx;
|
||||
color: #5b4a32;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 42rpx;
|
||||
color: #222;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.stats-link {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #7a5a3a;
|
||||
}
|
||||
|
||||
/* shortcuts */
|
||||
.shortcuts {
|
||||
margin-top: 30rpx;
|
||||
padding: 30rpx 40rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.shortcut-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.shortcut-text {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* popup 原有样式 */
|
||||
.popup {
|
||||
padding: 80rpx 0 50rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
margin-bottom: 30rpx;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 44rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bind-btn {
|
||||
width: 630rpx;
|
||||
height: 96rpx;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
line-height: 96rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
background: #00B85B;
|
||||
border-radius: 64rpx 64rpx 64rpx 64rpx;
|
||||
}
|
||||
|
||||
/* 确认弹框样式(su-popup 内部内容) */
|
||||
.modal-box {
|
||||
width: 640rpx;
|
||||
background: #fff;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.modal-body {
|
||||
padding: 40rpx 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.modal-title {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.modal-msg {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: 34rpx;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
padding: 26rpx 0;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.modal-btn.cancel {
|
||||
color: #666;
|
||||
border-right: 1rpx solid #eee;
|
||||
}
|
||||
.modal-btn.confirm {
|
||||
color: #1e9fff;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user