完善宠物管理功能
✨ 新增功能: - 宠物详情页面:展示完整的宠物信息和最近记录 - 添加宠物页面:支持头像上传、基本信息录入、表单验证 - 添加记录页面:支持多种记录类型、照片上传、日期选择 - 本地存储集成:宠物数据和记录数据持久化存储 🎨 界面优化: - 使用uView组件构建现代化表单界面 - 支持图片选择和预览功能 - 响应式网格布局展示信息 - 完善的空状态和加载状态 📱 用户体验: - 表单验证和错误提示 - 图片上传和预览 - 日期选择器集成 - 数据持久化存储 🔧 技术改进: - 页面路由配置完善 - 自定义导航栏样式 - 组件化开发模式
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<view class="add-pet-container">
|
||||
<u-navbar title="添加宠物" left-icon="arrow-left" @left-click="goBack"></u-navbar>
|
||||
|
||||
<u-form :model="petForm" ref="petFormRef" :rules="rules" label-width="120">
|
||||
<u-card :padding="20" margin="20">
|
||||
<view class="avatar-section">
|
||||
<u-avatar :src="petForm.avatar || '/static/default-pet.png'" size="80" shape="circle" @click="chooseAvatar"></u-avatar>
|
||||
<u-text text="点击上传头像" type="tips" size="12"></u-text>
|
||||
</view>
|
||||
</u-card>
|
||||
|
||||
<u-card :padding="20" margin="20">
|
||||
<u-form-item label="宠物姓名" prop="name" required>
|
||||
<u-input v-model="petForm.name" placeholder="请输入宠物姓名"></u-input>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="品种" prop="breed" required>
|
||||
<u-input v-model="petForm.breed" placeholder="请输入宠物品种"></u-input>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="性别" prop="gender" required>
|
||||
<u-radio-group v-model="petForm.gender" placement="row">
|
||||
<u-radio label="公" name="公"></u-radio>
|
||||
<u-radio label="母" name="母"></u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="生日" prop="birthday" required>
|
||||
<u-input v-model="petForm.birthday" placeholder="请选择生日" readonly @click="showDatePicker = true"></u-input>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="体重" prop="weight">
|
||||
<u-input v-model="petForm.weight" placeholder="请输入体重(如:4.5kg)"></u-input>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="备注" prop="notes">
|
||||
<u-textarea v-model="petForm.notes" placeholder="记录一些特殊信息..." maxlength="200"></u-textarea>
|
||||
</u-form-item>
|
||||
</u-card>
|
||||
</u-form>
|
||||
|
||||
<view class="submit-section">
|
||||
<u-button type="primary" text="保存宠物信息" @click="submitForm" :loading="loading"></u-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 {
|
||||
loading: false,
|
||||
showDatePicker: false,
|
||||
selectedDate: new Date().getTime(),
|
||||
petForm: {
|
||||
name: '',
|
||||
breed: '',
|
||||
gender: '公',
|
||||
birthday: '',
|
||||
weight: '',
|
||||
notes: '',
|
||||
avatar: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入宠物姓名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
breed: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入宠物品种',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
gender: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择宠物性别',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
birthday: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择宠物生日',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
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() {
|
||||
this.$refs.petFormRef.validate().then(valid => {
|
||||
if (valid) {
|
||||
this.savePet()
|
||||
}
|
||||
}).catch(errors => {
|
||||
console.log('表单验证失败', errors)
|
||||
})
|
||||
},
|
||||
|
||||
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)
|
||||
|
||||
const petData = {
|
||||
...this.petForm,
|
||||
id: Date.now(), // 简单的ID生成
|
||||
age: age,
|
||||
companionDays: companionDays,
|
||||
createTime: new Date().toISOString()
|
||||
}
|
||||
|
||||
// 模拟保存到本地存储
|
||||
setTimeout(() => {
|
||||
try {
|
||||
let pets = uni.getStorageSync('pets') || []
|
||||
pets.push(petData)
|
||||
uni.setStorageSync('pets', pets)
|
||||
|
||||
this.loading = false
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
} catch (error) {
|
||||
this.loading = false
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.add-pet-container {
|
||||
background-color: #f8f9fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.avatar-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
/deep/ .u-form-item {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user