添加新页面

This commit is contained in:
not-like-juvenile
2026-01-23 17:13:39 +08:00
parent d5a3a4e8f0
commit b1c845d571
9 changed files with 2229 additions and 557 deletions

View File

@@ -0,0 +1,439 @@
<template>
<view class="profile-edit-container">
<!-- 顶部导航栏 -->
<view class="page-header">
<!-- 左上角:返回上一页按钮(箭头+文字 垂直排列) -->
<view class="nav-left" @click="goBack">
<text class="nav-icon">←</text>
<text class="nav-title">返回</text>
</view>
<!-- 页面标题居中 -->
<text class="page-title">编辑资料</text>
<!-- 右上角:保存按钮 -->
<view class="save-btn" @click="saveProfile">保存</view>
</view>
<!-- 编辑表单 -->
<view class="edit-form">
<!-- 头像上传 -->
<view class="form-item">
<text class="item-label">头像</text>
<view class="avatar-upload" @click="chooseAvatar">
<image :src="formData.avatar_url || '/static/default-avatar.png'" class="avatar-image" />
<text class="upload-text">点击更换</text>
</view>
</view>
<!-- 姓名 -->
<view class="form-item">
<text class="item-label">姓名</text>
<input class="item-input" v-model="formData.real_name" placeholder="请输入姓名" />
</view>
<!-- 身份证号 -->
<view class="form-item">
<text class="item-label">身份证号</text>
<input class="item-input" v-model="formData.id_card" placeholder="请输入身份证号" />
</view>
<!-- 驾驶证号 -->
<view class="form-item">
<text class="item-label">驾驶证号</text>
<input class="item-input" v-model="formData.driver_license" placeholder="请输入驾驶证号" />
</view>
<!-- 车辆类型 -->
<view class="form-item">
<text class="item-label">车辆类型</text>
<picker :value="vehicleTypeIndex" :range="vehicleTypes" @change="onVehicleTypeChange">
<view class="picker-view">{{ formData.vehicle_type ? vehicleTypes[vehicleTypeIndex] : '请选择车辆类型' }}</view>
</picker>
</view>
<!-- 车牌号 -->
<view class="form-item">
<text class="item-label">车牌号</text>
<input class="item-input" v-model="formData.vehicle_number" placeholder="请输入车牌号" />
</view>
<!-- 服务区域 -->
<view class="form-item">
<text class="item-label">服务区域</text>
<view class="service-areas">
<view class="area-tag" v-for="(area, index) in formData.service_areas" :key="index">
<text class="area-text">{{ area }}</text>
<text class="remove-area" @click="removeArea(index)">×</text>
</view>
<view class="add-area" @click="showAddAreaModal">
<text class="add-icon">+</text>
<text class="add-text">添加区域</text>
</view>
</view>
</view>
<!-- 联系电话(可选) -->
<view class="form-item">
<text class="item-label">联系电话</text>
<input class="item-input" v-model="formData.phone" placeholder="请输入联系电话" />
</view>
</view>
<!-- 添加服务区域弹窗 -->
<view v-if="showAreaModal" class="modal-overlay" @click="hideAddAreaModal">
<view class="modal-content" @click.stop="noop">
<text class="modal-title">添加服务区域</text>
<input class="modal-input" v-model="newAreaName" placeholder="输入区域名称" />
<view class="modal-actions">
<button class="modal-btn cancel" @click="hideAddAreaModal">取消</button>
<button class="modal-btn confirm" @click="addNewArea">确定</button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, onMounted } from 'vue'
// 响应式数据
const formData = reactive({
id: '',
user_id: '',
real_name: '李师傅',
id_card: '110101199001011234',
driver_license: 'C1',
vehicle_type: 1,
vehicle_number: '京A12345',
phone: '13888888888',
service_areas: ['朝阳区', '东城区'],
avatar_url: ''
})
const vehicleTypeIndex = ref(0)
const showAreaModal = ref(false)
const newAreaName = ref('')
const vehicleTypes = ref(['摩托车', '电动自行车', '面包车', '小型货车'])
// 生命周期
onMounted(() => {
loadProfileData()
})
// 方法
function loadProfileData() {
// 模拟加载当前用户资料
// 实际项目中应从 API 获取
}
function chooseAvatar() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
formData.avatar_url = res.tempFilePaths[0]
}
})
}
function onVehicleTypeChange(e: UniEvent<HTMLInputElement>) {
const index = parseInt(e.detail.value)
vehicleTypeIndex.value = index
formData.vehicle_type = index + 1 // 假设后端从1开始
}
function showAddAreaModal() {
newAreaName.value = ''
showAreaModal.value = true
}
function hideAddAreaModal() {
showAreaModal.value = false
}
function addNewArea() {
if (newAreaName.value.trim()) {
if (!formData.service_areas.includes(newAreaName.value.trim())) {
formData.service_areas.push(newAreaName.value.trim())
}
newAreaName.value = ''
}
hideAddAreaModal()
}
function removeArea(index: number) {
formData.service_areas.splice(index, 1)
}
function saveProfile() {
// 模拟保存
uni.showLoading({
title: '保存中...'
})
setTimeout(() => {
uni.hideLoading()
uni.showToast({
title: '保存成功',
icon: 'success'
})
// 保存成功后返回上一页
uni.navigateBack()
}, 1000)
// 实际项目中应调用 API 保存数据
console.log('保存的资料:', formData)
}
function goBack() {
uni.navigateBack()
}
function noop() {
// 阻止事件冒泡的空函数
}
</script>
<style scoped>
.profile-edit-container {
background-color: #f5f5f5;
min-height: 100vh;
padding: 20rpx 30rpx;
}
/* 导航栏样式 */
.page-header {
background-color: #fff;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #e9ecef;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
position: relative;
min-height: 80rpx;
}
.nav-left {
position: absolute;
top: 20rpx;
left: 30rpx;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
padding: 10rpx;
border-radius: 8rpx;
transition: background-color 0.2s ease;
}
.nav-left:hover {
background-color: #f0f0f0;
}
.nav-left:active {
background-color: #e0e0e0;
}
.nav-icon {
font-size: 36rpx;
color: #333;
margin-bottom: 5rpx;
}
.nav-title {
font-size: 28rpx;
color: #333;
font-weight: 500;
text-align: center;
}
.page-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
text-align: center;
margin-top: 20rpx; /* 与 nav-left 保持一定距离 */
}
.save-btn {
position: absolute;
top: 20rpx;
right: 30rpx;
font-size: 28rpx;
color: #4CAF50;
font-weight: bold;
padding: 10rpx 20rpx;
background-color: #e8f5e8;
border-radius: 12rpx;
}
/* 编辑表单 */
.edit-form {
margin-top: 20rpx;
}
.form-item {
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx 30rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.item-label {
font-size: 28rpx;
color: #333;
font-weight: 500;
min-width: 120rpx;
}
.item-input {
flex: 1;
font-size: 28rpx;
color: #333;
padding: 10rpx 0;
border: none;
outline: none;
text-align: right;
}
.picker-view {
font-size: 28rpx;
color: #333;
text-align: right;
padding: 10rpx 0;
}
/* 头像上传 */
.avatar-upload {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.avatar-image {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
border: 4rpx solid #ddd;
}
.upload-text {
font-size: 24rpx;
color: #666;
margin-top: 10rpx;
}
/* 服务区域 */
.service-areas {
flex: 1;
display: flex;
flex-wrap: wrap;
gap: 10rpx;
align-items: center;
}
.area-tag {
display: flex;
align-items: center;
background-color: #e8f4fd;
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: #333;
}
.remove-area {
margin-left: 8rpx;
font-size: 20rpx;
color: #ff4757;
cursor: pointer;
}
.add-area {
display: flex;
align-items: center;
background-color: #f0f0f0;
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: #666;
cursor: pointer;
}
.add-icon {
margin-right: 5rpx;
font-size: 20rpx;
}
/* 弹窗样式 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #fff;
width: 80%;
max-width: 600rpx;
border-radius: 16rpx;
padding: 30rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.modal-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.modal-input {
width: 100%;
font-size: 28rpx;
color: #333;
padding: 10rpx 20rpx;
border: 1rpx solid #ddd;
border-radius: 8rpx;
margin-bottom: 20rpx;
}
.modal-actions {
display: flex;
justify-content: space-around;
width: 100%;
}
.modal-btn {
flex: 1;
height: 80rpx;
border-radius: 8rpx;
font-size: 28rpx;
font-weight: bold;
margin: 0 10rpx;
cursor: pointer;
}
.cancel {
background-color: #f0f0f0;
color: #333;
}
.confirm {
background-color: #4CAF50;
color: #fff;
}
</style>