feat: 消息ui优化
This commit is contained in:
@@ -6,7 +6,7 @@ import type { BubbleListInstance } from 'vue-element-plus-x/types/BubbleList';
|
|||||||
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
|
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
|
||||||
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
||||||
import type { UnifiedMessage } from '@/utils/apiFormatConverter';
|
import type { UnifiedMessage } from '@/utils/apiFormatConverter';
|
||||||
import { ArrowLeftBold, ArrowRightBold, Clock, Delete, Document, DocumentCopy, Edit, Loading, Refresh } from '@element-plus/icons-vue';
|
import { ArrowLeftBold, ArrowRightBold, Delete, Document, DocumentCopy, Edit, Loading, Refresh } from '@element-plus/icons-vue';
|
||||||
import { ElIcon, ElMessage } from 'element-plus';
|
import { ElIcon, ElMessage } from 'element-plus';
|
||||||
import { useHookFetch } from 'hook-fetch/vue';
|
import { useHookFetch } from 'hook-fetch/vue';
|
||||||
import mammoth from 'mammoth';
|
import mammoth from 'mammoth';
|
||||||
@@ -532,13 +532,9 @@ function enterDeleteMode(item?: MessageItem) {
|
|||||||
selectedMessageIds.value = [];
|
selectedMessageIds.value = [];
|
||||||
deleteTargetMessage.value = item || null;
|
deleteTargetMessage.value = item || null;
|
||||||
|
|
||||||
// 如果指定了消息,自动选中该消息及其之后的所有消息
|
// 如果指定了消息,只自动选中当前点击的这条消息
|
||||||
if (item && item.id) {
|
if (item && item.id) {
|
||||||
const itemIndex = bubbleItems.value.findIndex(msg => msg.key === item.key);
|
selectedMessageIds.value = [item.id];
|
||||||
if (itemIndex !== -1) {
|
|
||||||
const messagesToDelete = bubbleItems.value.slice(itemIndex);
|
|
||||||
selectedMessageIds.value = messagesToDelete.filter(msg => msg.id).map(msg => msg.id!);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1282,7 +1278,6 @@ onUnmounted(() => {
|
|||||||
<!-- 时间和token信息 -->
|
<!-- 时间和token信息 -->
|
||||||
<div class="footer-info">
|
<div class="footer-info">
|
||||||
<span v-if="item.creationTime" class="footer-time">
|
<span v-if="item.creationTime" class="footer-time">
|
||||||
<ElIcon><Clock /></ElIcon>
|
|
||||||
{{ item.creationTime }}
|
{{ item.creationTime }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="item.role !== 'user' && item?.tokenUsage?.total" class="footer-token">
|
<span v-if="item.role !== 'user' && item?.tokenUsage?.total" class="footer-token">
|
||||||
@@ -1410,6 +1405,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
// 删除模式
|
// 删除模式
|
||||||
&.delete-mode {
|
&.delete-mode {
|
||||||
|
|
||||||
.el-bubble {
|
.el-bubble {
|
||||||
// 删除模式下:用户消息加回 flex:auto
|
// 删除模式下:用户消息加回 flex:auto
|
||||||
&[class*="end"] .el-bubble-content-wrapper {
|
&[class*="end"] .el-bubble-content-wrapper {
|
||||||
@@ -1483,7 +1479,9 @@ onUnmounted(() => {
|
|||||||
border-color: #8ab4f8;
|
border-color: #8ab4f8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-bubble {
|
.el-bubble {
|
||||||
@@ -1517,14 +1515,22 @@ onUnmounted(() => {
|
|||||||
// 正常模式下:去掉 flex:auto
|
// 正常模式下:去掉 flex:auto
|
||||||
.el-bubble-content-wrapper {
|
.el-bubble-content-wrapper {
|
||||||
flex: none;
|
flex: none;
|
||||||
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑模式下:加回 flex:auto
|
// 编辑模式下:加回 flex:auto
|
||||||
&:has(.edit-message-wrapper-full) .el-bubble-content-wrapper {
|
&:has(.edit-message-wrapper-full) .el-bubble-content-wrapper {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-bubble-content {
|
.el-bubble-content {
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑模式下:加回 flex:auto
|
||||||
|
&:has(.edit-message-wrapper-full) .el-bubble-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@@ -1623,7 +1629,7 @@ onUnmounted(() => {
|
|||||||
.footer-wrapper {
|
.footer-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 8px;
|
margin-top: 4px;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1637,33 +1643,28 @@ onUnmounted(() => {
|
|||||||
.footer-info {
|
.footer-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #8c8c8c;
|
color: #888;
|
||||||
|
|
||||||
.footer-time {
|
.footer-time {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
color: #888;
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #bfbfbf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-token {
|
.footer-token {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
color: #888;
|
||||||
color: #8c8c8c;
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
width: 4px;
|
width: 3px;
|
||||||
height: 4px;
|
height: 3px;
|
||||||
background: #bfbfbf;
|
background: #bbb;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1671,23 +1672,17 @@ onUnmounted(() => {
|
|||||||
.footer-actions {
|
.footer-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 2px;
|
||||||
opacity: 0.4;
|
|
||||||
transition: opacity 0.2s ease;
|
|
||||||
|
|
||||||
.footer-wrapper:hover & {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button {
|
.el-button {
|
||||||
width: 26px;
|
width: 24px;
|
||||||
height: 26px;
|
height: 24px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #8c8c8c;
|
color: #555;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 6px;
|
border-radius: 4px;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -1700,12 +1695,12 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&[disabled] {
|
&[disabled] {
|
||||||
color: #d9d9d9;
|
color: #bbb;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,6 +215,9 @@
|
|||||||
--el-button-border-radius-base: var(--border-radius-md);
|
--el-button-border-radius-base: var(--border-radius-md);
|
||||||
--el-button-hover-bg-color: var(--color-primary-dark);
|
--el-button-hover-bg-color: var(--color-primary-dark);
|
||||||
--el-button-active-bg-color: var(--color-primary-darker);
|
--el-button-active-bg-color: var(--color-primary-darker);
|
||||||
|
|
||||||
|
|
||||||
|
--el-padding-sm: 6px
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========== 暗色模式变量 ========== */
|
/* ========== 暗色模式变量 ========== */
|
||||||
|
|||||||
Reference in New Issue
Block a user