feat: 重构聊天时间线与附件上传交互

- 管理端和用户中心统一切换到 chatTime 时间线模型,按真实 assistant/tool 时序渲染

- 收紧工具气泡与 JSON 展示样式,保留同气泡内的工具状态更新

- 回形针直接触发文件选择,附件列表上移到输入框上方并补充共享 helper 测试
This commit is contained in:
2026-05-11 21:25:21 +08:00
parent e27834ee0c
commit 4a15124183
27 changed files with 2527 additions and 751 deletions

View File

@@ -33,6 +33,7 @@ type SelfFilesCardProps = {
} & FilesCardProps;
const files = ref<SelfFilesCardProps[]>([]);
const fileInputRef = ref<HTMLInputElement>();
/**
* 上传前校验
*/
@@ -45,30 +46,11 @@ function handleBeforeUpload(file: File) {
return true;
}
/**
* 拖拽上传处理
*/
async function handleUploadDrop(dropFiles: File[]) {
if (dropFiles?.length) {
if (dropFiles[0]?.type === '') {
ElMessage.error('禁止上传文件夹!');
return false;
}
for (const file of dropFiles) {
if (handleBeforeUpload(file)) {
await handleHttpRequest({ file });
}
}
}
}
/**
* 自定义上传请求
*/
async function handleHttpRequest(options: { file: File }) {
const { file } = options;
const formData = new FormData();
formData.append('file', file);
try {
const res = await api.upload(props.action, { file }, {});
@@ -104,6 +86,18 @@ async function uploadExternalFiles(fileList: File[]) {
}
}
/**
* 处理原生文件选择
*/
async function handleFileInputChange(event: Event) {
const target = event.target as HTMLInputElement;
const selectedFiles = Array.from(target.files || []);
if (selectedFiles.length > 0) {
await uploadExternalFiles(selectedFiles);
}
target.value = '';
}
/**
* 组件内部完成删除逻辑
*/
@@ -122,6 +116,13 @@ function getFileList(): string[] {
return files.value.map((file) => file.url);
}
/**
* 触发原生文件选择
*/
function triggerFileSelect() {
fileInputRef.value?.click();
}
watch(
() => props.externalFiles,
async (newFiles) => {
@@ -135,6 +136,7 @@ watch(
defineExpose({
getFileList,
triggerFileSelect,
clearFiles() {
files.value = [];
},
@@ -142,17 +144,20 @@ defineExpose({
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<div v-if="files.length > 0" style="display: flex; flex-direction: column; gap: 12px">
<Attachments
:http-request="handleHttpRequest"
:items="files"
drag
:before-upload="handleBeforeUpload"
:hide-upload="false"
@upload-drop="handleUploadDrop"
:hide-upload="true"
@delete-card="handleDeleteCard"
/>
</div>
<input
ref="fileInputRef"
type="file"
multiple
class="hidden"
@change="handleFileInputChange"
/>
</template>
<style scoped lang="less"></style>