上传代码

This commit is contained in:
2025-08-18 09:57:10 +08:00
commit ff52db1edc
560 changed files with 102250 additions and 0 deletions

View File

@ -0,0 +1,301 @@
<template>
<view class="page">
<view class="form-item">
<view class="label">银行卡号</view>
<view class="value">
<input type="text" v-model="bankCard" placeholder="请输入银行卡号" />
</view>
</view>
<view class="upload-section">
<view class="upload-item" @click="takePhoto('front')">
<view v-if="!photoSrcFront" class="upload-icon-text">
<uni-icons type="plusempty" size="30" color="#6a7cbf"></uni-icons>
<view class="upload-text">点击上传身份证国徽面</view>
</view>
<image v-if="photoSrcFront" :src="photoSrcFront"></image>
</view>
<view class="upload-item" @click="takePhoto('back')">
<view v-if="!photoSrcBack" class="upload-icon-text">
<uni-icons type="plusempty" size="30" color="#6a7cbf"></uni-icons>
<view class="upload-text">点击上传身份证人像面</view>
</view>
<image v-if="photoSrcBack" :src="photoSrcBack"></image>
</view>
</view>
<!-- 提交按钮 -->
<button class="submit-button" @click="submit">提交</button>
<!-- 提交记录 -->
<view class="submit" v-if="submitRecord">
<view class="submit-title">
提交记录
</view>
<view class="submit-bankCard">
{{ submitRecord.bankCard }}
</view>
<view class="submit-frontIdCard">
<!-- 确保这里使用的是完整的URL -->
<view class="submit-title">
身份证正面
</view>
<image :src="submitRecord.frontIdCard" mode="widthFix"></image>
</view>
<view class="submit-backIdCard">
<!-- 修复这里的src添加协议前缀 -->
<view class="submit-title">
身份证背面
</view>
<image :src="submitRecord.backIdCard" mode="widthFix"></image>
</view>
</view>
</view>
</template>
<script>
import {
apiImageUrl
} from '../../API/api';
export default {
data() {
return {
photoSrcFront: '', // 徽面照片路径
photoSrcBack: '', // 人像面照片路径
bankCard: '', // 银行卡号
submitRecord: {}, // 修改为对象
currentUser: uni.getStorageSync("currentUser")
}
},
onLoad() {
this.getAuditRecords()
},
methods: {
takePhoto(side) {
const that = this;
uni.chooseImage({
count: 1,
sourceType: ['camera'],
success(res) {
if (side === 'front') {
that.photoSrcFront = res.tempFilePaths[0];
that.uploadPhoto(res.tempFilePaths[0], 'front');
} else if (side === 'back') {
that.photoSrcBack = res.tempFilePaths[0];
that.uploadPhoto(res.tempFilePaths[0], 'back');
}
}
});
},
uploadPhoto(filePath, side) {
uni.uploadFile({
url: apiImageUrl + '/api/file/upload/server',
filePath,
name: 'file',
formData: {
biz: 'card'
},
success: (res) => {
console.log('上传成功:', res);
// 根据接口返回的结果进行相应的处理
},
fail: (err) => {
console.error('上传失败:', err);
}
});
},
submit() {
const data = {
backIdCard: this.photoSrcBack,
bankCard: this.bankCard,
errandId: this.currentUser.id,
frontIdCard: this.photoSrcFront
};
uni.request({
url: apiImageUrl + '/api/errandAuth/add',
method: 'POST',
data,
header: {
'Content-Type': 'application/json', // 确保设置正确的 Content-Type
'cookie': uni.getStorageSync("cookie") || ''
},
success: (res) => {
console.log('提交成功:', res);
// 根据接口返回的结果进行相应的处理
if(res.data.code===40000){
uni.showToast({
title: res.data.description,
icon: 'fail',
duration: 2000
})
} else if(res.data.code===0){
uni.showToast({
title: '提交成功',
icon: 'success',
duration: 2000
})
}
},
fail: (err) => {
console.error('提交失败:', err);
}
});
},
getAuditRecords() {
uni.request({
url: apiImageUrl + '/api/errandAuth/get/my',
method: 'POST',
header: {
'Content-Type': 'application/json', // 确保设置正确的 Content-Type
'cookie': uni.getStorageSync("cookie") || ''
},
success: (res) => {
console.log(res);
if (res.data.code === 0 && res.data.data) {
this.submitRecord= res.data.data; // 更新审核记录
}
},
fail: (err) => {
console.error('获取审核记录失败:', err);
}
});
}
}
}
</script>
<style scoped>
/* 页面样式 */
.example-body {
background-color: #fff;
padding: 10px;
}
.page {
background-color: #fff;
padding: 20px;
}
/* 返回按钮样式 */
.back-button {
position: absolute;
top: 20px;
left: 20px;
}
/* 表单项样式 */
.form-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.label {
font-size: 16px;
color: #000;
}
.value {
font-size: 16px;
color: #666;
}
/* 上传区域样式 */
.upload-section {
margin-top: 20px;
display: flex;
flex-direction: column;
/* 改为垂直排列 */
gap: 20px;
/* 增加间距 */
}
.upload-item {
background-color: #ecf5ff;
border: 2px dashed #a6b2da;
border-radius: 10px;
padding: 10px;
text-align: center;
width: 100%;
/* 设置宽度为100% */
box-sizing: border-box;
position: relative;
height: 200px;
/* 固定高度 */
}
.upload-item .upload-icon-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.upload-item image {
width: 100%;
height: 100%;
object-fit: cover;
/* 确保图片覆盖容器并保持比例 */
border-radius: 8px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.upload-text {
font-size: 14px;
color: #8cb7fd;
}
/* 提交按钮样式 */
.submit-button {
width: 100%;
height: 50px;
background-color: #5e7dec;
border: none;
border-radius: 10px;
color: #fff;
font-size: 16px;
margin-top: 20px;
}
/* 提交记录样式 */
.submit {
margin-top: 20px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 10px;
background-color: #f9f9f9;
}
.submit-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.submit-bankCard {
font-size: 16px;
color: #333;
margin-bottom: 10px;
}
.submit-frontIdCard image,
.submit-backIdCard image {
width: 100%;
height: auto;
border-radius: 8px;
max-height: 300px; /* 设置最大高度以防图片过大 */
object-fit: contain; /* 确保图片内容完整显示 */
}
</style>

View File

@ -0,0 +1,257 @@
<template>
<view class="user-profile">
<!-- 头像区域 -->
<view class="avatar-container">
<image :src="tempAvatarUrl || user.errandAvatarUrl || '../../static/logo.png'" mode="aspectFill" class="avatar" @tap="chooseImage"></image>
<text class="edit-text">点击修改头像</text>
</view>
<!-- 表单区域 -->
<view class="form-container">
<view class="form-item">
<text class="label">昵称</text>
<input type="text" v-model="user.errandName" class="input-field"/>
</view>
<view class="form-item gender-item">
<text class="label">性别</text>
<radio-group class="gender-container">
<label>
<radio :checked="user.gender === 0" value="male" @click="user.gender = 0"></radio>
<text></text>
</label>
<label>
<radio :checked="user.gender === 1" value="female" @click="user.gender = 1"></radio>
<text></text>
</label>
</radio-group>
</view>
<view class="form-item">
<text class="label">手机</text>
<input type="text" v-model="user.errandPhone" class="input-field"/>
</view>
<view class="form-item">
<text class="label">范围</text>
<input type="text" v-model="user.distributionScope" class="input-field"/>
</view>
</view>
<!-- 保存按钮 -->
<button class="save-button" @click="saveUser"> </button>
</view>
</template>
<script setup>
import {
apiImageUrl
} from '../../API/api';
import { onMounted, ref } from 'vue';
import { onShow } from "@dcloudio/uni-app";
const user = ref({ errandName: '未登录', errandAvatarUrl: '', gender: '', errandPhone: '',distributionScope:'' });
const tempAvatarUrl = ref('');
// 获取当前用户信息
const getCurrentUser = () => {
uni.request({
url: apiImageUrl + '/api/errand/get/current',
method: 'POST',
header: {
'cookie': uni.getStorageSync("cookie")
},
success(res) {
console.log(res);
if (res.data.code === 0 && res.data.data) { // 检查HTTP状态码和业务状态码并确保有返回的数据
Object.assign(user.value, res.data.data); // 更新用户信息
}
},
fail(err) {
console.error('请求失败:', err);
}
});
};
// 页面显示时获取用户信息
onShow(() => {
getCurrentUser();
});
// 组件挂载时也获取用户信息
onMounted(() => {
getCurrentUser();
});
// 选择图片
const chooseImage = () => {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePaths = res.tempFilePaths;
tempAvatarUrl.value = tempFilePaths[0];
uploadImage(tempFilePaths[0]);
}
});
};
// 上传图片
const uploadImage = (filePath) => {
uni.uploadFile({
url: apiImageUrl + '/api/file/upload/server',
filePath,
name: 'file',
formData: {
biz: 'user_avatar'
},
success: (res) => {
const data = JSON.parse(res.data);
if (data.code === 0) {
user.value.errandAvatarUrl = data.data.url; // 注意这里应该是errandAvatarUrl而非avatarUrl
tempAvatarUrl.value = '';
}
},
fail: (err) => {
console.error('上传失败:', err);
}
});
};
// 保存用户信息
const saveUser = () => {
const updatedUser = {
distributionScope: user.value.distributionScope,
errandName: user.value.errandName,
errandPhone: user.value.errandPhone,
gender: user.value.gender,
id: user.value.id,
state: 0
};
uni.request({
url: apiImageUrl + '/api/errand/update/my',
method: 'POST',
data: updatedUser,
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie")
},
success(res) {
if (res.data.code === 0) {
uni.showToast({
title: '更新成功',
icon: 'success'
});
// 更新成功后重新获取用户信息
getCurrentUser();
} else {
uni.showToast({
title: '更新失败',
icon: 'none'
});
}
},
fail(err) {
console.error('请求失败:', err);
}
});
};
</script>
<style scoped>
.user-profile {
background: linear-gradient(to bottom, #5e7dec,white);
padding: 20px;
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
}
.avatar-container {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20px;
}
.avatar-container .avatar {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
}
.edit-text {
color: white;
margin-top: 10px;
}
.form-container {
background-color: white;
padding: 20px;
border-radius: 8px;
width: 90%;
max-width: 600px;
}
.form-item {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.label {
width: 35px;
text-align: right;
margin-right: 10px;
}
.gender-item {
align-items: flex-start;
}
/* 确保性别选项水平显示 */
.gender-container {
display: flex;
flex-direction: row; /* 默认值为row这里明确指定是为了清晰 */
}
.gender-container label {
margin-right: 10px;
display: flex;
align-items: center;
}
.input-field {
flex: 1;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 4px;
height: 45px;
border-radius: 15px;
}
.save-button {
background-color: transparent; /* 设置背景为透明 */
color: white;
padding: 0px 20px; /* 增加内边距以便按钮看起来更舒适 */
border: 2px solid #5e7dec; /* 添加边框以增强立体感 */
border-radius: 20px;
margin-top: 20px;
width: 100%;
max-width: 300px;
cursor: pointer;
transition: all 0.3s ease; /* 应用到所有属性的过渡效果 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 添加阴影以增加立体感 */
}
.save-button:hover {
background-color: rgba(94, 125, 236, 0.1); /* 鼠标悬停时轻微改变背景颜色 */
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2); /* 增强阴影效果 */
}
.save-button:active {
transform: translateY(2px); /* 点击时向下移动,模拟按下的效果 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 减弱阴影效果 */
}
</style>

View File

@ -0,0 +1,429 @@
<script setup>
import {
ref,
onMounted
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
apiImageUrl
} from '../../API/api';
const orderDetail = ref(uni.getStorageSync('orderDetail'));
// 公寓位置映射表
const apartmentLocations = {
"1公寓": {
latitude: 45.878148,
longitude: 126.542369
},
"2公寓": {
latitude: 45.878016,
longitude: 126.542924
},
"3公寓": {
latitude: 45.878117,
longitude: 126.543476
},
"4公寓": {
latitude: 45.878118,
longitude: 126.54415
},
"5公寓": {
latitude: 45.878978,
longitude: 126.54127
},
"6公寓": {
latitude: 45.878982,
longitude: 126.541879
},
"9公寓": {
latitude: 45.878435,
longitude: 126.544863
},
"10公寓": {
latitude: 45.879196,
longitude: 126.543891
},
"11公寓": {
latitude: 45.879157,
longitude: 126.542722
},
"12公寓": {
latitude: 45.875638,
longitude: 126.540502
},
"育才大厦": {
latitude: 45.875638,
longitude: 126.540502
},
};
// 格式化日期函数保持不变
const formatDate = (dateString) => {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
// 处理取货逻辑保持不变
const handlePickup = (id, imageUrl) => {
uni.showLoading({
title: '提交中...',
mask: true
});
uni.request({
url: apiImageUrl + '/api/errand/update/state',
method: 'POST',
data: {
errandsState: 4,
orderId: id,
imageAddress: imageUrl
},
header: {
'Content-Type': 'application/json', // 确保设置正确的 Content-Type
'cookie': uni.getStorageSync("cookie") || ''
},
success(res) {
console.log(res);
uni.hideLoading();
if (res.data.code === 0) {
uni.showToast({
title: '成功送达',
icon: 'none',
duration: 2000,
success: () => {
// 获取页面栈
const pages = getCurrentPages();
// 获取上一页和上上页实例
const prevPage = pages[pages.length - 3]; // 返回两级页面
// 执行刷新逻辑
if (prevPage && prevPage.robOrder) {
prevPage.robOrder(3); // 刷新待送达列表
}
// 返回两级页面
uni.navigateBack({
delta: 2,
success: () => {
// 通过事件总线触发刷新
uni.$emit('refresh-delivery-list');
}
});
}
});
} else {
uni.showToast({
title: res.data.message || '送达失败',
icon: 'none'
});
}
},
fail(err) {
console.log(err);
uni.showToast({
title: '网络异常,请检查连接',
icon: 'none'
});
}
});
};
// 联系商家和联系用户的逻辑保持不变
const handleContact = (item) => {
uni.makePhoneCall({
phoneNumber: item
});
};
const handleCall = (item) => {
console.log(item)
uni.makePhoneCall({
phoneNumber: item
});
};
// 初始化响应式变量
const latitude = ref(''); // 用户当前位置纬度
const longitude = ref(''); // 用户当前位置经度
const includePoints = ref([]); // 用于自动缩放的地图点集
const covers = ref([]); // 存储覆盖物
// 页面加载时获取位置信息
onMounted(() => {
getLocation();
});
// 获取用户当前位置并更新地图上的标记
function getLocation() {
uni.getLocation({
type: 'gcj02', // 返回可以用于uni.openLocation的坐标
success(res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
// 更新响应式数据
latitude.value = res.latitude;
longitude.value = res.longitude;
// 更新用户当前位置的标记信息
updateCover(res.latitude, res.longitude, 2, '我的位置', '/static/logo.png'); // 用户使用特定图标
// 根据orderDetail.location设置目标公寓的位置
if (orderDetail.value.location in apartmentLocations) {
const targetApartment = apartmentLocations[orderDetail.value.location];
updateCover(targetApartment.latitude, targetApartment.longitude, 1, orderDetail.value.location,
'/static/errand.jpg'); // 跑腿员使用特定图标
// 更新includePoints数组确保地图包含两个位置
includePoints.value = [{
latitude: targetApartment.latitude,
longitude: targetApartment.longitude
}, // 目标公寓的位置
{
latitude: res.latitude,
longitude: res.longitude
} // 用户的位置
];
} else {
console.warn(`未找到名为"${orderDetail.value.location}"的公寓位置`);
}
},
fail(err) {
console.error('获取位置失败', err);
}
});
}
// 更新覆盖物
function updateCover(lat, lng, id, title, iconPath) {
const position = {
id: id,
latitude: lat,
longitude: lng,
iconPath: iconPath, // 标记图标路径,现在通过参数传递
width: 30,
height: 30,
title: title // 可选:标记点标题
};
// 查找是否已存在指定ID的位置标记
const existingIndex = covers.value.findIndex(item => item.id === position.id);
if (existingIndex !== -1) {
// 如果存在则更新
covers.value[existingIndex] = position;
} else {
// 如果不存在则添加
covers.value.push(position);
}
}
const takephoto = () => {
uni.chooseImage({
count: 1, // 默认9这里设置为1因为只需要一张照片
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['camera'], // 从相机选择
success: function(res) {
const tempFilePaths = res.tempFilePaths; // 拍照后返回的临时文件路径数组
uploadPhoto(tempFilePaths[0]);
}
});
};
const uploadPhoto = (filePath) => {
uni.uploadFile({
url: `${apiImageUrl}/api/file/upload/server`, // 接口地址
filePath: filePath,
name: 'file',
formData: {
biz: 'takeout' // 根据要求填写的biz参数
},
header: {
'Content-Type': 'application/json', // 确保设置正确的 Content-Type
'cookie': uni.getStorageSync("cookie") || ''
},
success(res) {
console.log('上传成功', res);
const imageUrl = JSON.parse(res.data).data;
handlePickup(orderDetail.value.id, imageUrl);
},
fail(err) {
console.error('上传失败', err);
}
});
};
</script>
<template>
<view class="page">
<!-- 地图 -->
<view>
<map style="width:100%; height: 300px;" :latitude="latitude" :longitude="longitude" :markers="covers"
:include-points="includePoints">
</map>
</view>
<!-- 订单详情部分保持不变 -->
<view class="header">
<text class="location"></text>
<text class="distance">1km</text>
<text class="store-name">{{orderDetail.address}}</text>
</view>
<view class="header">
<text class="location"></text>
<text class="distance">1km</text>
<text class="store-name">{{orderDetail.location}}</text>
</view>
<view class="buttons">
<!-- <button class="button" @click="handlePickup(orderDetail.id)">我已取到</button> -->
<view class="icon-container">
<!-- 第一个图标和文字 -->
<view class="icon-wrapper" @click="handleCall(orderDetail.businessVO?.businessPhone)">
<uni-icons type="phone" size="30"></uni-icons>
<text>联系商家</text>
</view>
<!-- 第二个图标和文字 -->
<view class="icon-wrapper" @click="handleContact(orderDetail.phone)">
<uni-icons type="phone-filled" size="30"></uni-icons>
<text>联系用户</text>
</view>
<!-- 第三个图标和文字 -->
<view class="icon-wrapper">
<!-- <uni-icons type="camera" size="30" @click="handlePickup(orderDetail.id)"></uni-icons> -->
<uni-icons type="camera" size="30" @click="takephoto(orderDetail.id)"></uni-icons>
<text>拍照送达</text>
</view>
</view>
</view>
<view class="order-details">
<text class="title">跑单详情</text>
<view class="detail">
<text>取餐地址</text>
<text>{{orderDetail.address}}</text>
</view>
<view class="detail">
<text>下单时间</text>
<text>{{formatDate(orderDetail.createTime)}}</text>
</view>
<view class="detail">
<text>送达时间</text>
<text style="color: red;">{{formatDate(orderDetail.pickupEndTime)}}</text>
</view>
<view class="detail">
<text>送达地址</text>
<text>{{orderDetail.location}}</text>
</view>
</view>
</view>
</template>
<style scoped>
.page {
padding: 20px;
background-color: #fff;
}
.header {
display: flex;
align-items: center;
margin-bottom: 20px;
margin-top: 20px;
}
.location {
width: 24px;
/* 稍微增大圆形 */
height: 24px;
background-color: #ff6700;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
margin-right: 12px;
font-size: 12px;
/* 调整文本大小 */
font-weight: bold;
}
.distance {
color: #999;
font-size: 12px;
padding-right: 5px;
}
.store-name {
font-size: 20px;
font-weight: bold;
}
.buttons {
margin-bottom: 20px;
}
.button {
width: 100%;
padding: 10px;
margin: 10px 0;
text-align: center;
background-color: #2877f2;
color: #fff;
border: none;
border-radius: 8px;
cursor: pointer;
line-height: inherit;
}
.order-details {
margin-top: 20px;
font-size: 16px;
}
.title {
font-size: 20px;
font-weight: bold;
margin-bottom: 10px;
}
.detail {
display: flex;
align-items: center;
margin: 5px 0;
}
/* 定义图标容器的样式 */
.icon-container {
display: flex;
justify-content: space-around;
/* 水平均匀分布 */
align-items: center;
/* 垂直居中对齐 */
}
/* 定义每个图标和文字组合的样式 */
.icon-wrapper {
display: flex;
flex-direction: column;
/* 将子元素垂直排列 */
align-items: center;
/* 子元素水平居中对齐 */
}
/* 可选:定义文本标签的样式 */
.icon-wrapper text {
margin-top: 5px;
/* 文字与图标之间的间距 */
}
</style>

View File

@ -0,0 +1,820 @@
<template>
<view class="tab-menu">
<view v-for="(tab, index) in tabs" :key="tab.name" class="tab-item" :class="{ active: currentIndex === index }"
@click="switchTab(index)">
{{ tab.name }}
</view>
</view>
<uni-notice-bar show-icon scrollable text="今日放假" />
<view class="content">
<template v-if="currentIndex === 0">
<view class="order-card" v-for="(item,index) in errandOrder" :key="index">
<view class="delivery-info">
<view class="time-id">#{{item.id}}</view>
<view class="price">1.7</view>
</view>
<view class="delivery-info">
<view class="time">{{formatDate(item.pickupEndTime)}}内送达</view>
</view>
<view class="address-info">
<view class="address-item">
<view class="circle"></view>
<view class="distance">1km</view>
<view class="address-name">{{item.address}}·{{item.businessVO?.businessName}}</view>
</view>
<view class="address-item">
<view class="circle"></view>
<view class="distance">1.5km</view>
<view class="address-name">{{item.location}}</view>
</view>
</view>
<view class="button-container">
<view class="order-button" @click="plunder(item.id)">抢单</view>
</view>
</view>
</template>
<template v-if="currentIndex === 1">
<view class="order-card" v-for="(item,index) in errandOrder" :key="index" @click.stop="orderDetail(item)">
<view class="delivery-info">
<view class="time-id">#{{item.id}}</view>
<view class="price">1.7</view>
</view>
<view class="delivery-info">
<view class="time">{{formatDate(item.pickupEndTime)}}内送达</view>
</view>
<view class="address-info">
<view class="address-item">
<view class="circle"></view>
<view class="distance">1km</view>
<view class="address-name">{{item.address}}·{{item.businessVO?.businessName}}</view>
</view>
<view class="address-item">
<view class="circle"></view>
<view class="distance">1.5km</view>
<view class="address-name">{{item.location}}</view>
</view>
</view>
<view class="button-container" @click.stop="obtain(item.id)">
<view class="order-button">确认取货</view>
</view>
</view>
</template>
<template v-if="currentIndex === 2">
<view class="order-card" v-for="(item,index) in errandOrder" :key="index" @click.stop="deliveryDetail(item)">
<view class="delivery-info">
<view class="time-id">#{{item.id}}</view>
<view class="price">1.7</view>
</view>
<view class="delivery-info">
<view class="time">{{formatDate(item.pickupEndTime)}}内送达</view>
</view>
<view class="address-info">
<view class="address-item">
<view class="circle"></view>
<view class="distance">1km</view>
<view class="address-name">{{item.address}}·{{item.businessVO?.businessName}}</view>
</view>
<view class="address-item">
<view class="circle"></view>
<view class="distance">1.5km</view>
<view class="address-name">{{item.location}}</view>
</view>
</view>
<view class="button-container">
<view class="order-button">确认送达</view>
</view>
</view>
</template>
</view>
<view class="fixed-buttons">
<view class="button-container" @click="toggle('bottom')">
<uni-icons type="gear-filled" size="24"></uni-icons>
<text class="fixed-font">跑单设置</text>
</view>
<view class="button-container" @click="map">
<uni-icons type="location-filled" size="24"></uni-icons>
<text class="fixed-font">配送范围</text>
</view>
<button @click="refreshOrders" class="refresh-button">刷新订单</button>
</view>
<!-- 通弹窗 -->
<uni-popup ref="popupRef" background-color="#fff" @change="change">
<view class="popup-content" :class="{ 'popup-height': type === 'left' || type === 'right' }">
<view class="modal-header">
<button class="tab-button" :class="{ active: activeTab === 0 }" @click="switchTabs(0)">跑单设置</button>
<button class="tab-button" :class="{ active: activeTab === 1 }" @click="switchTabs(1)">运单排序</button>
</view>
<view class="modal-body">
<view v-if="activeTab === 0">
<view class="modal-item">
<text class="modal-label">配送区域</text>
<!-- 使用 currentUser distributionScope 来设置 picker 的默认值 -->
<picker :value="array.indexOf(radius.value)" :range="array" @change="bindPickerChange" class="modal-value">
<view>{{ radius.value || '修改配送区域' }}</view> <!-- 如果没有设置则显示提示 -->
</picker>
</view>
<view class="modal-item">
<text class="modal-label">同时接单量</text>
<text class="modal-value">15</text>
</view>
</view>
<view v-if="activeTab === 1">
<view class="modal-item">
<text class="modal-label">智能排序</text>
<view class="modal-value">
<text>未设置</text>
<text class="arrow">&gt;</text>
</view>
</view>
<view class="modal-list">
<view class="item" @click="handleClick(item)" v-for="(item, index) in items" :key="index"
:class="{ selected: selectedItem === item }">
{{ item }}
</view>
</view>
<view class="modal-item">
<text class="modal-label">置顶</text>
<view class="modal-value">
<switch color="#FFCC33" style="transform:scale(0.7)" />
</view>
</view>
<text class="tips">关闭之后订单将按默认顺序排序</text>
<view class="modal-list">
<view class="item" @click="handleClick(item)" v-for="(item, index) in tipsItems" :key="index"
:class="{ selected: selectedItem === item }">
{{ item }}
</view>
</view>
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import {
ref,
computed,
onMounted
} from 'vue';
import {
apiImageUrl
} from '../../API/api';
import {
onShow
} from "@dcloudio/uni-app";
const radius=ref(uni.getStorageSync("currentUser.distributionScope"))
const currentIndex = ref(0);
const tabs = [{
name: '待抢单'
},
{
name: '待取货'
},
{
name: '待送达'
}
];
// 修改选项卡切换逻辑
const switchTab = (index) => {
currentIndex.value = index;
// 根据文档状态映射关系0-待抢单对应errandState=11-待取货对应errandState=22-待送达对应errandState=3
const stateMap = [1, 2, 3];
if (index >= 0 && index < stateMap.length) {
robOrder(stateMap[index]);
}
};
const switchTabs = (index) => {
activeTab.value = index;
};
// 定义响应式变量
const type = ref('center');
const activeTab = ref(0); // 默认激活第一个标签页
const selectedItem = ref(null);
// 弹窗引用
const popupRef = ref(null);
// 数据源
const array = ref(['1公寓', '2公寓', '3公寓', '4公寓', '5公寓', '6公寓', '7公寓', '8公寓', '9公寓', '10公寓', '11公寓', '12公寓','育才大厦']);
const index = ref(0);
const items = ref([
'考核时间从多到少',
'运单金额从高到低',
'配送距离从近到远',
'取货距离从近到远',
'推荐排序'
]);
const tipsItems = ref([
'新单置顶',
'已抢商户置顶'
]);
// 方法定义
const change = (e) => {
console.log('当前模式:' + e.type + ',状态:' + e.show);
};
const toggle = (typeValue) => {
type.value = typeValue;
popupRef.value.open(typeValue);
};
const closePopup = () => {
popupRef.value.close();
};
const map = () => {
uni.navigateTo({
url: '/pages/map/map'
})
}
// Picker 选择改变时触发
const bindPickerChange = (e) => {
console.log('picker发送选择改变携带值为', e.detail.value);
const newValue = array.value[e.detail.value];
radius.value = newValue;
// 使用当前用户信息来构建请求数据
const requestData = {
distributionScope: newValue,
errandName: currentUser.value.errandName, // 动态获取
errandPhone: currentUser.value.errandPhone, // 动态获取
gender: currentUser.value.gender, // 动态获取
id: currentUser.value.id, // 动态获取
state: currentUser.value.state // 动态获取
};
// 更新用户的配送范围
uni.request({
url: apiImageUrl + '/api/errand/update/my',
method: 'POST',
data: requestData,
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie") || ''
},
success(res) {
console.log('配送范围更新成功:', res);
console.log(res.data.code);
if(res.data.code===50001){
uni.showToast({
title:'还有未送达订单',
icon: 'fail'
});
}
else if(res.data.code===0){
uni.showToast({
title: '配送范围已更新',
icon: 'success'
});
refreshOrders();
}
},
fail(err) {
console.error('配送范围更新失败:', err);
uni.showToast({
title: '更新失败,请重试',
icon: 'none'
});
}
});
};
const handleClick = (item) => {
selectedItem.value = item;
};
const takePhoto = () => {
uni.navigateTo({
url: '/pages/takePhoto/takePhoto'
})
};
// 修改刷新订单方法
const refreshOrders = () => {
const stateMap = [1, 2, 3];
const currentState = stateMap[currentIndex.value] || 1;
robOrder(currentState);
};
// 初始化加载数据
onMounted(() => {
robOrder(1); // 初始加载待抢单数据
});
let errandOrder = ref([]);
const robOrder = (errandStateValue) => {
// 添加参数校验
if (typeof errandStateValue !== 'number' || isNaN(errandStateValue)) {
console.error("Invalid errandState value:", errandStateValue);
return;
}
// 手动构建查询字符串
const params = `errandState=${encodeURIComponent(errandStateValue.toString())}`;
uni.request({
url: apiImageUrl + '/api/errand/list/order',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded', // 设置正确的内容类型
'cookie': uni.getStorageSync("cookie") || ''
},
data: params, // 直接使用构建好的查询字符串
success(res) {
console.log('请求成功:', res);
if (res.data.code !== 0) {
uni.showToast({
title: `请求失败:${res.data.message}`,
icon: 'none'
});
}else {
console.log(res.data.data)
errandOrder.value = res.data.data; // 更新响应式数据
console.log('Updated errandOrder:', errandOrder.value);
}
},
fail(err) {
console.log('请求失败:', err);
}
});
};
const plunder = (id) => {
console.log(id);
uni.request({
url: apiImageUrl + '/api/errand/get/order',
method: 'POST',
data: {
id: id
},
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie") || ''
},
success: (res) => { // 使用箭头函数保持上下文
console.log(res);
if (res.data.code === 0) {
uni.showToast({
title: '抢单成功',
icon: 'success',
success: () => {
// 根据当前标签页刷新数据
const stateMap = [1, 2, 3];
const currentState = stateMap[currentIndex.value];
robOrder(currentState);
// 如果是待抢单页面,额外刷新待取货列表
if (currentIndex.value === 0) {
robOrder(2);
}
}
});
} else {
uni.showToast({
title: res.data.message || '抢单失败',
icon: 'none'
});
}
},
fail: (err) => {
console.log(err);
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
});
}
})
};
const obtain = (id) => {
uni.request({
url: apiImageUrl + '/api/errand/update/state',
method: 'POST',
data: {
errandsState: 3,
orderId: id
},
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie") || ''
},
success: (res) => {
console.log(res);
if (res.data.code === 0) {
uni.showToast({
title: '取货成功',
icon: 'success',
success: () => {
// 刷新当前标签页数据(待取货列表)
robOrder(2);
// 同时刷新待送达列表
robOrder(3);
}
});
} else {
uni.showToast({
title: res.data.description || '取货失败',
icon: 'none'
});
}
},
fail: (err) => {
console.log(err);
uni.showToast({
title: '网络异常,请检查连接',
icon: 'none'
});
}
})
};
// const send=(id)=>{
// console.log(id);
// uni.request({
// url:apiImageUrl+'/api/errand/update/state',
// method:'POST',
// data:{
// errandsState:4,
// orderId:id,
// imageAddress:"https://bpic.588ku.com/back_list_pic/22/05/07/16474c1e1553210af8360bfeed9b5134.jpg"
// },
// header: {
// 'Content-Type': 'application/json', // 确保设置正确的 Content-Type
// 'cookie': uni.getStorageSync("cookie") || ''
// },
// success(res) {
// console.log(res);
// uni.showToast({
// title: '送货成功',
// icon: 'none'
// });
// },
// fail(err) {
// console.log(err);
// uni.showToast({
// title: '送货失败',
// icon: 'none'
// });
// }
// })
// }
let currentUser = ref({});
// 获取当前用户信息
// 获取当前用户信息
const getCurrentUser = () => {
uni.request({
url: apiImageUrl + '/api/errand/get/current',
method: 'POST',
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie")
},
success(res) {
console.log(res);
if (res.data.code === 0) { // 检查HTTP状态码和业务状态码
const userData = res.data.data;
currentUser.value = userData; // 更新响应式变量currentUser
// 检查用户的配送范围是否存在于我们的选项中
if (array.value.includes(userData.distributionScope)) {
radius.value = userData.distributionScope; // 保存用户的配送范围
} else {
console.warn('用户的配送范围不在预设的选项中');
// 可以选择设置一个默认值或者提示用户更新配送范围
}
}
},
fail(err) {
console.error('请求失败:', err);
}
});
};
onMounted(() => {
robOrder(1); // 初始加载待抢单数据
getCurrentUser(); // 获取当前用户信息
});
onShow(() => {
getCurrentUser()
robOrder(1);
})
const orderDetail=(item)=>{
uni.setStorageSync("orderDetail",item)
uni.navigateTo({
url:'/pages/orderDetail/orderDetail'
})
}
const deliveryDetail=(item)=>{
console.log("4567845678945678900");
console.log(item);
uni.setStorageSync("orderDetail",item)
uni.navigateTo({
url:'/pages/deliveryDetail/deliveryDetail'
})
}
// 新增时间格式化函数
const formatDate = (isoString) => {
if (!isoString) return '';
// 直接从 ISO 字符串中截取目标格式MM-DD HH:mm:ss
return isoString.slice(5, 10) + ' ' + isoString.slice(11, 19);
};
// 在订单列表页面的onShow中添加
uni.$on('refresh-delivery-list', () => {
this.robOrder(3); // 假设这是你的订单列表刷新方法
});
</script>
<style scoped lang="scss">
.time-id {
font-size: 20px;
color: #ff6700;
font-weight: 700;
}
.tab-menu {
display: flex;
justify-content: space-around;
padding: 10px 0;
background-color: #5e7dec;
color: #9cb0f4;
}
.tab-item {
padding: 10px;
cursor: pointer;
}
.tab-item.active {
color: #fff;
font-weight: bold;
}
.fixed-buttons {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
background-color: #fff;
padding: 10px;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}
.button-container {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 10px;
}
.button-container text {
margin-top: 5px;
}
.fixed-font {
font-size: 12px;
}
.refresh-button {
width: 60%;
background-color: pink;
border-radius: 15px;
color: #fff;
background-color: #5e7dec;
}
.button-text {
color: #fff;
font-size: 12px;
}
.text {
font-size: 12px;
color: #333;
}
.popup-content {
padding: 20px;
border-radius: 8px;
background-color: #fff;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.tab-button {
background-color: transparent;
border: none;
font-size: 16px;
cursor: pointer;
padding: 5px 10px;
&.active {
color: #007AFF;
border-bottom: 2px solid #007AFF;
}
}
.modal-title {
font-size: 18px;
font-weight: bold;
}
.modal-close {
font-size: 16px;
cursor: pointer;
}
.modal-body {
padding: 10px 0;
}
.modal-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.modal-label {
font-size: 15px;
font-weight: bold;
}
.modal-value {
font-size: 14px;
color: #333;
}
.arrow {
margin-left: 10px;
}
.modal-list {
display: grid;
grid-template-columns: 1fr 1fr;
/* 创建两列,每列占据相等的空间 */
gap: 10px;
padding: 10px 10px 10px 0;
border-radius: 5px;
}
.item {
background-color: #f1f1f1;
padding: 10px;
border-radius: 5px;
text-align: center;
cursor: pointer;
font-size: 14px;
&.selected {
background-color: #eef6ff;
color: #80a6da;
}
}
.tips {
font-size: 12px;
color: #c8c8c8;
}
// 抢单样式
.order-card {
background-color: #fff;
border-radius: 12px;
/* 增大圆角 */
padding: 10px;
/* 增大内边距 */
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.16);
/* 更深的阴影 */
width: 90%;
margin: 0 auto;
margin-bottom: 20px;
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
/* 添加过渡效果 */
}
.order-card:hover {
transform: translateY(-4px);
/* 当鼠标悬停时稍微提升 */
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
/* 更大的阴影当悬停 */
}
/* 修改前 */
.order-card:last-child {
margin-bottom: 100px;
}
/* 修改后 */
.order-card:last-child {
margin-bottom: 100px !important; /* 添加 !important 确保优先级 */
}
.delivery-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.time,
.price {
font-size: 16px;
/* 增大字体大小 */
}
.price {
color: #ff6700;
font-weight: bold;
}
.address-info {
margin-bottom: 15px;
border-bottom: 1px solid #e0e0e0;
/* 添加底部边框 */
padding-bottom: 10px;
}
.address-item {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.circle {
width: 24px;
/* 稍微增大圆形 */
height: 24px;
background-color: #ff6700;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
margin-right: 12px;
font-size: 12px;
/* 调整文本大小 */
font-weight: bold;
}
.distance {
color: #666;
font-size: 14px;
margin-right: 12px;
}
.address-name {
color: #333;
font-size: 16px;
font-weight: 600;
}
.button-container {
text-align: center;
/* 增加按钮顶部间距 */
}
.order-button {
background-color: #5e7dec;
color: #fff;
padding: 12px 24px;
/* 增大按钮尺寸 */
border-radius: 6px;
/* 圆滑按钮边缘 */
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease-in-out;
/* 添加过渡效果 */
width: 85%;
}
.order-button:hover {
background-color: #4a69bd;
/* 改变悬停颜色 */
}
.content {
padding-bottom: 50px; /* 根据底部按钮高度调整 */
}
</style>

View File

@ -0,0 +1,282 @@
<template>
<view class="normal-login-container">
<view class="logo-content align-center justify-center flex">
<image class="img-a" :src="apiImageUrl + '/static/images/b-1.png'" />
<image class="img-b" :src="apiImageUrl + '/static/images/b-2.png'" />
<view class="text">
<view class="t-b">校食通快送端</view>
<view class="t-b2">一款专为在校同学开发的配送app</view>
</view>
</view>
<view class="login-form-content">
<view class="input-item flex align-center">
<view class="iconfont icon-user icon"></view>
<input v-model="loginForm.userAccount" class="input" type="text" placeholder="请输入账号" maxlength="30" />
</view>
<view class="input-item flex align-center">
<view class="iconfont icon-password icon"></view>
<input v-model="loginForm.userPassword" type="password" class="input" placeholder="请输入密码" maxlength="20" />
</view>
<view class="action-btn">
<button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
</view>
<p @click="goLogin" class="goLogin">去注册</p>
</view>
</view>
</template>
<script>
export default {
data() {
return {
loginForm: {
userAccount: '',
userPassword: ''
},
apiImageUrl: 'https://xiaokuaisong.shop' // 直接在这里设置后端地址
};
},
methods: {
// handleLogin() {
// console.log('userAccount:', this.loginForm.userAccount);
// console.log('userPassword:', this.loginForm.userPassword);
// // 检查表单字段是否已填充
// if (!this.loginForm.userAccount || !this.loginForm.userPassword) {
// uni.showToast({
// icon: 'error',
// title: '请输入账号和密码'
// });
// return;
// }
// uni.request({
// url: this.apiImageUrl + '/api/user/login',
// method: 'POST',
// data: {
// userAccount: this.loginForm.userAccount,
// userPassword: this.loginForm.userPassword
// },
// header:{
// 'cookie':uni.getStorageSync("cookie")
// },
// success: (res) => {
// console.log(res.data.code);
// if (res.data.code === 0) {
// uni.showToast({
// title: '登录成功',
// duration: 2000
// });
// uni.removeStorageSync('cookie');
// uni.setStorageSync('userInfo', res.data.data);
// uni.setStorageSync('cookie', res.header['Set-Cookie']);
// uni.switchTab({
// url: '/pages/index/index'
// });
// } else {
// uni.showToast({
// icon: 'error',
// title: '登录失败,请联系管理员'
// });
// return;
// }
// },
// fail: (err) => {
// console.error(err);
// uni.showToast({
// icon: 'error',
// title: '请求失败,请检查网络'
// });
// }
// });
// }
handleLogin() {
console.log('userAccount:', this.loginForm.userAccount);
console.log('userPassword:', this.loginForm.userPassword);
uni.showLoading({
title: '正在登录...',
mask: true
});
uni.request({
url: this.apiImageUrl + '/api/user/login',
method: 'POST',
data: {
appName: "errand",
userAccount: this.loginForm.userAccount,
userPassword: this.loginForm.userPassword
},
header: {
'Content-Type': 'application/json', // 确保设置正确的 Content-Type
'cookie': uni.getStorageSync("cookie") || ''
},
success: (res) => {
console.log('Response Data:', res); // 添加日志查看完整响应
if (res.statusCode === 200 && res.data.code === 0) { // 确认状态码
uni.showToast({
title: '登录成功',
duration: 2000
});
// 移除旧的 cookie 并设置新的 userInfo 和 cookie
uni.removeStorageSync('cookie');
uni.setStorageSync('userInfo', res.data.data);
if (res.header && res.header['Set-Cookie']) {
uni.setStorageSync("cookie", res.header['Set-Cookie']);
}
// 尝试跳转
uni.switchTab({
url: '/pages/index/index'
});
} else {
uni.showToast({
icon: 'error',
title: "登录失败,请联系管理员"
});
}
},
fail: (err) => {
console.error('Request failed:', err); // 添加错误日志
uni.showToast({
icon: 'error',
title: "网络请求失败,请重试"
});
},
complete: () => {
uni.hideLoading(); // 请求完成后隐藏加载提示
}
});
},
goLogin(){
uni.navigateTo({
url:'/pages/register/register'
})
}
}
};
</script>
<style lang="scss">
page {
background: url('../../static/login.jpg') repeat fixed center;
}
.normal-login-container {
width: 100%;
.logo-content {
width: 100%;
font-size: 21px;
text-align: center;
padding-top: 15%;
image {
border-radius: 4px;
}
.title {
margin-left: 10px;
}
}
.login-form-content {
text-align: center;
margin: 20px auto;
width: 80%;
.input-item {
margin: 20px auto;
background-color: #f5f6f7;
height: 45px;
border-radius: 20px;
.icon {
font-size: 38rpx;
margin-left: 10px;
color: #999;
}
.input {
width: 80%;
font-size: 14px;
line-height: 20px;
text-align: left;
padding-left: 15px;
padding-top: 8px;
padding-bottom: 8px;
background-color: #f5f6f7;
}
}
.login-btn {
margin-top: 40px;
height: 45px;
border-radius: 30px;
}
.reg {
margin-top: 15px;
}
.xieyi {
color: #333;
margin-top: 20px;
}
.login-code {
height: 38px;
float: right;
.login-code-img {
height: 38px;
position: absolute;
margin-left: 10px;
width: 200rpx;
}
}
}
}
.img-a {
position: absolute;
width: 100%;
top: -74px;
right: 0;
z-index: 100;
}
.img-b {
position: absolute;
width: 50%;
bottom: 0;
left: -50rpx;
z-index: 100;
}
.text{
margin-left: -111px;
margin-top: 28px;
}
.t-b {
font-size: 29px;
color: #000;
padding: 60px 0 10px 0;
font-weight: bold;
}
.t-b2 {
text-align: center;
font-size: 32rpx;
color: #2a2a2a;
}
.goLogin {
float: right;
color: #444444;
padding: 10px;
}
</style>

View File

@ -0,0 +1,22 @@
<template>
<view>
<button @click="getAddress">获取定位</button>
</view>
</template>
<script setup>
const getAddress = () => {
uni.chooseLocation({
success: (res) => {
location.value = {
name: res.name,
address: res.address,
latitude: res.latitude,
longitude: res.longitude
};
}
});
};
</script>

View File

@ -0,0 +1,454 @@
<template>
<view class="container">
<!-- Header -->
<view class="header">
<image :src="user.errandAvatarUrl || '../../static/logo.png'" class="user-icon" @click="changeUserMessage"></image>
<view class="user-info">
<text class="name">{{ user.errandName||'未登录' }}</text>
<text class="rating">快送员星级 </text>
</view>
<view class="settings">
<text class="rule">快送员评分规则</text>
<uni-icons type="right" size="16" class="settings-icon"></uni-icons>
</view>
</view>
<!-- Summary -->
<view class="summary">
<view class="summary-item">
<text class="summary-value">{{allMoney}}</text>
<text class="summary-label">总收入</text>
<text class="summary-detail">总金额></text>
</view>
<view class="summary-item" @click="navigateToOrder">
<text class="summary-value">{{OrderNumber}}</text>
<text class="summary-label">今日完成</text>
<text class="summary-detail">完成订单数></text>
</view>
<view class="summary-item" @click="purse">
<text class="summary-value">{{OrderMoney}}</text>
<text class="summary-label">已结算</text>
<text class="summary-detail">用户已确认></text>
</view>
<view class="summary-item">
<text class="summary-value">{{waitMoney}}</text>
<text class="summary-label">待结算</text>
<text class="summary-detail">等待用户确认></text>
</view>
</view>
<!-- Menu -->
<view class="menu">
<view class="menu-item" @click="navigateToOrder">
<text>我的订单</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
<view>
<!-- 原来的菜单项改为触发弹窗 -->
<view class="menu-item" @click="purse">
<text>我的钱包</text>
<uni-icons type="right" size="25" class="arrow-icon"></uni-icons>
</view>
<!-- 自定义弹窗 -->
<uni-popup ref="popupRef" type="center" background-color="#fff">
<view class="popup-content">
<text class="popup-text" style="">敬请期待</text>
</view>
</uni-popup>
</view>
<view class="menu-item" @click="navigateToAuthentication">
<text>身份认证</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
<view class="menu-item" @click="navigateToAppeal">
<text>申诉中心</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
<view class="menu-item" @click="navigateToServiceEvaluation">
<text>服务评价</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
<view class="menu-item" @click="signOut">
<text>注销账户</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
<view class="menu-item" @click="login">
<text>{{loginState.loginName}}</text>
<uni-icons type="right" size="16" class="arrow-icon"></uni-icons>
</view>
</view>
</view>
</template>
<script setup>
import {
apiImageUrl
} from '../../API/api';
import {
onMounted,
ref
} from 'vue';
import {
onShow,
onLoad
} from "@dcloudio/uni-app";
const userInfo=uni.getStorageSync("userInfo")
const login = () => {
uni.request({
url:apiImageUrl+'/api/user/logout',
method:'POST',
success(res) {
console.log(res);
uni.removeStorageSync('userInfo');
uni.removeStorageSync('currentUser');
uni.reLaunch({
url: '/pages/login/login'
});
},
fail(err) {
console.log(err);
}
})
};
const signOut=()=>{
uni.showModal({
title: '是否注销账号',
content: '注销账号后将无法再次登录',
showCancel: true,
success: function (res) {
if (res.confirm) { //confirm为ture代表用户点击确定
console.log('点击了确定按钮');
uni.request({
url:apiImageUrl+'/api/errand/delete',
method:'POST',
success(res) {
console.log(res);
uni.reLaunch({
url: '/pages/login/login'
});
},
fail(err) {
console.log(err);
}
})
} else if (res.cancel) { //cancel为ture代表用户点击取消
console.log('点击了取消按钮');
}
}
})
}
const changeUserMessage=()=>{
uni.navigateTo({
url:'/pages/changeUserMessage/changeUserMessage'
})
}
const navigateToOrder = () => {
uni.navigateTo({
url: '/pages/order/order'
});
};
// 弹窗引用
const popupRef = ref('敬请期待')
const purse = () => {
popupRef.value.open()
// 1 秒后自动关闭
setTimeout(() => {
popupRef.value.close()
}, 1000)
};
const navigateToAuthentication = () => {
uni.navigateTo({
url: '/pages/authentication/authentication'
});
};
const navigateToAppeal = () => {
uni.navigateTo({
url: '/pages/appeal/appeal'
});
};
const navigateToServiceEvaluation = () => {
uni.navigateTo({
url: '/pages/serviceEvaluation/serviceEvaluation'
});
};
// 用户信息响应式引用
const user = ref({ username: '未登录' });
const loginState=ref({loginName:'去登录'})
// 获取当前用户信息
const getCurrentUser = () => {
uni.request({
url: apiImageUrl + '/api/errand/get/current',
method: 'POST',
header: {
'cookie': uni.getStorageSync("cookie")
},
success(res) {
console.log(res);
if (res.data.code === 0) { // 检查HTTP状态码和业务状态码
uni.setStorageSync("currentUser",res.data.data)
user.value = res.data.data; // 假设返回的数据结构包含用户信息
loginState.value={loginName:'退出登录'}
} else {
user.value = { username: '未登录' }; // 设置为未登录状态
}
},
fail(err) {
console.error('请求失败:', err);
user.value = { username: '未登录' }; // 请求失败时也设置为未登录状态
}
});
};
onShow(() => {
getCurrentUser(),
getOrderNumber(),
getOrderMoney()
getwaitMoney()
getallMoney()
})
const OrderNumber = ref(0);
const getOrderNumber=()=>{
uni.request({
url:apiImageUrl+'/api/errandIncome/count/number',
method:'POST',
success(res) {
console.log(res.data.data);
OrderNumber.value=res.data.data
},
fail(err) {
console.log(err);
}
})
}
const OrderMoney=ref(0)
const getOrderMoney=()=>{
uni.request({
url:apiImageUrl+'/api/errandIncome/count/money',
method:'POST',
success(res) {
console.log(res);
OrderMoney.value=res.data.data
},
fail(err) {
console.log(err);
}
})
}
const waitMoney=ref(0)
const getwaitMoney=()=>{
uni.request({
url:apiImageUrl+'/api/errandIncome/count/money/no',
method:'POST',
success(res) {
console.log(res);
waitMoney.value=res.data.data
},
fail(err) {
console.log(err);
}
})
}
const allMoney=ref(0)
const getallMoney=()=>{
uni.request({
url:apiImageUrl+'/api/errandIncome/count/money/no',
method:'POST',
success(res) {
console.log(res);
allMoney.value=res.data.data
},
fail(err) {
console.log(err);
}
})
}
</script>
<style scoped lang="scss">
.container {
background-image: linear-gradient(to bottom, #5e7dec, #d0f0ff);
padding: 20px;
height: 100vh;
}
.header {
display: flex;
align-items: center;
padding: 10px;
background-color: #ffffff;
border-radius: 15px;
}
.user-icon {
width: 60px;
height: 60px;
border-radius: 50%;
margin-right: 10px;
}
.user-info {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.name {
font-size: 16px;
font-weight: bold;
}
.rule {
font-size: 12px;
color: #999;
}
.rating {
color: #ff9800;
margin-top: 5px;
}
.settings {
margin-left: auto;
}
.settings-icon {
width: 24px;
height: 24px;
}
.summary {
display: flex;
justify-content: space-around;
margin-top: 20px;
background-color: #1970fd;
padding: 10px;
border-radius: 15px;
}
.summary-item {
text-align: center;
color: #ffffff;
display: flex;
flex-direction: column;
align-items: center;
}
.summary-label {
padding: 5px;
font-size: 14px;
}
.summary-detail {
font-size: 12px;
color: #92b1e9;
padding: 5px;
}
.summary-value {
font-size: 20px;
font-weight: bold;
padding: 5px;
}
.menu {
background-color: #ffffff;
border-radius: 8px;
margin-top: 20px;
padding: 0 15px;
.menu-item {
display: flex;
align-items: center;
justify-content: space-between; /* 关键属性 */
height: 50px;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
text {
font-size: 15px;
color: #333;
flex-shrink: 0; /* 防止文字被压缩 */
}
.arrow-icon {
color: #999;
margin-left: 20px; /* 增加图标与文字的间距 */
}
}
}
.popup-content {
background-color: #ffffff;
padding: 30px 40px;
border-radius: 16px;
min-width: 240px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
text-align: center;
animation: fadeIn 0.3s ease;
border: 2px solid #5e7dec; /* 主色调蓝边框 */
}
.popup-text {
font-size: 24px;
color: #2a3f88; /* 深蓝文字 */
font-weight: bold;
letter-spacing: 1px;
}
/* 弹出动画 */
@keyframes fadeIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
</style>
<script>
export default {
data() {
return {
items: [{
label: '我的订单'
},
{
label: '收入查询'
},
{
label: '我的钱包'
},
{
label: '身份认证'
},
{
label: '申诉中心'
},
{
label: '服务评价'
}
]
};
}
};
</script>

View File

@ -0,0 +1,304 @@
<script setup>
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { apiImageUrl } from '../../API/api';
const orderDetail = ref(uni.getStorageSync('orderDetail'));
// 公寓位置映射表
const apartmentLocations = {
"1公寓": { latitude: 45.878148, longitude: 126.542369 },
"2公寓": { latitude: 45.878016, longitude: 126.542924 },
"3公寓": { latitude: 45.878117, longitude: 126.543476 },
"4公寓": { latitude: 45.878118, longitude: 126.54415 },
"5公寓": { latitude: 45.878978, longitude: 126.54127 },
"6公寓": { latitude: 45.878982, longitude: 126.541879 },
"9公寓": { latitude: 45.878435, longitude: 126.544863 },
"10公寓": { latitude: 45.879196, longitude: 126.543891 },
"11公寓": { latitude: 45.879157, longitude: 126.542722 },
"12公寓": { latitude: 45.875638, longitude: 126.540502 },
"育才大厦": { latitude: 45.875638, longitude: 126.540502 },
};
// 格式化日期函数保持不变
const formatDate = (dateString) => {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
// 处理取货逻辑保持不变
const handlePickup = (id) => {
console.log(id);
uni.request({
url: apiImageUrl + '/api/errand/update/state',
method: 'POST',
data: {
errandsState: 3,
orderId: id
},
success(res) {
console.log(res);
uni.navigateBack({
delta: 1,
animationType: 'pop-out',
animationDuration: 200
});
},
fail(err) {
console.log(err);
}
});
};
// 联系商家和联系用户的逻辑保持不变
const handleContact = (item) => {
uni.makePhoneCall({
phoneNumber: item
});
};
const handleCall = (item) => {
uni.makePhoneCall({
phoneNumber: item
});
};
// 初始化响应式变量
const latitude = ref(''); // 用户当前位置纬度
const longitude = ref(''); // 用户当前位置经度
const includePoints = ref([]); // 用于自动缩放的地图点集
const covers = ref([]); // 存储覆盖物
// 页面加载时获取位置信息
onMounted(() => {
getLocation();
});
// 获取用户当前位置并更新地图上的标记
function getLocation() {
uni.getLocation({
type: 'gcj02', // 返回可以用于uni.openLocation的坐标
success(res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
// 更新响应式数据
latitude.value = res.latitude;
longitude.value = res.longitude;
// 更新用户当前位置的标记信息
updateCover(res.latitude, res.longitude, 2, '我的位置', '/static/logo.png'); // 用户使用特定图标
// 根据orderDetail.location设置目标公寓的位置
if (orderDetail.value.location in apartmentLocations) {
const targetApartment = apartmentLocations[orderDetail.value.location];
// 更新includePoints数组确保地图包含两个位置
includePoints.value = [
{ latitude: targetApartment.latitude, longitude: targetApartment.longitude }, // 目标公寓的位置
{ latitude: res.latitude, longitude: res.longitude } // 用户的位置
];
} else {
console.warn(`未找到名为"${orderDetail.value.location}"的公寓位置`);
}
},
fail(err) {
console.error('获取位置失败', err);
}
});
}
// 更新覆盖物
function updateCover(lat, lng, id, title, iconPath) {
const position = {
id: id,
latitude: lat,
longitude: lng,
iconPath: iconPath, // 标记图标路径,现在通过参数传递
width: 30,
height: 30,
title: title // 可选:标记点标题
};
// 查找是否已存在指定ID的位置标记
const existingIndex = covers.value.findIndex(item => item.id === position.id);
if (existingIndex !== -1) {
// 如果存在则更新
covers.value[existingIndex] = position;
} else {
// 如果不存在则添加
covers.value.push(position);
}
}
</script>
<template>
<view class="page">
<!-- 地图 -->
<view>
<map
style="width: 100%; height: 300px;"
:latitude="latitude"
:longitude="longitude"
:markers="covers"
:include-points="includePoints">
</map>
</view>
<!-- 订单详情部分保持不变 -->
<view class="header">
<text class="location"></text>
<text class="distance">1km</text>
<text class="store-name">{{orderDetail.address}}</text>
</view>
<view class="header">
<text class="location"></text>
<text class="distance">1km</text>
<text class="store-name">{{orderDetail.location}}</text>
</view>
<view class="buttons">
<!-- <button class="button" @click="handlePickup(orderDetail.id)">我已取到</button> -->
<view class="icon-container">
<!-- 第一个图标和文字 -->
<view class="icon-wrapper" @click="handleCall(orderDetail.businessVO?.businessPhone)">
<uni-icons type="phone" size="30"></uni-icons>
<text>联系商家</text>
</view>
<!-- 第二个图标和文字 -->
<view class="icon-wrapper" @click="handleContact(orderDetail.phone)">
<uni-icons type="phone-filled" size="30"></uni-icons>
<text>联系用户</text>
</view>
<!-- 第三个图标和文字 -->
<view class="icon-wrapper">
<uni-icons type="camera" size="30" @click="handlePickup(orderDetail.id)"></uni-icons>
<text>拍照取到</text>
</view>
</view>
</view>
<view class="order-details">
<text class="title">跑单详情</text>
<view class="detail">
<text>取餐地址</text>
<text>{{orderDetail.address}}</text>
</view>
<view class="detail">
<text>下单时间</text>
<text>{{formatDate(orderDetail.createTime)}}</text>
</view>
<view class="detail">
<text>送达时间</text>
<text style="color: red;">{{formatDate(orderDetail.pickupEndTime)}}</text>
</view>
<view class="detail">
<text>送达地址</text>
<text>{{orderDetail.location}}</text>
</view>
</view>
</view>
</template>
<style scoped>
.page {
padding: 20px;
background-color: #fff;
}
.header {
display: flex;
align-items: center;
margin-bottom: 20px;
margin-top: 20px;
}
.location {
width: 24px;
/* 稍微增大圆形 */
height: 24px;
background-color: #ff6700;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
margin-right: 12px;
font-size: 12px;
/* 调整文本大小 */
font-weight: bold;
}
.distance {
color: #999;
font-size: 12px;
padding-right: 5px;
}
.store-name {
font-size: 20px;
font-weight: bold;
}
.buttons {
margin-bottom: 20px;
}
.button {
width: 100%;
padding: 10px;
margin: 10px 0;
text-align: center;
background-color: #2877f2;
color: #fff;
border: none;
border-radius: 8px;
cursor: pointer;
line-height: inherit;
}
.order-details {
margin-top: 20px;
font-size: 16px;
}
.title {
font-size: 20px;
font-weight: bold;
margin-bottom: 10px;
}
.detail {
display: flex;
align-items: center;
margin: 5px 0;
}
/* 定义图标容器的样式 */
.icon-container {
display: flex;
justify-content: space-around; /* 水平均匀分布 */
align-items: center; /* 垂直居中对齐 */
}
/* 定义每个图标和文字组合的样式 */
.icon-wrapper {
display: flex;
flex-direction: column; /* 将子元素垂直排列 */
align-items: center; /* 子元素水平居中对齐 */
}
/* 可选:定义文本标签的样式 */
.icon-wrapper text {
margin-top: 5px; /* 文字与图标之间的间距 */
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<view class="order-list">
<block v-for="(item, index) in orderList" :key="index">
<view class="order-details">
<view class="left-column">
<view class="userName">订单派送-{{ item.username }}</view>
<view class="orderTime">{{ item.orderStartTime.slice(0,10) }}</view>
</view>
<view class="right-column">
<view class="orderMoney">
+{{ item.income }}
</view>
<view class="orderState" :style="{color: item.errandState === 0 ? '#ff9900' : '#00cc66'}">
{{ item.errandState === 0 ? '待结算' : '已结算' }}
</view>
</view>
</view>
</block>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { apiImageUrl } from '../../API/api';
const orderList = ref([])
const getOrder = () => {
uni.request({
url: apiImageUrl + '/api/bill/list',
method: 'POST',
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie") || ''
},
success(res) {
console.log(res);
if (res.data.code === 0) {
console.log(res.data.data);
orderList.value = res.data.data
}
},
fail(err) {
console.log(err);
}
})
}
onMounted(() => {
getOrder()
})
</script>
<style scoped>
/* 保持原有样式不变 */
.order-list {
display: flex;
flex-direction: column;
}
.order-details {
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
background-color: #fff;
padding: 5px 10px 5px 10px;
border-bottom: 1px solid #f6f6f6;
}
.left-column,
.right-column {
display: flex;
flex-direction: column;
}
.userName,
.orderMoney {
margin: 5px 0;
font-size: 14px;
}
.orderTime,
.orderState {
font-size: 12px;
margin-bottom: 5px;
}
.userName {
color: #333;
}
.orderTime {
color: #666;
}
.orderMoney {
color: #007bff;
}
</style>

View File

@ -0,0 +1,227 @@
<template>
<view class="wallet-page">
<!-- Balance Section -->
<view class="balance-section">
<text class="balance-label">钱包余额()</text>
<view class="balance-amount">
<text class="amount">{{ totalIncome.toFixed(2) }}</text>
<button class="view-detail" @click="viewDetail">去提现</button>
</view>
<view class="transactions-section">
<view class="transaction-item">
<text class="transaction-label">未到账0.00 &gt;</text>
<text class="transaction-label">可提现0.00 &gt;</text>
</view>
<view class="transaction-item">
<text class="transaction-label">已冻结0.00 &gt;</text>
</view>
</view>
</view>
<!-- Menu Section -->
<view class="menu-section">
<view class="menu-item">
<view>
<text class="menu-title">慧民贷款</text>
<view class="subtitles-container">
<text class="menu-subtitle">余额
<text style="color: #3292bc;">0.00</text>
</text>
<text class="menu-subtitle">未到账
<text style="color: #3292bc;">0.00</text>
</text>
</view>
</view>
<uni-icons type="angle-right" size="24" class="menu-icon"></uni-icons>
</view>
<view class="menu-item">
<text class="menu-title">保证金</text>
<uni-icons type="angle-right" size="24" class="menu-icon"></uni-icons>
</view>
<view class="menu-item today-bill">
<view>
<text class="menu-title">今日账单</text>
<view class="subtitles-container">
<text class="menu-subtitle">收入
<text style="color: #3292bc;">0.00</text>
</text>
<text class="menu-subtitle">支出
<text style="color: #3292bc;">0.00</text>
</text>
</view>
</view>
<text class="menu-subtitle view-history">查看历史账单
<uni-icons type="right" size="16"></uni-icons>
</text>
<uni-icons type="angle-right" size="24" class="menu-icon"></uni-icons>
</view>
</view>
<!-- No Bill Message -->
<view class="no-bill-message">
<text>今天还没有账单哦</text>
</view>
</view>
</template>
<script setup>
import {
apiImageUrl
} from '../../API/api';
import {
ref, onMounted,
} from 'vue'
// 定义响应式变量接收接口返回值
const totalIncome = ref(0)
// 在页面挂载时获取数据
onMounted(() => {
getIncome()
})
// 请求方法
const getIncome = () =>{
uni.request({
url: apiImageUrl + '/api/errandIncome/count/money',
method: 'POST',
header: {
'Content-Type': 'application/json',
'cookie': uni.getStorageSync("cookie") || '' // 如果需要带上登录态
},
success: (res) => {
console.log('接口返回:', res)
if (res.data.code === 0 && res.data.data != null) {
totalIncome.value = res.data.data // 例如:返回 1450.5
} else {
uni.showToast({
title: res.data.message || '获取数据失败',
icon: 'none'
})
}
},
fail: (err) => {
console.error('请求失败:', err)
uni.showToast({
title: '网络错误,请检查连接',
icon: 'none'
})
}
})
}
</script>
<style lang="scss" scoped>
.wallet-page {
display: flex;
flex-direction: column;
height: 100%;
background-color: #f1f1f1;
.balance-section {
padding: 16px;
background-color: #5e7dec;
color: #fff;
.balance-label {
margin-bottom: 8px;
padding-left: 20px;
}
.balance-amount {
display: flex;
justify-content: space-between;
align-items: center;
.amount {
font-size: 24px;
font-weight: bold;
padding: 20px;
}
.view-detail {
margin: 0 20px;
border-radius: 15px;
background-color: rgba(255, 255, 255, 0.2);
color: #fff;
border: none;
cursor: pointer;
line-height: inherit;
padding: 8px 20px; /* 添加内边距 */
}
}
.transactions-section {
padding: 16px;
border-top: 1rpx solid #e0e0e0;
.transaction-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px;
.transaction-label {
font-size: 16px;
color: #fff;
}
}
}
}
.menu-section {
flex: 1;
overflow-y: auto;
.menu-item {
display: flex;
justify-content: space-between;
align-items: flex-start; // Align items at the top for multi-line content
padding: 16px;
background-color: #fff;
border-bottom: 1px solid #e0e0e0;
margin-top: 10px;
.menu-title {
font-size: 18px;
font-weight: bold;
}
.menu-subtitle {
font-size: 16px;
color: #666;
}
.menu-icon {
margin-left: auto;
}
.subtitles-container {
display: flex;
gap: 16px; // Space between the subtitles
margin-top: 8px; // Space from the menu title
}
&.today-bill {
.subtitles-container {
margin-top: 16px; // More space from the menu title
}
.view-history {
margin-left: 16px; // Space from the menu icon
color: #333;
cursor: pointer;
}
}
}
}
.no-bill-message {
text-align: center;
padding: 16px;
color: #999;
background-color: #fff;
}
}
</style>

View File

@ -0,0 +1,413 @@
<template>
<view class="container">
<view class="header">
<view class="title">跑腿注册</view>
</view>
<view class="form">
<view class="input-group" v-for="(field, index) in fields" :key="index">
<view class="label">{{ field.label }}</view>
<view class="input">
<!-- 修改后的性别字段处理 -->
<template v-if="field.model === 'gender'">
<radio-group :value="formData.gender" @change="handleGenderChange" class="radio-group">
<label class="radio-label">
<view class="radio-wrapper">
<radio value="男" color="#5e7dec" />
</view>
</label>
<label class="radio-label">
<view class="radio-wrapper">
<radio value="女" color="#5e7dec" />
</view>
</label>
</radio-group>
</template>
<!-- 配送范围字段 -->
<template v-else-if="field.model === 'distributionScope'">
<uni-data-select v-model="formData.distributionScope" :localdata="range" :clear="false"
class="distribution-select"></uni-data-select>
</template>
<!-- 其他字段保持原样 -->
<input v-else v-model="formData[field.model]" :placeholder="field.placeholder"
class="styled-input" />
</view>
</view>
<view class="button">
<button @click="saveAddress" class="styled-button">点击注册</button>
</view>
</view>
</view>
</template>
<script>
import {
apiImageUrl
} from '../../API/api';
export default {
data() {
return {
formData: {
checkPassword: '',
distributionScope: '',
errandName: '',
errandPhone: '',
gender: '',
userAccount: '',
userPassword: ''
},
range: [{
value: '1公寓',
text: '1公寓'
},
{
value: '2公寓',
text: '2公寓'
},
{
value: '3公寓',
text: '3公寓'
},
{
value: '4公寓',
text: '4公寓'
},
{
value: '5公寓',
text: '5公寓'
},
{
value: '6公寓',
text: '6公寓'
},
{
value: '7公寓',
text: '7公寓'
},
{
value: '8公寓',
text: '8公寓'
},
{
value: '9公寓',
text: '9公寓'
},
{
value: '10公寓',
text: '10公寓'
},
{
value: '11公寓',
text: '11公寓'
},
{
value: '12公寓',
text: '12公寓'
},
{
value: '育才大厦',
text: '育才大厦'
}
],
fields: [{
label: '账户',
model: 'userAccount',
placeholder: '请输入账户'
},
{
label: '密码',
model: 'userPassword',
placeholder: '请输入密码'
},
{
label: '确认密码',
model: 'checkPassword',
placeholder: '请再次输入密码'
},
{
label: '用户名称',
model: 'errandName',
placeholder: '请输入用户名称'
},
{
label: '手机号',
model: 'errandPhone',
placeholder: '请输入手机号'
},
{
label: '性别',
model: 'gender',
placeholder: '请选择性别'
},
{
label: '配送范围',
model: 'distributionScope',
placeholder: '请选择配送范围'
}
]
};
},
methods: {
handleGenderChange(e) {
// 将性别转换为数字
this.formData.gender = e.detail.value === '男' ? 0 : 1;
},
saveAddress() {
// 验证表单数据
if (!this.validateForm()) {
return; // validateForm内部已处理提示
}
const url = apiImageUrl + '/api/errand/add';
const data = {
checkPassword: this.formData.checkPassword,
distributionScope: this.formData.distributionScope,
errandName: this.formData.errandName,
errandPhone: this.formData.errandPhone,
gender: this.formData.gender,
userAccount: this.formData.userAccount,
userPassword: this.formData.userPassword
};
uni.request({
url,
method: 'POST',
data,
header: {
'Content-Type': 'application/json'
},
success(res) {
console.log(res.data);
if (res.data.code === 0) {
uni.showToast({
title: '注册成功!',
duration: 2000,
icon: "success"
})
uni.reLaunch({
url:'/pages/login/login'
})
} else if (res.data.code === 40000) {
uni.showToast({
title: res.data.description,
duration: 2000,
icon: "fail"
})
}
},
fail(err) {
console.error(err);
uni.showModal({
title: '注册失败', //提示标题
content: '请重新输入', //提示内容
//showCancel: true, //是否显示取消按钮
// success: function (res) {
// if (res.confirm) { //confirm为ture代表用户点击确定
// console.log('点击了确定按钮');
// } else if (res.cancel) { //cancel为ture代表用户点击取消
// console.log('点击了取消按钮');
// }
// }
})
}
});
},
validateForm() {
// 逐个字段校验并给出具体提示
if (!this.formData.userAccount) {
uni.showToast({
title: '请输入账户',
icon: 'none'
});
return false;
}
if (!this.formData.userPassword) {
uni.showToast({
title: '请输入密码',
icon: 'none'
});
return false;
}
if (this.formData.userPassword.length < 8) {
uni.showToast({
title: '密码过短至少8位',
icon: 'none'
});
return false;
}
if (!this.formData.checkPassword) {
uni.showToast({
title: '请输入确认密码',
icon: 'none'
});
return false;
}
if (this.formData.userPassword !== this.formData.checkPassword) {
uni.showToast({
title: '两次密码不一致',
icon: 'none'
});
return false;
}
if (!this.formData.errandName) {
uni.showToast({
title: '请输入用户名称',
icon: 'none'
});
return false;
}
if (!this.formData.errandPhone) {
uni.showToast({
title: '请输入手机号',
icon: 'none'
});
return false;
}
if (!this.formData.gender) {
uni.showToast({
title: '请选择性别',
icon: 'none'
});
return false;
}
if (!this.formData.distributionScope) {
uni.showToast({
title: '请选择配送范围',
icon: 'none'
});
return false;
}
return true;
}
}
};
</script>
<style lang="scss" scoped>
.container {
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.title {
font-size: 24px;
font-weight: bold;
}
}
.form {
.input-group {
display: flex;
align-items: center;
margin-bottom: 20px;
.label {
flex: 1;
font-size: 14px;
margin-right: 20px;
}
.input {
flex: 3;
.styled-input {
font-size: 14px;
width: 100%;
padding: 10px;
background-color: rgba(255, 235, 59, 0.6);
/* 淡黄色并带有透明度 */
border: none;
border-radius: 20px;
/* 圆角 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
/* 添加阴影以创建立体效果 */
outline: none;
transition: all 0.2s ease-in-out;
&:focus {
background-color: rgba(255, 235, 59, 0.8);
/* 增加透明度 */
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1);
/* 更强的阴影 */
}
}
}
}
.button {
margin-top: 20px;
.styled-button {
width: 100%;
padding: 10px;
background-color: #5e7dec;
color: #fff;
border: none;
border-radius: 15px;
cursor: pointer;
font-size: 16px;
line-height: inherit;
transition: background-color 0.2s;
&:hover {
background-color: #5e7dec;
}
}
}
}
/* 新增radio样式 */
.radio-group {
display: flex;
align-items: center;
height: 100%;
.radio-label {
display: flex;
align-items: center;
margin-right: 30px;
font-size: 14px;
/* 移除直接对radio的样式操作 */
/* 改为通过包裹元素实现间距 */
.radio-wrapper {
display: inline-block;
margin-right: 5px;
transform: scale(0.9);
}
}
}
/* 新增下拉选择样式 */
.distribution-select {
width: 100%;
.uni-select {
padding: 10px;
background-color: rgba(255, 235, 59, 0.6);
border-radius: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
&::after {
border-color: #5e7dec; /* 下拉箭头颜色 */
}
}
}
</style>

View File

@ -0,0 +1,15 @@
<template>
<view class="container">
<view class="example-body">
<uni-file-picker limit="9" title="最多选择9张图片"></uni-file-picker>
</view>
</view>
</template>
<style lang="scss">
.example-body {
padding: 10px;
padding-top: 0;
}
</style>

View File

@ -0,0 +1,22 @@
<script setup>
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const getAddress = () => {
uni.chooseLocation({
success: res => {
console.log(res);
console.log('位置名称:' + res.name);
console.log('详细地址:' + res.address);
console.log('纬度:' + res.latitude);
console.log('经度:' + res.longitude);
}
});
}
</script>
<template>
<button @click="getAddress">获取定位</button>
</template>