From 1a6fde919b41e421585acc21b4dc3f6a83de5092 Mon Sep 17 00:00:00 2001 From: xiangsilian Date: Sat, 12 Sep 2026 13:23:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(hair):=20=E5=9B=BE=E7=89=87=E5=8C=BA?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E4=BF=AE=E5=A4=8D=E2=80=94=E2=80=94Stack=20?= =?UTF-8?q?=E6=98=BE=E5=BC=8F=E5=AE=9A=E9=AB=98=20320=EF=BC=88=E9=A2=9D?= =?UTF-8?q?=E5=BA=A6=E8=83=B6=E5=9B=8A=20Row=20height(100%)=20=E5=9C=A8?= =?UTF-8?q?=E8=87=AA=E9=80=82=E5=BA=94=20Stack=20=E9=87=8C=E4=BC=9A?= =?UTF-8?q?=E8=A2=AB=20Scroll=20=E8=A7=86=E5=8F=A3=E6=92=91=E9=A3=9E?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E5=9B=BE=E7=89=87=E5=8C=BA=E4=B8=8B?= =?UTF-8?q?=E5=9D=A0=E5=87=BA=E5=A4=A7=E7=89=87=E7=A9=BA=E7=99=BD=EF=BC=89?= =?UTF-8?q?=EF=BC=9B=E8=A3=81=E5=88=87=E5=9B=9E=20Cover=20=E5=B1=85?= =?UTF-8?q?=E4=B8=AD=EF=BC=88=E4=BA=BA=E8=84=B8=E9=80=9A=E5=B8=B8=E5=B1=85?= =?UTF-8?q?=E4=B8=AD=EF=BC=8C=E9=A1=B6=E9=83=A8=E9=94=9A=E5=AE=9A=E4=BC=9A?= =?UTF-8?q?=E5=8F=AA=E6=98=BE=E7=A4=BA=E5=A4=A9=E8=8A=B1=E6=9D=BF=EF=BC=89?= =?UTF-8?q?=EF=BC=9B=E9=80=89=E5=9B=BE/=E6=8B=8D=E7=85=A7=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8F=96=E6=B6=88=E9=9D=99=E9=BB=98=E5=8C=96=EF=BC=88?= =?UTF-8?q?13900042=20=E4=B8=8D=E5=86=8D=E8=AF=AF=E6=8A=A5=E3=80=8C?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E7=85=A7=E7=89=87=E5=A4=B1=E8=B4=A5=E3=80=8D?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 真机走查验证:布局紧贴页签、选中描边+「试戴『×××』」按钮、试戴成功自动切效果图页签、额度 3→2 递减 --- app/entry/src/main/ets/core/ImageCodec.ets | 13 +++++++++++++ .../src/main/ets/pages/HairColorPage.ets | 19 ++++++++----------- .../src/main/ets/pages/HairDesignPage.ets | 19 ++++++++----------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/app/entry/src/main/ets/core/ImageCodec.ets b/app/entry/src/main/ets/core/ImageCodec.ets index 2c24653..f1e8848 100644 --- a/app/entry/src/main/ets/core/ImageCodec.ets +++ b/app/entry/src/main/ets/core/ImageCodec.ets @@ -18,6 +18,7 @@ import { image } from '@kit.ImageKit' import { util } from '@kit.ArkTS' +import { BusinessError } from '@kit.BasicServicesKit' import { photoAccessHelper } from '@kit.MediaLibraryKit' import { cameraPicker } from '@kit.CameraKit' import { camera } from '@kit.CameraKit' @@ -70,6 +71,12 @@ export class ImageCodec { ) } + /** 用户取消判定:多数路径取消返回空数组,但预览态/部分 ROM 会 reject 13900042。 */ + private static isUserCancel(e: Object): boolean { + const code: number | undefined = (e as BusinessError).code + return code === 13900042 + } + /** 相册选 1 张。用户取消返回 undefined。 */ static async pickFromGallery(): Promise { const picker = new photoAccessHelper.PhotoViewPicker() @@ -90,6 +97,9 @@ export class ImageCodec { return { uri: res.photoUris[0], width: 0, height: 0 } } catch (e) { hilog.error(IMG_DOMAIN, IMG_TAG, 'gallery: pick failed: %{public}s', String(e)) + if (ImageCodec.isUserCancel(e)) { + return undefined // 取消不报错(页面保持原状,不弹「读取照片失败」) + } throw e as Error } } @@ -109,6 +119,9 @@ export class ImageCodec { return { uri: res.resultUri, width: 0, height: 0 } } catch (e) { hilog.error(IMG_DOMAIN, IMG_TAG, 'camera: pick failed: %{public}s', String(e)) + if (ImageCodec.isUserCancel(e)) { + return undefined // 取消不报错 + } throw e as Error } } diff --git a/app/entry/src/main/ets/pages/HairColorPage.ets b/app/entry/src/main/ets/pages/HairColorPage.ets index c812b3c..c097687 100644 --- a/app/entry/src/main/ets/pages/HairColorPage.ets +++ b/app/entry/src/main/ets/pages/HairColorPage.ets @@ -303,7 +303,8 @@ struct HairColorPage { .backgroundColor(COLOR_IMAGE_BG) .alignSelf(ItemAlign.Start) - // 图片区(单区域):无照片=上传入口;生成中=loading;按页签显示原图/效果图 + // 图片区(单区域,定高 320):无照片=上传入口;生成中=loading;按页签显示原图/效果图。 + // 注意 Stack 必须显式定高:内部额度胶囊 Row 用 height(100%),不定高会被 Scroll 视口撑飞 Stack({ alignContent: Alignment.BottomStart }) { if (this.photoUri.length === 0) { Column({ space: 6 }) { @@ -321,11 +322,9 @@ struct HairColorPage { .width('100%').height(320).justifyContent(FlexAlign.Center) .borderRadius(12).backgroundColor(COLOR_IMAGE_BG) } else if (this.imageTab === 1 && this.resultPm !== undefined) { - // 顶部对齐裁切:容器定高 clip,图片只定宽按原比缩放,头顶/发型不被居中裁掉 - Column() { - Image(this.resultPm).width('100%').objectFit(ImageFit.Cover) - } - .width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG) + // Cover 居中裁切:人脸通常在画面中央,头顶/下巴各让一点比只切下巴安全 + Image(this.resultPm) + .width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12) Text('效果图') .fontSize(11).fontColor(Color.White) .padding({ left: 10, right: 10, top: 4, bottom: 4 }) @@ -333,11 +332,8 @@ struct HairColorPage { .backgroundColor(COLOR_BADGE_BG) .margin(8) } else { - // 顶部对齐裁切:同上 - Column() { - Image(this.photoUri).width('100%').objectFit(ImageFit.Cover) - } - .width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG) + Image(this.photoUri) + .width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12) Text('原图') .fontSize(11).fontColor(Color.White) .padding({ left: 10, right: 10, top: 4, bottom: 4 }) @@ -363,6 +359,7 @@ struct HairColorPage { } } .width('100%') + .height(320) // 入口文字链:相册/拍照 + 保存(有结果才可点) Row({ space: 16 }) { diff --git a/app/entry/src/main/ets/pages/HairDesignPage.ets b/app/entry/src/main/ets/pages/HairDesignPage.ets index 9492ece..8deda87 100644 --- a/app/entry/src/main/ets/pages/HairDesignPage.ets +++ b/app/entry/src/main/ets/pages/HairDesignPage.ets @@ -340,7 +340,8 @@ struct HairDesignPage { .backgroundColor(COLOR_IMAGE_BG) .alignSelf(ItemAlign.Start) - // 图片区(单区域):无照片=上传入口;生成中=loading;按页签显示原图/效果图 + // 图片区(单区域,定高 320):无照片=上传入口;生成中=loading;按页签显示原图/效果图。 + // 注意 Stack 必须显式定高:内部额度胶囊 Row 用 height(100%),不定高会被 Scroll 视口撑飞 Stack({ alignContent: Alignment.BottomStart }) { if (this.photoUri.length === 0) { Column({ space: 6 }) { @@ -358,11 +359,9 @@ struct HairDesignPage { .width('100%').height(320).justifyContent(FlexAlign.Center) .borderRadius(12).backgroundColor(COLOR_IMAGE_BG) } else if (this.imageTab === 1 && this.resultPm !== undefined) { - // 顶部对齐裁切:容器定高 clip,图片只定宽按原比缩放,头顶/发型不被居中裁掉 - Column() { - Image(this.resultPm).width('100%').objectFit(ImageFit.Cover) - } - .width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG) + // Cover 居中裁切:人脸通常在画面中央,头顶/下巴各让一点比只切下巴安全 + Image(this.resultPm) + .width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12) Text('效果图') .fontSize(11).fontColor(Color.White) .padding({ left: 10, right: 10, top: 4, bottom: 4 }) @@ -370,11 +369,8 @@ struct HairDesignPage { .backgroundColor(COLOR_BADGE_BG) .margin(8) } else { - // 顶部对齐裁切:同上 - Column() { - Image(this.photoUri).width('100%').objectFit(ImageFit.Cover) - } - .width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG) + Image(this.photoUri) + .width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12) Text('原图') .fontSize(11).fontColor(Color.White) .padding({ left: 10, right: 10, top: 4, bottom: 4 }) @@ -400,6 +396,7 @@ struct HairDesignPage { } } .width('100%') + .height(320) // 入口文字链:相册/拍照 + 保存(有结果才可点) Row({ space: 16 }) {