feat: init fitness-coach (backend + miniprogram)

- backend: NestJS service with exercise/plan data
- miniprogram: WeChat mini program client
- exclude node_modules, dist, runtime data-store, local env
This commit is contained in:
2026-07-22 00:35:40 +08:00
commit b3b58e66fb
103 changed files with 154759 additions and 0 deletions

20
miniprogram/utils/auth.js Normal file
View File

@@ -0,0 +1,20 @@
// 极简登录占位:仅演示 wx.login 拿到 code不请求真实后端服务端。
// 生产环境中,应将 code 发送到后端换取 openid / session。
function getOpenid() {
return new Promise((resolve) => {
wx.login({
success(res) {
if (res.code) {
// 真实实现wx.request({ url: BASE_URL + '/api/auth/login', data: { code } })
console.log('[auth] wx.login code =', res.code);
}
resolve(res.code || '');
},
fail() {
resolve('');
}
});
});
}
module.exports = { getOpenid };

View File

@@ -0,0 +1,27 @@
// 通用格式化辅助函数
function truncate(str, n) {
if (!str) return '';
return str.length > n ? str.slice(0, n) + '…' : str;
}
// 训练类型 -> 主题色(用于标签 / 角标)
function typeColor(type) {
const map = {
strength: '#D9B36C', // 力量 -> 金
cardio: '#58C9B9', // 有氧 -> 青
flexibility: '#9B8CFF' // 拉伸 -> 紫
};
return map[type] || '#D9B36C';
}
// 训练类型 -> 中文名
function typeLabel(type) {
const map = {
strength: '力量',
cardio: '有氧',
flexibility: '拉伸'
};
return map[type] || '动作';
}
module.exports = { truncate, typeColor, typeLabel };

View File

@@ -0,0 +1,31 @@
// 统一的网络请求封装:所有请求都经过此包装器。
// 后端为公开 API无需鉴权头失败时统一 toast 提示。
const { BASE_URL } = require('../config');
function request({ url, method = 'GET', data = {} }) {
return new Promise((resolve, reject) => {
wx.request({
url: BASE_URL + url,
method,
data,
header: { 'content-type': 'application/json' },
success(res) {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data);
} else {
wx.showToast({
title: '请求失败 (' + res.statusCode + ')',
icon: 'none'
});
reject(res);
}
},
fail(err) {
wx.showToast({ title: '网络错误,请稍后重试', icon: 'none' });
reject(err);
}
});
});
}
module.exports = { request };