pet/pages/pets/edit-pet.vue

631 lines
13 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="edit-pet-container page-container-with-bg">
<!-- 页面标题 -->
<view class="page-header">
<view class="header-title">
<text class="title-icon"></text>
<text class="title-text">编辑宠物信息</text>
</view>
<text class="header-subtitle">修改您的爱宠档案</text>
</view>
<!-- 头像上传区域 -->
<view class="avatar-card card">
<view class="avatar-section">
<view class="avatar-container" @click="chooseAvatar">
<image
v-if="petForm.avatar"
:src="petForm.avatar"
class="pet-avatar"
mode="aspectFill"
/>
<view v-else class="avatar-placeholder">
<text class="avatar-icon">📷</text>
<text class="avatar-text">添加照片</text>
</view>
<view class="avatar-overlay">
<text class="overlay-icon">✏️</text>
</view>
</view>
<text class="avatar-tip">点击更换宠物照片</text>
</view>
</view>
<!-- 基本信息表单 -->
<view class="form-card card">
<view class="card-header">
<text class="card-title">基本信息</text>
</view>
<view class="form-content">
<!-- 宠物姓名 -->
<view class="input-container">
<text class="input-label">宠物姓名 <text class="required-star">*</text></text>
<input
class="input-field"
v-model="petForm.name"
placeholder="给您的宠物起个好听的名字"
maxlength="20"
/>
</view>
<!-- 品种 -->
<view class="input-container">
<text class="input-label">品种 <text class="required-star">*</text></text>
<input
class="input-field"
v-model="petForm.breed"
placeholder="如:金毛、英短、布偶猫等"
maxlength="30"
/>
</view>
<!-- 性别 -->
<view class="input-container">
<text class="input-label">性别 <text class="required-star">*</text></text>
<view class="gender-selector">
<view
class="gender-option"
:class="{ active: petForm.gender === '公' }"
@click="petForm.gender = '公'"
>
<text class="gender-icon">♂️</text>
<text class="gender-text">公</text>
</view>
<view
class="gender-option"
:class="{ active: petForm.gender === '母' }"
@click="petForm.gender = '母'"
>
<text class="gender-icon">♀️</text>
<text class="gender-text">母</text>
</view>
</view>
</view>
<!-- 生日 -->
<view class="input-container">
<text class="input-label">生日 <text class="required-star">*</text></text>
<view class="date-input" @click="showDatePicker = true">
<text class="date-text" :class="{ placeholder: !petForm.birthday }">
{{ petForm.birthday || '请选择宠物生日' }}
</text>
<text class="date-icon">📅</text>
</view>
</view>
<!-- 体重 -->
<view class="input-container">
<text class="input-label">体重</text>
<input
class="input-field"
v-model="petForm.weight"
placeholder="如4.5kg(可选填)"
maxlength="10"
/>
</view>
</view>
</view>
<!-- 备注信息 -->
<view class="notes-card card">
<view class="card-header">
<text class="card-title">备注信息</text>
</view>
<view class="notes-content">
<textarea
class="notes-textarea"
v-model="petForm.notes"
placeholder="记录一些特殊信息,如:性格特点、喜好、注意事项等..."
maxlength="200"
/>
<view class="char-count">
<text class="count-text">{{ petForm.notes?.length || 0 }}/200</text>
</view>
</view>
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<button class="submit-btn btn-primary" @click="submitForm" :disabled="loading">
<text v-if="loading" class="loading-icon">⏳</text>
<text class="btn-text">{{ loading ? '保存中...' : '保存修改' }}</text>
</button>
</view>
<!-- 日期选择器 -->
<u-datetime-picker
:show="showDatePicker"
v-model="selectedDate"
mode="date"
@confirm="confirmDate"
@cancel="showDatePicker = false">
</u-datetime-picker>
</view>
</template>
<script>
export default {
data() {
return {
petId: '',
loading: false,
showDatePicker: false,
selectedDate: new Date().getTime(),
petForm: {
name: '',
breed: '',
gender: '公',
birthday: '',
weight: '',
notes: '',
avatar: ''
}
}
},
onLoad(options) {
this.petId = options.id
this.loadPetInfo()
},
methods: {
loadPetInfo() {
try {
// 从本地存储获取宠物信息
const pets = uni.getStorageSync('pets') || []
const petInfo = pets.find(pet => pet.id == this.petId)
if (petInfo) {
this.petForm = {
name: petInfo.name || '',
breed: petInfo.breed || '',
gender: petInfo.gender || '公',
birthday: petInfo.birthday || '',
weight: petInfo.weight || '',
notes: petInfo.notes || '',
avatar: petInfo.avatar || ''
}
}
} catch (error) {
console.error('加载宠物信息失败', error)
uni.showToast({
title: '加载失败',
icon: 'error'
})
}
},
chooseAvatar() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
this.petForm.avatar = res.tempFilePaths[0]
},
fail: (err) => {
console.error('选择图片失败', err)
}
})
},
confirmDate(e) {
const date = new Date(e.value)
this.petForm.birthday = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`
this.showDatePicker = false
},
submitForm() {
// 简单验证
if (!this.petForm.name.trim()) {
uni.showToast({
title: '请输入宠物姓名',
icon: 'none'
})
return
}
if (!this.petForm.breed.trim()) {
uni.showToast({
title: '请输入宠物品种',
icon: 'none'
})
return
}
if (!this.petForm.birthday) {
uni.showToast({
title: '请选择宠物生日',
icon: 'none'
})
return
}
this.savePet()
},
savePet() {
this.loading = true
// 计算陪伴天数和年龄
const birthday = new Date(this.petForm.birthday)
const today = new Date()
const companionDays = Math.floor((today - birthday) / (1000 * 60 * 60 * 24))
const age = Math.floor(companionDays / 365)
// 模拟保存到本地存储
setTimeout(() => {
try {
let pets = uni.getStorageSync('pets') || []
const petIndex = pets.findIndex(pet => pet.id == this.petId)
if (petIndex > -1) {
// 更新现有宠物信息
pets[petIndex] = {
...pets[petIndex],
...this.petForm,
age: age,
companionDays: companionDays,
updateTime: new Date().toISOString()
}
uni.setStorageSync('pets', pets)
this.loading = false
uni.showToast({
title: '保存成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
} else {
this.loading = false
uni.showToast({
title: '宠物信息不存在',
icon: 'error'
})
}
} catch (error) {
this.loading = false
uni.showToast({
title: '保存失败',
icon: 'error'
})
}
}, 1000)
}
}
}
</script>
<style lang="scss" scoped>
.edit-pet-container {
padding: 20rpx;
padding-bottom: 120rpx;
}
/* 页面标题 */
.page-header {
text-align: center;
margin-bottom: 40rpx;
padding: 40rpx 20rpx;
.header-title {
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
margin-bottom: 16rpx;
.title-icon {
font-size: 48rpx;
}
.title-text {
font-size: 44rpx;
font-weight: bold;
color: #333333;
}
}
.header-subtitle {
font-size: 28rpx;
color: #666666;
opacity: 0.8;
}
}
/* 通用卡片样式 */
.card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20rpx);
border-radius: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.15);
border: 1rpx solid rgba(255, 255, 255, 0.3);
}
/* 头像卡片 */
.avatar-card {
padding: 40rpx;
.avatar-section {
text-align: center;
.avatar-container {
position: relative;
display: inline-block;
margin-bottom: 20rpx;
.pet-avatar {
width: 160rpx;
height: 160rpx;
border-radius: 80rpx;
border: 4rpx solid #FF8A80;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.3);
}
.avatar-placeholder {
width: 160rpx;
height: 160rpx;
border-radius: 80rpx;
border: 4rpx dashed #CCCCCC;
background: #F5F5F5;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8rpx;
.avatar-icon {
font-size: 48rpx;
color: #CCCCCC;
}
.avatar-text {
font-size: 24rpx;
color: #999999;
}
}
.avatar-overlay {
position: absolute;
bottom: 8rpx;
right: 8rpx;
width: 48rpx;
height: 48rpx;
background: #FF8A80;
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(255, 138, 128, 0.4);
.overlay-icon {
font-size: 24rpx;
color: white;
}
}
}
.avatar-tip {
font-size: 24rpx;
color: #999999;
}
}
}
/* 表单卡片 */
.form-card {
padding: 32rpx;
.card-header {
margin-bottom: 32rpx;
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.form-content {
.input-container {
margin-bottom: 32rpx;
&:last-child {
margin-bottom: 0;
}
.input-label {
font-size: 28rpx;
color: #333333;
margin-bottom: 16rpx;
display: block;
font-weight: 500;
.required-star {
color: #FF8A80;
margin-left: 4rpx;
}
}
.input-field {
width: 100%;
height: 88rpx;
background: rgba(255, 138, 128, 0.05);
border: 2rpx solid rgba(255, 138, 128, 0.1);
border-radius: 16rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
transition: all 0.3s ease;
&:focus {
border-color: #FF8A80;
background: rgba(255, 138, 128, 0.08);
}
&::placeholder {
color: #CCCCCC;
}
}
.gender-selector {
display: flex;
gap: 16rpx;
.gender-option {
flex: 1;
height: 88rpx;
background: rgba(255, 138, 128, 0.05);
border: 2rpx solid rgba(255, 138, 128, 0.1);
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
transition: all 0.3s ease;
&.active {
background: #FF8A80;
border-color: #FF8A80;
.gender-icon,
.gender-text {
color: white;
}
}
.gender-icon {
font-size: 32rpx;
color: #666666;
}
.gender-text {
font-size: 28rpx;
color: #666666;
font-weight: 500;
}
}
}
.date-input {
width: 100%;
height: 88rpx;
background: rgba(255, 138, 128, 0.05);
border: 2rpx solid rgba(255, 138, 128, 0.1);
border-radius: 16rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
.date-text {
font-size: 28rpx;
color: #333333;
&.placeholder {
color: #CCCCCC;
}
}
.date-icon {
font-size: 32rpx;
color: #FF8A80;
}
}
}
}
}
/* 备注卡片 */
.notes-card {
padding: 32rpx;
.card-header {
margin-bottom: 24rpx;
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.notes-content {
.notes-textarea {
width: 100%;
min-height: 200rpx;
background: rgba(255, 138, 128, 0.05);
border: 2rpx solid rgba(255, 138, 128, 0.1);
border-radius: 16rpx;
padding: 24rpx;
font-size: 28rpx;
color: #333333;
line-height: 1.6;
box-sizing: border-box;
resize: none;
&::placeholder {
color: #CCCCCC;
}
}
.char-count {
text-align: right;
margin-top: 12rpx;
.count-text {
font-size: 24rpx;
color: #999999;
}
}
}
}
/* 提交按钮 */
.submit-section {
padding: 0 20rpx;
margin-top: 40rpx;
.submit-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
border: none;
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.4);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(255, 138, 128, 0.3);
}
&:disabled {
opacity: 0.6;
transform: none;
}
.loading-icon {
font-size: 32rpx;
color: white;
}
.btn-text {
font-size: 32rpx;
color: white;
font-weight: bold;
}
}
}
</style>