pet/pages/pets/add-record-simple.vue

341 lines
9.8 KiB
Vue

<template>
<view class="add-record-container">
<u-navbar title="添加记录" left-icon="arrow-left" @left-click="goBack" bg-color="#FF8A80">
<template #right>
<u-text text="保存" color="#ffffff" @click="saveRecord"></u-text>
</template>
</u-navbar>
<view class="content-area">
<u-form ref="recordFormRef" :model="recordForm" :rules="rules" label-width="160rpx">
<!-- 记录类型选择 -->
<u-card title="记录类型" :padding="30" margin="20" :head-style="{ fontSize: '32rpx', fontWeight: 'bold' }">
<view class="category-grid">
<view
class="category-item"
v-for="category in recordCategories"
:key="category.value"
@click="selectCategory(category.value)"
>
<view class="category-icon" :class="{ active: recordForm.category === category.value }">
<u-icon :name="category.icon" size="24" :color="recordForm.category === category.value ? '#ffffff' : '#FF8A80'"></u-icon>
</view>
<u-text :text="category.label" size="12" :color="recordForm.category === category.value ? '#FF8A80' : '#666666'" bold></u-text>
</view>
</view>
</u-card>
<!-- 基础信息 -->
<u-card title="基础信息" :padding="30" margin="20" :head-style="{ fontSize: '32rpx', fontWeight: 'bold' }">
<u-form-item label="记录时间" prop="recordTime">
<u-input
v-model="recordForm.recordTime"
placeholder="选择记录时间"
readonly
@click="showDatePicker = true"
></u-input>
</u-form-item>
<u-form-item label="记录内容" prop="content">
<u-textarea
v-model="recordForm.content"
placeholder="描述一下具体情况..."
maxlength="500"
count
></u-textarea>
</u-form-item>
</u-card>
<!-- 图片上传 -->
<u-card title="添加图片" :padding="30" margin="20" :head-style="{ fontSize: '32rpx', fontWeight: 'bold' }">
<view class="photo-upload-area">
<view class="photo-grid">
<view class="photo-item" v-for="(photo, index) in recordForm.photos" :key="index">
<u-image :src="photo" width="140rpx" height="140rpx" border-radius="12rpx"></u-image>
<view class="photo-delete" @click="removePhoto(index)">
<u-icon name="close-circle-fill" size="16" color="#FF8A80"></u-icon>
</view>
</view>
<view class="photo-add" @click="choosePhotos" v-if="recordForm.photos.length < 9">
<u-icon name="camera-fill" size="24" color="#cccccc"></u-icon>
<u-text text="添加图片" size="12" color="#cccccc"></u-text>
</view>
</view>
<u-text :text="`${recordForm.photos.length}/9`" size="12" color="#999" style="margin-top: 20rpx;"></u-text>
</view>
</u-card>
<!-- 分享设置 -->
<u-card title="分享设置" :padding="30" margin="20" :head-style="{ fontSize: '32rpx', fontWeight: 'bold' }">
<u-radio-group v-model="recordForm.shareLevel">
<view class="share-options">
<view class="share-option" v-for="option in shareOptions" :key="option.value">
<u-radio :name="option.value" :disabled="false">
<template #icon="{ checked }">
<u-icon :name="checked ? 'checkmark-circle-fill' : 'circle'" :color="checked ? '#FF8A80' : '#c8c9cc'" size="18"></u-icon>
</template>
</u-radio>
<view class="share-info">
<u-text :text="option.label" size="14" bold></u-text>
<u-text :text="option.desc" size="12" color="#999"></u-text>
</view>
</view>
</view>
</u-radio-group>
</u-card>
</u-form>
</view>
<!-- 日期选择器 -->
<u-datetime-picker
:show="showDatePicker"
v-model="selectedDate"
mode="datetime"
@confirm="confirmDate"
@cancel="showDatePicker = false"
></u-datetime-picker>
</view>
</template>
<script>
export default {
name: 'AddRecordSimple',
data() {
return {
petId: '',
showDatePicker: false,
selectedDate: new Date().getTime(),
recordForm: {
category: 'daily',
recordTime: '',
content: '',
photos: [],
shareLevel: 'family'
},
rules: {
recordTime: [
{ required: true, message: '请选择记录时间', trigger: 'blur' }
],
content: [
{ required: true, message: '请输入记录内容', trigger: 'blur' }
]
},
recordCategories: [
{ value: 'daily', label: '随手记', icon: 'edit-pen' },
{ value: 'milestone', label: '大事记', icon: 'star' },
{ value: 'health', label: '健康记录', icon: 'heart' },
{ value: 'grooming', label: '洗护记录', icon: 'flower' },
{ value: 'cleaning', label: '清洁记录', icon: 'home' },
{ value: 'expense', label: '消费记录', icon: 'rmb-circle' }
],
shareOptions: [
{ value: 'public', label: '公开', desc: '所有用户可见' },
{ value: 'family', label: '家人', desc: '仅家庭成员可见' },
{ value: 'private', label: '私有', desc: '仅自己可见' }
]
}
},
onLoad(options) {
this.petId = options.petId || '1'
this.recordForm.recordTime = this.formatDateTime(new Date())
},
methods: {
formatDateTime(date) {
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}`
},
selectCategory(category) {
this.recordForm.category = category
},
confirmDate(e) {
const date = new Date(e.value)
this.recordForm.recordTime = this.formatDateTime(date)
this.showDatePicker = false
},
choosePhotos() {
const remainingCount = 9 - this.recordForm.photos.length
uni.chooseImage({
count: remainingCount,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
this.recordForm.photos.push(...res.tempFilePaths)
},
fail: (err) => {
console.error('选择图片失败', err)
uni.showToast({
title: '选择图片失败',
icon: 'error'
})
}
})
},
removePhoto(index) {
this.recordForm.photos.splice(index, 1)
},
saveRecord() {
// 表单验证
if (!this.recordForm.recordTime) {
uni.showToast({
title: '请选择记录时间',
icon: 'error'
})
return
}
if (!this.recordForm.content.trim()) {
uni.showToast({
title: '请输入记录内容',
icon: 'error'
})
return
}
// 构建记录数据
const recordData = {
id: Date.now().toString(),
petId: this.petId,
category: this.recordForm.category,
recordTime: this.recordForm.recordTime,
content: this.recordForm.content,
photos: this.recordForm.photos,
shareLevel: this.recordForm.shareLevel,
createTime: new Date().toISOString()
}
// 模拟保存到本地存储
try {
let records = uni.getStorageSync('petRecords') || []
records.unshift(recordData)
uni.setStorageSync('petRecords', records)
uni.showToast({
title: '保存成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
console.error('保存记录失败', error)
uni.showToast({
title: '保存失败',
icon: 'error'
})
}
},
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.add-record-container {
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
min-height: 100vh;
}
.content-area {
padding-top: 20rpx;
padding-bottom: 40rpx;
}
.category-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20rpx;
}
.category-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
cursor: pointer;
transition: transform 0.2s ease;
&:active {
transform: scale(0.95);
}
}
.category-icon {
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.active {
background: #FF8A80;
}
}
.photo-upload-area {
.photo-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15rpx;
}
.photo-item {
position: relative;
.photo-delete {
position: absolute;
top: -8rpx;
right: -8rpx;
background-color: #ffffff;
border-radius: 50%;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
}
.photo-add {
width: 140rpx;
height: 140rpx;
border: 2rpx dashed #cccccc;
border-radius: 12rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8rpx;
}
}
.share-options {
.share-option {
display: flex;
align-items: center;
gap: 20rpx;
padding: 20rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.share-info {
flex: 1;
}
}
}
</style>