feat: 英文字母描红开发

This commit is contained in:
R524809
2026-04-03 15:21:04 +08:00
parent 206c44cf6d
commit 1ef6770810
37 changed files with 1812 additions and 179 deletions
+3 -1
View File
@@ -4,5 +4,7 @@
"navigationBarBackgroundColor": "#FEF6E7",
"backgroundColor": "#FEF6E7",
"enablePullDownRefresh": false,
"usingComponents": {}
"usingComponents": {
"nav-bar": "../../components3.0/nav-bar/nav-bar"
}
}
-29
View File
@@ -15,35 +15,6 @@
box-sizing: border-box;
}
.age-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
background: fade(@bg-header, 85%);
backdrop-filter: blur(40rpx);
-webkit-backdrop-filter: blur(40rpx);
box-shadow: 0 2rpx 12rpx rgba(50, 46, 37, 0.05);
}
.age-nav__inner {
height: @nav-inner-height;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 0 @page-padding-x;
box-sizing: border-box;
}
.age-nav__title {
font-size: @fs-nav-title;
font-weight: @fw-nav-title;
color: @color-nav-title;
letter-spacing: @ls-nav-title;
}
.age-body {
width: 100%;
box-sizing: border-box;
-8
View File
@@ -1,5 +1,4 @@
import { AGE_BANDS, AgeBandKey } from '../../core/data/difficulty';
import { NAV_INNER_PX } from '../../utils/navMetrics';
type AbilityItem = {
icon: string;
@@ -186,8 +185,6 @@ const DEFAULT_AGE: AgeBandKey = '5-6';
Page({
data: {
statusBarHeight: 0,
navBlockHeight: 0,
ageTabs: AGE_BANDS.map((b) => ({
key: b.key,
rangeText: b.label.replace(/\s*岁\s*$/, ''),
@@ -201,11 +198,6 @@ Page({
},
onLoad() {
const win = wx.getWindowInfo();
this.setData({
statusBarHeight: win.statusBarHeight,
navBlockHeight: win.statusBarHeight + NAV_INNER_PX,
});
this.applyAge(DEFAULT_AGE);
},
+2 -6
View File
@@ -1,11 +1,7 @@
<view class="age-page">
<view class="age-nav" style="padding-top: {{statusBarHeight}}px;">
<view class="age-nav__inner">
<text class="age-nav__title">按年龄学</text>
</view>
</view>
<nav-bar title="按年龄学" />
<view class="age-body" style="padding-top: {{navBlockHeight}}px;">
<view class="age-body">
<scroll-view class="age-tab-scroll" scroll-x enable-flex>
<view class="age-tab-scroll__inner">
<view class="age-tab-row">
-16
View File
@@ -1,16 +0,0 @@
{
"navigationBarTitleText": "Debug",
"navigationBarBackgroundColor": "#FFD719",
"homeButton": true,
"backgroundColor": "#F6F6F6",
"enablePullDownRefresh": false,
"usingComponents": {
"toy-button": "../../ui/button/button",
"van-radio": "@vant/weapp/radio/index",
"van-radio-group": "@vant/weapp/radio-group/index",
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index",
"van-switch": "@vant/weapp/switch/index",
"van-field": "@vant/weapp/field/index"
}
}
-31
View File
@@ -1,31 +0,0 @@
.debug-page {
min-height: 100vh;
padding: 20rpx;
background-color: #F6F6F6;
.debug-wrapper {
margin-top: 30rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
.centered-title {
text-align: center;
color: #666;
border-top: 0 none;
}
.debug-cell {
display: flex;
align-items: center;
justify-content: space-between;
}
}
.btn-area {
display: flex;
align-items: center;
justify-content: center;
margin-top: 40rpx;
}
}
-43
View File
@@ -1,43 +0,0 @@
import { defaultPrintConfig } from '../../config/config';
Page({
data: {
printConfig: defaultPrintConfig,
enableDebug: false,
},
onLoad() {
const printConfig = getApp().getPrintConfig() || defaultPrintConfig;
const enableDebug = wx.getStorageSync('enableDebug') || false;
this.setData({ printConfig, enableDebug });
},
onChangeHeader(e: WechatMiniprogram.CustomEvent) {
const header = e.detail.value as PrintHeader;
this.setData({ printConfig: { ...this.data.printConfig, header } });
},
onClickHeaderSetting(e: WechatMiniprogram.CustomEvent) {
const header = e.currentTarget.dataset.name as PrintHeader;
this.setData({ printConfig: { ...this.data.printConfig, header } });
},
onAppNameChange(e: WechatMiniprogram.CustomEvent) {
const appName = e.detail + '';
this.setData({ printConfig: { ...this.data.printConfig, appName } });
},
onConfirm() {
getApp().setPrintConfig(this.data.printConfig);
const enableDebug = this.data.enableDebug;
wx.setStorageSync('enableDebug', enableDebug);
wx.setEnableDebug({ enableDebug });
wx.navigateBack();
},
/** 真机调试线上包 */
toggleDebug() {
const enableDebug = !this.data.enableDebug;
this.setData({ enableDebug });
},
});
-78
View File
@@ -1,78 +0,0 @@
<view class="debug-page">
<van-cell-group custom-class="debug-wrapper">
<van-cell
title="打印图片Header设置111"
size="large"
custom-class="centered-title" />
<van-radio-group
value="{{printConfig.header}}"
bind:change="onChangeHeader">
<van-cell
title="微信小程序头(wechat"
clickable
data-name="wechat"
bind:click="onClickHeaderSetting">
<van-radio slot="right-icon" name="wechat" />
</van-cell>
<van-cell
title="无Logo图片头(noLogo"
clickable
data-name="noLogoImage"
bind:click="onClickHeaderSetting">
<van-radio slot="right-icon" name="noLogoImage" />
</van-cell>
<van-cell
title="有Logo图片头(LogoImage"
clickable
data-name="LogoImage"
bind:click="onClickHeaderSetting">
<van-radio slot="right-icon" name="LogoImage" />
</van-cell>
<van-cell
title="最小Header头(minimal)(默认)"
clickable
data-name="minimal"
bind:click="onClickHeaderSetting"
border="{{ false }}">
<van-radio slot="right-icon" name="minimal" />
</van-cell>
</van-radio-group>
<van-field
label="appName"
value=""
placeholder="{{printConfig.appName}}"
bind:change="onAppNameChange" />
</van-cell-group>
<van-cell-group custom-class="debug-wrapper">
<van-cell
title="debug调整"
size="large"
custom-class="centered-title" />
<van-cell
custom-class="debug-cell"
title="真机调试线上包"
clickable
data-name="enableDebug"
border="{{ false }}"
bind:click="toggleDebug">
<van-switch
slot="right-icon"
name="enableDebug"
checked="{{enableDebug}}" />
</van-cell>
</van-cell-group>
<view class="btn-area">
<toy-button type="green" bind:click="onConfirm" width="360rpx">
确定
</toy-button>
</view>
<van-cell-group custom-class="debug-wrapper">
<van-cell
title="测试页面入口"
size="large"
custom-class="centered-title" />
</van-cell-group>
</view>
+2 -1
View File
@@ -5,6 +5,7 @@
"navigationBarBackgroundColor": "#F8F0E0",
"backgroundColor": "#FEF6E7",
"usingComponents": {
"van-icon": "@vant/weapp/icon/index"
"van-icon": "@vant/weapp/icon/index",
"nav-bar": "../../components3.0/nav-bar/nav-bar"
}
}
@@ -12,51 +12,6 @@
box-sizing: border-box;
}
.fav-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
flex-shrink: 0;
background: fade(@bg-header, 82%);
backdrop-filter: blur(40rpx);
-webkit-backdrop-filter: blur(40rpx);
box-shadow: 0 2rpx 12rpx rgba(50, 46, 37, 0.05);
}
.fav-nav__inner {
height: @nav-inner-height;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 0 @page-padding-x;
box-sizing: border-box;
}
.fav-nav__title {
font-size: @fs-nav-title;
font-weight: @fw-nav-title;
color: @color-nav-title;
letter-spacing: @ls-nav-title;
}
.fav-nav__actions {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
min-width: 120rpx;
}
.fav-nav__icon-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 8rpx;
border-radius: 50%;
}
.fav-nav__clear {
font-size: 26rpx;
+4 -7
View File
@@ -1,5 +1,8 @@
import { NAV_INNER_PX } from '../../utils/navMetrics';
const { statusBarHeight } = wx.getWindowInfo();
const NAV_BLOCK_HEIGHT = statusBarHeight + NAV_INNER_PX;
type FavoritesTab = 'favorites' | 'downloads';
type FavoriteItem =
@@ -114,9 +117,6 @@ const MOCK_DOWNLOADS: DownloadSection[] = [
Page({
data: {
statusBarHeight: 0,
navBlockHeight: 0,
/** 纵向 scroll-view 可视高度(窗口高 − 顶栏占位,避免内容滚入导航下) */
favScrollHeight: 0,
activeTab: 'favorites' as FavoritesTab,
favoriteList: MOCK_FAVORITES as FavoriteItem[],
@@ -125,11 +125,8 @@ Page({
onLoad() {
const win = wx.getWindowInfo();
const navBlockHeight = win.statusBarHeight + NAV_INNER_PX;
this.setData({
statusBarHeight: win.statusBarHeight,
navBlockHeight,
favScrollHeight: win.windowHeight - navBlockHeight,
favScrollHeight: win.windowHeight - NAV_BLOCK_HEIGHT,
});
},
+2 -6
View File
@@ -1,13 +1,9 @@
<view class="fav-page">
<view class="fav-nav" style="padding-top: {{statusBarHeight}}px;">
<view class="fav-nav__inner">
<text class="fav-nav__title">我的收藏</text>
</view>
</view>
<nav-bar title="我的收藏" />
<scroll-view
class="fav-scroll"
style="height: {{favScrollHeight}}px; margin-top: {{navBlockHeight}}px;"
style="height: {{favScrollHeight}}px;"
scroll-y
enhanced
show-scrollbar="{{false}}">
-6
View File
@@ -1,6 +0,0 @@
{
"navigationBarTitleText": "打印指南",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#f7ee47",
"backgroundColor": "#F6F6F6"
}
-150
View File
@@ -1,150 +0,0 @@
.guide-page {
min-height: 100vh;
background: #f6f6f6;
padding-bottom: 48rpx;
}
.guide-page__hero {
background: linear-gradient(180deg, #f7ee47 0%, #e6d520 100%);
padding: 60rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.guide-page__hero-icon {
font-size: 80rpx;
margin-bottom: 24rpx;
}
.guide-page__hero-title {
font-size: 40rpx;
font-weight: 700;
color: #333;
}
.guide-page__steps {
position: relative;
padding: 40rpx 32rpx 24rpx 32rpx;
margin: 0 24rpx;
margin-top: -24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
.guide-page__timeline-line {
position: absolute;
left: 62rpx;
top: 100rpx;
bottom: 100rpx;
width: 4rpx;
background: #eee;
z-index: 0;
}
.guide-page__step {
position: relative;
z-index: 1;
display: flex;
flex-direction: row;
margin-bottom: 48rpx;
}
.guide-page__step--last {
margin-bottom: 0;
}
.guide-page__step-num-wrap {
flex-shrink: 0;
width: 64rpx;
margin-right: 24rpx;
display: flex;
justify-content: center;
}
.guide-page__step-num {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: #f7ee47;
font-size: 28rpx;
font-weight: 700;
color: #333;
display: flex;
align-items: center;
justify-content: center;
}
.guide-page__step-body {
flex: 1;
padding-top: 4rpx;
}
.guide-page__step-title {
display: block;
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 12rpx;
}
.guide-page__step-desc {
display: block;
font-size: 28rpx;
color: #666;
line-height: 1.55;
margin-bottom: 16rpx;
}
.guide-page__tip {
background: #fff8e1;
border-radius: 16rpx;
padding: 20rpx 24rpx;
font-size: 26rpx;
color: #666;
line-height: 1.5;
}
.guide-page__tip-line {
display: block;
margin-bottom: 8rpx;
}
.guide-page__tip-line:last-child {
margin-bottom: 0;
}
.guide-page__faq-title {
font-size: 32rpx;
font-weight: 700;
color: #333;
padding: 40rpx 32rpx 16rpx;
}
.guide-page__faq {
padding: 0 24rpx;
}
.guide-page__faq-item {
background: #fff;
border-radius: 16rpx;
padding: 28rpx 32rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.guide-page__faq-q {
display: block;
font-size: 28rpx;
font-weight: 700;
color: #333;
margin-bottom: 12rpx;
}
.guide-page__faq-a {
display: block;
font-size: 26rpx;
color: #999;
line-height: 1.55;
}
-7
View File
@@ -1,7 +0,0 @@
Page({
data: {},
onLoad() {
// 静态说明页,无额外逻辑
},
});
-63
View File
@@ -1,63 +0,0 @@
<view class="guide-page">
<view class="guide-page__hero">
<text class="guide-page__hero-icon">🖨️</text>
<text class="guide-page__hero-title">3 步完成打印</text>
</view>
<view class="guide-page__steps">
<view class="guide-page__timeline-line" />
<view class="guide-page__step">
<view class="guide-page__step-num-wrap">
<view class="guide-page__step-num">1</view>
</view>
<view class="guide-page__step-body">
<text class="guide-page__step-title">保存到相册</text>
<text class="guide-page__step-desc">在练习纸预览页点击「保存」或「保存到相册」,授权后即可保存图片。</text>
<view class="guide-page__tip">提示:建议先关闭深色模式截图,打印对比度更好。</view>
</view>
</view>
<view class="guide-page__step">
<view class="guide-page__step-num-wrap">
<view class="guide-page__step-num">2</view>
</view>
<view class="guide-page__step-body">
<text class="guide-page__step-title">连接打印机</text>
<text class="guide-page__step-desc">确保打印机与手机处于同一 Wi-Fi,或按打印机说明完成蓝牙配对。</text>
<view class="guide-page__tip">家用喷墨 / 激光打印机均可;A4 纸竖向打印即可。</view>
</view>
</view>
<view class="guide-page__step guide-page__step--last">
<view class="guide-page__step-num-wrap">
<view class="guide-page__step-num">3</view>
</view>
<view class="guide-page__step-body">
<text class="guide-page__step-title">从相册打印</text>
<text class="guide-page__step-desc">打开手机相册,选中刚保存的练习纸图片,点击分享或打印。</text>
<view class="guide-page__tip">
<text class="guide-page__tip-line">iPhone:分享 → 打印 → 选择打印机。</text>
<text class="guide-page__tip-line">Android:更多 → 打印 或 使用系统相册自带的打印入口。</text>
</view>
</view>
</view>
</view>
<view class="guide-page__faq-title">常见问题</view>
<view class="guide-page__faq">
<view class="guide-page__faq-item">
<text class="guide-page__faq-q">保存失败怎么办?</text>
<text class="guide-page__faq-a">请在小程序设置中开启相册写入权限,并检查手机存储空间是否充足。</text>
</view>
<view class="guide-page__faq-item">
<text class="guide-page__faq-q">打印出来太小/太大?</text>
<text class="guide-page__faq-a">在打印预览中选择「适应页面」或调整缩放比例,通常 100% 即可。</text>
</view>
<view class="guide-page__faq-item">
<text class="guide-page__faq-q">没有打印机?</text>
<text class="guide-page__faq-a">可将图片发到电脑或拷贝至 U 盘,在打印店完成打印。</text>
</view>
</view>
</view>
+45 -11
View File
@@ -284,9 +284,9 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
ageBand: '4-6岁',
difficulty: '入门',
icon: '🔠',
path: '',
available: false,
source: '产品设计文档 P1-17',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
source: 'letter-tracing',
},
{
id: 'target-english-2',
@@ -721,21 +721,55 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
{
id: 'english',
title: '英语启蒙',
subtitle:
'当前暂无真实英语页面,先保留结构占位,便于首页保持完整信息架构',
subtitle: '字母描红等已上线,其余能力持续补充',
items: [
{
id: 'current-english-1',
title: '英语启蒙即将上线',
subtitle: '字母描红、闪卡、自然拼读',
title: '字母学习页',
subtitle: '字母配图与描红',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '🔠',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
source: 'letter-tracing-single',
},
{
id: 'current-english-2',
title: '26 字母描红',
subtitle: '整页四线三格练习',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '🔤',
badge: 'Soon',
path: '',
available: false,
source: '产品目标结构保留位',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-full',
available: true,
source: 'letter-tracing-full',
},
{
id: 'current-english-3',
title: '大小写字母对照',
subtitle: '一页认识 A-Z 与 a-z',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '🔡',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-upper-lower',
available: true,
source: 'letter-tracing-upper-lower',
},
{
id: 'current-english-4',
title: '字母描红(两列)',
subtitle: 'AM / NZ',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '✏️',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column',
available: true,
source: 'letter-tracing-two-column',
},
],
},
+2 -1
View File
@@ -5,6 +5,7 @@
"navigationBarBackgroundColor": "#F8F0E0",
"backgroundColor": "#F8F0E0",
"usingComponents": {
"van-icon": "@vant/weapp/icon/index"
"van-icon": "@vant/weapp/icon/index",
"nav-bar": "../../components3.0/nav-bar/nav-bar"
}
}
-38
View File
@@ -14,44 +14,6 @@ page {
box-sizing: border-box;
}
/* 顶栏:固定于顶部,正文区独立滚动 */
.profile-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
flex-shrink: 0;
background: fade(@bg-header, 85%);
backdrop-filter: blur(40rpx);
-webkit-backdrop-filter: blur(40rpx);
box-shadow: 0 2rpx 12rpx rgba(50, 46, 37, 0.05);
}
.profile-nav__inner {
height: @nav-inner-height;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 0 @page-padding-x;
box-sizing: border-box;
}
.profile-nav__title {
font-size: @fs-nav-title;
font-weight: @fw-nav-title;
color: @color-nav-title;
letter-spacing: @ls-nav-title;
}
.profile-nav__brand {
font-size: 40rpx;
font-weight: 800;
color: @brand;
letter-spacing: -0.04em;
}
.profile-body {
width: 100%;
box-sizing: border-box;
+2 -11
View File
@@ -1,11 +1,7 @@
import { getTodayDownloadCount } from '../../utils/downloadPrint';
import { NAV_INNER_PX } from '../../utils/navMetrics';
Page({
data: {
statusBarHeight: 0,
/** 状态栏 + 导航条高度,用于固定顶栏占位 */
navBlockHeight: 0,
userName: '微信用户',
avatarUrl: '',
printCount: 0,
@@ -14,14 +10,9 @@ Page({
},
onLoad() {
const win = wx.getWindowInfo();
const info = wx.getAccountInfoSync();
const version = info.miniProgram.version || '开发版';
this.setData({
statusBarHeight: win.statusBarHeight,
navBlockHeight: win.statusBarHeight + NAV_INNER_PX,
version,
});
this.setData({ version });
},
onShow() {
@@ -46,7 +37,7 @@ Page({
},
onGoToGuide() {
wx.navigateTo({ url: '/pages/guide/guide' });
wx.navigateTo({ url: '/supportPages/guide/guide' });
},
onGoToPrintSettings() {
+2 -6
View File
@@ -1,11 +1,7 @@
<view class="profile-page">
<view class="profile-nav" style="padding-top: {{statusBarHeight}}px;">
<view class="profile-nav__inner">
<text class="profile-nav__title">个人中心</text>
</view>
</view>
<nav-bar title="个人中心" />
<view class="profile-body" style="padding-top: {{navBlockHeight}}px;">
<view class="profile-body">
<view class="profile-main">
<!-- 用户卡(Stitch:白底大圆角 + 顶条淡黄) -->
<view class="profile-hero">