pet/pages/pets/pet-personality.vue

784 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<view class="personality-container page-container-with-bg">
<!-- 顶部操作栏 -->
<view class="top-action-bar">
<view class="action-item" @click="showHelp = true">
<u-icon name="question-circle" size="20" color="#666666"></u-icon>
<text class="action-text">帮助</text>
</view>
</view>
<!-- 进度指示器 -->
<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;
}
/* 顶部操作栏 */
.top-action-bar {
display: flex;
justify-content: flex-end;
padding: 20rpx 30rpx;
.action-item {
display: flex;
align-items: center;
gap: 8rpx;
padding: 12rpx 20rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.8);
.action-text {
font-size: 24rpx;
color: #666666;
}
}
}
/* 进度指示器 */
.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>