150 lines
3.4 KiB
Plaintext
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>
|