kuaifan 2180998e81 feat(ai-assistant): 添加图片发送功能支持多模态对话
- 支持上传图片并压缩(当前消息 1024px,历史 512px)
- 图片独立缓存存储,使用占位符 [IMG:xxx] 替代 base64
- 新增 prompt-image.vue 组件展示历史图片缩略图
- 后端 AI.php 支持多模态消息格式处理
- 添加图片缓存清理机制(删除会话时同步清理)
- 优化 parsePromptContent 避免重复调用
- 会话标题自动过滤图片占位符

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:31:34 +00:00

90 lines
2.0 KiB
Vue

<template>
<span class="prompt-image-wrapper" @click="showPreview">
<img v-if="imageUrl" :src="imageUrl" class="prompt-image-thumb" alt="uploaded image" />
<span v-else class="prompt-image-placeholder">
<i class="taskfont">&#xe6ef;</i>
</span>
</span>
</template>
<script>
export default {
name: 'PromptImage',
props: {
imageId: {
type: String,
required: true,
},
getImage: {
type: Function,
required: true,
},
},
data() {
return {
imageUrl: null,
loading: true,
};
},
mounted() {
this.loadImage();
},
methods: {
async loadImage() {
try {
const url = await this.getImage(this.imageId);
this.imageUrl = url;
} catch (e) {
console.warn('[PromptImage] 加载图片失败:', e);
} finally {
this.loading = false;
}
},
showPreview() {
if (this.imageUrl) {
$A.previewFile({
type: 'image',
url: this.imageUrl,
name: `image_${this.imageId}`,
});
}
},
},
};
</script>
<style lang="scss" scoped>
.prompt-image-wrapper {
display: inline-block;
width: 60px;
height: 60px;
border-radius: 6px;
overflow: hidden;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0.1);
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
}
.prompt-image-thumb {
width: 100%;
height: 100%;
object-fit: cover;
}
.prompt-image-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: #f5f5f5;
color: #999;
font-size: 18px;
}
</style>