Files
assistant/components/HistoryItem.uvue

150 lines
3.4 KiB
Plaintext

<template>
<view class="history-item" @tap="onTap">
<!-- Workflow color indicator -->
<view class="history-item__dot" :style="{ background: workflowColor }"></view>
<!-- Content -->
<view class="history-item__content">
<text class="history-item__title">{{ conversation.title }}</text>
<text class="history-item__preview">{{ lastMessagePreview }}</text>
</view>
<!-- Right side: time + delete -->
<view class="history-item__right">
<text class="history-item__time">{{ relativeTime }}</text>
<view class="history-item__delete" @tap.stop="onDelete">
<text class="history-item__delete-icon">🗑</text>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import type { Conversation } from '@/types/index'
import { WORKFLOWS } from '@/constants/index'
const props = defineProps<{
conversation: Conversation
}>()
const emit = defineEmits<{
tap: []
delete: []
}>()
// Find the workflow color for the dot
const workflowColor = computed<string>(() => {
const wf = WORKFLOWS.find((w) => w.id === props.conversation.workflowId)
return wf ? wf.color : '#6c5ce7'
})
// Last message preview (first 30 chars of last message)
const lastMessagePreview = computed<string>(() => {
const msgs = props.conversation.messages
if (msgs.length === 0) return '暂无消息'
const last = msgs[msgs.length - 1]
let preview = last.content.replace(/\n/g, ' ').replace(/```/g, '')
if (preview.length > 30) {
preview = preview.substring(0, 30) + '...'
}
return preview
})
// Relative time display
const relativeTime = computed<string>(() => {
const now = Date.now()
const diff = now - props.conversation.updatedAt
const minutes = Math.floor(diff / 60000)
const hours = Math.floor(diff / 3600000)
const days = Math.floor(diff / 86400000)
if (minutes < 1) return '刚刚'
if (minutes < 60) return `${minutes}分钟前`
if (hours < 24) return `${hours}小时前`
if (days < 7) return `${days}天前`
const d = new Date(props.conversation.updatedAt)
return `${d.getMonth() + 1}/${d.getDate()}`
})
function onTap(): void {
emit('tap')
}
function onDelete(): void {
emit('delete')
}
</script>
<style scoped>
.history-item {
display: flex;
flex-direction: row;
align-items: center;
padding: 20rpx 24rpx;
border-radius: 16rpx;
margin-bottom: 8rpx;
background: rgba(255, 255, 255, 0.03);
transition: background 0.2s ease;
}
.history-item:active {
background: rgba(255, 255, 255, 0.06);
}
.history-item__dot {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
flex-shrink: 0;
margin-right: 16rpx;
}
.history-item__content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.history-item__title {
font-size: 28rpx;
font-weight: 500;
color: rgba(255, 255, 255, 0.88);
margin-bottom: 6rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.history-item__preview {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.4);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.history-item__right {
display: flex;
flex-direction: column;
align-items: flex-end;
margin-left: 16rpx;
flex-shrink: 0;
}
.history-item__time {
font-size: 20rpx;
color: rgba(255, 255, 255, 0.3);
margin-bottom: 8rpx;
}
.history-item__delete {
padding: 4rpx;
}
.history-item__delete-icon {
font-size: 28rpx;
opacity: 0.6;
}
</style>