@ -0,0 +1,335 @@ | |||||
<template> | |||||
<view class="center-page"> | |||||
<!-- 顶部背景和个人信息 --> | |||||
<view class="header" :style="{ 'background-image': 'url(/static/image/红烧肉.png)' }"> | |||||
<view class="user-info"> | |||||
<image class="avatar" :src="userInfo.avatarUrl" mode="aspectFill"></image> | |||||
<view class="user-name-id"> | |||||
<text class="user-name">{{ userInfo.nickName }}</text> | |||||
<text class="user-id">ID:{{ userInfo.userId }}</text> | |||||
</view> | |||||
</view> | |||||
<view class="role-switch-btn"> | |||||
<uv-icon name="reload" size="30rpx" color="#fff" style="margin-right: 6rpx;" /> | |||||
<text>切换为{{ userInfo.role }}</text> | |||||
</view> | |||||
</view> | |||||
<!-- 我的订单区域 --> | |||||
<view class="orders-section"> | |||||
<view class="section-header"> | |||||
<text class="section-title">我的订单</text> | |||||
<view class="view-all" @tap="navigateTo('/pages/index/order?status=all')"> | |||||
<text>全部</text> | |||||
<uv-icon name="arrow-right" size="30rpx" color="#999" /> | |||||
</view> | |||||
</view> | |||||
<view class="order-types"> | |||||
<view class="order-type-item" @tap="navigateTo('/pages/index/order?status=pending')"> | |||||
<view class="order-icon-wrapper"> | |||||
<view class="green-circle"> | |||||
<uv-icon name="red-packet" size="44rpx" color="#fff" /> | |||||
</view> | |||||
<uv-badge max="9" absolute :offset="[-10, -12]" bgColor="#FF2A2A" | |||||
:value="userInfo.waitingPayCount" style="padding: 10rpx 15rpx;" /> | |||||
</view> | |||||
<text class="order-type-text">待支付</text> | |||||
</view> | |||||
<view class="order-type-item" @tap="navigateTo('/pages/index/order?status=processing')"> | |||||
<view class="order-icon-wrapper"> | |||||
<view class="green-circle"> | |||||
<uv-icon name="chat" size="44rpx" color="#fff" /> | |||||
</view> | |||||
<uv-badge max="9" absolute :offset="[-10, -12]" bgColor="#FF2A2A" | |||||
:value="userInfo.waitingDiningCount" style="padding: 10rpx 15rpx;" /> | |||||
</view> | |||||
<text class="order-type-text">待出餐</text> | |||||
</view> | |||||
<view class="order-type-item" @tap="navigateTo('/pages/index/order?status=shipping')"> | |||||
<view class="order-icon-wrapper"> | |||||
<view class="green-circle"> | |||||
<uv-icon name="chat" size="44rpx" color="#fff" /> | |||||
</view> | |||||
<uv-badge max="9" absolute :offset="[-10, -12]" bgColor="#FF2A2A" | |||||
:value="userInfo.deliveringCount" style="padding: 10rpx 15rpx;" /> | |||||
</view> | |||||
<text class="order-type-text">送餐中</text> | |||||
</view> | |||||
<view class="order-type-item" @tap="navigateTo('/pages/index/order?status=delivered')"> | |||||
<view class="order-icon-wrapper"> | |||||
<view class="green-circle"> | |||||
<uv-icon name="chat" size="44rpx" color="#fff" /> | |||||
</view> | |||||
<uv-badge max="9" absolute :offset="[-10, -12]" bgColor="#FF2A2A" :value="userInfo.pickupCount" | |||||
style="padding: 10rpx 15rpx;" /> | |||||
</view> | |||||
<text class="order-type-text">待取餐</text> | |||||
</view> | |||||
<view class="order-type-item" @tap="navigateTo('/pages/index/order?status=completed')"> | |||||
<view class="order-icon-wrapper"> | |||||
<view class="green-circle"> | |||||
<uv-icon name="chat" size="44rpx" color="#fff" /> | |||||
</view> | |||||
<uv-badge max="9" absolute :offset="[-10, -12]" bgColor="#FF2A2A" | |||||
:value="userInfo.completedCount" style="padding: 10rpx 15rpx;" /> | |||||
</view> | |||||
<text class="order-type-text">已完成</text> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
<!-- 团员功能区域 --> | |||||
<view class="member-functions"> | |||||
<view class="section-header"> | |||||
<text class="section-title">团员功能</text> | |||||
</view> | |||||
<view class="function-grid"> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/updateUser')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">资料修改</text> | |||||
</view> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/team')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">团长申请</text> | |||||
</view> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/leader')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">解绑团长</text> | |||||
</view> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/share')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">推广链接</text> | |||||
</view> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/coupon')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">优惠券</text> | |||||
</view> | |||||
<view class="function-item" @tap="navigateTo('/pages_order/mine/wallet')"> | |||||
<view class="function-icon"> | |||||
<uv-icon name="chat" size="94rpx" color="#019245" /> | |||||
</view> | |||||
<text class="function-text">钱包</text> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
<tabber select="center" /> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import tabber from '@/components/base/tabbar.vue' | |||||
import { mockUserInfo } from '@/static/js/mockUserInfo.js' | |||||
export default { | |||||
components: { | |||||
tabber | |||||
}, | |||||
data() { | |||||
return { | |||||
userInfo: mockUserInfo | |||||
} | |||||
}, | |||||
methods: { | |||||
navigateTo(url) { | |||||
console.log(111222); | |||||
this.$utils.navigateTo({ | |||||
url | |||||
}) | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.center-page { | |||||
min-height: 100vh; | |||||
background-color: #f5f5f5; | |||||
padding-bottom: 120rpx; | |||||
} | |||||
.header { | |||||
position: relative; | |||||
height: 340rpx; | |||||
background-size: cover; | |||||
background-position: center; | |||||
color: #fff; | |||||
padding: 60rpx 30rpx 0; | |||||
display: flex; | |||||
flex-direction: column; | |||||
align-items: start; | |||||
position: relative; | |||||
.user-info { | |||||
position: absolute; | |||||
display: flex; | |||||
align-items: center; | |||||
margin-top: 30rpx; | |||||
z-index: 2; | |||||
left: 30rpx; | |||||
top: 120rpx; | |||||
.avatar { | |||||
width: 110rpx; | |||||
height: 110rpx; | |||||
border-radius: 50%; | |||||
} | |||||
.user-name-id { | |||||
margin-left: 30rpx; | |||||
display: flex; | |||||
flex-direction: column; | |||||
.user-name { | |||||
font-size: 32rpx; | |||||
font-weight: bold; | |||||
margin-bottom: 6rpx; | |||||
} | |||||
.user-id { | |||||
font-size: 24rpx; | |||||
opacity: 0.9; | |||||
} | |||||
} | |||||
} | |||||
.role-switch-btn { | |||||
position: absolute; | |||||
right: 0; | |||||
top: 180rpx; | |||||
background-color: rgba(255, 255, 255, 0.2); | |||||
border-radius: 30rpx 0 0 30rpx; | |||||
padding: 10rpx 20rpx; | |||||
font-size: 24rpx; | |||||
z-index: 2; | |||||
display: flex; | |||||
align-items: center; | |||||
} | |||||
} | |||||
.orders-section { | |||||
background-color: #fff; | |||||
border-radius: 20rpx 20rpx 0 0; | |||||
margin: -70rpx auto 0; | |||||
padding: 15rpx; | |||||
position: relative; | |||||
z-index: 3; | |||||
width: 90%; | |||||
// margin: 0 auto; | |||||
} | |||||
.member-functions { | |||||
background-color: #fff; | |||||
padding: 30rpx; | |||||
margin-top: 20rpx; | |||||
width: 88%; | |||||
border-radius: 20rpx; | |||||
margin: 30rpx auto 0; | |||||
} | |||||
.section-header { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
margin-bottom: 40rpx; | |||||
.section-title { | |||||
font-size: 32rpx; | |||||
font-weight: 500; | |||||
position: relative; | |||||
padding-left: 15rpx; | |||||
} | |||||
.view-all { | |||||
display: flex; | |||||
align-items: center; | |||||
font-size: 26rpx; | |||||
color: $uni-color-third; | |||||
} | |||||
} | |||||
.order-types { | |||||
// background-color: red; | |||||
display: flex; | |||||
// justify-content: space-around; | |||||
.order-type-item { | |||||
display: flex; | |||||
flex-direction: column; | |||||
align-items: center; | |||||
width: 20%; | |||||
.order-icon-wrapper { | |||||
position: relative; | |||||
margin-bottom: 4rpx; | |||||
.green-circle { | |||||
width: 70rpx; | |||||
height: 70rpx; | |||||
background-color: $uni-color; | |||||
border-radius: 50%; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
} | |||||
} | |||||
.order-type-text { | |||||
font-size: 26rpx; | |||||
color: #666; | |||||
margin-top: 8rpx; | |||||
} | |||||
} | |||||
} | |||||
.function-grid { | |||||
display: flex; | |||||
flex-wrap: wrap; | |||||
.function-item { | |||||
width: 25%; | |||||
display: flex; | |||||
flex-direction: column; | |||||
align-items: center; | |||||
margin-bottom: 40rpx; | |||||
.function-icon { | |||||
width: 80rpx; | |||||
height: 80rpx; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
margin-bottom: 16rpx; | |||||
} | |||||
.function-text { | |||||
font-size: 26rpx; | |||||
color: #333; | |||||
} | |||||
} | |||||
} | |||||
</style> |
@ -0,0 +1,304 @@ | |||||
<template> | |||||
<view class="login"> | |||||
<view class="bg1"></view> | |||||
<view class="title"> | |||||
定制自己的形象 | |||||
</view> | |||||
<view v-if="back" @click="$utils.navigateBack" style="position: absolute;top: 120rpx;left: 20rpx;"> | |||||
<uv-icon size="30rpx" color="#000" name="arrow-left"></uv-icon> | |||||
</view> | |||||
<button class="chooseAvatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | |||||
<image :src="form.headImage" mode="aspectFill"></image> | |||||
</button> | |||||
<input type="nickname" placeholder="给自己起一个响亮的名字" class="nickname" id="nickName" v-model="form.nickName" /> | |||||
<!-- <view class="sexSelect"> | |||||
<view | |||||
@click="sexClick(item)" | |||||
v-for="(item, index) in sexList" | |||||
:key="index" | |||||
:style="{color : form.sex == item.value ? item.actColor : '#333'}"> | |||||
<uv-icon | |||||
size="30rpx" | |||||
:color="form.sex == item.value ? item.actColor : '#333'" | |||||
:name="item.icon"></uv-icon> | |||||
{{ item.value }} | |||||
</view> | |||||
</view> --> | |||||
<!-- <view class="address" | |||||
@click="$refs.datetimePicker.open()"> | |||||
您出生于{{ $dayjs(form.yearDate).format("YYYY") }}年 | |||||
</view> | |||||
<view class="address" | |||||
@click="$refs.picker.open()"> | |||||
{{ form.address || '请选择居住地址'}} | |||||
</view> --> | |||||
<uv-datetime-picker ref="datetimePicker" v-model="form.yearDate" mode="year" :minDate="minDate" | |||||
:maxDate="maxDate"> | |||||
</uv-datetime-picker> | |||||
<uv-picker ref="picker" :columns="columns" keyName="name" @confirm="confirmAddress"></uv-picker> | |||||
<view class="btn" @click="submit"> | |||||
确认 | |||||
</view> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import { mapState } from 'vuex' | |||||
export default { | |||||
data() { | |||||
return { | |||||
form: { | |||||
headImage: '', | |||||
nickName: '', | |||||
sex: '男', | |||||
yearDate: this.$dayjs().add(-18, 'y').valueOf(),//默认满18岁 | |||||
address: '', | |||||
}, | |||||
maxDate: this.$dayjs().valueOf(), | |||||
minDate: this.$dayjs().add(-100, 'y').valueOf(), | |||||
sex: { | |||||
男: { | |||||
name: 'man', | |||||
color: '#5baaff', | |||||
}, | |||||
女: { | |||||
name: 'woman', | |||||
color: '#ff50b3', | |||||
}, | |||||
}, | |||||
sexList: [ | |||||
{ | |||||
value: '男', | |||||
icon: 'man', | |||||
actColor: '#5baaff', | |||||
}, | |||||
{ | |||||
value: '女', | |||||
icon: 'woman', | |||||
actColor: '#ff50b3', | |||||
}, | |||||
], | |||||
columns: [], | |||||
back: '', | |||||
}; | |||||
}, | |||||
computed: { | |||||
...mapState(['cityList', 'userInfo']), | |||||
}, | |||||
onLoad({ back }) { | |||||
this.back = back | |||||
// this.$nextTick(() => { | |||||
// this.form.headImage = this.userInfo.headImage || this.form.headImage | |||||
// this.form.nickName = this.userInfo.nickName || this.form.nickName | |||||
// this.form.sex = this.userInfo.sex || this.form.sex | |||||
// this.form.yearDate = this.userInfo.yearDate || this.form.yearDate | |||||
// this.form.address = this.userInfo.address || this.form.address | |||||
// }) | |||||
}, | |||||
onShow() { | |||||
this.getCityList() | |||||
this.getUserInfo() | |||||
}, | |||||
computed: {}, | |||||
methods: { | |||||
onChooseAvatar(res) { | |||||
let self = this | |||||
self.$Oss.ossUpload(res.target.avatarUrl) | |||||
.then(url => { | |||||
self.form.headImage = url | |||||
}) | |||||
}, | |||||
sexClick(item) { | |||||
this.form.sex = item.value | |||||
}, | |||||
confirmAddress(e) { | |||||
this.form.address = e.value[0].name | |||||
}, | |||||
// 获取城市 | |||||
getCityList() { | |||||
this.$api('getCityList', res => { | |||||
if (res.code == 200) { | |||||
this.columns = [ | |||||
res.result | |||||
] | |||||
} | |||||
}) | |||||
}, | |||||
getUserInfo() { | |||||
this.$api('getInfo', res => { | |||||
if (res.code == 200) { | |||||
this.form.headImage = res.result.headImage || this.form.headImage | |||||
this.form.nickName = res.result.nickName || this.form.nickName | |||||
this.form.sex = res.result.sex || this.form.sex | |||||
this.form.yearDate = res.result.yearDate && | |||||
this.$dayjs(res.result.yearDate + '-01-01').valueOf() || this.form.yearDate | |||||
this.form.address = res.result.address || this.form.address | |||||
} | |||||
}) | |||||
}, | |||||
submit() { | |||||
let self = this | |||||
uni.createSelectorQuery().in(this) | |||||
.select("#nickName") | |||||
.fields({ | |||||
properties: ["value"], | |||||
}) | |||||
.exec((res) => { | |||||
const nickName = res?.[0]?.value | |||||
self.form.nickName = nickName | |||||
if (self.$utils.verificationAll(self.form, { | |||||
headImage: '请选择头像', | |||||
nickName: '请填写昵称', | |||||
// address: '请选择居住地址', | |||||
})) { | |||||
return | |||||
} | |||||
let data = { | |||||
...self.form, | |||||
// yearDate : this.$dayjs(self.form.yearDate).format("YYYY") | |||||
} | |||||
self.$api('updateInfo', data, res => { | |||||
if (res.code == 200) { | |||||
uni.reLaunch({ | |||||
url: '/pages/index/index' | |||||
}) | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
} | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.login { | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: center; | |||||
align-items: center; | |||||
height: 100vh; | |||||
background-color: #fff; | |||||
overflow: hidden; | |||||
.bg1 { | |||||
width: 700rpx; | |||||
height: 700rpx; | |||||
border-radius: 50%; | |||||
background-color: #ffc0b333; | |||||
position: absolute; | |||||
right: -300rpx; | |||||
top: -300rpx; | |||||
} | |||||
.title { | |||||
line-height: 45rpx; | |||||
font-weight: 900; | |||||
padding-bottom: 100rpx; | |||||
font-size: 40rpx; | |||||
} | |||||
.chooseAvatar { | |||||
width: 100%; | |||||
padding: 0 !important; | |||||
margin: 0 !important; | |||||
border: none; | |||||
background-color: #fff !important; | |||||
width: 220rpx; | |||||
height: 220rpx; | |||||
border-radius: 50%; | |||||
image { | |||||
width: 200rpx; | |||||
height: 200rpx; | |||||
border-radius: 50%; | |||||
box-shadow: 0 0 10rpx 10rpx #00000012; | |||||
margin: 10rpx; | |||||
} | |||||
} | |||||
.chooseAvatar::after { | |||||
border: none; | |||||
padding: 0 !important; | |||||
margin: 0 !important; | |||||
} | |||||
.nickname { | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
} | |||||
.sexSelect { | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
display: flex; | |||||
align-items: center; | |||||
font-size: 26rpx; | |||||
line-height: 80rpx; | |||||
overflow: hidden; | |||||
&>view { | |||||
flex: 1; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-content: center; | |||||
height: 100%; | |||||
} | |||||
&>view:nth-child(1) { | |||||
border-right: 1px solid #000; | |||||
} | |||||
} | |||||
.address { | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
line-height: 80rpx; | |||||
color: #555; | |||||
} | |||||
.btn { | |||||
// background: $uni-linear-gradient-btn-color; | |||||
background: $uni-color; | |||||
color: #fff; | |||||
width: 80%; | |||||
padding: 20rpx 0; | |||||
text-align: center; | |||||
border-radius: 15rpx; | |||||
margin-top: 10vh; | |||||
} | |||||
} | |||||
</style> |
@ -0,0 +1,335 @@ | |||||
<template> | |||||
<view class="page"> | |||||
<!-- 导航栏 --> | |||||
<navbar title="团长申请" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||||
<!-- 顶部图片区域 --> | |||||
<view class="banner"> | |||||
<image src="/static/image/红烧肉.png" mode="aspectFill" class="banner-image"></image> | |||||
</view> | |||||
<view class="content-area"> | |||||
<!-- 送餐点照片上传区域 --> | |||||
<view class="section-title">送餐点照片</view> | |||||
<view class="section-block"> | |||||
<view class="upload-container"> | |||||
<view class="upload-area" @click="chooseImage" v-if="!locationImage"> | |||||
<view class="plus">+</view> | |||||
<view class="upload-text">添加图片</view> | |||||
</view> | |||||
<image v-else :src="locationImage" mode="aspectFill" class="upload-area" @click="chooseImage" /> | |||||
</view> | |||||
</view> | |||||
<!-- 送餐点信息填写区域 --> | |||||
<view class="section-title">送餐点信息</view> | |||||
<view class="section-block"> | |||||
<view class="form-item"> | |||||
<text class="label">送餐点名称</text> | |||||
<input class="input" type="text" v-model="formData.name" placeholder="请输入送餐点名称" | |||||
placeholder-class="placeholder" /> | |||||
</view> | |||||
<view class="form-item"> | |||||
<text class="label">您的姓名</text> | |||||
<input class="input" type="text" v-model="formData.contactName" placeholder="请输入您的姓名" | |||||
placeholder-class="placeholder" /> | |||||
</view> | |||||
<view class="form-item"> | |||||
<text class="label">联系手机号</text> | |||||
<input class="input" type="number" v-model="formData.contactPhone" placeholder="请输入您的手机号" | |||||
placeholder-class="placeholder" /> | |||||
</view> | |||||
<view class="form-item region-item" @click="showRegionPicker"> | |||||
<text class="label">所在地区</text> | |||||
<view class="region-value"> | |||||
<text :class="{ 'placeholder': !formData.region }" style="color: #000;">{{ formData.region || '请选择' }}</text> | |||||
<uv-icon name="arrow-right" color="#000" /> | |||||
</view> | |||||
</view> | |||||
<view class="address-item"> | |||||
<text class="label">详细地址</text> | |||||
<view class="address-box"> | |||||
<textarea class="address-input" v-model="formData.address" placeholder="请输入详细地址" | |||||
placeholder-class="placeholder" /> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
<!-- 提交按钮 --> | |||||
<view class="submit-btn" @click="submitApplication"> | |||||
提交申请 | |||||
</view> | |||||
</view> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import navbar from '@/components/base/navbar.vue' | |||||
export default { | |||||
components: { | |||||
navbar | |||||
}, | |||||
data() { | |||||
return { | |||||
locationImage: '', // 上传的送餐点照片 | |||||
formData: { | |||||
name: '', // 送餐点名称 | |||||
contactName: '', // 联系人姓名 | |||||
contactPhone: '', // 联系电话 | |||||
region: '', // 所在地区 | |||||
address: '' // 详细地址 | |||||
} | |||||
} | |||||
}, | |||||
methods: { | |||||
// 选择图片 | |||||
chooseImage() { | |||||
uni.chooseImage({ | |||||
count: 1, | |||||
sizeType: ['compressed'], | |||||
sourceType: ['album', 'camera'], | |||||
success: (res) => { | |||||
// 这里可以添加图片上传到服务器的逻辑 | |||||
// 暂时只展示选择的图片 | |||||
this.locationImage = res.tempFilePaths[0] | |||||
} | |||||
}) | |||||
}, | |||||
// 显示地区选择器(当前只是一个简单的点击反应) | |||||
showRegionPicker() { | |||||
// 模拟选择了一个地区 | |||||
this.formData.region = '长沙市雨花区' | |||||
// 显示提示 | |||||
uni.showToast({ | |||||
title: '已选择地区', | |||||
icon: 'none' | |||||
}) | |||||
}, | |||||
// 提交申请 | |||||
submitApplication() { | |||||
// 表单验证 | |||||
if (!this.locationImage) { | |||||
return uni.showToast({ | |||||
title: '请上传送餐点照片', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.formData.name) { | |||||
return uni.showToast({ | |||||
title: '请输入送餐点名称', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.formData.contactName) { | |||||
return uni.showToast({ | |||||
title: '请输入您的姓名', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.formData.contactPhone) { | |||||
return uni.showToast({ | |||||
title: '请输入联系手机号', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.$utils.verificationPhone(this.formData.contactPhone)) { | |||||
return uni.showToast({ | |||||
title: '请输入正确的手机号', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.formData.region) { | |||||
return uni.showToast({ | |||||
title: '请选择所在地区', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
if (!this.formData.address) { | |||||
return uni.showToast({ | |||||
title: '请输入详细地址', | |||||
icon: 'none' | |||||
}) | |||||
} | |||||
// 显示提交中 | |||||
uni.showLoading({ | |||||
title: '提交中...' | |||||
}) | |||||
// 模拟提交申请的过程 | |||||
setTimeout(() => { | |||||
uni.hideLoading() | |||||
uni.showToast({ | |||||
title: '申请提交成功', | |||||
icon: 'success' | |||||
}) | |||||
// 延迟返回上一页 | |||||
setTimeout(() => { | |||||
this.$utils.navigateBack() | |||||
}, 1500) | |||||
}, 1000) | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
background-color: #f5f5f5; | |||||
min-height: 100vh; | |||||
} | |||||
.banner { | |||||
width: 100%; | |||||
height: 240rpx; | |||||
background-color: #019245; | |||||
.banner-image { | |||||
width: 100%; | |||||
height: 100%; | |||||
display: block; | |||||
} | |||||
} | |||||
.content-area { | |||||
padding: 20rpx; | |||||
} | |||||
.section-block { | |||||
margin-bottom: 20rpx; | |||||
background-color: #fff; | |||||
border-radius: 20rpx; | |||||
padding: 10rpx 20rpx; | |||||
overflow: hidden; | |||||
} | |||||
.section-title { | |||||
font-size: 28rpx; | |||||
color: #333; | |||||
padding: 20rpx; | |||||
// border-bottom: 1rpx solid #f5f5f5; | |||||
} | |||||
.upload-container { | |||||
padding: 20rpx; | |||||
min-height: 140rpx; | |||||
} | |||||
.upload-area { | |||||
width: 150rpx; | |||||
height: 150rpx; | |||||
border: 3rpx dashed $uni-color; | |||||
// border-radius: 8rpx; | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: center; | |||||
align-items: center; | |||||
.plus { | |||||
font-size: 80rpx; | |||||
color: $uni-color; | |||||
line-height: 1; | |||||
// margin-bottom: 5rpx; | |||||
font-weight: 100; | |||||
} | |||||
.upload-text { | |||||
font-size: 24rpx; | |||||
color: $uni-color-third; | |||||
} | |||||
} | |||||
.form-item { | |||||
padding: 24rpx 0; | |||||
display: flex; | |||||
align-items: center; | |||||
border-bottom: 2rpx solid #C7C7C7; | |||||
&:last-child { | |||||
border-bottom: none; | |||||
} | |||||
} | |||||
.label { | |||||
flex: 3; | |||||
font-size: 28rpx; | |||||
color: #333; | |||||
padding-left: 10rpx; | |||||
} | |||||
.input { | |||||
flex: 2; | |||||
font-size: 28rpx; | |||||
// height: 60rpx; | |||||
text-align: left; | |||||
} | |||||
.placeholder, | |||||
.region-item .region-value text.placeholder { | |||||
// height: 60rpx; | |||||
color: #999; | |||||
} | |||||
.region-item { | |||||
cursor: pointer; | |||||
.region-value { | |||||
flex: 1; | |||||
text-align: right; | |||||
font-size: 28rpx; | |||||
display: flex; | |||||
justify-content: flex-end; | |||||
align-items: center; | |||||
} | |||||
} | |||||
.address-item { | |||||
padding: 24rpx 0; | |||||
display: flex; | |||||
flex-direction: column; | |||||
gap: 20rpx; | |||||
.address-box { | |||||
} | |||||
.address-input { | |||||
padding: 20rpx; | |||||
background-color: #F5F5F5; | |||||
border-radius: 10rpx; | |||||
width: inherit; | |||||
height: 60rpx; | |||||
font-size: 28rpx; | |||||
} | |||||
} | |||||
.submit-btn { | |||||
width: 80%; | |||||
margin: 40rpx auto 0; | |||||
height: 100rpx; | |||||
background-color: $uni-color; | |||||
color: #fff; | |||||
font-size: 32rpx; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
border-radius: 50rpx; | |||||
// margin-top: 60rpx; | |||||
} | |||||
</style> |
@ -1,319 +1,282 @@ | |||||
<template> | <template> | ||||
<view class="login"> | |||||
<view class="bg1"></view> | |||||
<view class="title"> | |||||
定制自己的形象 | |||||
</view> | |||||
<view | |||||
v-if="back" | |||||
@click="$utils.navigateBack" | |||||
style="position: absolute;top: 120rpx;left: 20rpx;"> | |||||
<uv-icon | |||||
size="30rpx" | |||||
color="#000" | |||||
name="arrow-left"></uv-icon> | |||||
</view> | |||||
<button class="chooseAvatar" | |||||
open-type="chooseAvatar" | |||||
@chooseavatar="onChooseAvatar"> | |||||
<image :src="form.headImage" | |||||
mode="aspectFill"></image> | |||||
</button> | |||||
<input type="nickname" | |||||
placeholder="给自己起一个响亮的名字" | |||||
class="nickname" id="nickName" | |||||
v-model="form.nickName" /> | |||||
<!-- <view class="sexSelect"> | |||||
<view | |||||
@click="sexClick(item)" | |||||
v-for="(item, index) in sexList" | |||||
:key="index" | |||||
:style="{color : form.sex == item.value ? item.actColor : '#333'}"> | |||||
<uv-icon | |||||
size="30rpx" | |||||
:color="form.sex == item.value ? item.actColor : '#333'" | |||||
:name="item.icon"></uv-icon> | |||||
{{ item.value }} | |||||
<view class="profile-page"> | |||||
<!-- 头部导航栏 --> | |||||
<navbar title="资料修改" bgColor="#019245" color="#fff" leftClick @leftClick="$utils.navigateBack" /> | |||||
<!-- 基本资料区域 --> | |||||
<view class="main-content"> | |||||
<view class="section-title"> | |||||
<view class="title-indicator"></view> | |||||
<text>基本资料</text> | |||||
</view> | |||||
<!-- 头像选择区域 --> | |||||
<view class="avatar-section"> | |||||
<button class="chooseAvatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | |||||
<image class="avatar-img" :src="form.headImage" mode="aspectFill"></image> | |||||
</button> | |||||
<text class="avatar-hint">点击更换头像</text> | |||||
</view> | |||||
<!-- 表单区域 --> | |||||
<view class="form-section"> | |||||
<view class="form-item"> | |||||
<text class="label">昵称</text> | |||||
<input class="input" type="nickname" placeholder="请输入" v-model="form.nickName" id="nickName" | |||||
placeholderStyle="color: #999; text-align: right;" /> | |||||
</view> | |||||
<view class="form-item"> | |||||
<text class="label">手机号</text> | |||||
<input class="input" type="tel" placeholder="请输入" v-model="form.phone" | |||||
placeholderStyle="color: #999; text-align: right;" /> | |||||
</view> | |||||
</view> | |||||
<!-- 保存按钮 --> | |||||
<view class="save-button" @tap="submit"> | |||||
<text>保存</text> | |||||
</view> | </view> | ||||
</view> --> | |||||
<!-- <view class="address" | |||||
@click="$refs.datetimePicker.open()"> | |||||
您出生于{{ $dayjs(form.yearDate).format("YYYY") }}年 | |||||
</view> | |||||
<view class="address" | |||||
@click="$refs.picker.open()"> | |||||
{{ form.address || '请选择居住地址'}} | |||||
</view> --> | |||||
<uv-datetime-picker | |||||
ref="datetimePicker" | |||||
v-model="form.yearDate" | |||||
mode="year" | |||||
:minDate="minDate" | |||||
:maxDate="maxDate"> | |||||
</uv-datetime-picker> | |||||
<uv-picker ref="picker" | |||||
:columns="columns" | |||||
keyName="name" | |||||
@confirm="confirmAddress"></uv-picker> | |||||
<view class="btn" @click="submit"> | |||||
确认 | |||||
</view> | </view> | ||||
</view> | </view> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import { mapState } from 'vuex' | |||||
export default { | |||||
data() { | |||||
return { | |||||
form: { | |||||
headImage: '', | |||||
nickName: '', | |||||
sex : '男', | |||||
yearDate : this.$dayjs().add(-18, 'y').valueOf(),//默认满18岁 | |||||
address : '', | |||||
}, | |||||
maxDate : this.$dayjs().valueOf(), | |||||
minDate : this.$dayjs().add(-100, 'y').valueOf(), | |||||
sex : { | |||||
男 : { | |||||
name : 'man', | |||||
color : '#5baaff', | |||||
}, | |||||
女 : { | |||||
name : 'woman', | |||||
color : '#ff50b3', | |||||
}, | |||||
}, | |||||
sexList : [ | |||||
{ | |||||
value : '男', | |||||
icon : 'man', | |||||
actColor : '#5baaff', | |||||
}, | |||||
{ | |||||
value : '女', | |||||
icon : 'woman', | |||||
actColor : '#ff50b3', | |||||
}, | |||||
], | |||||
columns : [], | |||||
back : '', | |||||
}; | |||||
}, | |||||
computed: { | |||||
...mapState(['cityList', 'userInfo']), | |||||
}, | |||||
onLoad({back}) { | |||||
this.back = back | |||||
// this.$nextTick(() => { | |||||
// this.form.headImage = this.userInfo.headImage || this.form.headImage | |||||
// this.form.nickName = this.userInfo.nickName || this.form.nickName | |||||
// this.form.sex = this.userInfo.sex || this.form.sex | |||||
// this.form.yearDate = this.userInfo.yearDate || this.form.yearDate | |||||
// this.form.address = this.userInfo.address || this.form.address | |||||
// }) | |||||
}, | |||||
onShow() { | |||||
this.getCityList() | |||||
this.getUserInfo() | |||||
}, | |||||
computed: {}, | |||||
methods: { | |||||
onChooseAvatar(res) { | |||||
let self = this | |||||
self.$Oss.ossUpload(res.target.avatarUrl) | |||||
import { mapState } from 'vuex' | |||||
import { mockUserInfo } from '@/static/js/mockUserInfo.js' | |||||
import navbar from '@/components/base/navbar.vue' | |||||
export default { | |||||
components: { | |||||
navbar | |||||
}, | |||||
data() { | |||||
return { | |||||
form: { | |||||
headImage: '', | |||||
nickName: '', | |||||
phone: '' | |||||
}, | |||||
back: '', | |||||
} | |||||
}, | |||||
computed: { | |||||
...mapState(['userInfo']), | |||||
}, | |||||
onLoad({ back }) { | |||||
this.back = back | |||||
}, | |||||
onShow() { | |||||
this.getUserInfo() | |||||
}, | |||||
methods: { | |||||
onChooseAvatar(res) { | |||||
let self = this | |||||
self.$Oss.ossUpload(res.detail.avatarUrl) | |||||
.then(url => { | .then(url => { | ||||
self.form.headImage = url | self.form.headImage = url | ||||
}) | }) | ||||
}, | |||||
sexClick(item){ | |||||
this.form.sex = item.value | |||||
}, | |||||
confirmAddress(e){ | |||||
this.form.address = e.value[0].name | |||||
}, | |||||
// 获取城市 | |||||
getCityList(){ | |||||
this.$api('getCityList', res => { | |||||
if(res.code == 200){ | |||||
this.columns = [ | |||||
res.result | |||||
] | |||||
} | |||||
}, | |||||
getUserInfo() { | |||||
// 使用mock数据 | |||||
this.form.headImage = mockUserInfo.avatarUrl || this.form.headImage | |||||
this.form.nickName = mockUserInfo.nickName || this.form.nickName | |||||
this.form.phone = '13800138000' // 模拟手机号 | |||||
}, | |||||
submit() { | |||||
let self = this | |||||
// 之所以手动获取dom的input值 而不是v-model 是为了保证跨平台安全生效 | |||||
uni.createSelectorQuery().in(this) | |||||
.select("#nickName") | |||||
.fields({ | |||||
properties: ["value"], | |||||
}) | }) | ||||
}, | |||||
getUserInfo(){ | |||||
this.$api('getInfo', res => { | |||||
if(res.code == 200){ | |||||
this.form.headImage = res.result.headImage || this.form.headImage | |||||
this.form.nickName = res.result.nickName || this.form.nickName | |||||
this.form.sex = res.result.sex || this.form.sex | |||||
this.form.yearDate = res.result.yearDate && | |||||
this.$dayjs(res.result.yearDate + '-01-01').valueOf() || this.form.yearDate | |||||
this.form.address = res.result.address || this.form.address | |||||
.exec((res) => { | |||||
const nickName = res?.[0]?.value | |||||
self.form.nickName = nickName | |||||
if (self.$utils.verificationAll(self.form, { | |||||
headImage: '请选择头像', | |||||
nickName: '请填写昵称', | |||||
phone: '请填写手机号' | |||||
})) { | |||||
return | |||||
} | } | ||||
}) | |||||
}, | |||||
submit() { | |||||
let self = this | |||||
uni.createSelectorQuery().in(this) | |||||
.select("#nickName") | |||||
.fields({ | |||||
properties: ["value"], | |||||
}) | |||||
.exec((res) => { | |||||
const nickName = res?.[0]?.value | |||||
self.form.nickName = nickName | |||||
if (self.$utils.verificationAll(self.form, { | |||||
headImage: '请选择头像', | |||||
nickName: '请填写昵称', | |||||
// address: '请选择居住地址', | |||||
})) { | |||||
return | |||||
} | |||||
let data = { | |||||
...self.form, | |||||
// yearDate : this.$dayjs(self.form.yearDate).format("YYYY") | |||||
} | |||||
self.$api('updateInfo', data, res => { | |||||
if (res.code == 200) { | |||||
uni.reLaunch({ | |||||
url:'/pages/index/index' | |||||
}) | |||||
} | |||||
if (!self.$utils.verificationPhone(self.form.phone)) { | |||||
uni.showToast({ | |||||
icon: 'none', | |||||
title: '请填写正确的手机号' | |||||
}) | }) | ||||
return | |||||
} | |||||
uni.showLoading({ | |||||
title: '保存中...' | |||||
}) | }) | ||||
}, | |||||
setTimeout(() => { | |||||
uni.hideLoading() | |||||
uni.showToast({ | |||||
title: '保存成功', | |||||
icon: 'success' | |||||
}) | |||||
// 返回上一页 | |||||
setTimeout(() => { | |||||
this.$utils.navigateBack() | |||||
}, 1500) | |||||
}, 1000) | |||||
}) | |||||
} | } | ||||
} | } | ||||
} | |||||
</script> | </script> | ||||
<style lang="scss" scoped> | <style lang="scss" scoped> | ||||
.login { | |||||
.profile-page { | |||||
min-height: 100vh; | |||||
background-color: #f5f5f5; | |||||
} | |||||
.nav-bar { | |||||
height: 180rpx; | |||||
background-color: #019245; | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: space-between; | |||||
padding: 0 30rpx; | |||||
padding-top: 60rpx; | |||||
box-sizing: border-box; | |||||
color: #fff; | |||||
.back-btn { | |||||
width: 60rpx; | |||||
height: 60rpx; | |||||
display: flex; | display: flex; | ||||
flex-direction: column; | |||||
justify-content: center; | |||||
align-items: center; | align-items: center; | ||||
height: 100vh; | |||||
background-color: #fff; | |||||
overflow: hidden; | |||||
.bg1{ | |||||
width: 700rpx; | |||||
height: 700rpx; | |||||
border-radius: 50%; | |||||
background-color: #ffc0b333; | |||||
position: absolute; | |||||
right: -300rpx; | |||||
top: -300rpx; | |||||
} | |||||
.nav-title { | |||||
font-size: 36rpx; | |||||
font-weight: 500; | |||||
} | |||||
.right-actions { | |||||
display: flex; | |||||
align-items: center; | |||||
.icon-divider { | |||||
width: 2rpx; | |||||
height: 30rpx; | |||||
background-color: rgba(255, 255, 255, 0.5); | |||||
margin: 0 20rpx; | |||||
} | } | ||||
} | |||||
} | |||||
.main-content { | |||||
padding: 30rpx; | |||||
} | |||||
.section-title { | |||||
display: flex; | |||||
align-items: center; | |||||
margin-bottom: 30rpx; | |||||
.title-indicator { | |||||
width: 8rpx; | |||||
height: 32rpx; | |||||
background-color: $uni-color; | |||||
margin-right: 15rpx; | |||||
border-radius: 4rpx; | |||||
} | |||||
text { | |||||
font-size: 32rpx; | |||||
font-weight: 500; | |||||
color: #333; | |||||
} | |||||
} | |||||
.title { | |||||
line-height: 45rpx; | |||||
font-weight: 900; | |||||
padding-bottom: 100rpx; | |||||
font-size: 40rpx; | |||||
.avatar-section { | |||||
display: flex; | |||||
flex-direction: column; | |||||
align-items: center; | |||||
margin: 50rpx 0; | |||||
.chooseAvatar { | |||||
width: 180rpx; | |||||
height: 180rpx; | |||||
border-radius: 50%; | |||||
overflow: hidden; | |||||
padding: 0; | |||||
margin: 0; | |||||
background: none; | |||||
&::after { | |||||
border: none; | |||||
} | } | ||||
.chooseAvatar { | |||||
.avatar-img { | |||||
width: 100%; | width: 100%; | ||||
padding: 0 !important; | |||||
margin: 0 !important; | |||||
border: none; | |||||
background-color: #fff !important; | |||||
width: 220rpx; | |||||
height: 220rpx; | |||||
height: 100%; | |||||
border-radius: 50%; | border-radius: 50%; | ||||
image{ | |||||
width: 200rpx; | |||||
height: 200rpx; | |||||
border-radius: 50%; | |||||
box-shadow: 0 0 10rpx 10rpx #00000012; | |||||
margin: 10rpx; | |||||
} | |||||
} | } | ||||
.chooseAvatar::after{ | |||||
border: none; | |||||
padding: 0 !important; | |||||
margin: 0 !important; | |||||
} | |||||
.nickname{ | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
} | |||||
.sexSelect{ | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
display: flex; | |||||
align-items: center; | |||||
font-size: 26rpx; | |||||
line-height: 80rpx; | |||||
overflow: hidden; | |||||
&>view{ | |||||
flex: 1; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-content: center; | |||||
height: 100%; | |||||
} | |||||
&>view:nth-child(1){ | |||||
border-right: 1px solid #000; | |||||
} | |||||
} | |||||
.avatar-hint { | |||||
font-size: 26rpx; | |||||
color: $uni-color-third; | |||||
margin-top: 20rpx; | |||||
} | |||||
} | |||||
.form-section { | |||||
background-color: #fff; | |||||
border-radius: 30rpx; | |||||
overflow: hidden; | |||||
margin-bottom: 60rpx; | |||||
.form-item { | |||||
display: flex; | |||||
height: 100rpx; | |||||
align-items: center; | |||||
padding: 0 30rpx; | |||||
border-bottom: 1rpx solid #f5f5f5; | |||||
&:last-child { | |||||
border-bottom: none; | |||||
} | } | ||||
.address{ | |||||
background-color: #f7f7f7; | |||||
width: 600rpx; | |||||
height: 80rpx; | |||||
text-align: center; | |||||
border-radius: 40rpx; | |||||
margin-top: 30rpx; | |||||
line-height: 80rpx; | |||||
color: #555; | |||||
.label { | |||||
width: 150rpx; | |||||
font-size: 30rpx; | |||||
color: $uni-color-third; | |||||
} | } | ||||
.btn { | |||||
// background: $uni-linear-gradient-btn-color; | |||||
background: $uni-color; | |||||
color: #fff; | |||||
width: 80%; | |||||
padding: 20rpx 0; | |||||
text-align: center; | |||||
border-radius: 15rpx; | |||||
margin-top: 10vh; | |||||
.input { | |||||
flex: 1; | |||||
height: 100%; | |||||
font-size: 30rpx; | |||||
color: #666; | |||||
} | } | ||||
} | } | ||||
} | |||||
.save-button { | |||||
width: 90%; | |||||
margin: 160rpx auto 0; | |||||
height: 100rpx; | |||||
background-color: $uni-color; | |||||
border-radius: 45rpx; | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: center; | |||||
color: #fff; | |||||
font-size: 32rpx; | |||||
box-shadow: 0 6rpx 20rpx rgba(1, 146, 69, 0.3); | |||||
} | |||||
</style> | </style> |
@ -0,0 +1,11 @@ | |||||
export const mockUserInfo = { | |||||
avatarUrl: "/static/image/中森明菜.webp", | |||||
nickName: "李向西", | |||||
userId: "123456", | |||||
role: "团长", | |||||
waitingPayCount: 2, | |||||
waitingDiningCount: 0, | |||||
deliveringCount: 3, | |||||
pickupCount: 0, | |||||
completedCount: 0 | |||||
} |