feat: 任务卡片展示创建时间
CI / verify (push) Successful in 2m5s
CI / 部署到服务器 (push) Successful in 31s

- 元信息行右侧新增「创建于 M月D日」,与「完成于」互斥:已完成卡片仍只显示
  完成日期,避免两个时间挤占同一行把标签推到第二行
- 精确到分钟的时刻保留在 span 的 title 与卡片 title 中
- 「完成于」补 whitespace-nowrap,窄列下不再拆行
- 补充单元测试:待办/进行中显示创建日期、已完成不叠加、createdAt 非法时不渲染
This commit is contained in:
chenshoulin
2026-10-29 16:09:34 +08:00
parent 23fed50734
commit 6cbc0cfc0f
2 changed files with 52 additions and 1 deletions
+34
View File
@@ -173,6 +173,40 @@ describe('时间信息', () => {
expect(mountCard({ completedAt: null }).text()).not.toContain('完成于')
})
it('未完成卡片显示创建日期', () => {
const createdAt = new Date(2026, 9, 8, 9, 30).toISOString()
const wrapper = mountCard({ status: 'todo', createdAt })
const badge = wrapper.find('[data-role="created-at"]')
expect(badge.exists()).toBe(true)
expect(badge.text()).toBe('创建于 10月8日')
// 精确时刻放在 title,悬停即可看到
expect(badge.attributes('title')).toBe('创建于 2026-10-08 09:30')
})
it('进行中的卡片同样显示创建日期', () => {
const createdAt = new Date(2026, 9, 20, 14, 0).toISOString()
const badge = mountCard({ status: 'doing', createdAt }).find('[data-role="created-at"]')
expect(badge.exists()).toBe(true)
expect(badge.text()).toBe('创建于 10月20日')
})
it('已完成卡片只显示完成日期,不叠加创建日期', () => {
const createdAt = new Date(2026, 9, 8, 9, 30).toISOString()
const completedAt = new Date(2026, 9, 18, 10, 20).toISOString()
const wrapper = mountCard({ status: 'done', createdAt, completedAt })
expect(wrapper.text()).toContain('完成于')
expect(wrapper.find('[data-role="created-at"]').exists()).toBe(false)
})
it('创建时间无效时不渲染创建日期', () => {
expect(mountCard({ createdAt: 'not-a-date' }).find('[data-role="created-at"]').exists()).toBe(
false,
)
})
it('卡片 title 暴露完整创建与完成时间', () => {
const createdAt = new Date(2026, 9, 18, 10, 8).toISOString()
const completedAt = new Date(2026, 9, 18, 10, 20).toISOString()
+18 -1
View File
@@ -89,6 +89,14 @@ const hiddenTagCount = computed(() => Math.max(0, props.task.tags.length - MAX_V
const completedAtFull = computed(() => formatDateTime(props.task.completedAt))
const completedAtShort = computed(() => formatCompactDate(props.task.completedAt))
/**
* 创建时间:未完成卡片在元信息行右侧补一行短日期,用来判断这条待办躺了多久。
* 与「完成于」互斥 —— 已完成卡片右侧已被完成日期占用,再叠一个会把标签挤到第二行,
* 而且回顾已完成任务时更关心「什么时候做完的」。精确到分钟的时刻仍在 `title` 里。
*/
const createdAtShort = computed(() => formatCompactDate(props.task.createdAt))
const showCreatedAt = computed(() => !isDone.value && createdAtShort.value !== null)
/** 悬停卡片即可看到完整时间,不必先打开详情抽屉 */
const timeTitle = computed(() => {
const lines = [`创建于 ${formatDateTime(props.task.createdAt) ?? '—'}`]
@@ -269,10 +277,19 @@ const priorityTextClass = computed(() => {
v-if="completedAtShort"
data-role="completed-at"
:title="`完成于 ${completedAtFull}`"
class="ml-auto text-emerald-700 dark:text-emerald-400"
class="ml-auto whitespace-nowrap text-emerald-700 dark:text-emerald-400"
>
完成于 {{ completedAtShort }}
</span>
<span
v-else-if="showCreatedAt"
data-role="created-at"
:title="`创建于 ${formatDateTime(task.createdAt) ?? '—'}`"
class="ml-auto whitespace-nowrap text-slate-500 dark:text-zinc-400"
>
创建于 {{ createdAtShort }}
</span>
</div>
</div>
</article>