diff --git a/miniprogram/UPDATE_LOG.md b/miniprogram/UPDATE_LOG.md index c068bfd..c774f57 100644 --- a/miniprogram/UPDATE_LOG.md +++ b/miniprogram/UPDATE_LOG.md @@ -1,5 +1,81 @@ # 小程序 UI 更新日志 +## 更新时间 +2026年2月9日 + +## 修复:"选择"与搜索框垂直对齐问题 + +### 问题描述 +"选择"文字与右侧搜索框无法垂直居中对齐,"选择"看起来偏上。 + +### 根本原因 +1. **全局样式污染**:`app.wxss` 和 `index.wxss` 中的全局 `.section-title` 样式设置了 `padding: 12rpx 0` 和 `margin-bottom: 16rpx`,导致"选择"文字上下有额外间距 +2. **小程序 input 组件最小高度**:微信小程序的 `` 组件有默认最小高度(约 48rpx),无法通过 CSS 设置更小的高度,导致搜索框实际高度大于预期 + +### 解决方案 +1. **统一高度为 48rpx**:适配 input 组件的最小高度限制 +2. **覆盖全局样式**:在 `.selection-header .section-title` 中显式设置 `padding: 0; margin: 0` +3. **强制 flexbox 居中**: + - 父容器 `.selection-header` 使用 `display: flex; align-items: center` + - `.section-title` 使用 `display: flex; align-items: center; height: 48rpx` + - `.search-container` 使用 `height: 48rpx; overflow: hidden` + +### 关键代码 +```css +.selection-header { + display: flex; + align-items: center; + gap: 8rpx; + padding: 0; +} + +.selection-header .section-title { + padding: 0; + margin: 0; + font-size: 28rpx; + font-weight: 400; + flex-shrink: 0; + display: flex; + align-items: center; + height: 48rpx; +} + +.search-container { + flex: 1; + display: flex; + align-items: center; + background: #FEFDFE; + border-radius: 24rpx; + padding: 0 12rpx; + height: 48rpx; + min-width: 0; + overflow: hidden; +} + +.search-input { + flex: 1; + font-size: 24rpx; + color: #4E5969; + height: 48rpx; + line-height: 48rpx; + min-height: 0; + padding: 0; + margin: 0; + background: transparent; +} +``` + +### 经验教训 +1. **检查全局样式**:修改特定组件样式前,先检查是否有全局样式影响 +2. **小程序组件限制**:微信小程序原生组件(如 input、textarea)有内置最小尺寸,需要适配而非强制覆盖 +3. **调试技巧**:当 flexbox `align-items: center` 不生效时,优先检查子元素的 padding/margin/line-height + +### 其他修复 +- **搜索框初始状态**:将 `showSearch` 初始值从 `false` 改为 `true`,搜索框默认完整显示(符合 Figma 设计) +- **字体选中状态同步**:在 `bootstrap()` 中恢复 `selectedFonts` 后调用 `updateFontTrees()`,确保预览区的字体在字体树中正确显示为已选中 + +--- + ## 更新时间 2026年2月8日(远端渲染改造) diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js index 30947c2..c0bd411 100644 --- a/miniprogram/pages/index/index.js +++ b/miniprogram/pages/index/index.js @@ -30,10 +30,13 @@ const LOCAL_ICON_PATHS = { fontIcon: '/assets/icons/font-icon.svg', // 字体item图标 expandIcon: '/assets/icons/expand.svg', // 展开分类图标 collapseIcon: '/assets/icons/expand.svg', // 折叠使用同一图标,通过旋转实现 - favoriteIcon: '/assets/icons/favorite.svg', // 收藏图标(未收藏白色底,收藏红色底) - checkbox: '/assets/icons/checkbox.svg', // 复选框(未选中) - checkboxChecked: '/assets/icons/checkbox-no.svg', // 复选框(已选中) + favoriteIcon: '/assets/icons/favorite.svg', // 收藏图标(未收藏) + favoriteRedIcon: '/assets/icons/favorite-red.svg', // 已收藏图标(红色) + checkbox: '/assets/icons/checkbox-no.svg', // 复选框(未选中) + checkboxChecked: '/assets/icons/checkbox.svg', // 复选框(已选中) search: '/assets/icons/search.svg', // 搜索图标 + selectAll: '/assets/icons/selectall.svg', // 全选图标 + unselectAll: '/assets/icons/unselectall.svg', // 取消全选图标 } function toSvgDataUri(svg) { @@ -156,7 +159,7 @@ Page({ icons: LOCAL_ICON_PATHS, // 搜索功能 searchKeyword: '', - showSearch: false, + showSearch: true, }, async onLoad() { @@ -233,6 +236,8 @@ Page({ })) this.setData({ selectedFonts }) + // 更新字体树以反映选中状态 + this.updateFontTrees() await this.generateAllPreviews() } } catch (error) { @@ -284,6 +289,7 @@ Page({ ? true : (typeof expandedFromState === 'boolean' ? expandedFromState : false), fonts: [], + allSelected: false, }) } categoryMap.get(category).fonts.push({ @@ -303,6 +309,15 @@ Page({ }) const fontCategories = Array.from(categoryMap.values()).sort((a, b) => a.category.localeCompare(b.category)) + // 计算每个分类的allSelected状态 + fontCategories.forEach(cat => { + if (cat.fonts.length > 0) { + cat.allSelected = cat.fonts.every(f => f.selected) + } else { + cat.allSelected = false + } + }) + favoriteFonts.sort((a, b) => { const categoryCompare = String(a.category || '').localeCompare(String(b.category || '')) if (categoryCompare !== 0) return categoryCompare @@ -414,6 +429,56 @@ Page({ } }, + // 切换分类全选/取消全选 + onToggleSelectAllInCategory(e) { + const category = e.currentTarget.dataset.category + if (!category) return + + const categoryFonts = this.data.fontCategories.find(c => c.category === category) + if (!categoryFonts || categoryFonts.fonts.length === 0) return + + const allSelected = categoryFonts.allSelected + const selectedFonts = [...this.data.selectedFonts] + const selectedIdSet = new Set(selectedFonts.map(f => f.id)) + + if (allSelected) { + // 取消全选:移除该分类下的所有字体 + categoryFonts.fonts.forEach(font => { + selectedIdSet.delete(font.id) + }) + } else { + // 全选:添加该分类下的所有字体 + categoryFonts.fonts.forEach(font => { + selectedIdSet.add(font.id) + }) + } + + const newSelectedFonts = [] + this.fontMap.forEach(font => { + if (selectedIdSet.has(font.id)) { + newSelectedFonts.push({ + id: font.id, + name: font.name, + category: font.category, + showInPreview: true, + previewSrc: '', + }) + } + }) + + this.setData({ selectedFonts: newSelectedFonts }) + this.updateFontTrees() + this.scheduleGenerate() + + saveAppState({ + inputText: this.data.inputText, + selectedFontIds: newSelectedFonts.map(f => f.id), + fontSize: Number(this.data.fontSize), + letterSpacing: Number(this.data.letterSpacingInput || 0), + textColor: this.data.textColor, + }) + }, + // 生成单个字体的预览 async generatePreviewForFont(fontId) { const text = String(this.data.inputText || '') diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml index 0cec0ca..e040ffb 100644 --- a/miniprogram/pages/index/index.wxml +++ b/miniprogram/pages/index/index.wxml @@ -119,7 +119,10 @@ src="{{icons.expandIcon}}" style="transform: rotate({{item.expanded ? '90deg' : '0deg'}})" /> - {{item.category}}({{item.fonts.length}}) + {{item.category}} + + + @@ -134,15 +137,12 @@ {{font.name}} - - - + @@ -154,19 +154,19 @@ - 已收藏 + + 已收藏 + {{item.name}} - - - + - + @@ -175,6 +175,11 @@ + + + @版权说明:仅SVG和PNG分享,无TTF下载,如侵权,反馈:douboer@gmail.com + + diff --git a/miniprogram/pages/index/index.wxss b/miniprogram/pages/index/index.wxss index 2e58094..f0f7acb 100644 --- a/miniprogram/pages/index/index.wxss +++ b/miniprogram/pages/index/index.wxss @@ -122,8 +122,8 @@ display: flex; flex-direction: column; margin-top: 16rpx; - padding: 0 16rpx; - border: 1rpx solid #f7e0e0; + padding: 8rpx; + border: 1rpx solid #3EE4C3; border-radius: 12rpx; background: #fff; overflow: hidden; @@ -266,10 +266,11 @@ /* 字体选择和已收藏字体 */ .bottom-section { display: flex; + flex: 1; gap: 16rpx; - height: 600rpx; + min-height: 0; margin-top: 16rpx; - padding: 0 16rpx; + padding: 0; } .font-selection, @@ -277,11 +278,12 @@ flex: 1; display: flex; flex-direction: column; - border: 1rpx solid #f7e0e0; + border: 1rpx solid #3EE4C3; border-radius: 16rpx; background: #fff; - padding: 9rpx; + padding: 8rpx 8rpx; overflow: hidden; + min-width: 0; } /* 搜索相关样式 */ @@ -290,58 +292,90 @@ align-items: center; gap: 8rpx; padding: 0; - height: 40rpx; + margin-bottom: 8rpx; } .selection-header .section-title { padding: 0; + margin: 0; font-size: 28rpx; - line-height: 40rpx; + font-weight: 400; + flex-shrink: 0; display: flex; align-items: center; - flex-shrink: 0; + height: 48rpx; + width: 66rpx; +} + +.favorite-header { + display: flex; + align-items: center; + padding: 0; + margin-bottom: 8rpx; +} + +.favorite-header .section-title { + padding: 0; + margin: 0; + font-size: 28rpx; + font-weight: 400; + display: flex; + align-items: center; + height: 48rpx; } .search-container { flex: 1; display: flex; align-items: center; - gap: 6rpx; - background: #F7F8FA; - border-radius: 8rpx; - padding: 4rpx 12rpx; - height: 40rpx; + background: #FEFDFE; + border-radius: 24rpx; + padding: 0 12rpx; + height: 48rpx; min-width: 0; + overflow: hidden; } .search-icon { - width: 28rpx; - height: 28rpx; + width: 24rpx; + height: 24rpx; flex-shrink: 0; - opacity: 0.5; + margin-right: 8rpx; } .search-input { flex: 1; - font-size: 22rpx; + font-size: 24rpx; color: #4E5969; - height: 100%; + height: 48rpx; + line-height: 48rpx; + min-height: 0; + padding: 0; + margin: 0; + background: transparent; } .search-toggle { - width: 40rpx; - height: 40rpx; + width: 32rpx; + height: 32rpx; display: flex; align-items: center; justify-content: center; flex-shrink: 0; - background: #F7F8FA; - border-radius: 8rpx; + background: #8552A1; + border-radius: 20rpx; +} + +.search-toggle .search-icon { + width: 18rpx; + height: 18rpx; + opacity: 1; } .font-tree { flex: 1; min-height: 0; + overflow-y: auto; } .font-category { @@ -364,11 +398,28 @@ } .category-name { + flex: 1; font-size: 21rpx; font-weight: 500; color: #000; } +.category-select-all { + width: 24rpx; + height: 24rpx; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + padding: 4rpx; +} + +.select-all-icon { + width: 100%; + height: 100%; + display: block; +} + .font-list { display: flex; flex-direction: column; @@ -528,6 +579,15 @@ font-size: 28rpx; } +/* 版权说明 */ +.copyright-footer { + text-align: center; + font-size: 20rpx; + color: #86909C; + padding: 16rpx 0; + flex-shrink: 0; +} + /* 画布 */ .hidden-canvas { position: fixed;