This commit is contained in:
yvan 2025-08-12 22:00:08 +08:00
parent 5877a1ee43
commit bd1c7a713f
8 changed files with 1880 additions and 447 deletions

View File

@ -12,18 +12,16 @@
"path": "pages/assistant/assistant",
"style": {
"navigationBarTitleText": "AI助手",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#64B5F6",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/assistant/knowledge",
"style": {
"navigationBarTitleText": "宠物知识库",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#81C784",
"navigationBarTextStyle": "white"
}
},
{
@ -54,9 +52,8 @@
"path": "pages/pets/add-pet",
"style": {
"navigationBarTitleText": "添加宠物",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
@ -64,26 +61,23 @@
"style": {
"navigationBarTitleText": "添加记录",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/pets/pet-chat",
"style": {
"navigationBarTitleText": "AI聊天",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#64B5F6",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/pet-chat-simple",
"style": {
"navigationBarTitleText": "AI聊天",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#64B5F6",
"navigationBarTextStyle": "white"
}
},
{
@ -91,35 +85,47 @@
"style": {
"navigationBarTitleText": "添加记录",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/pets/add-record-simple",
"style": {
"navigationBarTitleText": "添加记录",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/select-record-type",
"style": {
"navigationBarTitleText": "选择记录类型",
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/add-record-form",
"style": {
"navigationBarTitleText": "添加记录",
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/pet-records",
"style": {
"navigationBarTitleText": "宠物记录",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/pet-timeline",
"style": {
"navigationBarTitleText": "成长时光",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
"navigationBarBackgroundColor": "#FFB74D",
"navigationBarTextStyle": "white"
}
},
{

View File

@ -0,0 +1,672 @@
<template>
<view class="add-record-container">
<!-- 表单内容 -->
<view class="form-content">
<!-- 第一组基础信息 -->
<view class="form-group">
<!-- 记录宠物 -->
<view class="form-item" @click="selectPet">
<view class="form-label">记录宠物</view>
<view class="form-value">
<text class="value-text">{{ petInfo.name || '选择宠物' }}</text>
<u-icon name="arrow-right" size="14" color="#c0c4cc"></u-icon>
</view>
</view>
<view class="form-divider"></view>
<!-- 记录时间 -->
<view class="form-item" @click="showDatePicker = true">
<view class="form-label">记录时间</view>
<view class="form-value">
<text class="value-text">{{ recordForm.recordTime || '选择时间' }}</text>
<u-icon name="arrow-right" size="14" color="#c0c4cc"></u-icon>
</view>
</view>
</view>
<!-- 第二组记录详情 -->
<view class="form-group">
<!-- 记录类型 -->
<view class="form-item" @click="selectRecordType">
<view class="form-label">记录类型</view>
<view class="form-value">
<text class="value-text">{{ getTypeName(recordType) || '选择记录类型' }}</text>
<u-icon name="arrow-right" size="14" color="#c0c4cc"></u-icon>
</view>
</view>
<!-- 动态表单项 -->
<template v-if="recordType === 'weight'">
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">体重</view>
<view class="form-input">
<input
v-model="recordForm.weight"
placeholder="填写体重"
type="digit"
class="input-field"
/>
<text class="unit">kg</text>
</view>
</view>
</template>
<template v-if="recordType === 'food'">
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">食物类型</view>
<view class="form-input">
<input
v-model="recordForm.foodType"
placeholder="填写食物类型"
class="input-field"
/>
</view>
</view>
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">食量</view>
<view class="form-input">
<input
v-model="recordForm.amount"
placeholder="填写食量"
type="digit"
class="input-field"
/>
<text class="unit">g</text>
</view>
</view>
</template>
<template v-if="recordType === 'water'">
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">饮水量</view>
<view class="form-input">
<input
v-model="recordForm.waterAmount"
placeholder="填写饮水量"
type="digit"
class="input-field"
/>
<text class="unit">ml</text>
</view>
</view>
</template>
<template v-if="recordType === 'medicine'">
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">药物名称</view>
<view class="form-input">
<input
v-model="recordForm.medicineName"
placeholder="填写药物名称"
class="input-field"
/>
</view>
</view>
<view class="form-divider"></view>
<view class="form-item">
<view class="form-label">剂量</view>
<view class="form-input">
<input
v-model="recordForm.dosage"
placeholder="填写剂量"
class="input-field"
/>
</view>
</view>
</template>
</view>
<!-- 第三组描述和媒体 -->
<view class="form-group description-group">
<view class="form-label">描述</view>
<view class="description-input">
<textarea
v-model="recordForm.content"
placeholder="请输入你想要记录的内容~"
class="textarea-field"
maxlength="500"
></textarea>
</view>
<!-- 媒体上传按钮 -->
<view class="media-upload">
<view class="media-item" @click="chooseImage">
<u-icon name="camera" size="24" color="#999"></u-icon>
</view>
<view class="media-item" @click="chooseVideo">
<u-icon name="play-circle" size="24" color="#999"></u-icon>
</view>
</view>
</view>
<!-- 第四组分享设置 -->
<view class="form-group privacy-group">
<view class="privacy-item" @click="setShareLevel('public')">
<view class="radio-icon" :class="{ active: recordForm.shareLevel === 'public' }">
<view class="radio-inner" v-if="recordForm.shareLevel === 'public'"></view>
</view>
<text class="privacy-text">公开</text>
</view>
<view class="privacy-item" @click="setShareLevel('family')">
<view class="radio-icon" :class="{ active: recordForm.shareLevel === 'family' }">
<view class="radio-inner" v-if="recordForm.shareLevel === 'family'"></view>
</view>
<text class="privacy-text">家人可见</text>
</view>
<view class="privacy-item" @click="setShareLevel('private')">
<view class="radio-icon" :class="{ active: recordForm.shareLevel === 'private' }">
<view class="radio-inner" v-if="recordForm.shareLevel === 'private'"></view>
</view>
<text class="privacy-text">仅自己可见</text>
</view>
<text class="privacy-desc">{{ getShareLevelDesc() }}</text>
</view>
</view>
<!-- 保存按钮 -->
<view class="save-button-container">
<button class="save-button" @click="saveRecord">保存</button>
</view>
<!-- 日期时间选择器 -->
<u-datetime-picker
ref="datetimePicker"
v-model="showDatePicker"
mode="datetime"
@confirm="confirmDateTime"
@cancel="showDatePicker = false"
></u-datetime-picker>
</view>
</template>
<script>
export default {
data() {
return {
petId: '',
recordType: '',
showDatePicker: false,
petInfo: {},
recordForm: {
petId: '',
recordTime: '',
content: '',
photos: [],
videos: [],
shareLevel: 'family', // public, family, private
//
weight: '',
foodType: '',
amount: '',
waterAmount: '',
toiletType: 'urine',
medicineName: '',
dosage: ''
},
typeNames: {
'daily-note': '随手记',
'milestone': '大事记',
'weight': '体重记录',
'toilet': '尿便记录',
'food': '饮食记录',
'water': '饮水记录',
'exercise': '运动记录',
'supplement': '保健品记录',
'abnormal': '异常记录',
'deworming': '驱虫记录',
'vaccine': '疫苗记录',
'antiparasitic': '抗体水平',
'checkup': '体检记录',
'illness': '看病记录',
'medicine': '用药记录',
'hospital': '住院记录',
'surgery': '手术记录',
'bath': '洗澡记录',
'nail-trim': '剪指甲',
'ear-clean': '洗耳朵',
'teeth-clean': '刷牙记录',
'hair-trim': '梳毛记录',
'hair-cut': '剃毛记录',
'beauty': '美容记录',
'anal-gland': '挤肛门腺',
'eye-clean': '擦眼屎',
'disinfect': '消毒记录',
'clean': '清洁记录',
'change-sand': '换猫砂',
'wash-litter': '洗猫砂盆',
'wash-food-bowl': '洗食盆',
'wash-water-bowl': '洗水盆',
'wash-toy': '洗玩具',
'wash-cage': '洗笼子',
'change-filter': '换滤芯',
'change-pad': '换干燥剂'
}
}
},
onLoad(options) {
this.petId = options.petId || '1'
this.recordType = options.type || 'daily-note'
this.recordForm.petId = this.petId
//
this.loadPetInfo()
//
const now = new Date()
this.recordForm.recordTime = this.formatDateTime(now)
},
methods: {
loadPetInfo() {
try {
const pets = uni.getStorageSync('pets') || []
this.petInfo = pets.find(pet => pet.id == this.petId) || { name: '未知宠物' }
} catch (error) {
console.error('加载宠物信息失败', error)
this.petInfo = { name: '未知宠物' }
}
},
getTypeName(type) {
return this.typeNames[type] || ''
},
selectPet() {
//
uni.showToast({
title: '选择宠物功能开发中',
icon: 'none'
})
},
selectRecordType() {
//
uni.navigateBack()
},
formatDateTime(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return `${year}.${month}.${day} ${hours}:${minutes}`
},
confirmDateTime(e) {
this.recordForm.recordTime = this.formatDateTime(new Date(e.value))
this.showDatePicker = false
},
chooseImage() {
uni.chooseImage({
count: 9 - this.recordForm.photos.length,
sizeType: ['compressed'],
sourceType: ['camera', 'album'],
success: (res) => {
this.recordForm.photos.push(...res.tempFilePaths)
}
})
},
chooseVideo() {
uni.chooseVideo({
count: 1,
sourceType: ['camera', 'album'],
success: (res) => {
this.recordForm.videos.push(res.tempFilePath)
}
})
},
setShareLevel(level) {
this.recordForm.shareLevel = level
},
getShareLevelDesc() {
const descriptions = {
'public': '所有用户都可以看到这条记录',
'family': '仅家庭成员可以看到这条记录',
'private': '设置为仅自己可见后,本条记录对其家庭成员和朋友圈隐藏'
}
return descriptions[this.recordForm.shareLevel] || descriptions['family']
},
async saveRecord() {
//
if (!this.recordForm.recordTime) {
uni.showToast({
title: '请选择记录时间',
icon: 'none'
})
return
}
if (!this.recordForm.content && !this.hasTypeSpecificData()) {
uni.showToast({
title: '请填写记录内容',
icon: 'none'
})
return
}
try {
//
const recordData = {
id: Date.now(),
petId: this.recordForm.petId,
type: this.recordType,
recordTime: this.recordForm.recordTime,
content: this.recordForm.content,
photos: this.recordForm.photos,
videos: this.recordForm.videos,
shareLevel: this.recordForm.shareLevel,
createTime: new Date().toISOString(),
...this.getTypeSpecificData()
}
//
let records = uni.getStorageSync('petRecords') || []
records.unshift(recordData)
uni.setStorageSync('petRecords', records)
console.log('保存记录:', recordData)
uni.showToast({
title: '保存成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack({
delta: 2 //
})
}, 1500)
} catch (error) {
console.error('保存记录失败:', error)
uni.showToast({
title: '保存失败',
icon: 'error'
})
}
},
hasTypeSpecificData() {
switch (this.recordType) {
case 'weight':
return !!this.recordForm.weight
case 'food':
return !!this.recordForm.foodType || !!this.recordForm.amount
case 'water':
return !!this.recordForm.waterAmount
case 'medicine':
return !!this.recordForm.medicineName || !!this.recordForm.dosage
default:
return false
}
},
getTypeSpecificData() {
const data = {}
switch (this.recordType) {
case 'weight':
data.weight = this.recordForm.weight
break
case 'food':
data.foodType = this.recordForm.foodType
data.amount = this.recordForm.amount
break
case 'water':
data.waterAmount = this.recordForm.waterAmount
break
case 'toilet':
data.toiletType = this.recordForm.toiletType
break
case 'medicine':
data.medicineName = this.recordForm.medicineName
data.dosage = this.recordForm.dosage
break
}
return data
}
}
}
</script>
<style lang="scss" scoped>
.add-record-container {
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
min-height: 100vh;
padding-bottom: 120rpx;
}
.form-content {
padding: 30rpx;
}
.form-group {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10rpx);
border-radius: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.1);
overflow: hidden;
}
.form-item {
padding: 40rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
transition: all 0.3s ease;
&:active {
background: rgba(255, 138, 128, 0.05);
}
.form-label {
font-size: 32rpx;
color: #333333;
font-weight: 500;
}
.form-value {
display: flex;
align-items: center;
gap: 16rpx;
.value-text {
font-size: 32rpx;
color: #666666;
}
}
.form-input {
display: flex;
align-items: center;
gap: 16rpx;
flex: 1;
justify-content: flex-end;
.input-field {
text-align: right;
font-size: 32rpx;
color: #333333;
border: none;
outline: none;
background: transparent;
min-width: 200rpx;
&::placeholder {
color: #cccccc;
font-size: 32rpx;
}
}
.unit {
font-size: 32rpx;
color: #FF8A80;
font-weight: 500;
}
}
}
.form-divider {
height: 1rpx;
background: rgba(0, 0, 0, 0.05);
margin: 0 30rpx;
}
.description-group {
padding: 40rpx 30rpx;
.form-label {
font-size: 32rpx;
color: #333333;
font-weight: 500;
margin-bottom: 24rpx;
}
.description-input {
margin-bottom: 40rpx;
.textarea-field {
width: 100%;
min-height: 300rpx;
font-size: 32rpx;
color: #333333;
border: none;
outline: none;
background: transparent;
resize: none;
line-height: 1.6;
&::placeholder {
color: #cccccc;
font-size: 32rpx;
}
}
}
.media-upload {
display: flex;
gap: 40rpx;
.media-item {
width: 100rpx;
height: 100rpx;
background: rgba(255, 138, 128, 0.1);
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
background: rgba(255, 138, 128, 0.2);
}
}
}
}
.privacy-group {
padding: 40rpx 30rpx;
.privacy-item {
display: flex;
align-items: center;
gap: 20rpx;
padding: 16rpx 0;
transition: all 0.3s ease;
&:active {
background: rgba(255, 138, 128, 0.05);
border-radius: 12rpx;
margin: 0 -16rpx;
padding: 16rpx;
}
.radio-icon {
width: 36rpx;
height: 36rpx;
border: 3rpx solid #ddd;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.active {
border-color: #FF8A80;
background: #FF8A80;
}
.radio-inner {
width: 12rpx;
height: 12rpx;
background: #ffffff;
border-radius: 50%;
}
}
.privacy-text {
font-size: 32rpx;
color: #333333;
font-weight: 500;
}
}
.privacy-desc {
font-size: 26rpx;
color: #999999;
line-height: 1.6;
margin-left: 56rpx;
margin-top: 16rpx;
padding: 20rpx;
background: rgba(255, 138, 128, 0.05);
border-radius: 12rpx;
}
}
.save-button-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 30rpx;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20rpx);
border-top: 1rpx solid rgba(255, 138, 128, 0.1);
.save-button {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 50%, #FECFEF 100%);
color: #ffffff;
font-size: 36rpx;
font-weight: 600;
border: none;
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.4);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
background: linear-gradient(135deg, #FF7043 0%, #FF8A65 50%, #FFAB91 100%);
box-shadow: 0 4rpx 16rpx rgba(255, 138, 128, 0.6);
}
}
}
</style>

