生日卡重排:方框放"还剩几天"、右侧放农历日期 + 阳历日期 (#88)
用户 2026-11-05:「还有5天,也就是10月2号,这个不好。因为"还有5天"这个事情 比较重要,所以方形框里面应该写几天,比如还有5天就写5天;现在还有5天, 那个位置应该写上10月2日。如果是农历的话,就要写上农历十月二日。 下面还要写上阳历:换算完之后,今年阳历是多少?比如11月10日, 都放在右侧"满42周岁"这个位置。」 上一版信息分工正好是**反的**:方框里放了「日」(几号),右侧放了「还有 N 天」。 用户要的相反。 重排后: 方框(84x84 浅主题色块) = **还剩几天**(大数字)+ 下方「天」/「今天」 右侧第一行 = 日期(农历生日「农历十月初二」;其余「11月16日」) 右侧第二行 = 阳历换算(**只有农历生日才画**) 右侧第三行 = 满 N 周岁 服务端 Anniversary::occurrences() 补两个**成品文字**字段: lunar_label = 「十月初二」「闰四月初五」(农历生日才有) solar_md = 「11月10日」(今年实际发生那天的公历月日) ⚠️ 农历文字为什么不在端上拼:Lunar 有完整的月名/日名对照表 (正月/冬月/腊月、初一/廿三…),端上再抄一份必然漂移, 而且闰月(闰四月)这种特例得一起处理。 ⚠️ solar_md 用 $date(今年换算后的实际日期)而不是 $a['month']/$a['day']: 农历生日的 month/day 是**农历**月日,直接拼出来会是错的公历。 ⚠️ 公历生日时 dateSolar() 返回空串 ⇒ 不画第二行: 那时第一行已经是「11月16日」,再画一次一模一样,纯噪音。 ⚠️ days = 0(就是今天)时方框写「今」而不是「0」: 0 看着像没数据,而且底下那行写「今天」,配成「今 / 今天」很奇怪。 实测服务端输出: 高雪玉 的农历生日 days=5 lunar=十月初二 solar=11月10日 date=2026-11-10 领证纪念日 days=7 lunar=(空) solar=11月12日 date=2026-11-12 杨永全 的农历生日 days=8 lunar=十月初五 solar=11月13日 date=2026-11-13 杨永全 的生日 days=11 lunar=(空) solar=11月16日 date=2026-11-16 刘巧莲 的农历生日 days=29 lunar=十月廿六 solar=12月4日 date=2026-12-04 编译通过,已装真机。
This commit is contained in:
@@ -110,35 +110,56 @@ export struct FbDayBirthdaySheet {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生日是「几号」—— 卡片正中的那个大数字。
|
||||
* 方框里的大数字:**还剩几天**。
|
||||
*
|
||||
* ⚠️ 优先用 `day`(用户填的那一天);为 0 才从 `date` 里截。
|
||||
* 农历生日的 `day` 是农历日,与 `date` 的公历日**不一样**,
|
||||
* 用户要看的是"生日那天"。
|
||||
* 🔴 #88(用户 2026-11-05):「"还有5天"这个事情比较重要,
|
||||
* 所以方形框里面应该写几天,比如还有5天就写5天。」
|
||||
*
|
||||
* ⚠️ 就是今天(days = 0)时返回「今」而不是「0」——
|
||||
* 0 看着像"没有数据",而且底下那行会写「今天」,配成「今 / 今天」很奇怪。
|
||||
*/
|
||||
private dayNum(): string {
|
||||
private daysNum(): string {
|
||||
const d: FbRecentDay | null = this.item;
|
||||
if (d === null) {
|
||||
return '';
|
||||
}
|
||||
if (d.day > 0) {
|
||||
return d.day.toString();
|
||||
}
|
||||
const dd: number = d.date.length >= 10 ? parseInt(d.date.substring(8, 10), 10) : 0;
|
||||
return dd > 0 ? dd.toString() : '';
|
||||
return d.days === 0 ? '今' : d.days.toString();
|
||||
}
|
||||
|
||||
/** 「11 月」—— 与「几号」配成「11 月 16 日」的读法 */
|
||||
private monthWord(): string {
|
||||
/**
|
||||
* 右侧第一行:这条纪念日的日期写法。
|
||||
*
|
||||
* · 农历生日 → 「十月初二」(服务端 `lunarLabel`)
|
||||
* · 公历生日 / 自建纪念日 → 「11月16日」(服务端 `solarMd`)
|
||||
*
|
||||
* ⚠️ 「农历十月二日」里的「十月」+「初二」在服务端已拼成「十月初二」,
|
||||
* 这里只补一个「农历」前缀把类别点明(用户原话就是这么念的)。
|
||||
*/
|
||||
private datePrimary(): string {
|
||||
const d: FbRecentDay | null = this.item;
|
||||
if (d === null) {
|
||||
return '';
|
||||
}
|
||||
if (d.month > 0) {
|
||||
return d.month.toString() + ' 月';
|
||||
if (d.lunarLabel !== '') {
|
||||
return '农历' + d.lunarLabel;
|
||||
}
|
||||
const mm: number = d.date.length >= 7 ? parseInt(d.date.substring(5, 7), 10) : 0;
|
||||
return mm > 0 ? mm.toString() + ' 月' : '';
|
||||
return d.solarMd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 右侧第二行:阳历换算(**只有农历生日才需要**)。
|
||||
*
|
||||
* 🔴 #88:「下面还要写上阳历:换算完之后,今年阳历是多少?比如11月10日」
|
||||
*
|
||||
* ⚠️ 公历生日返回空串 ⇒ 不画这一行:
|
||||
* 那时第一行已经是「11月16日」,再画一次一模一样,纯噪音。
|
||||
*/
|
||||
private dateSolar(): string {
|
||||
const d: FbRecentDay | null = this.item;
|
||||
if (d === null || d.lunarLabel === '' || d.solarMd === '') {
|
||||
return '';
|
||||
}
|
||||
return '阳历 ' + d.solarMd;
|
||||
}
|
||||
|
||||
/** 完整日期 `2026 年 11 月 16 日`(下一次发生的公历日期) */
|
||||
@@ -153,19 +174,6 @@ export struct FbDayBirthdaySheet {
|
||||
return y.toString() + ' 年 ' + m.toString() + ' 月 ' + dd.toString() + ' 日';
|
||||
}
|
||||
|
||||
/** 「还有 12 天」/「就是今天」 */
|
||||
private daysWord(): string {
|
||||
const d: FbRecentDay | null = this.item;
|
||||
if (d === null) {
|
||||
return '';
|
||||
}
|
||||
if (d.days === 0) {
|
||||
return '就是今天';
|
||||
}
|
||||
return '还有 ' + d.days.toString() + ' 天';
|
||||
}
|
||||
|
||||
/** 是农历生日吗(决定副标题写「农历生日」还是「生日」) */
|
||||
private isLunar(): boolean {
|
||||
const d: FbRecentDay | null = this.item;
|
||||
return d !== null && d.source === 'birthday_lunar';
|
||||
@@ -248,17 +256,33 @@ export struct FbDayBirthdaySheet {
|
||||
.padding({ top: 4, bottom: 18 })
|
||||
.alignItems(VerticalAlign.Center)
|
||||
|
||||
/* ---- 「几号」大字块 + 剩余天数 ---- */
|
||||
/* 用户第 2 条:「显示…生日的『日』和日期就可以了」
|
||||
⇒ 把「日」做成一个视觉焦点(大数字),日期在下面一行小字。
|
||||
底色用浅一档主题色(fbMixWhite 0.91),与下拉框/胶囊同一套。 */
|
||||
Row({ space: 12 }) {
|
||||
Column({ space: 0 }) {
|
||||
Text(this.dayNum())
|
||||
/* ---- 方框(还剩几天)+ 右侧(日期 / 年龄)----
|
||||
🔴🔴 #88(用户 2026-11-05):
|
||||
「还有5天,也就是10月2号,这个不好。因为"还有5天"这个事情比较重要,
|
||||
所以方形框里面应该写几天,比如还有5天就写5天;
|
||||
现在还有5天,那个位置应该写上10月2日。
|
||||
如果是农历的话,就要写上农历十月二日。下面还要写上阳历:
|
||||
换算完之后,今年阳历是多少?比如11月10日,
|
||||
都放在右侧"满42周岁"这个位置。」
|
||||
|
||||
⇒ 信息分工重排(上一版正好是反的:方框放"几号"、右侧放"还有几天"):
|
||||
方框 = **还剩几天**(用户说这件事最重要,要大)
|
||||
右侧第一行 = 日期(农历生日写「十月初二」,公历生日写「11月16日」)
|
||||
右侧第二行 = 阳历换算(农历生日才需要;公历生日与第一行重复,不画)
|
||||
右侧第三行 = 满 N 周岁
|
||||
|
||||
⚠️ 「还剩几天」为什么不做成"5 天"两个单位分开:
|
||||
30 以上是两位数,分开排会挤;`fontSize(34)` 放「12」正好。
|
||||
⚠️ 农历生日的两行日期**不是同一天**(十月初二 ↔ 11月10日),
|
||||
所以必须都画;公历生日两行会一模一样,只画一行。 */
|
||||
Row({ space: 14 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text(this.daysNum())
|
||||
.fontSize(34)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor(this.accent)
|
||||
Text(this.monthWord())
|
||||
/* 「还有 5 天」的时候,这一行是「天」;就是今天时写「今天」 */
|
||||
Text(this.item !== null && this.item.days === 0 ? '今天' : '天')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(fbMixWhite(this.accent, 0.35))
|
||||
}
|
||||
@@ -269,21 +293,22 @@ export struct FbDayBirthdaySheet {
|
||||
.borderRadius(FbMetric.radiusS)
|
||||
|
||||
Column({ space: 6 }) {
|
||||
Text(this.daysWord())
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
/* 第一行:日期 */
|
||||
Text(this.datePrimary())
|
||||
.fontSize(FbMetric.fontBody)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(this.accent)
|
||||
if (this.item !== null && this.item.age >= 0) {
|
||||
Text('满 ' + this.item.age.toString() + ' 周岁')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
/* 第二行:阳历换算(只有农历生日才画) */
|
||||
if (this.dateSolar() !== '') {
|
||||
Text(this.dateSolar())
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.muted)
|
||||
}
|
||||
if (this.isLunar()) {
|
||||
/* 农历生日时「日」是农历日,与上面的公历日期不同 ——
|
||||
不说明一句用户会以为"日子算错了"。 */
|
||||
Text('农历日期,每年按农历换算')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
/* 第三行:满 N 周岁 */
|
||||
if (this.item !== null && this.item.age >= 0) {
|
||||
Text('满 ' + this.item.age.toString() + ' 周岁')
|
||||
.fontSize(FbMetric.fontSmall)
|
||||
.fontColor(FbColors.muted)
|
||||
}
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
|
||||
@@ -187,6 +187,8 @@ interface RawRecentDay {
|
||||
/* #87:生日只读卡要用(服务端 Anniversary::occurrences 已输出) */
|
||||
person_name?: string | null; avatar?: string | null; avatar_color?: string | null;
|
||||
day?: number | null; month?: number | null;
|
||||
/* #88:卡片右侧的两种日期写法(服务端给成品文字) */
|
||||
lunar_label?: string | null; solar_md?: string | null;
|
||||
}
|
||||
|
||||
interface RawTaskBoard {
|
||||
@@ -921,6 +923,8 @@ export function parseRecentDays(v: Object | null | undefined): FbRecentDay[] {
|
||||
avatarColor: s(r.avatar_color),
|
||||
day: r.day !== null && r.day !== undefined ? n(r.day) : 0,
|
||||
month: r.month !== null && r.month !== undefined ? n(r.month) : 0,
|
||||
lunarLabel: s(r.lunar_label),
|
||||
solarMd: s(r.solar_md),
|
||||
};
|
||||
out.push(it);
|
||||
}
|
||||
|
||||
@@ -238,6 +238,25 @@ export interface FbRecentDay {
|
||||
day: number;
|
||||
/** 「月」—— 同理(农历生日的月份是农历月) */
|
||||
month: number;
|
||||
/**
|
||||
* 农历写法的成品文字,如「十月初二」「闰四月初五」。
|
||||
* 只有农历生日才有;公历生日 / 自建纪念日为**空串**。
|
||||
*
|
||||
* 🔴 #88(用户 2026-11-05):「如果是农历的话,就要写上农历十月二日。」
|
||||
* ⚠️ 为什么由服务端给成品:`Lunar` 有完整的月名/日名对照表
|
||||
* (正月/冬月/腊月、初一/廿三…),端上再抄一份必然漂移,
|
||||
* 闰月(闰四月)这种特例也得一起处理。
|
||||
*/
|
||||
lunarLabel: string;
|
||||
/**
|
||||
* 今年实际发生那天的公历月日,如「11月10日」。
|
||||
*
|
||||
* 🔴 #88(用户 2026-11-05):「下面还要写上阳历:换算完之后,今年阳历是多少?
|
||||
* 比如11月10日,都放在右侧『满42周岁』这个位置。」
|
||||
* ⚠️ 农历生日时它与 `lunarLabel` **不是同一天**(一个农历一个公历),
|
||||
* 这正是用户要同时看到两个的原因。
|
||||
*/
|
||||
solarMd: string;
|
||||
}
|
||||
|
||||
/** 首页「模块卡片」—— 一块一块的入口,带一句关键数字 */
|
||||
|
||||
Reference in New Issue
Block a user