feat(card): 实现卡片预览区域自适应缩放功能

- 添加预览区高度动态计算逻辑,确保按钮始终可见
- 实现超大卡片等比缩放功能,避免超出屏幕范围
- 添加卡片真实高度测量和缩放比例计算
- 优化页面布局结构,设置固定操作按钮区域
- 调整样式防止内容溢出和滚动条显示
This commit is contained in:
cg
2026-08-20 22:34:11 +08:00
parent c0d4d1a219
commit 26b7111af0
+57 -9
View File
@@ -7,9 +7,15 @@
<text class="card-nav-title">酒局卡片</text> <text class="card-nav-title">酒局卡片</text>
</view> </view>
<!-- 大卡片预览 --> <!-- 大卡片预览:超高时自动等比缩放,保证按钮始终可见 -->
<view class="card-preview-area"> <view class="card-preview-area" :style="{ height: previewH + 'px' }">
<DrinkCard v-if="record" :record="record" /> <view
v-if="record"
class="card-scale-wrap"
:style="previewScale < 1 ? { transform: 'scale(' + previewScale + ')', width: '620rpx' } : {}"
>
<DrinkCard :record="record" />
</view>
<view v-else class="card-empty">暂无记录</view> <view v-else class="card-empty">暂无记录</view>
</view> </view>
@@ -50,7 +56,11 @@ export default {
record: null, record: null,
saving: false, saving: false,
saved: false, saved: false,
posterPath: '' // 预生成的海报图片路径 posterPath: '', // 预生成的海报图片路径
// 预览区自适应缩放
previewScale: 1,
previewH: 400,
cardNaturalH: 0
} }
}, },
async onLoad(options) { async onLoad(options) {
@@ -76,12 +86,45 @@ export default {
} }
} }
if (!this.record) this.record = this.loadLocalRecord(options.recordId) || this.fallback() if (!this.record) this.record = this.loadLocalRecord(options.recordId) || this.fallback()
this.$nextTick(() => this.fitPreview())
}, },
onReady() { onReady() {
// 页面渲染完成后预生成海报,供分享使用 // 页面渲染完成后预生成海报,供分享使用
this.preGeneratePoster() this.preGeneratePoster()
// 图片加载完成后卡片高度会变化,延迟再适配一次
setTimeout(() => this.fitPreview(), 1500)
}, },
methods: { methods: {
// ===== 预览区自适应:卡片超高时等比缩放,按钮始终完整可见 =====
fitPreview() {
const sys = uni.getSystemInfoSync()
// 头部导航与底部按钮区的实测高度
const query = uni.createSelectorQuery().in(this)
query.select('.card-nav').boundingClientRect()
query.select('.card-actions').boundingClientRect()
query.exec(res => {
const navH = (res && res[0] && res[0].height) || 88
const actH = (res && res[1] && res[1].height) || 320
this.previewH = Math.max(200, sys.windowHeight - navH - actH)
this.measureCard()
})
},
measureCard() {
uni.createSelectorQuery().in(this)
.select('.card-root').boundingClientRect()
.exec(res => {
const h = res && res[0] && res[0].height
if (!h || h <= 0) {
// 卡片尚未渲染完成,稍后重试
setTimeout(() => this.measureCard(), 150)
return
}
// scale 后测量值已被缩放,还原真实高度
const natural = this.previewScale < 1 ? h / this.previewScale : h
this.cardNaturalH = natural
this.previewScale = natural > this.previewH ? Math.max(0.5, this.previewH / natural) : 1
})
},
loadLocalRecord(id) { loadLocalRecord(id) {
if (!id) return null if (!id) return null
try { try {
@@ -757,7 +800,8 @@ export default {
padding: 0; padding: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 100vh; height: 100vh;
overflow: hidden;
background: $bg-base; background: $bg-base;
} }
@@ -792,14 +836,17 @@ export default {
color: $text-primary; color: $text-primary;
} }
/* 大卡片预览区 */ /* 大卡片预览区:高度由 JS 按剩余可用空间动态设定,卡片超高时缩放 */
.card-preview-area { .card-preview-area {
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: $sp-lg; padding: 0 $sp-lg;
min-height: 0; overflow: hidden;
}
.card-scale-wrap {
transform-origin: center center;
} }
.card-empty { .card-empty {
@@ -809,6 +856,7 @@ export default {
/* 操作按钮 */ /* 操作按钮 */
.card-actions { .card-actions {
flex-shrink: 0;
padding: $sp-lg; padding: $sp-lg;
padding-bottom: calc($sp-lg + env(safe-area-inset-bottom)); padding-bottom: calc($sp-lg + env(safe-area-inset-bottom));
display: flex; display: flex;