| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <template>
- <!-- 消息操作栏:AI 与用户消息共用,按传入能力位决定显示哪些按钮 -->
- <div class="message-actions">
- <div class="action-btn" :title="copied ? '复制成功' : '复制'" @click="emit('copy')">
- <img :src="copied ? successIcon : copyIcon" width="14" height="14" />
- </div>
- <div v-if="canRegenerate" class="action-btn" @click="emit('regenerate')" title="重新生成">
- <img :src="getCssUrl('--img-chat-regenerate-icon')" width="14" height="14" />
- </div>
- <div v-if="canEdit" class="action-btn" @click="emit('edit')" title="编辑">
- <img :src="getCssUrl('--img-chat-edit-icon')" width="14" height="14" />
- </div>
- <div v-if="message.id" class="action-btn" @click="emit('delete')" title="删除消息">
- <img :src="getCssUrl('--img-chat-delete-icon')" width="14" height="14" />
- </div>
- <div v-if="showAnswerSwitcher" class="answer-switcher">
- <div class="action-btn answer-nav-btn" :class="{ 'is-disabled': !canPrev }" @click="emit('prevAnswer')" title="上一个回答">
- <img :src="getCssUrl('--img-chat-prev-icon')" width="14" height="14" />
- </div>
- <span class="answer-switcher-text">{{ answerPosition }}</span>
- <div class="action-btn answer-nav-btn" :class="{ 'is-disabled': !canNext }" @click="emit('nextAnswer')" title="下一个回答">
- <img :src="getCssUrl('--img-chat-next-icon')" width="14" height="14" />
- </div>
- </div>
- <span v-if="message.createdAt" class="action-time">{{ formatFullTime(message.createdAt) }}</span>
- </div>
- </template>
- <script setup lang="ts">
- import dayjs from 'dayjs';
- import type { Message } from '/@/views/ventAI/manageAssistent/types/index';
- import { getCssUrl } from '/@/views/ventAI/manageAssistent/lib/index';
- /**
- * 消息操作栏。显示与否(能否重新生成/编辑、多回答切换器、是否已复制)都是父组件的状态,
- * 这里只做呈现,所有点击以事件形式交回父组件。
- */
- defineProps<{
- message: Message;
- copied: boolean;
- canEdit?: boolean;
- canRegenerate?: boolean;
- showAnswerSwitcher?: boolean;
- canPrev?: boolean;
- canNext?: boolean;
- answerPosition?: string;
- }>();
- const emit = defineEmits<{
- (e: 'copy'): void;
- (e: 'delete'): void;
- (e: 'regenerate'): void;
- (e: 'edit'): void;
- (e: 'prevAnswer'): void;
- (e: 'nextAnswer'): void;
- }>();
- const copyIcon = getCssUrl('--img-chat-copy-icon');
- const successIcon = getCssUrl('--img-chat-copy-success-icon');
- const formatFullTime = (createdAt: string) => dayjs(createdAt).format('YYYY-MM-DD HH:mm:ss');
- </script>
- <style scoped lang="less">
- .message-actions {
- display: flex;
- align-items: center;
- gap: 8px;
- width: 100%;
- opacity: 0;
- transition: opacity 0.2s;
- .action-btn {
- width: 26px;
- height: 26px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 4px;
- color: #8b949e;
- cursor: pointer;
- transition: all 0.2s;
- &:hover {
- color: #e0e6ed;
- background: rgba(10, 132, 255, 0.15);
- }
- }
- .action-time {
- font-size: 12px;
- color: #8b949e;
- }
- .answer-switcher {
- display: flex;
- align-items: center;
- gap: 2px;
- padding: 0 4px;
- border-radius: 4px;
- background: rgba(255, 255, 255, 0.04);
- .answer-nav-btn {
- width: 22px;
- height: 22px;
- &.is-disabled {
- opacity: 0.35;
- cursor: not-allowed;
- &:hover {
- background: transparent;
- color: #8b949e;
- }
- }
- }
- .answer-switcher-text {
- font-size: 12px;
- color: #8b949e;
- min-width: 32px;
- text-align: center;
- user-select: none;
- }
- }
- }
- </style>
|