View File

@ -1,88 +1,90 @@
<template>
<view class="add-record-container">
<u-navbar title="添加记录" left-icon="arrow-left" @left-click="goBack">
<u-navbar title="添加记录" left-icon="arrow-left" @left-click="goBack" bg-color="#FF8A80">
<template #right>
<u-text text="保存" color="#ff6b6b" @click="saveRecord"></u-text>
<u-text text="保存" color="#ffffff" @click="saveRecord"></u-text>
</template>
</u-navbar>
<u-form ref="recordFormRef" :model="recordForm" :rules="rules" label-width="80">
<!-- 记录类型选择 -->
<u-card title="记录类型" :padding="20" margin="20">
<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' : '#666666'"></u-icon>
<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>
<u-text :text="category.label" size="12" :color="recordForm.category === category.value ? '#ff6b6b' : '#666666'"></u-text>
</view>
</view>
</u-card>
</u-card>
<!-- 基础信息 -->
<u-card title="基础信息" :padding="20" margin="20">
<u-form-item label="记录时间" prop="recordTime">
<u-input
v-model="recordForm.recordTime"
placeholder="选择记录时间"
readonly
@click="showDatePicker = true"
></u-input>
</u-form-item>
<!-- 基础信息 -->
<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-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="20" margin="20">
<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="80px" height="80px" border-radius="8px"></u-image>
<view class="photo-delete" @click="removePhoto(index)">
<u-icon name="close-circle-fill" size="16" color="#ff6b6b"></u-icon>
<!-- 图片上传 -->
<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>
<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>
<u-text :text="`${recordForm.photos.length}/9`" size="12" color="#999" style="margin-top: 20rpx;"></u-text>
</view>
<u-text :text="`${recordForm.photos.length}/9`" size="12" color="#999" style="margin-top: 10px;"></u-text>
</view>
</u-card>
</u-card>
<!-- 分享设置 -->
<u-card title="分享设置" :padding="20" margin="20">
<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 ? '#ff6b6b' : '#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>
<!-- 分享设置 -->
<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>
</view>
</u-radio-group>
</u-card>
</u-form>
</u-radio-group>
</u-card>
</u-form>
</view>
<!-- 日期选择器 -->
<u-datetime-picker
@ -242,37 +244,46 @@ export default {
<style lang="scss" scoped>
.add-record-container {
background-color: #f8f9fa;
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: 15px;
margin-top: 10px;
gap: 20rpx;
}
.category-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
gap: 12rpx;
cursor: pointer;
transition: transform 0.2s ease;
&:active {
transform: scale(0.95);
}
}
.category-icon {
width: 50px;
height: 50px;
border-radius: 25px;
background-color: #f5f5f5;
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.active {
background-color: #ff6b6b;
background: #FF8A80;
}
}
@ -280,31 +291,32 @@ export default {
.photo-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
gap: 15rpx;
}
.photo-item {
position: relative;
.photo-delete {
position: absolute;
top: -5px;
right: -5px;
top: -8rpx;
right: -8rpx;
background-color: #ffffff;
border-radius: 50%;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
}
.photo-add {
width: 80px;
height: 80px;
border: 2px dashed #cccccc;
border-radius: 8px;
width: 140rpx;
height: 140rpx;
border: 2rpx dashed #cccccc;
border-radius: 12rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 5px;
gap: 8rpx;
}
}
@ -312,14 +324,14 @@ export default {
.share-option {
display: flex;
align-items: center;
gap: 15px;
padding: 15px 0;
border-bottom: 1px solid #f0f0f0;
gap: 20rpx;
padding: 20rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.share-info {
flex: 1;
}

View File

@ -1,20 +1,25 @@
<template>
<view class="pet-chat-container">
<u-navbar :title="`与${petInfo.name}聊天`" left-icon="arrow-left" @left-click="goBack">
<template #right>
<u-icon name="more-circle" size="20" @click="showChatMenu"></u-icon>
</template>
</u-navbar>
<!-- 宠物信息卡片 -->
<view class="pet-info-card">
<u-avatar :src="petInfo.avatar || '/static/default-pet.png'" size="40" shape="circle"></u-avatar>
<view class="pet-info-text">
<u-text :text="petInfo.name" type="primary" size="14" bold></u-text>
<u-text :text="petInfo.personality" type="tips" size="12"></u-text>
</view>
<view class="chat-status">
<u-tag text="在线" type="success" size="mini"></u-tag>
<!-- 聊天头部 -->
<view class="chat-header">
<view class="header-content">
<view class="back-button" @click="goBack">
<u-icon name="arrow-left" size="18" color="#ffffff"></u-icon>
</view>
<view class="pet-info">
<view class="pet-avatar">
<image :src="petInfo.avatar || '/static/default-pet.png'" class="avatar-img"></image>
</view>
<view class="pet-details">
<text class="pet-name">{{ petInfo.name }}聊天</text>
<text class="pet-status">在线</text>
</view>
</view>
<view class="header-actions">
<view class="action-button" @click="showChatMenu">
<u-icon name="more-dot-fill" size="18" color="#ffffff"></u-icon>
</view>
</view>
</view>
</view>

View File

@ -181,7 +181,7 @@ export default {
addRecord() {
uni.navigateTo({
url: `/pages/pets/add-record-simple?petId=${this.petId}`
url: `/pages/pets/select-record-type?petId=${this.petId}`
})
},

View File

@ -394,7 +394,7 @@ export default {
//
const addRecord = () => {
uni.navigateTo({
url: `/pages/pets/add-record-enhanced?petId=${state.petId}`
url: `/pages/pets/select-record-type?petId=${state.petId}`
})
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,302 @@
<template>
<view class="select-type-container">
<view class="content-area">
<!-- 快捷记录 -->
<view class="section">
<view class="section-header">
<view class="section-line"></view>
<text class="section-title">快捷记录</text>
</view>
<view class="type-grid">
<view class="type-item" @click="selectType('daily-note')">
<view class="type-icon">📝</view>
<text class="type-name">随手记</text>
</view>
<view class="type-item" @click="selectType('milestone')">
<view class="type-icon"></view>
<text class="type-name">大事记</text>
</view>
</view>
</view>
<!-- 日常记录 -->
<view class="section">
<view class="section-header">
<view class="section-line"></view>
<text class="section-title">日常记录</text>
</view>
<view class="type-grid">
<view class="type-item" @click="selectType('weight')">
<view class="type-icon"></view>
<text class="type-name">体重</text>
</view>
<view class="type-item" @click="selectType('toilet')">
<view class="type-icon">🚽</view>
<text class="type-name">尿便</text>
</view>
<view class="type-item" @click="selectType('food')">
<view class="type-icon">🍽</view>
<text class="type-name">饮食</text>
</view>
<view class="type-item" @click="selectType('water')">
<view class="type-icon">💧</view>
<text class="type-name">喝水</text>
</view>
<view class="type-item" @click="selectType('exercise')">
<view class="type-icon">🏃</view>
<text class="type-name">运动</text>
</view>
</view>
</view>
<!-- 健康记录 -->
<view class="section">
<view class="section-header">
<view class="section-line"></view>
<text class="section-title">健康记录</text>
</view>
<view class="type-grid">
<view class="type-item" @click="selectType('supplement')">
<view class="type-icon">💊</view>
<text class="type-name">保健品</text>
</view>
<view class="type-item" @click="selectType('abnormal')">
<view class="type-icon"></view>
<text class="type-name">异常</text>
</view>
<view class="type-item" @click="selectType('deworming')">
<view class="type-icon">🐛</view>
<text class="type-name">驱虫</text>
</view>
<view class="type-item" @click="selectType('vaccine')">
<view class="type-icon">💉</view>
<text class="type-name">疫苗</text>
</view>
<view class="type-item" @click="selectType('antiparasitic')">
<view class="type-icon">🛡</view>
<text class="type-name">抗体水平</text>
</view>
<view class="type-item" @click="selectType('checkup')">
<view class="type-icon">🩺</view>
<text class="type-name">体检</text>
</view>
<view class="type-item" @click="selectType('illness')">
<view class="type-icon">🤒</view>
<text class="type-name">看病</text>
</view>
<view class="type-item" @click="selectType('medicine')">
<view class="type-icon">💊</view>
<text class="type-name">给药</text>
</view>
<view class="type-item" @click="selectType('hospital')">
<view class="type-icon">🏥</view>
<text class="type-name">住院</text>
</view>
<view class="type-item" @click="selectType('surgery')">
<view class="type-icon">🔪</view>
<text class="type-name">手术</text>
</view>
</view>
</view>
<!-- 洗护记录 -->
<view class="section">
<view class="section-header">
<view class="section-line"></view>
<text class="section-title">洗护记录</text>
</view>
<view class="type-grid">
<view class="type-item" @click="selectType('bath')">
<view class="type-icon">🛁</view>
<text class="type-name">洗澡</text>
</view>
<view class="type-item" @click="selectType('nail-trim')">
<view class="type-icon"></view>
<text class="type-name">剪指甲</text>
</view>
<view class="type-item" @click="selectType('ear-clean')">
<view class="type-icon">👂</view>
<text class="type-name">洗耳朵</text>
</view>
<view class="type-item" @click="selectType('teeth-clean')">
<view class="type-icon">🦷</view>
<text class="type-name">刷牙</text>
</view>
<view class="type-item" @click="selectType('hair-trim')">
<view class="type-icon">💇</view>
<text class="type-name">梳毛</text>
</view>
<view class="type-item" @click="selectType('hair-cut')">
<view class="type-icon"></view>
<text class="type-name">剃毛毛</text>
</view>
<view class="type-item" @click="selectType('beauty')">
<view class="type-icon">💅</view>
<text class="type-name">美容</text>
</view>
<view class="type-item" @click="selectType('anal-gland')">
<view class="type-icon">🍑</view>
<text class="type-name">挤肛门腺</text>
</view>
<view class="type-item" @click="selectType('eye-clean')">
<view class="type-icon">👁</view>
<text class="type-name">擦眼屎</text>
</view>
</view>
</view>
<!-- 清洁记录 -->
<view class="section">
<view class="section-header">
<view class="section-line"></view>
<text class="section-title">清洁记录</text>
</view>
<view class="type-grid">
<view class="type-item" @click="selectType('disinfect')">
<view class="type-icon">🧴</view>
<text class="type-name">消毒</text>
</view>
<view class="type-item" @click="selectType('clean')">
<view class="type-icon">🧽</view>
<text class="type-name">清洁</text>
</view>
<view class="type-item" @click="selectType('change-sand')">
<view class="type-icon">📦</view>
<text class="type-name">换猫砂</text>
</view>
<view class="type-item" @click="selectType('wash-litter')">
<view class="type-icon">🧼</view>
<text class="type-name">洗猫砂盆</text>
</view>
<view class="type-item" @click="selectType('wash-food-bowl')">
<view class="type-icon">🍽</view>
<text class="type-name">洗食盆</text>
</view>
<view class="type-item" @click="selectType('wash-water-bowl')">
<view class="type-icon">💧</view>
<text class="type-name">洗水盆</text>
</view>
<view class="type-item" @click="selectType('wash-toy')">
<view class="type-icon">🧸</view>
<text class="type-name">洗玩具</text>
</view>
<view class="type-item" @click="selectType('wash-cage')">
<view class="type-icon">🏠</view>
<text class="type-name">洗笼子</text>
</view>
<view class="type-item" @click="selectType('change-filter')">
<view class="type-icon">🔄</view>
<text class="type-name">换滤芯</text>
</view>
<view class="type-item" @click="selectType('change-pad')">
<view class="type-icon">🛏</view>
<text class="type-name">换干燥剂</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
petId: ''
}
},
onLoad(options) {
this.petId = options.petId || '1'
},
methods: {
goBack() {
uni.navigateBack()
},
selectType(type) {
//
uni.navigateTo({
url: `/pages/pets/add-record-form?petId=${this.petId}&type=${type}`
})
}
}
}
</script>
<style lang="scss" scoped>
.select-type-container {
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
min-height: 100vh;
padding-bottom: env(safe-area-inset-bottom);
}
.content-area {
padding: 20rpx 30rpx 60rpx;
min-height: calc(100vh - 88rpx); /* 减去导航栏高度 */
box-sizing: border-box;
}
.section {
margin-bottom: 60rpx;
}
.section-header {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.section-line {
width: 8rpx;
height: 32rpx;
background: #FF8A80;
border-radius: 4rpx;
margin-right: 20rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.type-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
}
.type-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12rpx;
padding: 24rpx 16rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 20rpx;
backdrop-filter: blur(10rpx);
transition: all 0.3s ease;
min-height: 140rpx;
box-sizing: border-box;
&:active {
transform: scale(0.95);
background: rgba(255, 138, 128, 0.2);
}
}
.type-icon {
font-size: 40rpx;
line-height: 1;
}
.type-name {
font-size: 22rpx;
color: #333;
font-weight: 500;
text-align: center;
line-height: 1.2;
word-break: keep-all;
}
</style>