diff --git a/src/api/ai/creativeAssistant/model/index.ts b/src/api/ai/creativeAssistant/model/index.ts index f10b33b..4a7a67b 100644 --- a/src/api/ai/creativeAssistant/model/index.ts +++ b/src/api/ai/creativeAssistant/model/index.ts @@ -16,6 +16,15 @@ export interface CreativeAssistantUploadFile { export interface CreativeAssistantRequest { user_content?: string; user_contentString?: string; + /** + * 端上的模式。`image` 时后端会把 user_content 包装成一张「生成图片」的意图声明, + * 让上游「问题分类器」不把画面描述判成文案/脚本分支(见 issue 19)。 + */ + mode?: 'chat' | 'writing' | 'image'; + /** + * 参考素材。2026-10 起端上已不再发送:上游出图工具只做文生图,没有任何节点消费它 + * (见 issue 16)。字段暂时保留,便于回退。 + */ user_files?: CreativeAssistantUploadFile[]; } diff --git a/src/views/gxmu/creativeAssistant/index.vue b/src/views/gxmu/creativeAssistant/index.vue index a54b443..adc3c96 100644 --- a/src/views/gxmu/creativeAssistant/index.vue +++ b/src/views/gxmu/creativeAssistant/index.vue @@ -30,40 +30,6 @@ placeholder="请输入用户的文本指令或需求描述,例如:根据活动照片和通知文档,生成一条公众号推文封面及 60 秒短视频脚本。" /> - - - - - 添加附件 - - -
- 支持图片、视频、文档、音频。 -
-
-
-
-
{{ getFileTypeLabel(item) }}
-
-
{{ item.name || getFileName(item) }}
-
{{ resolveFileUrl(item) || '-' }}
-
-
- 移除 -
-
-
@@ -97,11 +63,11 @@ 则「已执行但失败 / 未识别到输出」时 hasAnyResult 为假, 会落回这个空状态,把下方 result-body 里的 status-alert (失败文案 / 兜底文案)整个盖住 —— 用户看到的仍是 - 「填写文本指令并上传附件后执行工作流」,等于什么都没发生(见 issue 10)。 + 「填写文本指令后执行工作流」,等于什么都没发生(见 issue 10)。 -->
@@ -222,10 +188,8 @@ import 'highlight.js/styles/default.css'; import { computed, ref } from 'vue'; import { message } from 'ant-design-vue'; - import { UploadOutlined } from '@ant-design/icons-vue'; - import { messageLoading } from 'ele-admin-pro'; import ByteMdViewer from '@/components/ByteMdViewer/index.vue'; - import { creativeAssistant, uploadAiFile } from '@/api/ai/creativeAssistant'; + import { creativeAssistant } from '@/api/ai/creativeAssistant'; import type { FileRecord } from '@/api/system/file/model'; import type { CreativeAssistantOutputs, @@ -236,8 +200,6 @@ type ExampleType = 'video' | 'script' | 'image'; - const acceptTypes = - 'image/*,video/*,audio/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.md'; const plugins = ref([ gfm({ locale: zh_HansGfm @@ -247,12 +209,11 @@ const loading = ref(false); const content = ref(''); - const uploadedFiles = ref[]>([]); const workflowResponse = ref(null); const workflowOutputs = ref(null); const canSubmit = computed(() => { - return !!content.value.trim() || uploadedFiles.value.length > 0; + return !!content.value.trim(); }); const videoFiles = computed(() => workflowOutputs.value?.video_result || []); @@ -316,12 +277,6 @@ return 'default'; }); const loadingTitle = computed(() => { - if (uploadedFiles.value.length && content.value.trim()) { - return '正在分析指令并处理附件'; - } - if (uploadedFiles.value.length) { - return '正在解析附件并生成结果'; - } return '正在根据文本指令生成内容'; }); const loadingDescription = computed(() => { @@ -375,25 +330,6 @@ return name.split('.').pop() || ''; }; - const DOCUMENT_FILE_EXTS = new Set([ - 'TXT', - 'MD', - 'MARKDOWN', - 'PDF', - 'HTML', - 'XLSX', - 'XLS', - 'DOCX', - 'CSV', - 'EML', - 'MSG', - 'PPTX', - 'PPT', - 'XML', - 'EPUB' - ]); - const AUDIO_FILE_EXTS = new Set(['MP3', 'M4A', 'WAV', 'WEBM', 'AMR']); - const VIDEO_FILE_EXTS = new Set(['MP4', 'MOV', 'MPEG', 'MPGA']); const isImageFile = (file?: Partial | null) => { const contentType = String(file?.contentType || '').toLowerCase(); @@ -419,26 +355,6 @@ return ['mp3', 'wav', 'aac', 'm4a', 'ogg'].includes(getFileExt(file)); }; - const getUploadFileType = ( - file?: Partial | null - ): 'image' | 'document' | 'audio' | 'video' => { - const contentType = String(file?.contentType || '').toLowerCase(); - const ext = getFileExt(file).toUpperCase(); - if (contentType.startsWith('image/')) { - return 'image'; - } - if (AUDIO_FILE_EXTS.has(ext)) { - return 'audio'; - } - if (VIDEO_FILE_EXTS.has(ext)) { - return 'video'; - } - if (DOCUMENT_FILE_EXTS.has(ext)) { - return 'document'; - } - return 'document'; - }; - const getFileTypeLabel = (file?: Partial | null) => { if (isImageFile(file)) { return '图片'; @@ -459,70 +375,31 @@ const resetAll = () => { content.value = ''; - uploadedFiles.value = []; clearResult(); }; - const removeUploadedFile = (index: number) => { - uploadedFiles.value = uploadedFiles.value.filter((_, current) => current !== index); - }; - - const handleUpload = async (options: any) => { - const rawFile = options.file as File; - if (rawFile.size / 1024 / 1024 > 100) { - message.error('单个附件不能超过 100MB'); - options.onError?.(new Error('文件过大')); - return; - } - const hide = messageLoading({ - content: '上传中..', - duration: 0, - mask: true - }); - try { - // 必须用创意助手自己的应用凭证上传:Dify 的 /files/upload 按应用鉴权, - // 用别的应用的 Key 上传,工作流的 file-list 变量会报 Invalid upload file。 - const result = await uploadAiFile(rawFile, 'creativeAssistant'); - uploadedFiles.value = [ - ...uploadedFiles.value, - { - id: result.id, - name: result.name || rawFile.name, - path: result.path, - url: result.url, - downloadUrl: result.downloadUrl, - contentType: result.contentType - } - ]; - options.onSuccess?.(result); - message.success('附件上传成功'); - } catch (e: any) { - message.error(e.message || '上传失败'); - options.onError?.(e); - } finally { - hide(); - } - }; + /** + * 请求体。 + * + *

附件已下线:上游出图工具只做文生图,开始节点的 file-list 变量没有任何节点消费 + * (见 issue 16),继续传只是让用户白等上传。 + * + *

不传 {@code mode}:这个页面是通用的创意助手入口,用户可能写视频、脚本或图片需求, + * 由用户的文字自己说明意图;只有聊天页「图片」模式这类**用户显式选了功能**的地方 + * 才传 {@code mode=image} 让后端包装提示词(见 issue 19)。 + */ const buildRequestPayload = () => { - const payload: any = { - user_content: content.value.trim(), - user_contentString: content.value.trim() + const value = content.value.trim(); + return { + user_content: value, + user_contentString: value }; - if (uploadedFiles.value.length) { - payload.user_files = uploadedFiles.value.map((item) => ({ - transfer_method: 'local_file', - type: getUploadFileType(item), - upload_file_id: item.id, - url: '' - })); - } - return payload; }; const runWorkflow = async () => { if (!canSubmit.value) { - message.warning('请先输入文本指令或上传附件'); + message.warning('请先输入文本指令'); return; } loading.value = true; @@ -557,7 +434,7 @@ const fillExample = (type: ExampleType) => { if (type === 'video') { content.value = - '请根据我上传的活动照片和通知文档,生成一条 45 秒校园活动宣传短视频,画面节奏明快,配一段适合配音的解说文案,并输出视频结果。'; + '以「青年志愿者进社区」为主题,生成一条 45 秒校园活动宣传短视频,画面节奏明快,配一段适合配音的解说文案,并输出视频结果。'; return; } if (type === 'script') { @@ -566,7 +443,7 @@ return; } content.value = - '请根据上传的活动照片、LOGO 和文案素材,生成一套公众号头图与活动海报排版,风格青春、明亮,输出图片文件。'; + '以「毕业季」为主题,生成一套公众号头图与活动海报排版,风格青春、明亮,输出图片文件。'; }; @@ -645,38 +522,6 @@ gap: 8px; } - .upload-tip { - margin-top: 10px; - color: #88715f; - font-size: 12px; - line-height: 1.7; - } - - .file-list { - margin-top: 14px; - display: grid; - gap: 10px; - } - - .file-item { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 12px 14px; - border-radius: 14px; - background: #faf5ef; - border: 1px solid #c7e8ff; - } - - .file-main { - display: flex; - align-items: center; - gap: 12px; - flex: 1; - min-width: 0; - } - .file-badge { flex-shrink: 0; min-width: 48px; @@ -689,35 +534,12 @@ font-weight: 600; } - .file-text { - flex: 1; - min-width: 0; - } - - .file-name, - .file-url, .result-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } - .file-name { - color: #3b2c20; - font-weight: 600; - } - - .file-url { - margin-top: 4px; - color: #8c7462; - font-size: 12px; - } - - .file-remove { - flex-shrink: 0; - color: #ff4d4f; - } - .submit-bar { display: flex; justify-content: flex-end; diff --git a/src/views/oa/chatgpt/index.vue b/src/views/oa/chatgpt/index.vue index 1dc7a97..5c292d7 100644 --- a/src/views/oa/chatgpt/index.vue +++ b/src/views/oa/chatgpt/index.vue @@ -334,44 +334,6 @@

-
- 参考素材 - - - 最多 {{ IMAGE_FILE_LIMIT }} 个,支持图片 / 视频 / 音频 / 文档 - - - -