feat(app): all album date displays date-only — formatAlbumDateTime drops HH:mm
相册列表卡/详情信息/分享页 meta/照片查看器日期一律纯日期(y/M/d)。 全量测试断言同步;397/397 全绿。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -57,7 +57,8 @@ String formatAlbumDateTime(
|
|||||||
String locale,
|
String locale,
|
||||||
) {
|
) {
|
||||||
final zoned = tryToAlbumZone(utcInstant, timeZone) ?? utcInstant.toUtc();
|
final zoned = tryToAlbumZone(utcInstant, timeZone) ?? utcInstant.toUtc();
|
||||||
return DateFormat('y/M/d HH:mm', locale).format(zoned);
|
// UI06(用户需求 2026-09-24):相册日期一律纯日期显示(不带 HH:mm)。
|
||||||
|
return DateFormat('y/M/d', locale).format(zoned);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 相册墙钟(表单里选择的日期时间,设备本地时区标记的 naive 值)→
|
/// 相册墙钟(表单里选择的日期时间,设备本地时区标记的 naive 值)→
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ void main() {
|
|||||||
|
|
||||||
test('UTC 瞬间按 Asia/Shanghai 展示(intl 格式化)', () {
|
test('UTC 瞬间按 Asia/Shanghai 展示(intl 格式化)', () {
|
||||||
final utc = DateTime.utc(2026, 9, 18, 6, 30);
|
final utc = DateTime.utc(2026, 9, 18, 6, 30);
|
||||||
expect(formatAlbumDateTime(utc, 'Asia/Shanghai', 'en'), '2026/9/18 14:30');
|
expect(formatAlbumDateTime(utc, 'Asia/Shanghai', 'en'), '2026/9/18');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('非 Asia/Shanghai 时区亦按各自墙钟展示(America/New_York)', () {
|
test('非 Asia/Shanghai 时区亦按各自墙钟展示(America/New_York)', () {
|
||||||
@@ -21,13 +21,13 @@ void main() {
|
|||||||
// 9 月为纽约夏令时 UTC-4 → 02:30。
|
// 9 月为纽约夏令时 UTC-4 → 02:30。
|
||||||
expect(
|
expect(
|
||||||
formatAlbumDateTime(utc, 'America/New_York', 'en'),
|
formatAlbumDateTime(utc, 'America/New_York', 'en'),
|
||||||
'2026/9/18 02:30',
|
'2026/9/18',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('无效时区回退 UTC 展示', () {
|
test('无效时区回退 UTC 展示', () {
|
||||||
final utc = DateTime.utc(2026, 9, 18, 6, 30);
|
final utc = DateTime.utc(2026, 9, 18, 6, 30);
|
||||||
expect(formatAlbumDateTime(utc, 'Mars/Olympus', 'en'), '2026/9/18 06:30');
|
expect(formatAlbumDateTime(utc, 'Mars/Olympus', 'en'), '2026/9/18');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('墙钟 → UTC 往返一致(表单提交与回显)', () {
|
test('墙钟 → UTC 往返一致(表单提交与回显)', () {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ void main() {
|
|||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
find.text('2026/9/18 14:30 ~ Not set (Asia/Shanghai) · 大宴会厅'),
|
find.text('2026/9/18 ~ Not set (Asia/Shanghai) · 大宴会厅'),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
expect(find.byIcon(Icons.image_outlined), findsOneWidget);
|
expect(find.byIcon(Icons.image_outlined), findsOneWidget);
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ void main() {
|
|||||||
// 信息栏:上传者 / 相册时区墙钟·尺寸·大小 / 真实状态 / ID 诊断区。
|
// 信息栏:上传者 / 相册时区墙钟·尺寸·大小 / 真实状态 / ID 诊断区。
|
||||||
expect(find.text('Uploaded by Staff Two'), findsOneWidget);
|
expect(find.text('Uploaded by Staff Two'), findsOneWidget);
|
||||||
// uploadedAt 07:00Z → 相册时区上海 15:00;4000×3000 · 121 KB。
|
// uploadedAt 07:00Z → 相册时区上海 15:00;4000×3000 · 121 KB。
|
||||||
expect(find.text('2026/9/18 15:00 · 4000×3000 · 121 KB'), findsOneWidget);
|
expect(find.text('2026/9/18 · 4000×3000 · 121 KB'), findsOneWidget);
|
||||||
expect(find.text('Status: Published'), findsOneWidget);
|
expect(find.text('Status: Published'), findsOneWidget);
|
||||||
expect(find.text('ph-info-1'), findsOneWidget);
|
expect(find.text('ph-info-1'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ void main() {
|
|||||||
final title = tester.widget<Text>(find.text('Opening Gala'));
|
final title = tester.widget<Text>(find.text('Opening Gala'));
|
||||||
expect(title.style?.color, Colors.white);
|
expect(title.style?.color, Colors.white);
|
||||||
final meta = tester.widget<Text>(
|
final meta = tester.widget<Text>(
|
||||||
find.text('2026/9/18 14:30 ~ Not set · 大宴会厅'),
|
find.text('2026/9/18 ~ Not set · 大宴会厅'),
|
||||||
);
|
);
|
||||||
expect(meta.style?.color, Colors.white70);
|
expect(meta.style?.color, Colors.white70);
|
||||||
// 底部暗色渐变叠层存在(LinearGradient 的 DecoratedBox)。
|
// 底部暗色渐变叠层存在(LinearGradient 的 DecoratedBox)。
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ void main() {
|
|||||||
// 标题按界面语言回退(en → en 翻译),最多两行。
|
// 标题按界面语言回退(en → en 翻译),最多两行。
|
||||||
expect(find.text('Opening Gala'), findsOneWidget);
|
expect(find.text('Opening Gala'), findsOneWidget);
|
||||||
// 时间用相册时区(上海墙钟 14:30)+ 场地(en 未填场地回退 zh-CN)。
|
// 时间用相册时区(上海墙钟 14:30)+ 场地(en 未填场地回退 zh-CN)。
|
||||||
expect(find.text('2026/9/18 14:30 ~ Not set · 大宴会厅'), findsOneWidget);
|
expect(find.text('2026/9/18 ~ Not set · 大宴会厅'), findsOneWidget);
|
||||||
// 封面未配置 → 固定 16:9 中性占位(非转圈)。
|
// 封面未配置 → 固定 16:9 中性占位(非转圈)。
|
||||||
expect(find.byType(PhotoThumbnail), findsOneWidget);
|
expect(find.byType(PhotoThumbnail), findsOneWidget);
|
||||||
expect(find.byIcon(Icons.image_outlined), findsOneWidget);
|
expect(find.byIcon(Icons.image_outlined), findsOneWidget);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ void main() {
|
|||||||
// 名称与日期地点(en 回退:Opening Gala;上海墙钟 14:30)。
|
// 名称与日期地点(en 回退:Opening Gala;上海墙钟 14:30)。
|
||||||
expect(find.text('Opening Gala'), findsOneWidget);
|
expect(find.text('Opening Gala'), findsOneWidget);
|
||||||
expect(
|
expect(
|
||||||
find.text('2026/9/18 14:30 · 大宴会厅'),
|
find.text('2026/9/18 · 大宴会厅'),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
reason: '开始时间(相册时区;结束未定不伪造区间)+ 场地(展示回退链)',
|
reason: '开始时间(相册时区;结束未定不伪造区间)+ 场地(展示回退链)',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -73,10 +73,6 @@ watch(
|
|||||||
watch([titleEl, descEl, titleExpanded, descExpanded], () => measureOverflow(), { flush: 'post' });
|
watch([titleEl, descEl, titleExpanded, descExpanded], () => measureOverflow(), { flush: 'post' });
|
||||||
|
|
||||||
// —— 元信息行 ——
|
// —— 元信息行 ——
|
||||||
const viewsText = computed(() => {
|
|
||||||
if (props.viewCount === null) return t('viewer.viewsUnknown');
|
|
||||||
return t('viewer.views', { count: new Intl.NumberFormat(locale.value).format(props.viewCount) });
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 紧凑日期(无时分):首页元信息行用;窄屏也不爆宽。 */
|
/** 紧凑日期(无时分):首页元信息行用;窄屏也不爆宽。 */
|
||||||
const dateText = computed(() => formatDate({ year: 'numeric', month: 'long', day: 'numeric' }));
|
const dateText = computed(() => formatDate({ year: 'numeric', month: 'long', day: 'numeric' }));
|
||||||
@@ -205,10 +201,7 @@ watch(
|
|||||||
|
|
||||||
<!-- 参考稿:元信息行用简洁 Unicode 图标(◉ 浏览 / ▦ 日期 / ♧ 地点) -->
|
<!-- 参考稿:元信息行用简洁 Unicode 图标(◉ 浏览 / ▦ 日期 / ♧ 地点) -->
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="meta-item view-count">
|
<!-- 浏览次数已按用户要求隐藏(2026-09-24)——后端计数与上报不受影响。 -->
|
||||||
<span class="meta-icon" aria-hidden="true">◉</span>
|
|
||||||
<span>{{ viewsText }}</span>
|
|
||||||
</span>
|
|
||||||
<span v-if="dateText !== ''" class="meta-item" :title="dateFullText">
|
<span v-if="dateText !== ''" class="meta-item" :title="dateFullText">
|
||||||
<span class="meta-icon" aria-hidden="true">▦</span>
|
<span class="meta-icon" aria-hidden="true">▦</span>
|
||||||
<span>{{ dateText }}</span>
|
<span>{{ dateText }}</span>
|
||||||
@@ -392,9 +385,6 @@ watch(
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.view-count {
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— 排序 tab(参考稿:分隔线由上方元信息行承担;选中项 2px 底线) —— */
|
/* —— 排序 tab(参考稿:分隔线由上方元信息行承担;选中项 2px 底线) —— */
|
||||||
.sort-tabs {
|
.sort-tabs {
|
||||||
|
|||||||
Reference in New Issue
Block a user