feat: 小程序连接服务器IP + 同步未提交开发
- miniprogram/config.js: BASE_URL 指向 http://192.227.237.8:3001 - 动作标题中文化(nameZh),搜索匹配 name/nameZh/nameEn - 新增计划/收藏/我的 等页面与组件 - 后端 Docker 化(Dockerfile/.dockerignore)与翻译脚本 - .gitignore 补充 .DS_Store
This commit is contained in:
@@ -1,25 +1,40 @@
|
||||
const app = getApp();
|
||||
const svc = require('../../services/exercise');
|
||||
const favSvc = require('../../services/favorite');
|
||||
const planSvc = require('../../services/plan');
|
||||
const auth = require('../../utils/auth');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 20,
|
||||
id: '',
|
||||
planId: '',
|
||||
exercise: null,
|
||||
heroSrc: '',
|
||||
heroError: false,
|
||||
related: [],
|
||||
loading: true
|
||||
loading: true,
|
||||
favorited: false
|
||||
},
|
||||
|
||||
onLoad(query) {
|
||||
const id = query.id || '';
|
||||
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, id });
|
||||
const planId = query.planId || '';
|
||||
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, id, planId });
|
||||
this.load();
|
||||
if (auth.isLogin()) {
|
||||
favSvc.exerciseStatus(id).then((r) => {
|
||||
this.setData({ favorited: !!(r && r.favorited) });
|
||||
}).catch(() => {});
|
||||
}
|
||||
},
|
||||
|
||||
load() {
|
||||
this.setData({ loading: true });
|
||||
svc.getExercise(this.data.id).then((ex) => {
|
||||
this.setData({ exercise: ex, loading: false });
|
||||
// 详情页用 GIF 演示动作;记录当前图源以便失败时降级到 JPG / 占位
|
||||
const heroSrc = ex && (ex.gifUrl || ex.image) ? (ex.gifUrl || ex.image) : '';
|
||||
this.setData({ exercise: ex, heroSrc, heroError: false, loading: false });
|
||||
if (ex && ex.target) {
|
||||
svc.listExercises({ target: ex.target, pageSize: 6 }).then((res) => {
|
||||
const related = ((res && res.items) || [])
|
||||
@@ -33,8 +48,52 @@ Page({
|
||||
});
|
||||
},
|
||||
|
||||
// 收藏 / 取消收藏(心形按钮)
|
||||
onToggleFav() {
|
||||
auth.ensureLogin().then(() => {
|
||||
const id = this.data.id;
|
||||
const wasFav = this.data.favorited;
|
||||
const op = wasFav ? favSvc.removeExercise(id) : favSvc.addExercise(id);
|
||||
op.then(() => {
|
||||
this.setData({ favorited: !wasFav });
|
||||
wx.showToast({ title: wasFav ? '已取消收藏' : '已收藏', icon: 'none' });
|
||||
}).catch(() => {});
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
// 底部主按钮:加入计划(真实选择器)
|
||||
onAdd() {
|
||||
wx.showToast({ title: '已加入今日训练', icon: 'success' });
|
||||
if (this.data.planId) {
|
||||
planSvc.addExercise(this.data.planId, this.data.id).then(() => {
|
||||
wx.showToast({ title: '已加入计划', icon: 'success' });
|
||||
setTimeout(() => wx.navigateBack(), 500);
|
||||
}).catch(() => {});
|
||||
return;
|
||||
}
|
||||
auth.ensureLogin().then(() => planSvc.listMine()).then((res) => {
|
||||
const plans = (res && res.items) || res || [];
|
||||
if (!plans.length) {
|
||||
wx.showModal({
|
||||
title: '还没有训练计划',
|
||||
content: '先创建一个计划,再把动作加进去吧~',
|
||||
confirmText: '去创建',
|
||||
cancelText: '稍后',
|
||||
success: (r) => { if (r.confirm) wx.navigateTo({ url: '/pages/plan-edit/plan-edit' }); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
const names = plans.slice(0, 6).map((p) => p.name);
|
||||
wx.showActionSheet({
|
||||
itemList: names,
|
||||
success: (sheet) => {
|
||||
const plan = plans[sheet.tapIndex];
|
||||
if (!plan) return;
|
||||
planSvc.addExercise(plan.id, this.data.id).then(() => {
|
||||
wx.showToast({ title: '已加入「' + plan.name + '」', icon: 'success' });
|
||||
}).catch(() => {});
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
onBack() {
|
||||
@@ -46,14 +105,26 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 详情大图加载失败:GIF→JPG→emoji 占位,三级降级保证不空白
|
||||
onHeroError() {
|
||||
const ex = this.data.exercise || {};
|
||||
const showingGif = this.data.heroSrc && ex.gifUrl && this.data.heroSrc === ex.gifUrl;
|
||||
if (showingGif && ex.image) {
|
||||
this.setData({ heroSrc: ex.image });
|
||||
} else {
|
||||
this.setData({ heroError: true });
|
||||
}
|
||||
},
|
||||
|
||||
onExercise(e) {
|
||||
wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) });
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ex = this.data.exercise || {};
|
||||
const name = ex.displayName || ex.name || '';
|
||||
return {
|
||||
title: ex.name ? ('FITCOACH · ' + ex.name) : 'FITCOACH 智能健身教练',
|
||||
title: name ? ('FITCOACH · ' + name) : 'FITCOACH 智能健身教练',
|
||||
path: '/pages/detail/detail?id=' + this.data.id
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
<view class="page" wx:if="{{exercise}}">
|
||||
<navbar title="{{exercise.name}}" show-back />
|
||||
<navbar title="{{exercise.displayName || exercise.name}}" show-back />
|
||||
|
||||
<view class="favbtn" style="top: {{statusBarHeight + 12}}px;" bindtap="onToggleFav">
|
||||
<text>{{favorited ? '♥' : '♡'}}</text>
|
||||
</view>
|
||||
|
||||
<view class="hero">
|
||||
<image
|
||||
wx:if="{{exercise.gifUrl || exercise.image}}"
|
||||
wx:if="{{heroSrc && !heroError}}"
|
||||
class="hero__img"
|
||||
src="{{exercise.gifUrl || exercise.image}}"
|
||||
mode="aspectFill" />
|
||||
src="{{heroSrc}}"
|
||||
mode="aspectFill"
|
||||
lazy-load="true"
|
||||
binderror="onHeroError" />
|
||||
<view wx:else class="hero__ph">🏋️</view>
|
||||
</view>
|
||||
|
||||
<view class="body section">
|
||||
<view class="name">{{exercise.name}}</view>
|
||||
<view class="name">{{exercise.displayName || exercise.name}}</view>
|
||||
|
||||
<view class="metas">
|
||||
<view class="meta"><view class="meta__k">部位</view><view class="meta__v">{{exercise.bodyPartLabel}}</view></view>
|
||||
@@ -60,7 +66,7 @@
|
||||
</view>
|
||||
|
||||
<view class="addbar">
|
||||
<view class="cta" bindtap="onAdd">加入今日训练</view>
|
||||
<view class="cta" bindtap="onAdd">{{ planId ? '加入该计划' : '加入计划' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -55,3 +55,13 @@
|
||||
.topbar { height: 88rpx; display: flex; align-items: center; padding: 0 24rpx; }
|
||||
.topbar__back { font-size: 56rpx; color: var(--gold); width: 60rpx; line-height: 1; }
|
||||
.empty { color: var(--text-3); font-size: 28rpx; text-align: center; padding: 120rpx 0; }
|
||||
|
||||
.favbtn {
|
||||
position: fixed; right: 28rpx; z-index: 60;
|
||||
width: 72rpx; height: 72rpx; border-radius: 999rpx;
|
||||
background: rgba(14,17,16,0.55);
|
||||
backdrop-filter: blur(8px);
|
||||
border: 1rpx solid var(--gold-line);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 44rpx; color: var(--gold-2); line-height: 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user