310 lines
9.4 KiB
JavaScript
310 lines
9.4 KiB
JavaScript
const { getLayout } = require('../../utils/layout');
|
|
// pages/pet/pet.js
|
|
const { api } = require('../../utils/request');
|
|
|
|
const BREED_NAMES = {
|
|
'golden': '金毛',
|
|
'husky': '哈士奇',
|
|
'corgi': '柯基',
|
|
'shiba': '柴犬'
|
|
};
|
|
|
|
const BREED_EMOJIS = {
|
|
'golden': '🐕',
|
|
'husky': '🐺',
|
|
'corgi': '🦊',
|
|
'shiba': '🐶'
|
|
};
|
|
|
|
const STAGE_NAMES = ['', '幼犬期', '少年期', '青年期', '成年期', '终极期'];
|
|
|
|
Page({
|
|
onResize: function() { this.setData(getLayout()); },
|
|
data: { loading: true, loadError: false,
|
|
hasPet: false,
|
|
pet: null,
|
|
daily: null,
|
|
achievements: [],
|
|
dynamics: [],
|
|
displayDynamics: [],
|
|
equipped: [],
|
|
|
|
// 领养表单
|
|
breedSelect: 'golden',
|
|
genderSelect: 1,
|
|
petName: '',
|
|
adopting: false,
|
|
|
|
// 宠物状态
|
|
dailyStatus: {},
|
|
partnerDaily: {},
|
|
allDone: false,
|
|
expProgress: 0,
|
|
expForNextLevel: 0,
|
|
breedName: '',
|
|
petEmoji: '',
|
|
stageName: '',
|
|
equippedCollar: false,
|
|
|
|
// 最近成就
|
|
recentAchievements: [],
|
|
achievementCount: 0,
|
|
|
|
// 改名
|
|
showRename: false,
|
|
renameValue: '',
|
|
renaming: false,
|
|
// 动态折叠(默认收起,收起时显示一条)
|
|
showAllDynamics: false
|
|
},
|
|
|
|
onLoad: function() {
|
|
this.setData(getLayout());
|
|
this.loadPetInfo();
|
|
},
|
|
|
|
onShow: function() {
|
|
this.loadPetInfo();
|
|
},
|
|
|
|
loadPetInfo: async function() {
|
|
if (this._pageLoading) return;
|
|
this._pageLoading = true;
|
|
this.setData({loading:true, loadError:false});
|
|
try {
|
|
const res = await api.petInfo();
|
|
if (res.has_pet && res.pet) {
|
|
const pet = res.pet;
|
|
const dailyStatus = {};
|
|
const partnerDaily = {};
|
|
if (res.daily) {
|
|
const d = res.daily;
|
|
const suffix = res.is_user1 ? 'u1' : 'u2';
|
|
const partnerSuffix = res.is_user1 ? 'u2' : 'u1';
|
|
['feed', 'water', 'walk', 'bath', 'sleep', 'play'].forEach(a => {
|
|
dailyStatus[a] = d[a + '_' + suffix] == 1;
|
|
partnerDaily[a] = d[a + '_' + partnerSuffix] == 1;
|
|
});
|
|
}
|
|
// 获取已装备物品
|
|
const equipped = res.equipped || [];
|
|
const equippedCollar = equipped.some(e => e.item_type === 'collar');
|
|
// 计算最近成就
|
|
const allAch = this.getAllAchievementDefs();
|
|
const recentAch = allAch.filter(a => res.achievements.indexOf(a.key) >= 0).slice(0, 5);
|
|
|
|
// 计算领养天数
|
|
var adoptDays = 0;
|
|
if (pet.adopted_at) {
|
|
var adoptDate = new Date(pet.adopted_at.replace(/-/g, '/'));
|
|
if (!isNaN(adoptDate.getTime())) {
|
|
adoptDays = Math.floor((Date.now() - adoptDate.getTime()) / 86400000);
|
|
}
|
|
}
|
|
var pageData = {
|
|
hasPet: true,
|
|
pet: pet,
|
|
daily: res.daily,
|
|
achievements: res.achievements,
|
|
dynamics: this._formatDynamics(res.dynamics || []),
|
|
showAllDynamics: false,
|
|
equipped: equipped,
|
|
dailyStatus: dailyStatus,
|
|
partnerDaily: partnerDaily,
|
|
allDone: res.daily ? res.daily.all_done == 1 : false,
|
|
expProgress: res.exp_progress || 0,
|
|
expForNextLevel: res.exp_for_next_level || 0,
|
|
breedName: BREED_NAMES[pet.breed] || '金毛',
|
|
petEmoji: BREED_EMOJIS[pet.breed] || '🐕',
|
|
stageName: STAGE_NAMES[pet.stage] || '幼犬期',
|
|
equippedCollar: equippedCollar,
|
|
recentAchievements: recentAch,
|
|
achievementCount: (res.achievements || []).length,
|
|
adoptDays: adoptDays
|
|
};
|
|
|
|
this.setData(pageData);
|
|
this._buildDisplayDynamics();
|
|
|
|
} else {
|
|
this.setData({ hasPet: false, pet:null, daily:null, achievements:[], dynamics:[], displayDynamics:[] });
|
|
}
|
|
} catch (e) {
|
|
this.setData({loadError:true});
|
|
console.error(e);
|
|
}
|
|
finally { this._pageLoading = false; this.setData({loading:false}); }
|
|
},
|
|
|
|
// 格式化动态数据:时间转为友好显示,昵称取首字
|
|
_formatDynamics: function(list) {
|
|
var now = Date.now();
|
|
return list.map(function(d) {
|
|
var timeText = '';
|
|
if (d.created_at) {
|
|
var t = new Date(String(d.created_at).replace(/-/g, '/').replace('T', ' '));
|
|
if (!isNaN(t.getTime())) {
|
|
var diff = Math.floor((now - t.getTime()) / 1000);
|
|
if (diff < 60) timeText = '刚刚';
|
|
else if (diff < 3600) timeText = Math.floor(diff / 60) + '分钟前';
|
|
else if (diff < 86400) timeText = Math.floor(diff / 3600) + '小时前';
|
|
else if (diff < 172800) timeText = '昨天';
|
|
else timeText = (t.getMonth() + 1) + '月' + t.getDate() + '日';
|
|
}
|
|
}
|
|
var initial = d.user_id == 0 ? '🐾' : (d.nickname ? String(d.nickname).trim()[0] : '?');
|
|
return {
|
|
user_id: d.user_id,
|
|
nickname: d.nickname,
|
|
avatar: d.avatar || '',
|
|
action: d.action,
|
|
message: d.message,
|
|
time_text: timeText,
|
|
initial: initial
|
|
};
|
|
});
|
|
},
|
|
|
|
getAllAchievementDefs: function() {
|
|
return [
|
|
{ key: 'first_adopt', name: '初次相遇', icon: '🐣' },
|
|
{ key: 'level_5', name: '成长之路', icon: '⭐' },
|
|
{ key: 'level_10', name: '小有成就', icon: '🌟' },
|
|
{ key: 'level_20', name: '资深铲屎官', icon: '👑' },
|
|
{ key: 'level_30', name: '终极陪伴', icon: '💎' },
|
|
{ key: 'stage_2', name: '少年初长成', icon: '🐕' },
|
|
{ key: 'stage_3', name: '青春活力', icon: '🦮' },
|
|
{ key: 'stage_4', name: '成熟稳重', icon: '🐩' },
|
|
{ key: 'stage_5', name: '终极形态', icon: '🦁' },
|
|
{ key: 'all_done_7', name: '一周全勤', icon: '📅' },
|
|
{ key: 'all_done_30', name: '月度之星', icon: '🏆' },
|
|
{ key: 'feed_100', name: '大胃王', icon: '🍖' },
|
|
{ key: 'walk_50', name: '散步达人', icon: '🚶' },
|
|
{ key: 'bath_30', name: '爱干净', icon: '🛁' },
|
|
{ key: 'play_50', name: '玩伴', icon: '🎾' },
|
|
{ key: 'happiness_100', name: '快乐满分', icon: '😊' },
|
|
{ key: 'rename_first', name: '取名大师', icon: '✏️' },
|
|
{ key: 'adopt_7days', name: '一周陪伴', icon: '📆' },
|
|
{ key: 'adopt_30days', name: '一月相伴', icon: '🗓️' },
|
|
{ key: 'adopt_100days', name: '百日纪念', icon: '💯' }
|
|
];
|
|
},
|
|
|
|
// 选择品种
|
|
selectBreed: function(e) {
|
|
this.setData({ breedSelect: e.currentTarget.dataset.breed });
|
|
},
|
|
|
|
// 选择性别
|
|
selectGender: function(e) {
|
|
this.setData({ genderSelect: parseInt(e.currentTarget.dataset.gender) });
|
|
},
|
|
|
|
// 输入名字
|
|
onNameInput: function(e) {
|
|
this.setData({ petName: e.detail.value });
|
|
},
|
|
|
|
// 领养
|
|
doAdopt: async function() {
|
|
var name = this.data.petName.trim();
|
|
if (!name) {
|
|
wx.showToast({ title: '请给宠物取个名字', icon: 'none' });
|
|
return;
|
|
}
|
|
this.setData({ adopting: true });
|
|
try {
|
|
const res = await api.petAdopt({
|
|
name: name,
|
|
breed: this.data.breedSelect,
|
|
gender: this.data.genderSelect
|
|
});
|
|
wx.showToast({ title: '🎉 领养成功!', icon: 'success' });
|
|
this.loadPetInfo();
|
|
} catch (e) {
|
|
wx.showToast({ title: e.error || '领养失败', icon: 'none' });
|
|
} finally {
|
|
this.setData({ adopting: false });
|
|
}
|
|
},
|
|
|
|
// 执行日常任务
|
|
doDailyAction: async function(e) {
|
|
var action = e.currentTarget.dataset.action;
|
|
if (this.data.dailyStatus[action]) {
|
|
wx.showToast({ title: '已完成', icon: 'none' });
|
|
return;
|
|
}
|
|
try {
|
|
const res = await api.petDailyAction({ action: action });
|
|
wx.showToast({ title: '✅ +' + (res.exp_gain || 0) + '经验', icon: 'success', duration: 1500 });
|
|
this.loadPetInfo();
|
|
} catch (e) {
|
|
if (e.already_done) {
|
|
wx.showToast({ title: '今天已完成啦', icon: 'none' });
|
|
this.loadPetInfo();
|
|
} else {
|
|
wx.showToast({ title: e.error || '操作失败', icon: 'none' });
|
|
}
|
|
}
|
|
},
|
|
|
|
// 改名
|
|
showRenameModal: function() {
|
|
this.setData({
|
|
showRename: true,
|
|
renameValue: this.data.pet ? this.data.pet.name : ''
|
|
});
|
|
},
|
|
hideRenameModal: function() {
|
|
this.setData({ showRename: false });
|
|
},
|
|
onRenameInput: function(e) {
|
|
this.setData({ renameValue: e.detail.value });
|
|
},
|
|
doRename: async function() {
|
|
var name = this.data.renameValue.trim();
|
|
if (!name) {
|
|
wx.showToast({ title: '请输入名字', icon: 'none' });
|
|
return;
|
|
}
|
|
this.setData({ renaming: true });
|
|
try {
|
|
await api.petRename({ name: name });
|
|
wx.showToast({ title: '改名成功 ✏️', icon: 'success' });
|
|
this.setData({ showRename: false });
|
|
this.loadPetInfo();
|
|
} catch (e) {
|
|
wx.showToast({ title: e.error || '改名失败', icon: 'none' });
|
|
} finally {
|
|
this.setData({ renaming: false });
|
|
}
|
|
},
|
|
|
|
// 展开/收起动态
|
|
toggleDynamics: function() {
|
|
this.setData({ showAllDynamics: !this.data.showAllDynamics }, () => {
|
|
this._buildDisplayDynamics();
|
|
});
|
|
},
|
|
|
|
// 根据折叠状态计算要展示的动态列表(收起时只显示一条)
|
|
_buildDisplayDynamics: function() {
|
|
var list = this.data.dynamics || [];
|
|
var show = this.data.showAllDynamics;
|
|
this.setData({ displayDynamics: show ? list : list.slice(0, 1) });
|
|
},
|
|
|
|
// 跳转到成就页
|
|
goToAchievements: function() {
|
|
wx.navigateTo({ url: '/pages/pet/achievements' });
|
|
},
|
|
|
|
// 返回
|
|
goBack: function() {
|
|
wx.navigateBack();
|
|
},
|
|
|
|
stopPropagation: function() {}
|
|
});
|