1
This commit is contained in:
@@ -0,0 +1,761 @@
|
||||
<template>
|
||||
<view class="health-charts-container">
|
||||
<!-- 自定义导航栏 -->
|
||||
<u-navbar :title="`${petInfo.name}的健康档案`" left-icon="arrow-left" @left-click="goBack">
|
||||
<template #right>
|
||||
<u-icon name="more-circle" size="20" @click="showMoreActions = true"></u-icon>
|
||||
</template>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 宠物基本信息卡片 -->
|
||||
<view class="pet-info-card">
|
||||
<u-avatar :src="petInfo.avatar || '/static/default-pet.png'" size="60" shape="circle"></u-avatar>
|
||||
<view class="pet-info">
|
||||
<text class="pet-name">{{ petInfo.name }}</text>
|
||||
<text class="pet-details">{{ petInfo.breed }} · {{ petInfo.age }}岁</text>
|
||||
<view class="health-status" :class="petInfo.healthStatus || 'healthy'">
|
||||
<u-icon :name="getHealthIcon(petInfo.healthStatus)" size="12" color="#ffffff"></u-icon>
|
||||
<text class="status-text">{{ getHealthText(petInfo.healthStatus) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 健康指标切换 -->
|
||||
<view class="chart-tabs">
|
||||
<u-tabs
|
||||
:list="chartTabs"
|
||||
:current="currentTab"
|
||||
@change="onTabChange"
|
||||
line-color="#FF8A80"
|
||||
active-color="#FF8A80"
|
||||
inactive-color="#999999"
|
||||
></u-tabs>
|
||||
</view>
|
||||
|
||||
<!-- 图表内容区域 -->
|
||||
<view class="chart-content">
|
||||
<!-- 体重趋势图 -->
|
||||
<view class="chart-section" v-if="currentTab === 0">
|
||||
<view class="chart-header">
|
||||
<text class="chart-title">体重趋势</text>
|
||||
<text class="chart-subtitle">最近6个月</text>
|
||||
</view>
|
||||
<view class="chart-container">
|
||||
<canvas
|
||||
canvas-id="weightChart"
|
||||
id="weightChart"
|
||||
class="chart-canvas"
|
||||
@touchstart="touchChart"
|
||||
@touchmove="touchChart"
|
||||
@touchend="touchChart"
|
||||
></canvas>
|
||||
</view>
|
||||
<view class="chart-stats">
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">当前体重</text>
|
||||
<text class="stat-value">{{ currentWeight }}kg</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">体重变化</text>
|
||||
<text class="stat-value" :class="weightChange >= 0 ? 'positive' : 'negative'">
|
||||
{{ weightChange >= 0 ? '+' : '' }}{{ weightChange }}kg
|
||||
</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-label">理想体重</text>
|
||||
<text class="stat-value">{{ idealWeight }}kg</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 健康指标雷达图 -->
|
||||
<view class="chart-section" v-if="currentTab === 1">
|
||||
<view class="chart-header">
|
||||
<text class="chart-title">健康指标</text>
|
||||
<text class="chart-subtitle">综合评估</text>
|
||||
</view>
|
||||
<view class="chart-container">
|
||||
<canvas
|
||||
canvas-id="healthRadar"
|
||||
id="healthRadar"
|
||||
class="chart-canvas"
|
||||
></canvas>
|
||||
</view>
|
||||
<view class="health-indicators">
|
||||
<view class="indicator-item" v-for="indicator in healthIndicators" :key="indicator.name">
|
||||
<view class="indicator-info">
|
||||
<text class="indicator-name">{{ indicator.name }}</text>
|
||||
<text class="indicator-score">{{ indicator.score }}/10</text>
|
||||
</view>
|
||||
<view class="indicator-bar">
|
||||
<view class="indicator-progress" :style="{ width: indicator.score * 10 + '%' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 疫苗接种时间轴 -->
|
||||
<view class="chart-section" v-if="currentTab === 2">
|
||||
<view class="chart-header">
|
||||
<text class="chart-title">疫苗接种</text>
|
||||
<text class="chart-subtitle">接种记录与计划</text>
|
||||
</view>
|
||||
<view class="vaccine-timeline">
|
||||
<view class="timeline-item" v-for="vaccine in vaccineRecords" :key="vaccine.id">
|
||||
<view class="timeline-dot" :class="vaccine.status"></view>
|
||||
<view class="timeline-content">
|
||||
<text class="vaccine-name">{{ vaccine.name }}</text>
|
||||
<text class="vaccine-date">{{ vaccine.date }}</text>
|
||||
<text class="vaccine-status">{{ vaccine.statusText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 体检记录 -->
|
||||
<view class="chart-section" v-if="currentTab === 3">
|
||||
<view class="chart-header">
|
||||
<text class="chart-title">体检记录</text>
|
||||
<text class="chart-subtitle">健康检查历史</text>
|
||||
</view>
|
||||
<view class="checkup-list">
|
||||
<view class="checkup-item" v-for="checkup in checkupRecords" :key="checkup.id">
|
||||
<view class="checkup-date">
|
||||
<text class="date-text">{{ checkup.date }}</text>
|
||||
</view>
|
||||
<view class="checkup-info">
|
||||
<text class="checkup-type">{{ checkup.type }}</text>
|
||||
<text class="checkup-result">{{ checkup.result }}</text>
|
||||
<text class="checkup-note" v-if="checkup.note">{{ checkup.note }}</text>
|
||||
</view>
|
||||
<view class="checkup-status" :class="checkup.status">
|
||||
<u-icon :name="getCheckupIcon(checkup.status)" size="16" color="#ffffff"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 添加记录按钮 -->
|
||||
<view class="add-record-btn" @click="addHealthRecord">
|
||||
<u-icon name="plus" size="20" color="#ffffff"></u-icon>
|
||||
</view>
|
||||
|
||||
<!-- 更多操作弹窗 -->
|
||||
<u-popup v-model="showMoreActions" mode="bottom" border-radius="20">
|
||||
<view class="more-actions-popup">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">更多操作</text>
|
||||
<u-icon name="close" size="20" @click="showMoreActions = false"></u-icon>
|
||||
</view>
|
||||
<view class="action-list">
|
||||
<view class="action-item" @click="exportHealthData">
|
||||
<u-icon name="share" size="24" color="#64B5F6"></u-icon>
|
||||
<text class="action-text">导出健康数据</text>
|
||||
</view>
|
||||
<view class="action-item" @click="setHealthReminder">
|
||||
<u-icon name="bell" size="24" color="#FFB74D"></u-icon>
|
||||
<text class="action-text">设置健康提醒</text>
|
||||
</view>
|
||||
<view class="action-item" @click="consultVet">
|
||||
<u-icon name="phone" size="24" color="#81C784"></u-icon>
|
||||
<text class="action-text">咨询兽医</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 引入uCharts图表库
|
||||
import uCharts from '@/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
petId: '',
|
||||
petInfo: {},
|
||||
currentTab: 0,
|
||||
showMoreActions: false,
|
||||
chartTabs: [
|
||||
{ name: '体重趋势' },
|
||||
{ name: '健康指标' },
|
||||
{ name: '疫苗接种' },
|
||||
{ name: '体检记录' }
|
||||
],
|
||||
// 体重相关数据
|
||||
currentWeight: 4.5,
|
||||
weightChange: 0.2,
|
||||
idealWeight: 4.3,
|
||||
weightData: [],
|
||||
// 健康指标数据
|
||||
healthIndicators: [
|
||||
{ name: '食欲', score: 9 },
|
||||
{ name: '精神状态', score: 8 },
|
||||
{ name: '毛发光泽', score: 7 },
|
||||
{ name: '活动量', score: 8 },
|
||||
{ name: '睡眠质量', score: 9 }
|
||||
],
|
||||
// 疫苗记录
|
||||
vaccineRecords: [
|
||||
{
|
||||
id: 1,
|
||||
name: '三联疫苗',
|
||||
date: '2024-01-15',
|
||||
status: 'completed',
|
||||
statusText: '已接种'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '狂犬疫苗',
|
||||
date: '2024-02-15',
|
||||
status: 'completed',
|
||||
statusText: '已接种'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '三联疫苗加强',
|
||||
date: '2024-07-15',
|
||||
status: 'upcoming',
|
||||
statusText: '即将到期'
|
||||
}
|
||||
],
|
||||
// 体检记录
|
||||
checkupRecords: [
|
||||
{
|
||||
id: 1,
|
||||
date: '2024-01-10',
|
||||
type: '常规体检',
|
||||
result: '健康状况良好',
|
||||
note: '建议定期驱虫',
|
||||
status: 'normal'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
date: '2023-12-05',
|
||||
type: '血液检查',
|
||||
result: '各项指标正常',
|
||||
status: 'normal'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.petId = options.petId || '1'
|
||||
this.loadPetInfo()
|
||||
this.loadHealthData()
|
||||
},
|
||||
onReady() {
|
||||
this.$nextTick(() => {
|
||||
this.initWeightChart()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
loadPetInfo() {
|
||||
// 模拟加载宠物信息
|
||||
const mockPets = [
|
||||
{
|
||||
id: '1',
|
||||
name: '小橘',
|
||||
breed: '橘猫',
|
||||
age: 2,
|
||||
avatar: '/static/default-pet.png',
|
||||
healthStatus: 'healthy'
|
||||
}
|
||||
]
|
||||
this.petInfo = mockPets.find(pet => pet.id === this.petId) || mockPets[0]
|
||||
},
|
||||
|
||||
loadHealthData() {
|
||||
// 模拟加载健康数据
|
||||
this.weightData = [
|
||||
{ date: '2023-08', weight: 4.1 },
|
||||
{ date: '2023-09', weight: 4.2 },
|
||||
{ date: '2023-10', weight: 4.3 },
|
||||
{ date: '2023-11', weight: 4.4 },
|
||||
{ date: '2023-12', weight: 4.3 },
|
||||
{ date: '2024-01', weight: 4.5 }
|
||||
]
|
||||
},
|
||||
|
||||
initWeightChart() {
|
||||
// 初始化体重趋势图
|
||||
const ctx = uni.createCanvasContext('weightChart', this)
|
||||
// 这里应该使用uCharts库绘制图表
|
||||
// 由于篇幅限制,这里只是示例代码
|
||||
},
|
||||
|
||||
onTabChange(index) {
|
||||
this.currentTab = index
|
||||
this.$nextTick(() => {
|
||||
if (index === 0) {
|
||||
this.initWeightChart()
|
||||
} else if (index === 1) {
|
||||
this.initHealthRadar()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
initHealthRadar() {
|
||||
// 初始化健康指标雷达图
|
||||
const ctx = uni.createCanvasContext('healthRadar', this)
|
||||
// 雷达图绘制逻辑
|
||||
},
|
||||
|
||||
getHealthIcon(status) {
|
||||
const iconMap = {
|
||||
healthy: 'checkmark',
|
||||
warning: 'warning',
|
||||
sick: 'close'
|
||||
}
|
||||
return iconMap[status] || 'checkmark'
|
||||
},
|
||||
|
||||
getHealthText(status) {
|
||||
const textMap = {
|
||||
healthy: '健康',
|
||||
warning: '注意',
|
||||
sick: '生病'
|
||||
}
|
||||
return textMap[status] || '健康'
|
||||
},
|
||||
|
||||
getCheckupIcon(status) {
|
||||
const iconMap = {
|
||||
normal: 'checkmark',
|
||||
warning: 'warning',
|
||||
abnormal: 'close'
|
||||
}
|
||||
return iconMap[status] || 'checkmark'
|
||||
},
|
||||
|
||||
addHealthRecord() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/add-health-record?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
exportHealthData() {
|
||||
this.showMoreActions = false
|
||||
uni.showToast({
|
||||
title: '导出功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
setHealthReminder() {
|
||||
this.showMoreActions = false
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/health-reminder?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
consultVet() {
|
||||
this.showMoreActions = false
|
||||
uni.navigateTo({
|
||||
url: '/pages/assistant/assistant'
|
||||
})
|
||||
},
|
||||
|
||||
touchChart(e) {
|
||||
// 处理图表触摸事件
|
||||
},
|
||||
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.health-charts-container {
|
||||
background: linear-gradient(135deg, #FFF8F0 0%, #F8F9FA 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 宠物信息卡片 */
|
||||
.pet-info-card {
|
||||
background: #ffffff;
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.pet-info {
|
||||
margin-left: 24rpx;
|
||||
flex: 1;
|
||||
|
||||
.pet-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.pet-details {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.health-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
width: fit-content;
|
||||
|
||||
&.healthy {
|
||||
background: #81C784;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background: #FFB74D;
|
||||
}
|
||||
|
||||
&.sick {
|
||||
background: #FF8A80;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 22rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 图表切换标签 */
|
||||
.chart-tabs {
|
||||
background: #ffffff;
|
||||
margin: 0 20rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 图表内容区域 */
|
||||
.chart-content {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.chart-section {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.chart-header {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.chart-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chart-subtitle {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 400rpx;
|
||||
position: relative;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.chart-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding-top: 20rpx;
|
||||
border-top: 2rpx solid #F5F5F5;
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
|
||||
&.positive {
|
||||
color: #81C784;
|
||||
}
|
||||
|
||||
&.negative {
|
||||
color: #FF8A80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 健康指标 */
|
||||
.health-indicators {
|
||||
.indicator-item {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.indicator-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.indicator-name {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.indicator-score {
|
||||
font-size: 24rpx;
|
||||
color: #FF8A80;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator-bar {
|
||||
height: 8rpx;
|
||||
background: #F5F5F5;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.indicator-progress {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #FF8A80, #81C784);
|
||||
border-radius: 4rpx;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 疫苗时间轴 */
|
||||
.vaccine-timeline {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 4rpx;
|
||||
background: #E0E0E0;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 40rpx;
|
||||
position: relative;
|
||||
|
||||
.timeline-dot {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 24rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
&.completed {
|
||||
background: #81C784;
|
||||
}
|
||||
|
||||
&.upcoming {
|
||||
background: #FFB74D;
|
||||
}
|
||||
|
||||
&.overdue {
|
||||
background: #FF8A80;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
flex: 1;
|
||||
|
||||
.vaccine-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.vaccine-date {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.vaccine-status {
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 体检记录 */
|
||||
.checkup-list {
|
||||
.checkup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 2rpx solid #F5F5F5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.checkup-date {
|
||||
width: 120rpx;
|
||||
margin-right: 24rpx;
|
||||
|
||||
.date-text {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.checkup-info {
|
||||
flex: 1;
|
||||
|
||||
.checkup-type {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.checkup-result {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.checkup-note {
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.checkup-status {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.normal {
|
||||
background: #81C784;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background: #FFB74D;
|
||||
}
|
||||
|
||||
&.abnormal {
|
||||
background: #FF8A80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 添加记录按钮 */
|
||||
.add-record-btn {
|
||||
position: fixed;
|
||||
right: 30rpx;
|
||||
bottom: 120rpx;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
background: linear-gradient(135deg, #FF8A80, #FFB74D);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.4);
|
||||
z-index: 100;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
/* 更多操作弹窗 */
|
||||
.more-actions-popup {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
padding: 40rpx 30rpx 60rpx;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.action-list {
|
||||
.action-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 2rpx solid #F5F5F5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #F8F9FA;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+131
-10
@@ -51,10 +51,69 @@
|
||||
</u-card>
|
||||
|
||||
<u-gap height="20"></u-gap>
|
||||
|
||||
<view class="action-buttons">
|
||||
<u-button type="primary" text="添加记录" @click="addRecord"></u-button>
|
||||
<u-button type="warning" text="AI聊天" @click="chatWithPet"></u-button>
|
||||
|
||||
<!-- 性格标签展示 -->
|
||||
<u-card title="性格特征" :padding="20" v-if="petInfo.personality && petInfo.personality.length > 0">
|
||||
<view class="personality-tags">
|
||||
<u-tag
|
||||
v-for="tag in petInfo.personality"
|
||||
:key="tag"
|
||||
:text="tag"
|
||||
type="primary"
|
||||
size="small"
|
||||
plain
|
||||
></u-tag>
|
||||
</view>
|
||||
<u-button
|
||||
text="重新设置性格"
|
||||
type="info"
|
||||
size="mini"
|
||||
plain
|
||||
@click="setPersonality"
|
||||
style="margin-top: 20rpx;"
|
||||
></u-button>
|
||||
</u-card>
|
||||
|
||||
<u-card title="性格设置" :padding="20" v-else>
|
||||
<u-empty mode="data" text="还未设置宠物性格" :show="true">
|
||||
<template #bottom>
|
||||
<u-button type="primary" text="设置性格特征" size="mini" @click="setPersonality"></u-button>
|
||||
</template>
|
||||
</u-empty>
|
||||
</u-card>
|
||||
|
||||
<u-gap height="20"></u-gap>
|
||||
|
||||
<!-- 快捷功能按钮 -->
|
||||
<view class="quick-actions">
|
||||
<view class="action-row">
|
||||
<view class="action-item" @click="addRecord">
|
||||
<u-icon name="edit-pen" size="24" color="#81C784"></u-icon>
|
||||
<text class="action-text">添加记录</text>
|
||||
</view>
|
||||
<view class="action-item" @click="chatWithPet">
|
||||
<u-icon name="chat" size="24" color="#64B5F6"></u-icon>
|
||||
<text class="action-text">AI聊天</text>
|
||||
</view>
|
||||
<view class="action-item" @click="viewHealth">
|
||||
<u-icon name="heart" size="24" color="#FF8A80"></u-icon>
|
||||
<text class="action-text">健康档案</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="action-row">
|
||||
<view class="action-item" @click="viewTimeline">
|
||||
<u-icon name="clock" size="24" color="#FFB74D"></u-icon>
|
||||
<text class="action-text">成长时光</text>
|
||||
</view>
|
||||
<view class="action-item" @click="viewRecords">
|
||||
<u-icon name="list" size="24" color="#9C27B0"></u-icon>
|
||||
<text class="action-text">所有记录</text>
|
||||
</view>
|
||||
<view class="action-item" @click="shareProfile">
|
||||
<u-icon name="share" size="24" color="#FF9800"></u-icon>
|
||||
<text class="action-text">分享档案</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -134,7 +193,32 @@ export default {
|
||||
|
||||
viewHealth() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/health-record?petId=${this.petId}`
|
||||
url: `/pages/pets/health-charts?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
setPersonality() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/pet-personality?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
viewTimeline() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/pet-timeline?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
viewRecords() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/pets/pet-records?petId=${this.petId}`
|
||||
})
|
||||
},
|
||||
|
||||
shareProfile() {
|
||||
uni.showToast({
|
||||
title: '分享功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -200,13 +284,50 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
padding: 30rpx;
|
||||
/* 性格标签 */
|
||||
.personality-tags {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
:deep(.u-button) {
|
||||
flex: 1;
|
||||
/* 快捷功能按钮 */
|
||||
.quick-actions {
|
||||
background: #ffffff;
|
||||
margin: 0 30rpx;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.action-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
padding: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
transition: all 0.3s ease;
|
||||
min-width: 120rpx;
|
||||
|
||||
&:active {
|
||||
background: #F5F5F5;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,761 @@
|
||||
<template>
|
||||
<view class="personality-container">
|
||||
<!-- 自定义导航栏 -->
|
||||
<u-navbar title="宠物性格预设" left-icon="arrow-left" @left-click="goBack">
|
||||
<template #right>
|
||||
<u-icon name="question-circle" size="20" @click="showHelp = true"></u-icon>
|
||||
</template>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 进度指示器 -->
|
||||
<view class="progress-container">
|
||||
<view class="progress-bar">
|
||||
<view class="progress-fill" :style="{ width: (currentStep / totalSteps) * 100 + '%' }"></view>
|
||||
</view>
|
||||
<text class="progress-text">{{ currentStep }}/{{ totalSteps }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 问卷内容 -->
|
||||
<view class="questionnaire-content">
|
||||
<!-- 第一步:基本性格倾向 -->
|
||||
<view class="question-section" v-if="currentStep === 1">
|
||||
<view class="question-header">
|
||||
<text class="question-title">🐾 基本性格倾向</text>
|
||||
<text class="question-subtitle">选择最符合你家宠物的描述</text>
|
||||
</view>
|
||||
<view class="options-grid">
|
||||
<view
|
||||
class="option-card"
|
||||
v-for="option in basicPersonalityOptions"
|
||||
:key="option.value"
|
||||
:class="{ active: selectedAnswers.basicPersonality === option.value }"
|
||||
@click="selectOption('basicPersonality', option.value)"
|
||||
>
|
||||
<text class="option-emoji">{{ option.emoji }}</text>
|
||||
<text class="option-title">{{ option.title }}</text>
|
||||
<text class="option-desc">{{ option.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 第二步:社交倾向 -->
|
||||
<view class="question-section" v-if="currentStep === 2">
|
||||
<view class="question-header">
|
||||
<text class="question-title">👥 社交倾向</text>
|
||||
<text class="question-subtitle">你的宠物对人和其他动物的态度</text>
|
||||
</view>
|
||||
<view class="options-grid">
|
||||
<view
|
||||
class="option-card"
|
||||
v-for="option in socialOptions"
|
||||
:key="option.value"
|
||||
:class="{ active: selectedAnswers.social === option.value }"
|
||||
@click="selectOption('social', option.value)"
|
||||
>
|
||||
<text class="option-emoji">{{ option.emoji }}</text>
|
||||
<text class="option-title">{{ option.title }}</text>
|
||||
<text class="option-desc">{{ option.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 第三步:活动水平 -->
|
||||
<view class="question-section" v-if="currentStep === 3">
|
||||
<view class="question-header">
|
||||
<text class="question-title">⚡ 活动水平</text>
|
||||
<text class="question-subtitle">你的宠物平时的活跃程度</text>
|
||||
</view>
|
||||
<view class="options-grid">
|
||||
<view
|
||||
class="option-card"
|
||||
v-for="option in activityOptions"
|
||||
:key="option.value"
|
||||
:class="{ active: selectedAnswers.activity === option.value }"
|
||||
@click="selectOption('activity', option.value)"
|
||||
>
|
||||
<text class="option-emoji">{{ option.emoji }}</text>
|
||||
<text class="option-title">{{ option.title }}</text>
|
||||
<text class="option-desc">{{ option.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 第四步:特殊习惯 -->
|
||||
<view class="question-section" v-if="currentStep === 4">
|
||||
<view class="question-header">
|
||||
<text class="question-title">🎯 特殊习惯</text>
|
||||
<text class="question-subtitle">选择你的宠物具有的特殊习惯(可多选)</text>
|
||||
</view>
|
||||
<view class="habits-grid">
|
||||
<view
|
||||
class="habit-tag"
|
||||
v-for="habit in habitOptions"
|
||||
:key="habit.value"
|
||||
:class="{ active: selectedAnswers.habits.includes(habit.value) }"
|
||||
@click="toggleHabit(habit.value)"
|
||||
>
|
||||
<text class="habit-emoji">{{ habit.emoji }}</text>
|
||||
<text class="habit-text">{{ habit.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 第五步:性格结果 -->
|
||||
<view class="result-section" v-if="currentStep === 5">
|
||||
<view class="result-header">
|
||||
<text class="result-title">🎉 性格分析完成</text>
|
||||
<text class="result-subtitle">为你的宠物生成了专属性格档案</text>
|
||||
</view>
|
||||
<view class="personality-result">
|
||||
<view class="personality-type">
|
||||
<text class="type-emoji">{{ personalityResult.emoji }}</text>
|
||||
<text class="type-name">{{ personalityResult.typeName }}</text>
|
||||
</view>
|
||||
<view class="personality-description">
|
||||
<text class="desc-text">{{ personalityResult.description }}</text>
|
||||
</view>
|
||||
<view class="personality-tags">
|
||||
<u-tag
|
||||
v-for="tag in personalityResult.tags"
|
||||
:key="tag"
|
||||
:text="tag"
|
||||
type="primary"
|
||||
size="small"
|
||||
plain
|
||||
></u-tag>
|
||||
</view>
|
||||
<view class="care-suggestions">
|
||||
<text class="suggestions-title">💡 饲养建议</text>
|
||||
<view class="suggestion-item" v-for="suggestion in personalityResult.suggestions" :key="suggestion">
|
||||
<text class="suggestion-text">• {{ suggestion }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions">
|
||||
<u-button
|
||||
v-if="currentStep > 1 && currentStep < 5"
|
||||
text="上一步"
|
||||
type="info"
|
||||
plain
|
||||
@click="prevStep"
|
||||
></u-button>
|
||||
<u-button
|
||||
v-if="currentStep < 4"
|
||||
text="下一步"
|
||||
type="primary"
|
||||
:disabled="!canProceed"
|
||||
@click="nextStep"
|
||||
></u-button>
|
||||
<u-button
|
||||
v-if="currentStep === 4"
|
||||
text="生成性格档案"
|
||||
type="primary"
|
||||
:disabled="!canProceed"
|
||||
@click="generatePersonality"
|
||||
></u-button>
|
||||
<u-button
|
||||
v-if="currentStep === 5"
|
||||
text="保存并完成"
|
||||
type="primary"
|
||||
@click="savePersonality"
|
||||
></u-button>
|
||||
</view>
|
||||
|
||||
<!-- 帮助弹窗 -->
|
||||
<u-popup v-model="showHelp" mode="center" border-radius="20">
|
||||
<view class="help-popup">
|
||||
<view class="help-header">
|
||||
<text class="help-title">性格预设说明</text>
|
||||
<u-icon name="close" size="20" @click="showHelp = false"></u-icon>
|
||||
</view>
|
||||
<view class="help-content">
|
||||
<text class="help-text">通过简单的问卷,我们将为你的宠物生成专属的性格档案,包括:</text>
|
||||
<view class="help-list">
|
||||
<text class="help-item">• 性格类型分析</text>
|
||||
<text class="help-item">• 个性化饲养建议</text>
|
||||
<text class="help-item">• AI聊天个性化设置</text>
|
||||
<text class="help-item">• 健康管理建议</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentStep: 1,
|
||||
totalSteps: 5,
|
||||
showHelp: false,
|
||||
selectedAnswers: {
|
||||
basicPersonality: '',
|
||||
social: '',
|
||||
activity: '',
|
||||
habits: []
|
||||
},
|
||||
// 基本性格选项
|
||||
basicPersonalityOptions: [
|
||||
{
|
||||
value: 'gentle',
|
||||
emoji: '😇',
|
||||
title: '温顺天使',
|
||||
desc: '性格温和,很少发脾气'
|
||||
},
|
||||
{
|
||||
value: 'active',
|
||||
emoji: '🌟',
|
||||
title: '活泼精灵',
|
||||
desc: '精力充沛,喜欢玩耍'
|
||||
},
|
||||
{
|
||||
value: 'independent',
|
||||
emoji: '👑',
|
||||
title: '独立王者',
|
||||
desc: '独立自主,有自己的想法'
|
||||
},
|
||||
{
|
||||
value: 'clingy',
|
||||
emoji: '🥰',
|
||||
title: '粘人小宝',
|
||||
desc: '喜欢粘着主人,需要陪伴'
|
||||
}
|
||||
],
|
||||
// 社交倾向选项
|
||||
socialOptions: [
|
||||
{
|
||||
value: 'friendly',
|
||||
emoji: '🤗',
|
||||
title: '社交达人',
|
||||
desc: '对人和动物都很友好'
|
||||
},
|
||||
{
|
||||
value: 'selective',
|
||||
emoji: '🤔',
|
||||
title: '选择性社交',
|
||||
desc: '对熟悉的人友好,对陌生人警惕'
|
||||
},
|
||||
{
|
||||
value: 'shy',
|
||||
emoji: '😊',
|
||||
title: '害羞内向',
|
||||
desc: '比较内向,需要时间适应'
|
||||
},
|
||||
{
|
||||
value: 'protective',
|
||||
emoji: '🛡️',
|
||||
title: '保护型',
|
||||
desc: '对主人很保护,对陌生人警惕'
|
||||
}
|
||||
],
|
||||
// 活动水平选项
|
||||
activityOptions: [
|
||||
{
|
||||
value: 'high',
|
||||
emoji: '🏃',
|
||||
title: '超级活跃',
|
||||
desc: '精力旺盛,需要大量运动'
|
||||
},
|
||||
{
|
||||
value: 'medium',
|
||||
emoji: '🚶',
|
||||
title: '适度活跃',
|
||||
desc: '喜欢适量的运动和玩耍'
|
||||
},
|
||||
{
|
||||
value: 'low',
|
||||
emoji: '😴',
|
||||
title: '安静悠闲',
|
||||
desc: '喜欢安静,更愿意休息'
|
||||
}
|
||||
],
|
||||
// 特殊习惯选项
|
||||
habitOptions: [
|
||||
{ value: 'foodie', emoji: '🍖', title: '贪吃鬼' },
|
||||
{ value: 'sleepy', emoji: '😴', title: '瞌睡虫' },
|
||||
{ value: 'playful', emoji: '🎾', title: '玩具控' },
|
||||
{ value: 'vocal', emoji: '🗣️', title: '话唠' },
|
||||
{ value: 'curious', emoji: '🔍', title: '好奇宝宝' },
|
||||
{ value: 'neat', emoji: '🧼', title: '爱干净' },
|
||||
{ value: 'guard', emoji: '👮', title: '小卫士' },
|
||||
{ value: 'escape', emoji: '🏃♂️', title: '逃跑专家' }
|
||||
],
|
||||
personalityResult: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canProceed() {
|
||||
switch (this.currentStep) {
|
||||
case 1:
|
||||
return this.selectedAnswers.basicPersonality !== ''
|
||||
case 2:
|
||||
return this.selectedAnswers.social !== ''
|
||||
case 3:
|
||||
return this.selectedAnswers.activity !== ''
|
||||
case 4:
|
||||
return this.selectedAnswers.habits.length > 0
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.petId = options.petId
|
||||
},
|
||||
methods: {
|
||||
selectOption(type, value) {
|
||||
this.selectedAnswers[type] = value
|
||||
},
|
||||
|
||||
toggleHabit(value) {
|
||||
const index = this.selectedAnswers.habits.indexOf(value)
|
||||
if (index > -1) {
|
||||
this.selectedAnswers.habits.splice(index, 1)
|
||||
} else {
|
||||
this.selectedAnswers.habits.push(value)
|
||||
}
|
||||
},
|
||||
|
||||
nextStep() {
|
||||
if (this.canProceed && this.currentStep < this.totalSteps) {
|
||||
this.currentStep++
|
||||
}
|
||||
},
|
||||
|
||||
prevStep() {
|
||||
if (this.currentStep > 1) {
|
||||
this.currentStep--
|
||||
}
|
||||
},
|
||||
|
||||
generatePersonality() {
|
||||
// 根据选择生成性格结果
|
||||
const { basicPersonality, social, activity, habits } = this.selectedAnswers
|
||||
|
||||
// 简单的性格分析逻辑
|
||||
let typeName = ''
|
||||
let emoji = ''
|
||||
let description = ''
|
||||
let tags = []
|
||||
let suggestions = []
|
||||
|
||||
// 根据基本性格确定类型
|
||||
if (basicPersonality === 'gentle') {
|
||||
typeName = '温柔天使型'
|
||||
emoji = '😇'
|
||||
description = '你的宠物是一个温柔的小天使,性格温和,很少发脾气,是理想的家庭伴侣。'
|
||||
tags = ['温顺', '乖巧', '易相处']
|
||||
suggestions = ['提供安静舒适的环境', '温柔的互动方式', '定期的关爱和陪伴']
|
||||
} else if (basicPersonality === 'active') {
|
||||
typeName = '活力四射型'
|
||||
emoji = '🌟'
|
||||
description = '你的宠物充满活力,精力旺盛,喜欢各种游戏和活动,是天生的运动健将。'
|
||||
tags = ['活泼', '精力充沛', '爱玩']
|
||||
suggestions = ['提供充足的运动空间', '准备丰富的玩具', '安排规律的运动时间']
|
||||
} else if (basicPersonality === 'independent') {
|
||||
typeName = '独立自主型'
|
||||
emoji = '👑'
|
||||
description = '你的宠物很有个性,独立自主,有自己的想法和节奏,是个小小的独立王者。'
|
||||
tags = ['独立', '有个性', '自主']
|
||||
suggestions = ['尊重它的个人空间', '不要过度干预', '提供选择的自由']
|
||||
} else {
|
||||
typeName = '粘人小可爱型'
|
||||
emoji = '🥰'
|
||||
description = '你的宠物是个粘人的小宝贝,喜欢和主人在一起,需要很多的关爱和陪伴。'
|
||||
tags = ['粘人', '需要陪伴', '情感丰富']
|
||||
suggestions = ['多花时间陪伴', '建立固定的互动时间', '给予充分的关爱']
|
||||
}
|
||||
|
||||
// 添加社交和活动相关的标签
|
||||
if (social === 'friendly') tags.push('友好')
|
||||
if (social === 'shy') tags.push('内向')
|
||||
if (activity === 'high') tags.push('高能量')
|
||||
if (activity === 'low') tags.push('安静')
|
||||
|
||||
// 添加习惯相关的标签
|
||||
habits.forEach(habit => {
|
||||
const habitOption = this.habitOptions.find(h => h.value === habit)
|
||||
if (habitOption) {
|
||||
tags.push(habitOption.title)
|
||||
}
|
||||
})
|
||||
|
||||
this.personalityResult = {
|
||||
typeName,
|
||||
emoji,
|
||||
description,
|
||||
tags: tags.slice(0, 6), // 最多显示6个标签
|
||||
suggestions
|
||||
}
|
||||
|
||||
this.currentStep = 5
|
||||
},
|
||||
|
||||
savePersonality() {
|
||||
// 保存性格数据到本地存储
|
||||
try {
|
||||
const personalityData = {
|
||||
answers: this.selectedAnswers,
|
||||
result: this.personalityResult,
|
||||
createdAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
// 如果有petId,更新对应宠物的性格数据
|
||||
if (this.petId) {
|
||||
let pets = uni.getStorageSync('pets') || []
|
||||
const petIndex = pets.findIndex(pet => pet.id == this.petId)
|
||||
if (petIndex > -1) {
|
||||
pets[petIndex].personality = this.personalityResult.tags
|
||||
pets[petIndex].personalityType = this.personalityResult.typeName
|
||||
pets[petIndex].personalityData = personalityData
|
||||
uni.setStorageSync('pets', pets)
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
.personality-container {
|
||||
background: linear-gradient(135deg, #FFF8F0 0%, #F8F9FA 100%);
|
||||
min-height: 100vh;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
/* 进度指示器 */
|
||||
.progress-container {
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
|
||||
.progress-bar {
|
||||
flex: 1;
|
||||
height: 8rpx;
|
||||
background: #E0E0E0;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #FF8A80, #FFB74D);
|
||||
border-radius: 4rpx;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
/* 问卷内容 */
|
||||
.questionnaire-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.question-section {
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.question-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.question-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.question-subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.options-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20rpx;
|
||||
|
||||
.option-card {
|
||||
background: #F8F9FA;
|
||||
border: 3rpx solid transparent;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx 20rpx;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
background: #FFF8F0;
|
||||
border-color: #FF8A80;
|
||||
transform: translateY(-4rpx);
|
||||
box-shadow: 0 8rpx 24rpx rgba(255, 138, 128, 0.2);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.option-emoji {
|
||||
font-size: 48rpx;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.option-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.option-desc {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.habits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16rpx;
|
||||
|
||||
.habit-tag {
|
||||
background: #F8F9FA;
|
||||
border: 3rpx solid transparent;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx 16rpx;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
background: #FFF8F0;
|
||||
border-color: #FF8A80;
|
||||
transform: translateY(-2rpx);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.habit-emoji {
|
||||
font-size: 32rpx;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.habit-text {
|
||||
font-size: 22rpx;
|
||||
color: #333333;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 结果展示 */
|
||||
.result-section {
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.result-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.result-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.result-subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.personality-result {
|
||||
.personality-type {
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.type-emoji {
|
||||
font-size: 80rpx;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.type-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #FF8A80;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.personality-description {
|
||||
background: #FFF8F0;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.desc-text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
.personality-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.care-suggestions {
|
||||
.suggestions-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.suggestion-item {
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.suggestion-text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 底部操作按钮 */
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #ffffff;
|
||||
padding: 30rpx;
|
||||
border-top: 2rpx solid #F0F0F0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
:deep(.u-button) {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 帮助弹窗 */
|
||||
.help-popup {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
width: 600rpx;
|
||||
|
||||
.help-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.help-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.help-content {
|
||||
.help-text {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.help-list {
|
||||
.help-item {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
line-height: 1.6;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 微信小程序适配 */
|
||||
@media screen and (max-width: 375px) {
|
||||
.questionnaire-content {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.question-section {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.options-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.habits-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+346
-13
@@ -300,30 +300,363 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pets-container {
|
||||
background-color: #f8f9fa;
|
||||
background: linear-gradient(135deg, #FFF8F0 0%, #F8F9FA 100%);
|
||||
min-height: 100vh;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.pet-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
background: linear-gradient(135deg, #FF8A80 0%, #FFB74D 100%);
|
||||
padding: 20rpx 30rpx 30rpx;
|
||||
border-radius: 0 0 40rpx 40rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.3);
|
||||
|
||||
.pet-info {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
.navbar-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
:deep(.u-text) {
|
||||
margin-bottom: 8rpx;
|
||||
.navbar-title {
|
||||
.title-text {
|
||||
color: #ffffff;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.pet-actions {
|
||||
margin-left: 20rpx;
|
||||
.navbar-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 36rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(10rpx);
|
||||
|
||||
&.add-btn {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 统计卡片 */
|
||||
.stats-card {
|
||||
background: #ffffff;
|
||||
margin: 30rpx;
|
||||
padding: 40rpx;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.stats-item {
|
||||
text-align: center;
|
||||
|
||||
.stats-number {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #FF8A80;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 宠物列表 */
|
||||
.pets-list {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.pet-card {
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 8rpx;
|
||||
background: linear-gradient(90deg, #FF8A80, #81C784, #64B5F6);
|
||||
}
|
||||
|
||||
.pet-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.pet-avatar-container {
|
||||
position: relative;
|
||||
margin-right: 24rpx;
|
||||
|
||||
.pet-status {
|
||||
position: absolute;
|
||||
bottom: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4rpx solid #ffffff;
|
||||
|
||||
&.healthy {
|
||||
background: #81C784;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background: #FFB74D;
|
||||
}
|
||||
|
||||
&.sick {
|
||||
background: #FF8A80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pet-basic-info {
|
||||
flex: 1;
|
||||
|
||||
.pet-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.pet-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.pet-gender {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.male {
|
||||
background: #64B5F6;
|
||||
}
|
||||
|
||||
&.female {
|
||||
background: #F06292;
|
||||
}
|
||||
}
|
||||
|
||||
.pet-breed {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pet-age {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.pet-tags {
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pet-actions {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding-top: 24rpx;
|
||||
border-top: 2rpx solid #F5F5F5;
|
||||
|
||||
.action-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background: #F5F5F5;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 22rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 60rpx;
|
||||
text-align: center;
|
||||
|
||||
.empty-image {
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
margin-bottom: 40rpx;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.empty-desc {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.add-first-pet-btn {
|
||||
width: 400rpx;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #FF8A80, #FFB74D);
|
||||
border: none;
|
||||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
/* 快捷操作弹窗 */
|
||||
.quick-actions-popup {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
padding: 40rpx 30rpx 60rpx;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.quick-actions-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 40rpx;
|
||||
|
||||
.quick-action-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
padding: 24rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
background: #F8F9FA;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background: #E9ECEF;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.quick-action-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 微信小程序适配 */
|
||||
@media screen and (max-width: 375px) {
|
||||
.custom-navbar {
|
||||
padding: 15rpx 25rpx 25rpx;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
margin: 25rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.pets-list {
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.pet-card {
|
||||
padding: 25rpx;
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.pets-container {
|
||||
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
|
||||
}
|
||||
|
||||
.stats-card,
|
||||
.pet-card {
|
||||
background: #2d2d2d;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.pet-name {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pet-breed {
|
||||
color: #cccccc !important;
|
||||
}
|
||||
|
||||
.pet-age {
|
||||
color: #999999 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user