feat: 任务卡片展示创建时间
- 元信息行右侧新增「创建于 M月D日」,与「完成于」互斥:已完成卡片仍只显示 完成日期,避免两个时间挤占同一行把标签推到第二行 - 精确到分钟的时刻保留在 span 的 title 与卡片 title 中 - 「完成于」补 whitespace-nowrap,窄列下不再拆行 - 补充单元测试:待办/进行中显示创建日期、已完成不叠加、createdAt 非法时不渲染
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user