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:
2026-07-22 14:05:30 +08:00
parent b3b58e66fb
commit 70ff806042
79 changed files with 2397 additions and 146070 deletions

View File

@@ -0,0 +1,33 @@
// 计划卡片:复用官方计划(CollectionDef)与我自己的计划(PlanSummary)。
// props:
// plan: { id|slug, emoji, color, name, description, count|exerciseCount, cover? }
// target: 点击跳转的完整 url
Component({
properties: {
plan: { type: Object, value: {} },
target: { type: String, value: '' }
},
data: {
count: 0,
cover: '',
hasCover: false,
color: '#D9B36C'
},
observers: {
plan: function (plan) {
plan = plan || {};
this.setData({
count: plan.count || plan.exerciseCount || 0,
cover: plan.cover || '',
hasCover: !!(plan.cover),
color: plan.color || '#D9B36C'
});
}
},
methods: {
onTap() {
const url = this.data.target;
if (url) wx.navigateTo({ url });
}
}
});

View File

@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@@ -0,0 +1,22 @@
<view class="pc">
<view
wx:if="{{hasCover}}"
class="pc__cover"
style="background: {{color}}22;">
<image class="pc__img" src="{{cover}}" mode="aspectFill" lazy-load="true" />
<view class="pc__badge" style="background: {{color}}22; color: {{color}};">{{plan.emoji}}</view>
</view>
<view wx:else class="pc__top" style="background: linear-gradient(135deg, {{color}}26, var(--surface));">
<view class="pc__emoji" style="background: {{color}}22; color: {{color}};">{{plan.emoji}}</view>
</view>
<view class="pc__body">
<view class="pc__name" style="color: {{color}};">{{plan.name}}</view>
<view wx:if="{{plan.description}}" class="pc__desc">{{plan.description}}</view>
</view>
<view class="pc__foot">
<text wx:if="{{count > 0}}" class="pc__count">{{count}} 个动作</text>
<text class="pc__arrow"></text>
</view>
</view>

View File

@@ -0,0 +1,37 @@
.pc {
background: var(--surface);
border-radius: var(--radius);
overflow: hidden;
border: 1rpx solid var(--line);
box-shadow: var(--shadow);
width: 100%;
}
.pc__cover { position: relative; width: 100%; height: 220rpx; background: var(--surface-2); }
.pc__img { width: 100%; height: 100%; display: block; }
.pc__badge {
position: absolute; left: 16rpx; top: 16rpx;
width: 64rpx; height: 64rpx; border-radius: 18rpx;
display: flex; align-items: center; justify-content: center;
font-size: 38rpx; line-height: 1;
}
.pc__top { padding: 28rpx; display: flex; }
.pc__emoji {
width: 96rpx; height: 96rpx; border-radius: 24rpx;
display: flex; align-items: center; justify-content: center;
font-size: 52rpx; line-height: 1;
}
.pc__body { padding: 18rpx 22rpx 8rpx; }
.pc__name { font-size: 30rpx; font-weight: 700; }
.pc__desc {
margin-top: 10rpx;
font-size: 24rpx; color: var(--text-2); line-height: 1.5;
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.pc__foot {
display: flex; align-items: center; justify-content: space-between;
padding: 16rpx 22rpx 22rpx;
border-top: 1rpx solid var(--line);
margin-top: 8rpx;
}
.pc__count { font-size: 24rpx; color: var(--text-2); }
.pc__arrow { font-size: 36rpx; color: var(--gold); line-height: 1; }