Commit 7e15b57b authored by 周成波's avatar 周成波

增加营销模板

parent 5c019015
...@@ -13,6 +13,7 @@ declare module 'vue' { ...@@ -13,6 +13,7 @@ declare module 'vue' {
ElDivider: typeof import('element-plus/es')['ElDivider'] ElDivider: typeof import('element-plus/es')['ElDivider']
ElForm: typeof import('element-plus/es')['ElForm'] ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage'] ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
import request from '@/api/request' import request from '@/api/request'
export default { export default {
submitLLM(prompt: string, llm: string = "gpt"): Promise<string> { submitLLM(prompt: string, llm: string = "gpt", history: Wm.PromptHistory[] = []): Promise<string> {
if (!prompt) { if (!prompt) {
return Promise.reject("输入不能为空"); return Promise.reject("输入不能为空");
} }
const post_data = { source_text: prompt, llm: llm } const post_data = { source_text: prompt, history: history, llm: llm }
return request.post('/text2video/text2llm', post_data) return request.post('/text2video/text2llm', post_data)
.then((res: any) => { .then((res: any) => {
// console.log(res); // console.log(res);
...@@ -130,4 +130,22 @@ export default { ...@@ -130,4 +130,22 @@ export default {
return Promise.reject(`与翻译接口通讯失败:${JSON.stringify(err.message)}`); return Promise.reject(`与翻译接口通讯失败:${JSON.stringify(err.message)}`);
}); });
}, },
submitAddTextToImg(param: any): Promise<{"domain_image_path": string, "local_image_path": string}> {
const post_data = param
return request.post('/text2video/add_text_to_img', post_data)
.then((res: any) => {
// console.log(res);
if (res && res.code === 0) {
return {"domain_image_path": res.data.result.domain_image_path, "local_image_path": res.data.result.local_image_path};
} else {
const errorMessage = res ? res.message : "未知错误";
return Promise.reject(errorMessage);
}
})
.catch((err: any) => {
console.log(`err = ${JSON.stringify(err)}`);
return Promise.reject(`add_text_to_img接口通讯失败:${JSON.stringify(err.message)}`);
});
},
} }
src/assets/waiting.png

1.02 KB | W: | H:

src/assets/waiting.png

957 Bytes | W: | H:

src/assets/waiting.png
src/assets/waiting.png
src/assets/waiting.png
src/assets/waiting.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -36,7 +36,7 @@ export default class utils { ...@@ -36,7 +36,7 @@ export default class utils {
static splitText(str: string) { static splitText(str: string) {
str = str.replaceAll('“','').replaceAll('”','') str = str.replaceAll('“','').replaceAll('”','')
// 使用正则表达式拆分文本 // 使用正则表达式拆分文本
let sentences = str.split(/[!|?|。]/); let sentences = str.split(/[!|?|。|"|!]/);
// 过滤掉长度为 0 的句子 // 过滤掉长度为 0 的句子
sentences = sentences.filter(s => s.length > 0); sentences = sentences.filter(s => s.length > 0);
// console.log(sentences) // console.log(sentences)
......
...@@ -69,7 +69,7 @@ export const useManyValues = () => { ...@@ -69,7 +69,7 @@ export const useManyValues = () => {
const vertical_data = { const vertical_data = {
task_id: "20240220181602687", task_id: "20240220181602687",
chatgpt_prompt: `生成一个50字的科幻小故事,阿凡达系列`, chatgpt_prompt: `生成一个50字的科幻小故事,阿凡达系列`,
chatgpt_answer: `在宁静的森林里。一场奇特的食物大战正在上演。一只机灵的小松鼠。眼尖地发现了一块香气扑鼻的奶油蛋糕,正惬意地躺在熊猫阿宝的竹篮里。蛋糕上的水果点缀和醇厚的奶油似乎在向小松鼠招手,它的口水都快流成一条小溪了。`, chatgpt_answer: `在宁静的森林里。一场奇特的食物大战正在上演。`,
chatgpt_answer_roles: [], chatgpt_answer_roles: [],
adapt_result_json: [], adapt_result_json: [],
final_video: ``, final_video: ``,
...@@ -262,6 +262,47 @@ export const useManyValues = () => { ...@@ -262,6 +262,47 @@ export const useManyValues = () => {
sd_prompt_prefix: sd_prompt_prefix + ", <lora:sdxl_lightning_8step_lora:0.2>", sd_prompt_prefix: sd_prompt_prefix + ", <lora:sdxl_lightning_8step_lora:0.2>",
}, },
}; };
const marketing_template = {
product_name: "金巧蒂原味猪肉松",
product_description:
`1. 酥而不腻,入口即化
2. 原料主要采用新鲜猪后腿肉,经过水域立即处理,加上老师傅祖传的配方,结合现代化的生产工艺,锤炼出柔软酥松,绵而不腻,味香可口的“猪肉松”,并全程使用“多力牌”葵花油
3. 选用天然万家香酱油
4. 选用蒂纳海盐
5. 猪肉松的主要营养成分有碳水化合物、脂肪、蛋白质和多种矿物质,胆固醇含量低,且易于人体消化吸收,具有很高的营养价值。但是要注意一点,猪肉松不能与鹌鹑肉同食,吃多容易生黑斑哦
6. 我们“金巧蒂”的产品,确保是在屠宰后2小时内进行加工,绝对锁住肉质口感不流失。猪肉肉质细腻且营养价值丰富,对人体有极高的营养价值及保健作用,如长期食用可延年益寿,并有着汤汁浓郁,绕齿留香的特点`,
target_people: "20-30岁年轻女生",
text_role: "小松鼠",
text_style: "幽默",
story_type: "科幻",
reference: "猪八戒娶媳妇儿的情节",
words_num: 100,
result1: "",
result2: "",
if_need_product_pic: "false",
product_pic: "http://wm-tools-backend.frp.wmdigit.com:8888/assets/2024/03/06/4784edb2-db68-11ee-a7de-9be5c7a16c02_resized.jpg",
product_pic_local: "assets/2024/03/06/4784edb2-db68-11ee-a7de-9be5c7a16c02_resized.jpg",
product_pic_with_text: "http://wm-tools-backend.frp.wmdigit.com:8888/assets/2024/03/06/4784edb2-db68-11ee-a7de-9be5c7a16c02_resized_with_text.jpg",
product_pic_with_text_local: "assets/2024/03/06/4784edb2-db68-11ee-a7de-9be5c7a16c02_resized_with_text.jpg",
product_pic_titles: [
{
text: "金巧蒂原味猪肉松",
color: "#FB7D01",
bg_color: "",
font_size: 45,
position: 0.8,
},
{
text: "促销价只要8.8!快来抢购吧~",
color: "#FF0800",
bg_color: "",
font_size: 45,
position: 0.2,
},
],
product_pic_speech: "我们的产品正在促销热卖中,点点关注哦~",
};
return { return {
screen: screen, screen: screen,
...@@ -281,5 +322,6 @@ export const useManyValues = () => { ...@@ -281,5 +322,6 @@ export const useManyValues = () => {
bgm_volume_marks: bgm_volume_marks, bgm_volume_marks: bgm_volume_marks,
role_attribute_options: role_attribute_options, role_attribute_options: role_attribute_options,
sd_paras: sd_paras, sd_paras: sd_paras,
marketing_template: marketing_template,
} }
} }
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, ref, nextTick } from "vue"; import { onMounted, reactive, ref, nextTick } from "vue";
import { Sunny, UploadFilled } from "@element-plus/icons-vue"; import { Sunny, UploadFilled, Delete, Download, Plus, ZoomIn } from "@element-plus/icons-vue";
import { import {
ElMessage, genFileId, ElMessage, genFileId,
type UploadInstance, type UploadInstance,
type UploadProps, type UploadProps,
type UploadRawFile type UploadRawFile,
type UploadFile
} from "element-plus"; } from "element-plus";
import text2videoService from "@/api/service/text2videoService"; import text2videoService from "@/api/service/text2videoService";
import utils from "@/utils/utils"; import utils from "@/utils/utils";
...@@ -51,6 +52,30 @@ const sub_bg_color = ref() ...@@ -51,6 +52,30 @@ const sub_bg_color = ref()
const sub_font_size = ref(25) const sub_font_size = ref(25)
const sub_position = ref(0.3) const sub_position = ref(0.3)
const marketingTemplateVisible = ref(false);
const marketing_template = reactive({
product_name: "",
product_description: "",
target_people: "",
text_role: "",
text_style: "",
story_type: "",
reference: "",
words_num: 0,
prompt1: "",
prompt2: "",
result1: "",
result2: "",
if_need_product_pic: "",
product_pic: "src/assets/waiting.png",
product_pic_local: "",
product_pic_with_text: "",
product_pic_with_text_local: "",
product_pic_titles: <Wm.PicText[]>[],
product_pic_speech: "",
});
const previewMarketingTemplatePicTextVisible = ref(false);
onMounted(() => { onMounted(() => {
// 初始化示例数据 // 初始化示例数据
...@@ -101,17 +126,20 @@ const onAdaptRoles = async () => { ...@@ -101,17 +126,20 @@ const onAdaptRoles = async () => {
console.log(roles_arr); console.log(roles_arr);
// 推理属性 // 推理属性
const attribute_options = default_data.role_attribute_options.map(option => option.value); const attribute_options = default_data.role_attribute_options.map(option => option.value);
console.log('dddddddd', attribute_options)
for (const one_role of roles_arr) { for (const one_role of roles_arr) {
// const adapt_attribute_restrict = `根据这个故事:“${form.chatgpt_answer}”,你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`; // const adapt_attribute_restrict = `根据这个故事:“${form.chatgpt_answer}”,你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
// const adapt_attribute_restrict = `你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`; // const adapt_attribute_restrict = `你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
const adapt_attribute_restrict = `故事全文:“${form.chatgpt_answer}”,请理解故事全文,然后判断:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`; const adapt_attribute_restrict = `故事全文:“${form.chatgpt_answer}”,请理解故事全文,然后判断:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
let attribute = await text2videoService.submitLLM(adapt_attribute_restrict, role_keywords_llm.api); let attribute = await text2videoService.submitLLM(adapt_attribute_restrict, role_keywords_llm.api);
form.chatgpt_answer_roles.push({ if (attribute_options.includes(attribute)) {
form.chatgpt_answer_roles.push({
"角色": one_role.trim(), "角色": one_role.trim(),
"角色关键词": "", "角色关键词": "",
"角色关键词英文": "", "角色关键词英文": "",
"属性": attribute, "属性": attribute,
}); });
}
} }
console.log(form.chatgpt_answer_roles) console.log(form.chatgpt_answer_roles)
} catch (error) { } catch (error) {
...@@ -206,7 +234,7 @@ const onAdapt = async () => { ...@@ -206,7 +234,7 @@ const onAdapt = async () => {
console.log(form.task_id) console.log(form.task_id)
// 按标点拆分成分镜 // 按标点拆分成分镜
const sentences = utils.splitText(form.chatgpt_answer); const sentences = utils.splitText(form.chatgpt_answer);
console.log(sentences.length) // console.log(sentences.length)
// 分镜 // 分镜
form.adapt_result_json = [] form.adapt_result_json = []
for (let i = 0; i < sentences.length; i++) { for (let i = 0; i < sentences.length; i++) {
...@@ -523,7 +551,8 @@ const onDrawOne = async (item: any) => { ...@@ -523,7 +551,8 @@ const onDrawOne = async (item: any) => {
message: String(error), message: String(error),
type: "error", type: "error",
}); });
item.本镜配图 = "" item.本镜配图 = "";
item.local_image_path = "";
} }
}; };
...@@ -626,7 +655,25 @@ const onChangeScreen = (val: string) => { ...@@ -626,7 +655,25 @@ const onChangeScreen = (val: string) => {
form.adapt_result_json = default_data.vertical_data.adapt_result_json; form.adapt_result_json = default_data.vertical_data.adapt_result_json;
form.final_video = default_data.vertical_data.final_video; form.final_video = default_data.vertical_data.final_video;
} }
marketing_template.product_pic = default_data.marketing_template.product_pic;
marketing_template.product_pic_local = default_data.marketing_template.product_pic_local;
marketing_template.product_pic_with_text = default_data.marketing_template.product_pic_with_text;
marketing_template.product_pic_with_text_local = default_data.marketing_template.product_pic_with_text_local;
} }
marketing_template.product_name = default_data.marketing_template.product_name;
marketing_template.product_description = default_data.marketing_template.product_description;
marketing_template.target_people = default_data.marketing_template.target_people;
marketing_template.text_role = default_data.marketing_template.text_role;
marketing_template.text_style = default_data.marketing_template.text_style;
marketing_template.story_type = default_data.marketing_template.story_type;
marketing_template.reference = default_data.marketing_template.reference;
marketing_template.words_num = default_data.marketing_template.words_num;
marketing_template.if_need_product_pic = default_data.marketing_template.if_need_product_pic;
marketing_template.product_pic_titles = default_data.marketing_template.product_pic_titles;
marketing_template.product_pic_speech = default_data.marketing_template.product_pic_speech;
// 宽高 // 宽高
if (val == "横屏") { if (val == "横屏") {
form.img_size = default_data.horizontal_img_size; form.img_size = default_data.horizontal_img_size;
...@@ -738,6 +785,135 @@ const onDeleteOne = (item: any) => { ...@@ -738,6 +785,135 @@ const onDeleteOne = (item: any) => {
}); });
} }
}; };
// /////// 模板相关 ////////////
// const activeTab = ref("first");
// const goToNextPage = () => {
// activeTab.value = "second";
// };
const MarketingTemplateUploadSuccess = (val: Wm.UploadResult) => {
console.log(val)
if (val.code == 0) {
marketing_template.product_pic = val.data[0].url + "?v=" + utils.genDateTimeStr();
marketing_template.product_pic_local = val.data[0].path;
ElMessage({
message: '上传成功',
type: 'success'
})
} else {
ElMessage({
message: '上传失败:'+val.message,
type: 'error'
})
}
}
const onAddMarketingTemplatePicText = () => {
const newElement = {
text: "新的文本",
color: "#000000",
bg_color: "#FFFFFF",
font_size: 20,
position: 0.5
};
marketing_template.product_pic_titles.push(newElement);
};
const onMarketingTemplateAddTextToPic = async () => {
if (!marketing_template.product_pic_local) {
ElMessage({
message: '请上传图片',
type: 'error'
})
return false;
}
const texts = marketing_template.product_pic_titles.map(item => {
return {
text: item.text,
text_color: item.color ? item.color : '',
text_bg_color: item.bg_color ? item.bg_color : '',
font_size: String(item.font_size),
position: String(1 - item.position),
lang: 'zh',
};
});
const params = {
image_path: marketing_template.product_pic_local,
image_texts: texts,
};
try {
const result = await text2videoService.submitAddTextToImg(params);
console.log(result);
marketing_template.product_pic_with_text = result.domain_image_path + "?v=" + utils.genDateTimeStr();
marketing_template.product_pic_with_text_local = result.local_image_path;
return true;
} catch (error) {
ElMessage({
message: String(error),
type: "error",
});
marketing_template.product_pic_with_text = "";
marketing_template.product_pic_with_text_local = "";
return false;
}
};
const onPreviewMarketingTemplatePicText = async () => {
let res = await onMarketingTemplateAddTextToPic();
if (!res) {return;}
previewMarketingTemplatePicTextVisible.value = true;
};
const onMarketingTemplateSubmitGpt = async () => {
marketing_template.prompt1 = `
商品名称:{${marketing_template.product_name}}
商品卖点:[${marketing_template.product_description}]
文案主角:{${marketing_template.text_role}}
产品目标群体:{${marketing_template.target_people}}
参考信息:[${marketing_template.reference}]
你是营销专家,请写一个文案主角和商品的互动文案,要先理解商品卖点,学习参考信息,以${marketing_template.text_style}的风格,先整理出这篇营销文案的文案提纲。
注意,要用精简的语言总结出文案的提纲,文案提纲是:{}
在最后总结,把故事情节总结成一句夺人眼球的疑问句开头,设置悬念,需要你总结成15个字以内,开头语总结是:{}
`
marketing_template.prompt2 = `
你是${marketing_template.story_type}作家,请根据原始内容和你分析的框架,写一个${marketing_template.words_num}字的${marketing_template.story_type}故事文案。
特别注意,不能提到功效类用词,不要直接用目标群体的描述带入到框架中,用这个群体的特征描述来代。第一句用你总结的开头语,整体字数是${marketing_template.words_num}字。
你给出的文案是:{}
`
try {
if (marketing_template.if_need_product_pic == 'true') {
console.log("添加文字到图片")
let res = await onMarketingTemplateAddTextToPic();
if (!res) {return;}
}
console.log("第一次提问")
let result1 = await text2videoService.submitLLM(marketing_template.prompt1, wen_an_llm.api);
marketing_template.result1 = result1;
console.log(marketing_template.prompt1);
console.log(marketing_template.result1);
console.log("第二次带历史提问")
const history = [{'role': 'user', 'content': marketing_template.prompt1}, {'role': 'assistant', 'content': result1}]
let result2 = await text2videoService.submitLLM(marketing_template.prompt2, wen_an_llm.api, history);
marketing_template.result2 = result2;
console.log(JSON.stringify(history), marketing_template.prompt2);
console.log(marketing_template.result2);
form.chatgpt_answer = result2;
marketingTemplateVisible.value = false;
}
catch (error) {
ElMessage({
message: String(error),
type: "error",
});
}
};
</script> </script>
<template> <template>
...@@ -762,8 +938,17 @@ const onDeleteOne = (item: any) => { ...@@ -762,8 +938,17 @@ const onDeleteOne = (item: any) => {
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmitGpt">生成文案({{ wen_an_llm.name }}</el-button> <el-button type="primary" @click="onSubmitGpt">生成文案({{ wen_an_llm.name }}</el-button>
<el-button type="danger" @click="marketingTemplateVisible = true">通过营销模板生成文案</el-button>
</el-form-item> </el-form-item>
<el-form-item label="文案"> <el-form-item label="文案">
<template v-if="marketing_template.result2">
<el-text class="mx-1" type="danger">第一次提问:</el-text>
<el-text class="mx-1">{{ marketing_template.prompt1 }}</el-text>
<el-text class="mx-1" type="danger">返回:</el-text>
<el-text class="mx-1">{{ marketing_template.result1 }}</el-text>
<el-text class="mx-1" type="danger">第二次提问:</el-text>
<el-text class="mx-1">{{ marketing_template.prompt2 }}</el-text>
</template>
<el-input v-model="form.chatgpt_answer" :autosize="true" type="textarea" /> <el-input v-model="form.chatgpt_answer" :autosize="true" type="textarea" />
</el-form-item> </el-form-item>
<!-- 角色 --> <!-- 角色 -->
...@@ -955,6 +1140,99 @@ const onDeleteOne = (item: any) => { ...@@ -955,6 +1140,99 @@ const onDeleteOne = (item: any) => {
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- 营销模板 -->
<el-dialog v-model=marketingTemplateVisible title="营销模板" width="60%" height="500" :close-on-click-modal="false"
:close-on-press-escape="true" :show-close="true" :lock-scroll="true">
<!--
<el-tabs v-model="activeTab">
<el-tab-pane label="商品" name="first">User</el-tab-pane>
<el-tab-pane label="Config" name="second">Config</el-tab-pane>
<el-tab-pane label="Role" name="third">Role</el-tab-pane>
<el-tab-pane label="Task" name="fourth">Task</el-tab-pane>
</el-tabs>
<el-button @click="goToNextPage">下一步</el-button>
-->
<el-form :model="marketing_template">
<el-form-item label="商品名称">
<el-input v-model="marketing_template.product_name" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="商品描述">
<el-input v-model="marketing_template.product_description" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="目标群体">
<el-input v-model="marketing_template.target_people" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="文案主角">
<el-input v-model="marketing_template.text_role" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="文案风格">
<el-input v-model="marketing_template.text_style" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="故事类型">
<el-input v-model="marketing_template.story_type" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="参考信息">
<el-input v-model="marketing_template.reference" :autosize="true" type="textarea"></el-input>
</el-form-item>
<el-form-item label="文案字数">
<el-input-number v-model="marketing_template.words_num" :min="10" :max="500" controls-position="right"/>
</el-form-item>
<el-form-item label="商品图片">
<el-switch v-model="marketing_template.if_need_product_pic" active-value="true" inactive-value="false" />
</el-form-item>
<div v-if="JSON.parse(marketing_template.if_need_product_pic.toLowerCase())">
<el-form-item style="margin-left: 68px;">
<!-- :style="{ width: String(parseInt(form.img_size.width) / 3)+'px', height: String(parseInt(form.img_size.height) / 3)+'px' }" -->
<div :style="{ width: String(parseInt(form.img_size.width) / 3)+'px' }" class="dashed-div">
<el-image :src="marketing_template.product_pic" />
</div>
</el-form-item>
<el-form-item style="margin-left: 60px;">
<el-upload class="upload-demo" ref="upload" list-type="picture" :show-file-list="false" :limit="1"
accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
:action="actionUrl" :on-success="MarketingTemplateUploadSuccess" :on-exceed="handleUploadExceed"
:on-error="handleUploadError" :data="{ width: form.img_size.width, height: form.img_size.height }">
<el-button type="primary" size="small" style="margin: 10px;">上传图片</el-button>
</el-upload>
<el-button type="danger" size="small" @click="marketing_template.product_pic = 'src/assets/waiting.png';" style="margin-left: 15px;">清除图片</el-button>
</el-form-item>
<el-form-item label="图片文字">
<div style="width: 100%;">
<el-button type="primary" size="small" @click="onAddMarketingTemplatePicText">增加</el-button>
</div>
<div v-for="(pic_title, index) in marketing_template.product_pic_titles" :key="index" class="dashed-div">
<el-input v-model="pic_title.text" :autosize="true" type="textarea"></el-input>
<span style="margin-left:10px;">字体颜色:</span>
<el-color-picker v-model="pic_title.color" />
<span style="margin-left:30px;">字体背景:</span>
<el-color-picker v-model="pic_title.bg_color" />
<span style="margin-left:30px;">字体大小:</span>
<el-input-number v-model="pic_title.font_size" :min="1" :max="50" controls-position="right" />
<span style="margin-left:30px;">在图片上的位置:</span>
<el-slider v-model="pic_title.position" :step="0.1" :min="0" :max="1" show-input vertical height="100px" style="margin-top: 10px;"/>
<el-button type="danger" size="small" @click="marketing_template.product_pic_titles.splice(index, 1);" style="margin-left: 80px;">删除</el-button>
</div>
<el-button type="success" size="small" @click="onPreviewMarketingTemplatePicText">预览</el-button>
<el-dialog title="预览" v-model="previewMarketingTemplatePicTextVisible" append-to-body :width="parseInt(form.img_size.width) / 2 + 40">
<div :style="{ width: String(parseInt(form.img_size.width) / 2)+'px' } " class="dashed-div">
<el-image :src="marketing_template.product_pic_with_text" />
</div>
</el-dialog>
</el-form-item>
<el-form-item label="镜头旁白">
<el-input v-model="marketing_template.product_pic_speech" :autosize="true" type="textarea"></el-input>
</el-form-item>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="marketingTemplateVisible = false">取消</el-button>
<el-button type="primary" @click="onMarketingTemplateSubmitGpt()">提交</el-button>
</div>
</template>
</el-dialog>
</main> </main>
</template> </template>
...@@ -970,4 +1248,9 @@ const onDeleteOne = (item: any) => { ...@@ -970,4 +1248,9 @@ const onDeleteOne = (item: any) => {
z-index: calc(var(--el-table-index) -1); z-index: calc(var(--el-table-index) -1);
} }
} }
.dashed-div {
border: 1px dashed #999;
margin: 5px 0;
padding: 2px;
}
</style> </style>
...@@ -4,6 +4,19 @@ declare namespace Wm { ...@@ -4,6 +4,19 @@ declare namespace Wm {
"height": string, "height": string,
} }
interface PromptHistory {
"role": string,
"content": string,
}
interface PicText {
"text": string,
"color": string,
"bg_color": string,
"font_size": number,
"position": number,
}
interface ScriptsItem { interface ScriptsItem {
"编号": string, "编号": string,
"场景描述": string, "场景描述": string,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment