refactor(web): 文件/文件夹图标统一改用 FileTypeIcon

- 文件预览、工作区文件列表、侧边栏文件树、知识库 FileTable、上传弹窗、
  @mention、附件预览等处统一渲染彩色文件/文件夹图标
- 移除 file_utils 旧的 Ant 单色图标映射与 mention_icon_utils 的 file 分支
- 清理各组件因替换产生的孤儿图标导入;按钮图标保持不变
This commit is contained in:
Wenjie Zhang 2026-06-05 01:29:34 +08:00
parent 3c7ac61ca4
commit a5663a8bb2
16 changed files with 82 additions and 206 deletions

View File

@ -7,11 +7,7 @@
:title="`打开 ${file.name}`"
@click="openPreview(file)"
>
<component
:is="getFileIcon(file.path)"
class="item-icon"
:style="{ color: getFileIconColor(file.path) }"
/>
<FileTypeIcon :name="file.path" :size="20" class="item-icon" />
<div class="item-meta">
<div class="item-name">{{ file.name }}</div>
<div class="item-desc">{{ getFileMetaLabel(file.path) }}</div>
@ -41,7 +37,7 @@ import { computed, ref } from 'vue'
import { message } from 'ant-design-vue'
import { Download, LoaderCircle, Save } from 'lucide-vue-next'
import { threadApi } from '@/apis/agent_api'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import { downloadViewerFile } from '@/apis/viewer_filesystem'
const props = defineProps({

View File

@ -246,10 +246,10 @@
</div>
<div v-if="currentStateFiles.length" class="state-list">
<div v-for="file in currentStateFiles" :key="file.key" class="state-list-item">
<component
:is="file.icon"
<FileTypeIcon
:name="file.name || file.path"
:size="18"
class="state-list-item-icon"
:style="{ color: file.iconColor }"
/>
<div class="state-list-item-body">
<div class="state-list-item-title">{{ file.name }}</div>
@ -274,10 +274,10 @@
:title="`打开 ${file.name}`"
@click="openPanelPreview(file)"
>
<component
:is="file.icon"
<FileTypeIcon
:name="file.name || file.path"
:size="18"
class="state-list-item-icon"
:style="{ color: file.iconColor }"
/>
<div class="state-list-item-body">
<div class="state-list-item-title">{{ file.name }}</div>
@ -362,7 +362,8 @@ import {
} from 'vue'
import { message } from 'ant-design-vue'
import { RefreshCw, SquareCheck } from 'lucide-vue-next'
import { getFileIcon, getFileIconColor, formatFileSize } from '@/utils/file_utils'
import { formatFileSize } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import { generatePixelAvatar } from '@/utils/pixelAvatar'
import {
CheckCircleOutlined,
@ -720,9 +721,7 @@ const currentArtifactFiles = computed(() =>
.map((path) => ({
path,
name: getPanelFileName({ path }),
meta: getArtifactMetaLabel(path),
icon: getFileIcon(path),
iconColor: getFileIconColor(path)
meta: getArtifactMetaLabel(path)
}))
)
const currentTodos = computed(() => {
@ -780,9 +779,7 @@ const currentStateFiles = computed(() => {
key: path,
path,
name,
meta: [status, sizeLabel === '-' ? '' : sizeLabel, path].filter(Boolean).join(' · '),
icon: getFileIcon(name || path),
iconColor: getFileIconColor(name || path)
meta: [status, sizeLabel === '-' ? '' : sizeLabel, path].filter(Boolean).join(' · ')
})
}

View File

@ -5,11 +5,7 @@
>
<div v-if="showHeader" class="preview-header">
<div class="file-title">
<component
v-if="showFileIcon"
:is="getFileIcon(filePath)"
:style="{ color: getFileIconColor(filePath), fontSize: '18px' }"
/>
<FileTypeIcon v-if="showFileIcon" :name="filePath" :size="18" />
<span class="file-path-title">{{ filePath }}</span>
</div>
<div class="modal-actions">
@ -269,8 +265,8 @@ import {
} from 'lucide-vue-next'
import hljs from 'highlight.js/lib/common'
import MarkdownPreview from '@/components/common/MarkdownPreview.vue'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import { useThemeStore } from '@/stores/theme'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import { escapeHtml } from '@/utils/html'
import {
getCodeLanguageByPath,

View File

@ -47,8 +47,8 @@
:key="attachment.fileId"
class="attachment-file-card"
>
<div class="attachment-file-icon" :style="{ color: attachment.iconColor }">
<component :is="attachment.icon" />
<div class="attachment-file-icon">
<FileTypeIcon :name="attachment.name" :size="18" />
</div>
<div class="attachment-file-body">
<div class="attachment-file-name" :title="attachment.name">{{ attachment.name }}</div>
@ -95,6 +95,7 @@ import ImagePreviewComponent from '@/components/ImagePreviewComponent.vue'
import AttachmentOptionsComponent from '@/components/AttachmentOptionsComponent.vue'
import { X } from 'lucide-vue-next'
import { normalizeAttachmentPreviews } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
modelValue: { type: String, default: '' },

View File

@ -121,8 +121,8 @@
:key="attachment.fileId"
class="message-attachment-file"
>
<div class="message-attachment-icon" :style="{ color: attachment.iconColor }">
<component :is="attachment.icon" />
<div class="message-attachment-icon">
<FileTypeIcon :name="attachment.name" :size="18" />
</div>
<div class="message-attachment-body">
<div class="message-attachment-name" :title="attachment.name">
@ -148,6 +148,7 @@ import { storeToRefs } from 'pinia'
import { MessageProcessor } from '@/utils/messageProcessor'
import { normalizeAttachmentPreviews } from '@/utils/file_utils'
import { buildMentionDisplayLabels } from '@/utils/mention_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import { enrichTaskToolCalls } from '@/components/ToolCallingResult/toolRegistry'
const props = defineProps({

View File

@ -16,11 +16,7 @@
:title="tab.path"
@click="activatePreviewTab(tab.path)"
>
<component
:is="getFileIcon(tab.path)"
class="preview-tab-icon"
:style="{ color: getFileIconColor(tab.path) }"
/>
<FileTypeIcon :name="tab.path" :size="16" class="preview-tab-icon" />
<span class="preview-tab-name">{{ tab.name }}</span>
</button>
<button
@ -137,7 +133,7 @@ import { Download, Folders, RefreshCw, Trash2, X } from 'lucide-vue-next'
import { Modal, message } from 'ant-design-vue'
import FileTreeComponent from '@/components/FileTreeComponent.vue'
import AgentFilePreview from '@/components/AgentFilePreview.vue'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import {
deleteViewerFile,
downloadViewerFile,

View File

@ -22,8 +22,8 @@
<div v-if="fileItems.length" class="attachment-list">
<div v-for="item in fileItems" :key="item.localId" class="attachment-item">
<div class="attachment-file-icon" :style="{ color: getFileIconColor(item.fileName) }">
<component :is="getFileIcon(item.fileName)" />
<div class="attachment-file-icon">
<FileTypeIcon :name="item.fileName" :size="20" />
</div>
<div class="attachment-item-content">
@ -152,7 +152,7 @@ import { message } from 'ant-design-vue'
import { ChevronDown, ChevronUp, X } from 'lucide-vue-next'
import { threadApi } from '@/apis'
import { ocrApi } from '@/apis/system_api'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
open: { type: Boolean, default: false },

View File

@ -12,7 +12,7 @@
<div class="modal-title-wrapper">
<!-- 左侧文件名和图标 -->
<div class="file-title">
<component :is="fileIcon" :style="{ color: fileIconColor, fontSize: '18px' }" />
<FileTypeIcon :name="file?.filename" :size="18" />
<span class="file-name">{{ file?.filename || '文件详情' }}</span>
</div>
@ -123,9 +123,9 @@ import { useDatabaseStore } from '@/stores/database'
import { message } from 'ant-design-vue'
import { documentApi } from '@/apis/knowledge_api'
import { mergeChunks } from '@/utils/chunkUtils'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import { getPreviewTypeByPath } from '@/utils/file_preview'
import MarkdownPreview from '@/components/common/MarkdownPreview.vue'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import { Download, ChevronDown, FileText, X } from 'lucide-vue-next'
const store = useDatabaseStore()
@ -138,10 +138,6 @@ const visible = computed({
const file = computed(() => store.selectedFile)
const loading = computed(() => store.state.fileDetailLoading)
//
const fileIcon = computed(() => getFileIcon(file.value?.filename))
const fileIconColor = computed(() => getFileIconColor(file.value?.filename))
const downloadingOriginal = ref(false)
const downloadingMarkdown = ref(false)
const sourcePreviewLoading = ref(false)

View File

@ -226,24 +226,12 @@
<div v-if="column.key === 'filename'">
<template v-if="record.is_folder">
<span class="folder-row" @click="toggleExpand(record)">
<component
:is="
expandedRowKeys.includes(record.file_id) ? h(FolderOpenFilled) : h(FolderFilled)
"
style="margin-right: 8px; color: #ffb800; font-size: 16px"
/>
<FileTypeIcon is-dir :size="16" :style="{ marginRight: '8px' }" />
{{ record.filename }}
</span>
</template>
<a-button v-else class="main-btn" type="link" @click="openFileDetail(record)">
<component
:is="getFileIcon(record.displayName || text)"
:style="{
marginRight: '0',
color: getFileIconColor(record.displayName || text),
fontSize: '16px'
}"
/>
<FileTypeIcon :name="record.displayName || text" :size="16" :style="{ marginRight: '8px' }" />
{{ record.displayName || text }}
</a-button>
</div>
@ -389,8 +377,6 @@ import {
HourglassFilled,
CloseCircleFilled,
ClockCircleFilled,
FolderFilled,
FolderOpenFilled,
FileTextFilled
} from '@ant-design/icons-vue'
import {
@ -1167,9 +1153,10 @@ const handleIndexConfigCancel = () => {
}
//
import { getFileIcon, getFileIconColor, formatStandardTime } from '@/utils/file_utils'
import { formatStandardTime } from '@/utils/file_utils'
import { buildChunkParamsPayload, isPlainObject } from '@/utils/chunk_presets'
import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
</script>
<style scoped>
@ -1282,6 +1269,8 @@ import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue'
}
.my-table .main-btn {
display: flex;
justify-content: center;
padding: 0;
height: auto;
line-height: 1.4;

View File

@ -17,11 +17,7 @@
<template #icon="{ data, expanded }">
<slot name="icon" :node="data" :expanded="expanded">
<template v-if="data.isLeaf">
<component
v-if="useFileIcons"
:is="getFileIcon(data.key)"
:style="{ color: getFileIconColor(data.key), fontSize: '16px' }"
/>
<FileTypeIcon v-if="useFileIcons" :name="data.key" :size="16" />
<FileText v-else :size="16" class="file-icon" />
</template>
<template v-else>
@ -30,8 +26,7 @@
class="folder-loading-icon"
aria-label="正在加载"
></span>
<FolderOpen v-else-if="expanded" :size="18" class="folder-icon open" />
<Folder v-else :size="18" class="folder-icon" />
<FileTypeIcon v-else is-dir :size="18" />
</template>
</slot>
</template>
@ -55,8 +50,8 @@
<script setup>
import { ref } from 'vue'
import { Folder, FolderOpen, FileText } from 'lucide-vue-next'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import { FileText } from 'lucide-vue-next'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
treeData: {

View File

@ -293,7 +293,7 @@
@click="openWorkspaceDirectory(item.path)"
>
<a-checkbox disabled />
<Folder :size="14" class="workspace-file-icon" />
<FileTypeIcon is-dir :size="16" class="workspace-file-icon" />
<span class="workspace-file-name" :title="item.path">{{ item.name }}</span>
</button>
@ -308,7 +308,7 @@
:disabled="!item.supported || chunkLoading"
@change="toggleWorkspacePath(item.path, $event.target.checked)"
/>
<FileText :size="14" class="workspace-file-icon" />
<FileTypeIcon :name="item.path" :size="16" class="workspace-file-icon" />
<span class="workspace-file-name" :title="item.path">{{ item.path }}</span>
<span class="workspace-file-size">{{ formatFileSize(item.size) }}</span>
</label>
@ -423,9 +423,7 @@ import { ReloadOutlined } from '@ant-design/icons-vue'
import {
FileUp,
FolderUp,
Folder,
FolderOpen,
FileText,
ArrowLeft,
RotateCw,
CircleHelp,
@ -439,6 +437,7 @@ import {
} from 'lucide-vue-next'
import { buildChunkParamsPayload } from '@/utils/chunk_presets'
import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
visible: {

View File

@ -60,9 +60,10 @@
@click="insertMention(item)"
>
<div class="file-info-left">
<component
:is="item.is_dir ? FolderFilled : getFileIcon(item.label)"
:style="{ color: item.is_dir ? '#ffa940' : getFileIconColor(item.label) }"
<FileTypeIcon
:name="item.label"
:is-dir="item.is_dir"
:size="16"
class="file-type-icon"
/>
<span class="file-name" :title="item.label">
@ -280,10 +281,10 @@ import {
h,
render
} from 'vue'
import { SendOutlined, ArrowUpOutlined, PauseOutlined, FolderFilled } from '@ant-design/icons-vue'
import { SendOutlined, ArrowUpOutlined, PauseOutlined } from '@ant-design/icons-vue'
import { Paperclip } from 'lucide-vue-next'
import { searchMentionFiles } from '@/apis/mention_api'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
import {
getMentionIconComponent,
getMentionIconStyle,
@ -472,14 +473,25 @@ const createEditorMentionElement = (segment) => {
const icon = document.createElement('span')
icon.className = 'mention-ref-icon'
icon.dataset.vueIcon = 'true'
Object.assign(icon.style, getMentionIconStyle(segment.type, segment.value) || {})
render(
h(getMentionIconComponent(segment.type, segment.value), {
size: MENTION_ICON_SIZE,
strokeWidth: MENTION_ICON_STROKE_WIDTH
}),
icon
)
if (segment.type === 'file') {
render(
h(FileTypeIcon, {
name: segment.value,
isDir: segment.value.endsWith('/'),
size: MENTION_ICON_SIZE
}),
icon
)
} else {
Object.assign(icon.style, getMentionIconStyle(segment.type, segment.value) || {})
render(
h(getMentionIconComponent(segment.type, segment.value), {
size: MENTION_ICON_SIZE,
strokeWidth: MENTION_ICON_STROKE_WIDTH
}),
icon
)
}
token.appendChild(icon)
const label = document.createElement('span')

View File

@ -12,7 +12,15 @@
:data-mention-value="editable ? segment.value : undefined"
:title="segment.raw"
>
<FileTypeIcon
v-if="segment.type === 'file'"
class="mention-ref-icon"
:name="segment.value"
:is-dir="segment.value.endsWith('/')"
:size="MENTION_ICON_SIZE"
/>
<component
v-else
:is="getMentionIconComponent(segment.type, segment.value)"
class="mention-ref-icon"
:style="getMentionIconStyle(segment.type, segment.value)"
@ -34,6 +42,7 @@ import {
MENTION_ICON_STROKE_WIDTH
} from '@/utils/mention_icon_utils'
import { getMentionDisplayLabel, parseMentionText } from '@/utils/mention_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
content: {

View File

@ -86,12 +86,7 @@
/>
</span>
<span class="name-cell">
<Folder v-if="entry.is_dir" :size="17" class="folder-icon" />
<component
v-else
:is="getFileIcon(entry.name || entry.path)"
:style="{ color: getFileIconColor(entry.name || entry.path), fontSize: '16px' }"
/>
<FileTypeIcon :name="entry.name || entry.path" :is-dir="entry.is_dir" :size="17" />
<span class="entry-name" :title="entry.name">{{ entry.name }}</span>
</span>
<span>{{ entry.is_dir ? '-' : formatFileSize(entry.size) }}</span>
@ -147,13 +142,9 @@
<script setup>
import { computed } from 'vue'
import { Download, Folder, ListChecks, MoreHorizontal, Trash2 } from 'lucide-vue-next'
import {
formatFileSize,
formatRelativeTime,
getFileIcon,
getFileIconColor
} from '@/utils/file_utils'
import { Download, ListChecks, MoreHorizontal, Trash2 } from 'lucide-vue-next'
import { formatFileSize, formatRelativeTime } from '@/utils/file_utils'
import FileTypeIcon from '@/components/common/FileTypeIcon.vue'
const props = defineProps({
entries: { type: Array, default: () => [] },

View File

@ -1,95 +1,6 @@
import {
FileTextFilled,
FileMarkdownFilled,
FilePdfFilled,
FileWordFilled,
FileExcelFilled,
FileImageFilled,
FileFilled,
FilePptFilled,
FileZipFilled,
LinkOutlined,
CodeFilled
} from '@ant-design/icons-vue'
import { getPreviewFileExtension, getPreviewTypeByPath } from '@/utils/file_preview'
import { formatRelative, parseToShanghai } from '@/utils/time'
const DEFAULT_FILE_ICON = { icon: FileFilled, color: 'var(--gray-600)' }
const LINK_FILE_ICON = { icon: LinkOutlined, color: 'var(--color-info-500)' }
const FILE_ICON_CONFIG = {
txt: { icon: FileTextFilled, color: 'var(--color-info-500)' },
text: { icon: FileTextFilled, color: 'var(--color-info-500)' },
log: { icon: FileTextFilled, color: 'var(--color-info-500)' },
md: { icon: FileMarkdownFilled, color: 'var(--gray-700)' },
markdown: { icon: FileMarkdownFilled, color: 'var(--gray-700)' },
pdf: { icon: FilePdfFilled, color: 'var(--color-error-500)' },
doc: { icon: FileWordFilled, color: 'var(--color-info-700)' },
docx: { icon: FileWordFilled, color: 'var(--color-info-700)' },
xls: { icon: FileExcelFilled, color: 'var(--color-success-500)' },
xlsx: { icon: FileExcelFilled, color: 'var(--color-success-500)' },
csv: { icon: FileExcelFilled, color: 'var(--color-success-500)' },
ppt: { icon: FilePptFilled, color: 'var(--color-warning-700)' },
pptx: { icon: FilePptFilled, color: 'var(--color-warning-700)' },
apng: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
avif: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
jpg: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
jpeg: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
png: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
gif: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
bmp: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
svg: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
webp: { icon: FileImageFilled, color: 'var(--color-accent-700)' },
zip: { icon: FileZipFilled, color: 'var(--gray-700)' },
rar: { icon: FileZipFilled, color: 'var(--gray-700)' },
'7z': { icon: FileZipFilled, color: 'var(--gray-700)' },
tar: { icon: FileZipFilled, color: 'var(--gray-700)' },
gz: { icon: FileZipFilled, color: 'var(--gray-700)' },
py: { icon: CodeFilled, color: 'var(--color-primary-700)' },
js: { icon: CodeFilled, color: 'var(--color-primary-700)' },
jsx: { icon: CodeFilled, color: 'var(--color-primary-700)' },
ts: { icon: CodeFilled, color: 'var(--color-primary-700)' },
tsx: { icon: CodeFilled, color: 'var(--color-primary-700)' },
vue: { icon: CodeFilled, color: 'var(--color-primary-700)' },
sh: { icon: CodeFilled, color: 'var(--color-primary-700)' },
go: { icon: CodeFilled, color: 'var(--color-primary-700)' },
rs: { icon: CodeFilled, color: 'var(--color-primary-700)' },
cpp: { icon: CodeFilled, color: 'var(--color-primary-700)' },
c: { icon: CodeFilled, color: 'var(--color-primary-700)' },
h: { icon: CodeFilled, color: 'var(--color-primary-700)' },
java: { icon: CodeFilled, color: 'var(--color-primary-700)' },
html: { icon: CodeFilled, color: 'var(--color-primary-700)' },
htm: { icon: CodeFilled, color: 'var(--color-primary-700)' },
css: { icon: CodeFilled, color: 'var(--color-primary-700)' },
less: { icon: CodeFilled, color: 'var(--color-primary-700)' },
scss: { icon: CodeFilled, color: 'var(--color-primary-700)' },
sql: { icon: CodeFilled, color: 'var(--color-primary-700)' },
json: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
yaml: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
yml: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
toml: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
ini: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
conf: { icon: FileTextFilled, color: 'var(--color-primary-700)' },
env: { icon: FileTextFilled, color: 'var(--color-primary-700)' }
}
const getFileIconConfig = (filename) => {
const normalizedName = String(filename || '')
.trim()
.toLowerCase()
if (!normalizedName) return DEFAULT_FILE_ICON
if (normalizedName.startsWith('http://') || normalizedName.startsWith('https://'))
return LINK_FILE_ICON
const cleanName = normalizedName.split(/[?#]/)[0]
const extension = cleanName.includes('.') ? cleanName.split('.').pop() : cleanName
return FILE_ICON_CONFIG[extension] || DEFAULT_FILE_ICON
}
export const getFileIcon = (filename) => getFileIconConfig(filename).icon
export const getFileIconColor = (filename) => getFileIconConfig(filename).color
export const formatRelativeTime = (value) => formatRelative(value)
export const formatStandardTime = (value) => {
@ -152,9 +63,7 @@ export const normalizeAttachmentPreview = (attachment) => {
name,
previewUrl: attachment?.original_artifact_url || attachment?.artifact_url || '',
isImage: fileType.startsWith('image/') || getPreviewTypeByPath(name) === 'image',
meta: [typeLabel, sizeLabel === '-' ? '' : sizeLabel].filter(Boolean).join(' · '),
icon: getFileIcon(name),
iconColor: getFileIconColor(name)
meta: [typeLabel, sizeLabel === '-' ? '' : sizeLabel].filter(Boolean).join(' · ')
}
}

View File

@ -1,10 +1,9 @@
import { FolderFilled } from '@ant-design/icons-vue'
import { BookMarked, BookOpen, Bot, Plug } from 'lucide-vue-next'
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
export const MENTION_ICON_SIZE = 15
export const MENTION_ICON_STROKE_WIDTH = 2.2
// 注意file 类型的图标由 FileTypeIcon 组件直接渲染,此处仅处理其余 mention 类型。
const MENTION_TYPE_ICON_COMPONENTS = {
knowledge: BookOpen,
skill: BookMarked,
@ -12,16 +11,6 @@ const MENTION_TYPE_ICON_COMPONENTS = {
subagent: Bot
}
export const getMentionIconComponent = (type, value = '') => {
if (type === 'file') {
return String(value || '').endsWith('/') ? FolderFilled : getFileIcon(value)
}
return MENTION_TYPE_ICON_COMPONENTS[type] || Plug
}
export const getMentionIconComponent = (type) => MENTION_TYPE_ICON_COMPONENTS[type] || Plug
export const getMentionIconStyle = (type, value = '') => {
if (type !== 'file') return null
return {
color: String(value || '').endsWith('/') ? '#ffa940' : getFileIconColor(value)
}
}
export const getMentionIconStyle = () => null