提交 c72cfcea authored 作者: 王鹏飞's avatar 王鹏飞

feat: 营销内容创作图片增加AI图像生成

上级 fb5296da
<script setup> <script setup>
import { ref, nextTick } from 'vue' import { ref, nextTick } from 'vue'
import { Promotion, Close, Download, ZoomIn, Check } from '@element-plus/icons-vue' import { Promotion, CloseBold, Download, ZoomIn, Check, Picture } from '@element-plus/icons-vue'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { useChatImage } from '@/composables/useChatImage' import { useChatImage } from '@/composables/useChatImage'
...@@ -113,7 +113,7 @@ const handleSend = () => { ...@@ -113,7 +113,7 @@ const handleSend = () => {
</script> </script>
<template> <template>
<el-dialog title="AI生成图片" :close-on-click-modal="false" @closed="$emit('update:modelValue', false)" width="860px"> <el-dialog title="AI图像生成" :close-on-click-modal="false" @closed="$emit('update:modelValue', false)" width="860px">
<div class="chat-container"> <div class="chat-container">
<div class="chat-messages" ref="chatMessages"> <div class="chat-messages" ref="chatMessages">
<div v-for="(message, index) in allMessages" :key="index" class="chat-message" :class="message.role"> <div v-for="(message, index) in allMessages" :key="index" class="chat-message" :class="message.role">
...@@ -174,13 +174,22 @@ const handleSend = () => { ...@@ -174,13 +174,22 @@ const handleSend = () => {
placeholder="输入您的想法或问题..." placeholder="输入您的想法或问题..."
@keyup.enter="handleSend" @keyup.enter="handleSend"
:disabled="isLoading"></el-input> :disabled="isLoading"></el-input>
<el-button <template v-if="isLoading">
type="primary" <el-tooltip content="取消生成">
size="large" <el-button circle type="primary" size="large" :icon="CloseBold" @click="cancel"></el-button>
:icon="Promotion" </el-tooltip>
@click="handleSend" </template>
:disabled="isLoading || !inputMessage.trim()"></el-button> <template v-else>
<el-button type="primary" size="large" :icon="Close" @click="cancel" v-if="isLoading"></el-button> <el-button circle size="large" :icon="Picture" v-if="false"></el-button>
<el-button
circle
type="primary"
size="large"
:icon="Promotion"
@click="handleSend"
:disabled="!inputMessage.trim()"
:loading="isLoading"></el-button>
</template>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
......
...@@ -308,7 +308,7 @@ export function useAI(config) { ...@@ -308,7 +308,7 @@ export function useAI(config) {
messages.value.push({ messages.value.push({
type: 'image', type: 'image',
role: 'assistant', role: 'assistant',
image_url: `data:image/jpeg;base64,${res.url}`, image_url: res.url,
content: data.content, content: data.content,
}) })
} else { } else {
......
...@@ -4,7 +4,7 @@ import { useFileDialog } from '@vueuse/core' ...@@ -4,7 +4,7 @@ import { useFileDialog } from '@vueuse/core'
import { upload } from '@/utils/upload' import { upload } from '@/utils/upload'
import dayjs from 'dayjs' import dayjs from 'dayjs'
const ImageDesign = defineAsyncComponent(() => import('./ImageDesign.vue')) const ImageDesign = defineAsyncComponent(() => import('./ImageDesign.vue'))
const ImageChat = defineAsyncComponent(() => import('./ImageChat.vue')) const ImageChat = defineAsyncComponent(() => import('@/components/ImageChat.vue'))
const props = defineProps({ const props = defineProps({
modelValue: { type: [Array, String], default: () => [] }, modelValue: { type: [Array, String], default: () => [] },
......
...@@ -74,5 +74,5 @@ export function updateImprovementPlan(data: { id: string; improvement_plan: stri ...@@ -74,5 +74,5 @@ export function updateImprovementPlan(data: { id: string; improvement_plan: stri
// AI 打分 // AI 打分
export function aiScore(data: { id: string }) { export function aiScore(data: { id: string }) {
return httpRequest.post('/api/dev/v1/experiment/live-practice/score-live-practice-record', data) return httpRequest.post('/api/lab/v1/experiment/live-practice/score-live-practice-record', data)
} }
...@@ -16,7 +16,7 @@ const formRef = ref() ...@@ -16,7 +16,7 @@ const formRef = ref()
const rules = ref({ const rules = ref({
type: [{ required: true, message: '请选择营销内容类型' }], type: [{ required: true, message: '请选择营销内容类型' }],
name: [{ required: true, message: '请输入内容名称' }], name: [{ required: true, message: '请输入内容名称' }],
teacher_id:[{ required: true, message: '请选择老师标签' }], teacher_id: [{ required: true, message: '请选择老师标签' }],
}) })
async function handleValidate() { async function handleValidate() {
...@@ -85,13 +85,9 @@ const { hasQuestion, teacherMaterialList } = useQuestion(questionType, form.valu ...@@ -85,13 +85,9 @@ const { hasQuestion, teacherMaterialList } = useQuestion(questionType, form.valu
</el-form-item> </el-form-item>
<el-form-item label="创作方式" prop="way"> <el-form-item label="创作方式" prop="way">
<el-radio-group v-model="form.way"> <el-radio-group v-model="form.way">
<el-radio <template v-for="item in materialMethodList" :key="item.value">
v-for="item in materialMethodList" <el-radio :value="item.value" v-show="!wayDisabled(item, form.type)">{{ item.label }}</el-radio>
:key="item.value" </template>
:value="item.value"
:disabled="wayDisabled(item, form.type)"
>{{ item.label }}</el-radio
>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
......
...@@ -7,7 +7,7 @@ import { ...@@ -7,7 +7,7 @@ import {
materialMethodList, materialMethodList,
materialUsageList, materialUsageList,
materialUsersList, materialUsersList,
materialPictureStyleList materialPictureStyleList,
} from '@/utils/dictionary' } from '@/utils/dictionary'
import AppUpload from '@/components/base/AppUpload.vue' import AppUpload from '@/components/base/AppUpload.vue'
...@@ -31,58 +31,64 @@ const typeName = computed(() => { ...@@ -31,58 +31,64 @@ const typeName = computed(() => {
</el-form> </el-form>
<el-divider></el-divider> <el-divider></el-divider>
<el-form label-suffix=":" label-width="120" ref="formRef"> <el-form label-suffix=":" label-width="120" ref="formRef">
<template v-if="data.type == 2 && data.way == 1"> <template v-if="data.way != 3">
<!-- 图片AI --> <template v-if="data.type == 2 && data.way == 1">
<el-form-item label="图片风格" prop="extend_info.picture_style"> <!-- 图片AI -->
<el-radio-group :modelValue="data.extend_info.picture_style"> <el-form-item label="图片风格" prop="extend_info.picture_style">
<el-radio v-for="item in materialPictureStyleList" :key="item.id" :value="item.value">{{ <el-radio-group :modelValue="data.extend_info.picture_style">
item.label <el-radio v-for="item in materialPictureStyleList" :key="item.id" :value="item.value">{{
}}</el-radio> item.label
</el-radio-group> }}</el-radio>
</el-form-item> </el-radio-group>
<el-form-item label="人物描述" prop="extend_info.person_des"> </el-form-item>
<el-input type="textarea" :rows="3" :modelValue="data.extend_info.person_des" /> <el-form-item label="人物描述" prop="extend_info.person_des">
</el-form-item> <el-input type="textarea" :rows="3" :modelValue="data.extend_info.person_des" />
<el-form-item label="场景描述" prop="extend_info.scene_des"> </el-form-item>
<el-input type="textarea" :rows="3" :modelValue="data.extend_info.scene_des" /> <el-form-item label="场景描述" prop="extend_info.scene_des">
</el-form-item> <el-input type="textarea" :rows="3" :modelValue="data.extend_info.scene_des" />
<el-form-item label="突出重点信息描述" prop="extend_info.important_info_desc"> </el-form-item>
<el-input type="textarea" :rows="3" :modelValue="data.extend_info.important_info_desc" /> <el-form-item label="突出重点信息描述" prop="extend_info.important_info_desc">
</el-form-item> <el-input type="textarea" :rows="3" :modelValue="data.extend_info.important_info_desc" />
</template> </el-form-item>
<template v-else> </template>
<el-form-item label="所属行业" prop="industry_id"> <template v-else>
<el-select :model-value="data.industry_id"> <el-form-item label="所属行业" prop="industry_id">
<el-option v-for="item in industryList" :key="item.id" :label="item.name" :value="item.id + ''"></el-option> <el-select :model-value="data.industry_id">
</el-select> <el-option
</el-form-item> v-for="item in industryList"
<el-form-item label="使用场景" prop="scenario_type"> :key="item.id"
<el-radio-group :model-value="data.scenario_type"> :label="item.name"
<el-radio v-for="item in materialUsageList" :key="item.id" :value="item.value">{{ item.label }}</el-radio> :value="item.id + ''"></el-option>
</el-radio-group> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="使用人员" prop="personnel_type"> <el-form-item label="使用场景" prop="scenario_type">
<el-radio-group :model-value="data.personnel_type"> <el-radio-group :model-value="data.scenario_type">
<el-radio v-for="item in materialUsersList" :key="item.id" :value="item.value">{{ item.label }}</el-radio> <el-radio v-for="item in materialUsageList" :key="item.id" :value="item.value">{{ item.label }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="内容投放渠道" prop="channel"> <el-form-item label="使用人员" prop="personnel_type">
<el-radio-group :model-value="data.channel"> <el-radio-group :model-value="data.personnel_type">
<el-radio v-for="item in connectionList" :key="item.id" :value="item.id">{{ item.type_name }}</el-radio> <el-radio v-for="item in materialUsersList" :key="item.id" :value="item.value">{{ item.label }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="关键点" prop="key_points"> <el-form-item label="内容投放渠道" prop="channel">
<el-input <el-radio-group :model-value="data.channel">
type="textarea" <el-radio v-for="item in connectionList" :key="item.id" :value="item.id">{{ item.type_name }}</el-radio>
:rows="4" </el-radio-group>
:model-value="data.key_points" </el-form-item>
placeholder="请输入内容的核心内容或者关键点,多个请使用英文“,”号进行隔离。" /> <el-form-item label="关键点" prop="key_points">
</el-form-item> <el-input
type="textarea"
:rows="4"
:model-value="data.key_points"
placeholder="请输入内容的核心内容或者关键点,多个请使用英文“,”号进行隔离。" />
</el-form-item>
</template>
</template> </template>
<el-form-item :label="`${typeName}资源`" prop="content"> <el-form-item :label="`${typeName}资源`" prop="content">
<template v-if="data.type == 1"> <template v-if="data.type == 1">
<!-- 文本 --> <!-- 文本 -->
<el-input type="textarea" rows="12" :model-value="data.content"></el-input> <el-input type="textarea" :rows="12" :model-value="data.content"></el-input>
</template> </template>
<template v-if="['2', '6', '7', '8'].includes(data.type)"> <template v-if="['2', '6', '7', '8'].includes(data.type)">
<!-- 图片|二维码|小程序|卡券 --> <!-- 图片|二维码|小程序|卡券 -->
......
...@@ -8,6 +8,7 @@ const props = defineProps<{ action: string }>() ...@@ -8,6 +8,7 @@ const props = defineProps<{ action: string }>()
const StepOne = defineAsyncComponent(() => import('../components/StepOne.vue')) const StepOne = defineAsyncComponent(() => import('../components/StepOne.vue'))
const StepTwo = defineAsyncComponent(() => import('../components/StepTwo.vue')) const StepTwo = defineAsyncComponent(() => import('../components/StepTwo.vue'))
const StepThree = defineAsyncComponent(() => import('../components/StepThree.vue')) const StepThree = defineAsyncComponent(() => import('../components/StepThree.vue'))
const ImageChat = defineAsyncComponent(() => import('@/components/ImageChat.vue'))
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
...@@ -45,6 +46,10 @@ function handlePrev() { ...@@ -45,6 +46,10 @@ function handlePrev() {
// 下一步 // 下一步
function handleNext() { function handleNext() {
if (form.way == 3) {
chatVisible.value = true
return
}
activeName.value = activeName.value + 1 activeName.value = activeName.value + 1
} }
...@@ -76,6 +81,13 @@ async function handleUpdate() { ...@@ -76,6 +81,13 @@ async function handleUpdate() {
ElMessage.success('修改成功') ElMessage.success('修改成功')
router.replace('/material') router.replace('/material')
} }
const chatVisible = ref(false)
async function handleChatSave(url: string) {
form.content = url
await handleSubmit()
chatVisible.value = false
}
</script> </script>
<template> <template>
...@@ -97,6 +109,7 @@ async function handleUpdate() { ...@@ -97,6 +109,7 @@ async function handleUpdate() {
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</AppCard> </AppCard>
<ImageChat v-model="chatVisible" @update="handleChatSave" v-if="chatVisible"></ImageChat>
</template> </template>
<style lang="scss"> <style lang="scss">
......
...@@ -116,6 +116,7 @@ export const materialMethodList = [ ...@@ -116,6 +116,7 @@ export const materialMethodList = [
{ label: '离线上传 ', value: '2' }, { label: '离线上传 ', value: '2' },
{ label: '在线AI', value: '1' }, { label: '在线AI', value: '1' },
// { label: '在线设计', value: '3' }, // { label: '在线设计', value: '3' },
{ label: 'AI图像生成', value: '3' },
] ]
// 使用场景 // 使用场景
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论