fix(app): 我的页 Tab 内嵌修复 + 身高体重改滚轮选择器——ProfileContent 组件化(占位+跳页方案把用户锁死在独立路由页,只能登出);身高 100-250/体重 25-300 滚轮选择(showTextPickerDialog),不再键盘输入
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
* ReportCreatePage —— 报告创建(F3):问卷六字段 + 模拟照片键 + 提交 + 任务轮询。
|
||||
*
|
||||
* 流程:
|
||||
* 1) 问卷表单(性别/身高/体重/生日/核心诉求多选/心理风格九型),提交前前端校验
|
||||
* 1) 问卷表单(性别/身高/体重/生日/核心诉求多选/心理风格九型),提交前前端校验;
|
||||
* 身高/体重为滚轮选择器(showTextPickerDialog),不提供键盘输入
|
||||
* 2) 照片键为模拟:V1 骨架 COS 直传未接入,留空自动生成 report_photo/{userId}/{随机}.jpg
|
||||
* 3) POST /api/v1/reports(request_key 随机 hex;失败重试沿用同一 key,服务端幂等重放)
|
||||
* 4) 40920(本期已生成)→ 页内对话框:可跳最近一次报告(AppStorage 记录),
|
||||
@@ -24,6 +25,25 @@ const GOAL_OPTIONS: string[] = ['显高', '显瘦', '显白', '显气质', '遮
|
||||
const STYLE_OPTIONS: string[] = ['戏剧', '睿智', '自然', '古典', '优雅', '浪漫', '前卫', '少女', '少年']
|
||||
const LAST_REPORT_STORAGE_KEY: string = 'f3_last_report_id'
|
||||
|
||||
// 身高/体重改为选择器(不允许键盘输入):数值范围与原校验一致
|
||||
const HEIGHT_MIN: number = 100
|
||||
const HEIGHT_MAX: number = 250
|
||||
const HEIGHT_DEFAULT: number = 165
|
||||
const WEIGHT_MIN: number = 25
|
||||
const WEIGHT_MAX: number = 300
|
||||
const WEIGHT_DEFAULT: number = 52
|
||||
|
||||
function buildRangeOptions(min: number, max: number): string[] {
|
||||
const arr: string[] = []
|
||||
for (let v = min; v <= max; v++) {
|
||||
arr.push(`${v}`)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
const HEIGHT_OPTIONS: string[] = buildRangeOptions(HEIGHT_MIN, HEIGHT_MAX)
|
||||
const WEIGHT_OPTIONS: string[] = buildRangeOptions(WEIGHT_MIN, WEIGHT_MAX)
|
||||
|
||||
interface FieldLabelParams {
|
||||
label: string
|
||||
err: string
|
||||
@@ -66,23 +86,18 @@ struct ReportCreatePage {
|
||||
}
|
||||
}
|
||||
|
||||
private isNumeric(s: string): boolean {
|
||||
return /^\d+(\.\d+)?$/.test(s.trim())
|
||||
}
|
||||
|
||||
private validateForm(): boolean {
|
||||
let ok = true
|
||||
this.genderErr = this.gender === '' ? '请选择性别' : ''
|
||||
if (this.genderErr !== '') {
|
||||
ok = false
|
||||
}
|
||||
const h = Number(this.heightInput)
|
||||
this.heightErr = !this.isNumeric(this.heightInput) || h < 100 || h > 250 ? '需为 100~250' : ''
|
||||
// 选择器产出必然在合法区间,未选才是唯一错误态
|
||||
this.heightErr = this.heightInput === '' ? '请选择身高' : ''
|
||||
if (this.heightErr !== '') {
|
||||
ok = false
|
||||
}
|
||||
const w = Number(this.weightInput)
|
||||
this.weightErr = !this.isNumeric(this.weightInput) || w < 25 || w > 300 ? '需为 25~300' : ''
|
||||
this.weightErr = this.weightInput === '' ? '请选择体重' : ''
|
||||
if (this.weightErr !== '') {
|
||||
ok = false
|
||||
}
|
||||
@@ -111,6 +126,46 @@ struct ReportCreatePage {
|
||||
return this.coreGoals.indexOf(g) >= 0
|
||||
}
|
||||
|
||||
/** TextPickerResult.index 是联合类型(多列选择器为数组),单列取数字下标。 */
|
||||
private pickIndex(v: TextPickerResult): number {
|
||||
return typeof v.index === 'number' ? v.index : -1
|
||||
}
|
||||
|
||||
/** 已有值从当前值滚起,未选过从常见默认值(165cm)滚起。 */
|
||||
private openHeightPicker(): void {
|
||||
const cur = this.heightInput !== '' ? Number(this.heightInput) : HEIGHT_DEFAULT
|
||||
const clamped = Math.min(Math.max(cur - HEIGHT_MIN, 0), HEIGHT_OPTIONS.length - 1)
|
||||
this.getUIContext().showTextPickerDialog({
|
||||
range: HEIGHT_OPTIONS,
|
||||
selected: clamped,
|
||||
canLoop: false,
|
||||
onAccept: (value: TextPickerResult) => {
|
||||
const idx = this.pickIndex(value)
|
||||
if (idx >= 0 && idx < HEIGHT_OPTIONS.length) {
|
||||
this.heightInput = HEIGHT_OPTIONS[idx]
|
||||
this.heightErr = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private openWeightPicker(): void {
|
||||
const cur = this.weightInput !== '' ? Number(this.weightInput) : WEIGHT_DEFAULT
|
||||
const clamped = Math.min(Math.max(cur - WEIGHT_MIN, 0), WEIGHT_OPTIONS.length - 1)
|
||||
this.getUIContext().showTextPickerDialog({
|
||||
range: WEIGHT_OPTIONS,
|
||||
selected: clamped,
|
||||
canLoop: false,
|
||||
onAccept: (value: TextPickerResult) => {
|
||||
const idx = this.pickIndex(value)
|
||||
if (idx >= 0 && idx < WEIGHT_OPTIONS.length) {
|
||||
this.weightInput = WEIGHT_OPTIONS[idx]
|
||||
this.weightErr = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private onSubmitTap(): void {
|
||||
if (this.submitting) {
|
||||
return
|
||||
@@ -349,16 +404,23 @@ struct ReportCreatePage {
|
||||
Row({ space: 12 }) {
|
||||
Column({ space: 8 }) {
|
||||
this.FieldLabel({ label: '身高 (cm)', err: this.heightErr, required: true })
|
||||
TextInput({ placeholder: '如 165', text: this.heightInput })
|
||||
.type(InputType.Number)
|
||||
.height(44)
|
||||
.fontSize(14)
|
||||
.backgroundColor('#F5F6F8')
|
||||
.borderRadius(10)
|
||||
.onChange((v: string) => {
|
||||
this.heightInput = v
|
||||
this.heightErr = ''
|
||||
})
|
||||
Row() {
|
||||
Text(this.heightInput === '' ? '请选择' : `${this.heightInput} cm`)
|
||||
.fontSize(14)
|
||||
.fontColor(this.heightInput === '' ? '#AAAAAA' : '#333333')
|
||||
.layoutWeight(1)
|
||||
Text('▼')
|
||||
.fontSize(10)
|
||||
.fontColor('#999999')
|
||||
}
|
||||
.height(44)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#F5F6F8')
|
||||
.borderRadius(10)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.onClick(() => {
|
||||
this.openHeightPicker()
|
||||
})
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
@@ -366,16 +428,23 @@ struct ReportCreatePage {
|
||||
|
||||
Column({ space: 8 }) {
|
||||
this.FieldLabel({ label: '体重 (kg)', err: this.weightErr, required: true })
|
||||
TextInput({ placeholder: '如 52', text: this.weightInput })
|
||||
.type(InputType.Number)
|
||||
.height(44)
|
||||
.fontSize(14)
|
||||
.backgroundColor('#F5F6F8')
|
||||
.borderRadius(10)
|
||||
.onChange((v: string) => {
|
||||
this.weightInput = v
|
||||
this.weightErr = ''
|
||||
})
|
||||
Row() {
|
||||
Text(this.weightInput === '' ? '请选择' : `${this.weightInput} kg`)
|
||||
.fontSize(14)
|
||||
.fontColor(this.weightInput === '' ? '#AAAAAA' : '#333333')
|
||||
.layoutWeight(1)
|
||||
Text('▼')
|
||||
.fontSize(10)
|
||||
.fontColor('#999999')
|
||||
}
|
||||
.height(44)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.backgroundColor('#F5F6F8')
|
||||
.borderRadius(10)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.onClick(() => {
|
||||
this.openWeightPicker()
|
||||
})
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
|
||||
Reference in New Issue
Block a user