Files
sionrui/frontend/app/web-gold/src/views/content-style/components/BatchAnalyzeModal.vue
2025-11-13 01:06:28 +08:00

243 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref, watch } from 'vue'
import { EditOutlined, CopyOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import ChatMessageRenderer from '@/components/ChatMessageRenderer.vue'
import { ChatMessageApi } from '@/api/chat'
import { streamChat } from '@/utils/streamChat'
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
mergedText: {
type: String,
default: '',
},
textCount: {
type: Number,
default: 0,
},
})
const emit = defineEmits(['update:visible', 'copy', 'save', 'use'])
const batchPrompt = ref('')
const batchPromptEditMode = ref(false)
const batchPromptGenerating = ref(false)
const hasGenerated = ref(false)
watch(() => props.visible, (newVal) => {
if (newVal && props.mergedText && !hasGenerated.value) {
generateBatchPrompt()
} else if (!newVal) {
batchPrompt.value = ''
batchPromptEditMode.value = false
batchPromptGenerating.value = false
hasGenerated.value = false
}
})
watch(() => props.mergedText, (newVal) => {
if (props.visible && newVal && !hasGenerated.value) {
generateBatchPrompt()
}
})
async function generateBatchPrompt() {
if (!props.mergedText || hasGenerated.value) return
hasGenerated.value = true
try {
batchPromptGenerating.value = true
const createPayload = { roleId: 20 }
console.debug('createChatConversationMy payload(batch):', createPayload)
const conversationResp = await ChatMessageApi.createChatConversationMy(createPayload)
let conversationId = null
if (conversationResp?.data) {
conversationId = typeof conversationResp.data === 'object' ? conversationResp.data.id : conversationResp.data
}
if (!conversationId) {
throw new Error('创建对话失败:未获取到 conversationId')
}
const aiContent = await streamChat({
conversationId,
content: props.mergedText,
onUpdate: (fullText) => {
batchPrompt.value = fullText
},
enableTypewriter: true,
typewriterSpeed: 10,
typewriterBatchSize: 2
})
if (aiContent && aiContent !== batchPrompt.value) {
batchPrompt.value = aiContent
}
message.success(`批量分析完成:已基于 ${props.textCount} 个视频的文案生成综合提示词`)
} catch (aiError) {
console.error('AI生成失败:', aiError)
message.error('AI生成失败请稍后重试')
} finally {
batchPromptGenerating.value = false
}
}
function handleClose() {
emit('update:visible', false)
}
function handleCopy() {
emit('copy', batchPrompt.value)
}
function handleSave() {
emit('save', batchPrompt.value)
}
function handleUse() {
emit('use', batchPrompt.value)
}
</script>
<template>
<a-modal
:open="visible"
title="综合分析结果"
:width="800"
:maskClosable="false"
:keyboard="false"
@cancel="handleClose">
<div class="batch-prompt-modal">
<div v-if="!batchPromptEditMode" class="batch-prompt-display">
<ChatMessageRenderer
:content="batchPrompt"
:is-streaming="batchPromptGenerating"
/>
</div>
<a-textarea
v-else
v-model:value="batchPrompt"
:rows="15"
placeholder="内容将在这里显示..." />
</div>
<template #footer>
<a-space>
<a-button size="small" :title="batchPromptEditMode ? '取消编辑' : '编辑'" @click="batchPromptEditMode = !batchPromptEditMode">
<template #icon>
<EditOutlined />
</template>
</a-button>
<a-button size="small" title="复制" @click="handleCopy">
<template #icon>
<CopyOutlined />
</template>
</a-button>
<a-button size="small" title="保存提示词" @click="handleSave" :disabled="!batchPrompt.trim()">
保存提示词
</a-button>
<a-button @click="handleClose">取消</a-button>
<a-button
type="primary"
:disabled="batchPromptGenerating || !batchPrompt.trim()"
@click="handleUse">去创作</a-button>
</a-space>
</template>
</a-modal>
</template>
<style scoped>
.batch-prompt-modal {
min-height: 200px;
}
.batch-prompt-display {
min-height: 300px;
max-height: 500px;
overflow-y: auto;
padding: 12px;
background: #0d0d0d;
border: 1px solid var(--color-border);
border-radius: 6px;
line-height: 1.6;
}
.batch-prompt-display :deep(h1) {
font-size: 18px;
font-weight: 600;
margin: 12px 0;
color: var(--color-text);
}
.batch-prompt-display :deep(h2) {
font-size: 16px;
font-weight: 600;
margin: 16px 0 8px 0;
color: var(--color-text);
}
.batch-prompt-display :deep(h3) {
font-size: 14px;
font-weight: 600;
margin: 12px 0 6px 0;
color: var(--color-text-secondary);
}
.batch-prompt-display :deep(p) {
margin: 8px 0;
color: var(--color-text-secondary);
}
.batch-prompt-display :deep(ul),
.batch-prompt-display :deep(ol) {
margin: 8px 0;
padding-left: 20px;
}
.batch-prompt-display :deep(li) {
margin: 4px 0;
color: var(--color-text-secondary);
}
.batch-prompt-display :deep(strong) {
font-weight: 600;
color: var(--color-text);
}
.batch-prompt-display :deep(code) {
background: #1a1a1a;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 12px;
color: #e11d48;
}
.batch-prompt-display :deep(pre) {
background: #1a1a1a;
padding: 12px;
border-radius: 6px;
overflow-x: auto;
margin: 8px 0;
}
.batch-prompt-display :deep(pre code) {
background: transparent;
padding: 0;
}
.batch-prompt-display :deep(blockquote) {
border-left: 3px solid var(--color-primary);
padding-left: 12px;
margin: 8px 0;
color: var(--color-text-secondary);
}
</style>