hookehuyr

fix(plan): 支持从出生年月日推算年龄判断多阶段提取方案

当用户只填了生日而没填年龄时,现在可以从 birthday 自动
推算年龄,用于判断是 3 阶段还是 1 阶段提取方案。

- 新增 effectiveAge 计算属性,优先使用 age,否则从 birthday 推算
- 更新 canAddStage、canRemoveStage、initializeStages 使用有效年龄
- 监听 effectiveAge 变化而不是只监听 form.age

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 +## 2026-03-04
2 +
3 +### 16:28:49 - fix(plan): 支持从出生年月日推算年龄判断多阶段提取方案
4 +
5 +**影响文件**:
6 +- `无`
7 +
8 +**变更摘要**:
9 +- 支持从出生年月日推算年龄判断多阶段提取方案
10 +
11 +---
12 +
13 +
14 +
1 # 变更日志 15 # 变更日志
2 16
3 记录项目开发过程中的重要变更和完成任务。 17 记录项目开发过程中的重要变更和完成任务。
......
...@@ -363,6 +363,40 @@ const isMultiStageMode = computed(() => { ...@@ -363,6 +363,40 @@ const isMultiStageMode = computed(() => {
363 }) 363 })
364 364
365 /** 365 /**
366 + * 有效年龄(用于阶段判断)
367 + * @description 优先使用填写的 age,否则从 birthday 推算年龄
368 + */
369 +const effectiveAge = computed(() => {
370 + // 1. 优先使用填写的年龄
371 + if (form.age && form.age !== '') {
372 + const parsedAge = parseInt(form.age)
373 + if (!Number.isNaN(parsedAge)) {
374 + return parsedAge
375 + }
376 + }
377 +
378 + // 2. 从生日推算年龄
379 + if (form.birthday && form.birthday !== '') {
380 + const birthDate = new Date(form.birthday)
381 + if (!Number.isNaN(birthDate.getTime())) {
382 + const today = new Date()
383 + let age = today.getFullYear() - birthDate.getFullYear()
384 + const monthDiff = today.getMonth() - birthDate.getMonth()
385 +
386 + // 如果还没到生日,年龄减1
387 + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
388 + age--
389 + }
390 +
391 + return age
392 + }
393 + }
394 +
395 + // 3. 都没有,返回0
396 + return 0
397 +})
398 +
399 +/**
366 * 多阶段配置对象(便捷访问) 400 * 多阶段配置对象(便捷访问)
367 */ 401 */
368 const multiStageConfig = computed(() => { 402 const multiStageConfig = computed(() => {
...@@ -386,10 +420,10 @@ const stages = ref([]) ...@@ -386,10 +420,10 @@ const stages = ref([])
386 420
387 /** 421 /**
388 * 是否可添加阶段 422 * 是否可添加阶段
389 - * @description 年龄 ≥ 阈值且未达上限 423 + * @description 有效年龄 ≥ 阈值且未达上限
390 */ 424 */
391 const canAddStage = computed(() => { 425 const canAddStage = computed(() => {
392 - const age = parseInt(form.age) || 0 426 + const age = effectiveAge.value
393 const threshold = multiStageConfig.value.age_threshold || 12 427 const threshold = multiStageConfig.value.age_threshold || 12
394 const limit = multiStageConfig.value.stage_limit || 4 428 const limit = multiStageConfig.value.stage_limit || 4
395 return age >= threshold && stages.value.length < limit 429 return age >= threshold && stages.value.length < limit
...@@ -397,10 +431,10 @@ const canAddStage = computed(() => { ...@@ -397,10 +431,10 @@ const canAddStage = computed(() => {
397 431
398 /** 432 /**
399 * 是否可删除阶段 433 * 是否可删除阶段
400 - * @description 年龄 ≥ 阈值且至少有2个阶段 434 + * @description 有效年龄 ≥ 阈值且至少有2个阶段
401 */ 435 */
402 const canRemoveStage = computed(() => { 436 const canRemoveStage = computed(() => {
403 - const age = parseInt(form.age) || 0 437 + const age = effectiveAge.value
404 const threshold = multiStageConfig.value.age_threshold || 12 438 const threshold = multiStageConfig.value.age_threshold || 12
405 return age >= threshold && stages.value.length > 1 439 return age >= threshold && stages.value.length > 1
406 }) 440 })
...@@ -468,25 +502,26 @@ const createStage = () => { ...@@ -468,25 +502,26 @@ const createStage = () => {
468 502
469 /** 503 /**
470 * 初始化阶段数据 504 * 初始化阶段数据
471 - * @description 根据年龄初始化阶段数量: 505 + * @description 根据有效年龄初始化阶段数量:
472 * - 年龄 < 12岁:固定 3 组 506 * - 年龄 < 12岁:固定 3 组
473 * - 年龄 ≥ 12岁:初始 1 组 507 * - 年龄 ≥ 12岁:初始 1 组
508 + * - 有效年龄优先使用 age,否则从 birthday 推算
474 */ 509 */
475 const initializeStages = () => { 510 const initializeStages = () => {
476 console.log('=== initializeStages() 调用 ===') 511 console.log('=== initializeStages() 调用 ===')
477 - console.log('form.age:', form.age) 512 + console.log('form.age:', form.age, 'form.birthday:', form.birthday)
478 - const age = parseInt(form.age) || 0 513 + const age = effectiveAge.value
479 const threshold = multiStageConfig.value.age_threshold || 12 514 const threshold = multiStageConfig.value.age_threshold || 12
480 - console.log('age:', age, 'threshold:', threshold) 515 + console.log('effectiveAge:', age, 'threshold:', threshold)
481 516
482 if (age < threshold) { 517 if (age < threshold) {
483 // 固定 3 组 518 // 固定 3 组
484 stages.value = [createStage(), createStage(), createStage()] 519 stages.value = [createStage(), createStage(), createStage()]
485 - console.log('初始化 3 组阶段') 520 + console.log('初始化 3 组阶段(年龄 < 12')
486 } else { 521 } else {
487 // 初始 1 组 522 // 初始 1 组
488 stages.value = [createStage()] 523 stages.value = [createStage()]
489 - console.log('初始化 1 组阶段') 524 + console.log('初始化 1 组阶段(年龄 12')
490 } 525 }
491 console.log('stages.value:', stages.value) 526 console.log('stages.value:', stages.value)
492 } 527 }
...@@ -608,18 +643,19 @@ watch( ...@@ -608,18 +643,19 @@ watch(
608 { deep: true } 643 { deep: true }
609 ) 644 )
610 645
611 -// 监听年龄变化,重新初始化阶段(仅在多阶段模式下) 646 +// 监听有效年龄变化,重新初始化阶段(仅在多阶段模式下)
647 +// 有效年龄变化可能由 age 或 birthday 引起
612 watch( 648 watch(
613 - () => form.age, 649 + effectiveAge,
614 (newAge, oldAge) => { 650 (newAge, oldAge) => {
615 - if (isMultiStageMode.value && newAge !== oldAge && newAge !== undefined) { 651 + if (isMultiStageMode.value && newAge !== oldAge) {
616 const threshold = multiStageConfig.value.age_threshold || 12 652 const threshold = multiStageConfig.value.age_threshold || 12
617 - const newAgeInt = parseInt(newAge) || 0
618 - const oldAgeInt = parseInt(oldAge) || 0
619 653
620 // 跨越阈值时重新初始化 654 // 跨越阈值时重新初始化
621 - if ((newAgeInt < threshold && oldAgeInt >= threshold) || 655 + if ((newAge < threshold && oldAge >= threshold) ||
622 - (newAgeInt >= threshold && oldAgeInt < threshold)) { 656 + (newAge >= threshold && oldAge < threshold)) {
657 + console.log('=== 有效年龄跨越阈值,重新初始化阶段 ===')
658 + console.log('oldAge:', oldAge, 'newAge:', newAge, 'threshold:', threshold)
623 initializeStages() 659 initializeStages()
624 } 660 }
625 } 661 }
......