<script setup lang="ts">
import text2videoService from '@/api/service/text2videoService'
import utils from '@/utils/utils'
import {
  ElMessage,
  genFileId,
  type UploadInstance,
  type UploadProps,
  type UploadRawFile
} from 'element-plus'
import { nextTick, onMounted, reactive, ref } from 'vue'
import { useManyValues } from './compositions/useManyValues'

const debug = ref(import.meta.env.MODE === 'production' ? false : true)
// const debug = ref(false);
const loading = ref(false)
const dialogVisible = ref(false)
const dialogData = ref('')
const default_data = useManyValues()
const form = reactive({
  screen: default_data.screen,
  img_size: <Wm.ImgSize>{},
  if_need_subtitle: default_data.if_need_subtitle,
  chatgpt_prompt: '',
  chatgpt_answer: '',
  chatgpt_answer_roles: <Wm.RolesItem[]>[],
  all_roles: '',
  adapt_result_json: <Wm.ScriptsItem[]>[],
  task_id: '',
  final_video: ''
})
const sd_model = default_data.sd_paras.juggernautXL_v9Rdphoto2Lightning
const sd_prompt_prefix = sd_model.sd_prompt_prefix
const sd_negative_prompt_prefix = default_data.sd_negative_prompt_prefix

const wen_an_llm = default_data.llms.tyqw_online
const role_llm = default_data.llms.tyqw_online
const role_keywords_llm = default_data.llms.tyqw_online
const tuili_llm = default_data.llms.tyqw_online
const tuili_keyword_llm = default_data.llms.tyqw_online
// const fanyi_llm = default_data.llms.tyqw_online;

const voice_rate = ref(0)
const voice_volume = ref(0)
const voice = ref('zh-CN-YunjianNeural')
const bgm = ref('解忧曲')
const bgm_volume = ref(0.3)
const pwdCheckDialogVisible = ref(false)
const pwdCheckValue = ref('')
const sub_font_color = ref('#FFFF00')
const sub_bg_color = ref()
const sub_font_size = ref(35)
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: ''
})

const cover_backcover = reactive({
  if_need_cover_pic: 'false',
  cover_pic: 'src/assets/waiting.png',
  cover_pic_local: '',
  cover_pic_with_text: 'src/assets/waiting.png',
  cover_pic_with_text_local: '',
  cover_pic_titles: <Wm.PicText[]>[],
  cover_pic_use_scene: '',

  if_need_product_pic: 'false',
  product_pic: 'src/assets/waiting.png',
  product_pic_local: '',
  product_pic_with_text: 'src/assets/waiting.png',
  product_pic_with_text_local: '',
  product_pic_titles: <Wm.PicText[]>[],
  product_pic_speech: ''
})

const inPaintVisible = ref(false)
const inPaintBaseImgData = ref('')
const inPaintMaskData = ref('')
const inPaintType = ref('')
const inPaintItem = ref()
const inPaintPrompt = ref('')

const update_and_modify_product = reactive({
  if_need: 'false',
  pic: 'src/assets/waiting.png',
  pic_local: '',
  pic_preview: 'src/assets/waiting.png',
  pic_preview_local: '',
  pic_mask: 'src/assets/waiting.png',
  pic_mask_local: '',
  inPaintVisible: false,
  inPaintBaseImgData: '',
  inPaintMaskData: '',
  inPaintPrompt: '',
  cutout_obj: <Wm.Coordinate[]>[],
  cutout_no_obj: <Wm.Coordinate[]>[],
  cutoutPart: '1'
})
const radio1 = ref('1')

onMounted(() => {
  // 初始化task_id
  form.task_id = utils.genDateTimeStr()
  console.log('页面加载，task_id=', form.task_id)
  // 初始化示例数据
  onChangeScreen(form.screen)
  // 初始化密码框
  if (debug.value == true) {
    pwdCheckDialogVisible.value = false
  } else {
    pwdCheckDialogVisible.value = true
  }
})

const delay = (ms: any) => new Promise((res) => setTimeout(res, ms))

const onSubmitGpt = () => {
  text2videoService
    .submitLLM(
      utils.aesEncrypt(form.chatgpt_prompt),
      utils.aesEncrypt(wen_an_llm.api),
      [],
      form.task_id,
      'true'
    )
    .then((result: string) => {
      // console.log(form.chatgpt_prompt);
      // console.log(result);
      form.chatgpt_answer = result
    })
    .catch((error: any) => {
      // console.error(error);
      ElMessage({
        message: error,
        type: 'error'
      })
    })
}

const onAdaptRoles = async () => {
  if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
    ElMessage({
      message: '文案不能为空',
      type: 'error'
    })
    return
  }
  if (!form.task_id) {
    // 初始化task_id
    form.task_id = utils.genDateTimeStr()
    console.log('推理角色，生成task_id=', form.task_id)
  }
  // 推理角色
  try {
    form.chatgpt_answer_roles = []
    const adapt_restrict = `请理解这个故事：“${form.chatgpt_answer}”，给出这个故事中的所有角色，多个角色以逗号分隔。\n要求：只返回角色名称即可，不要添加其他的内容。`
    let roles = await text2videoService.submitLLM(
      utils.aesEncrypt(adapt_restrict),
      utils.aesEncrypt(role_llm.api),
      [],
      form.task_id,
      'true'
    )
    form.all_roles = roles.replace(/。|（|）/g, '').replace(/、/g, ',')
    console.log(form.all_roles)
    const roles_arr = form.all_roles.split(/[，,]/)
    console.log(roles_arr)
    // 推理属性
    const attribute_options = default_data.role_attribute_options.map((option) => option.value)
    console.log('dddddddd', attribute_options)
    for (const one_role of roles_arr) {
      // 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 = `故事全文：“${
        form.chatgpt_answer
      }”，请理解故事全文，然后判断：“${one_role}”是“${String(
        attribute_options
      )}”中的哪一种？请返回选择的结果。\n要求：只返回选择的结果即可，不要添加其他的内容。`
      let attribute = await text2videoService.submitLLM(
        utils.aesEncrypt(adapt_attribute_restrict),
        utils.aesEncrypt(role_llm.api),
        [],
        form.task_id,
        'true'
      )
      console.log('dddddddd', attribute)
      if (attribute_options.includes(attribute)) {
        form.chatgpt_answer_roles.push({
          角色: one_role.trim(),
          角色关键词: '',
          角色关键词英文: '',
          属性: attribute
        })
      }
    }
    console.log(form.chatgpt_answer_roles)
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  }
}

const onAdaptRolesKeywords = async () => {
  if (!form.chatgpt_answer_roles || form.chatgpt_answer_roles.length == 0) {
    ElMessage({
      message: '总角色不能为空',
      type: 'error'
    })
    return
  }
  for (const one_role of form.chatgpt_answer_roles) {
    if (!one_role.属性) {
      ElMessage({
        message: `请选择 ${one_role.角色} 的属性`,
        type: 'error'
      })
      return
    }
  }
  loading.value = true
  // 推理角色关键词
  try {
    async function processRoles() {
      for (const one_role of form.chatgpt_answer_roles) {
        await delay(100)
        let adapt_keyword_restrict = `请理解这个故事：“${form.chatgpt_answer}”，给出其中这个角色“${one_role.角色}”的关键词，以逗号分隔。包括但不限于：`
        let temp_restrict = ''
        if (one_role.属性.includes('人')) {
          temp_restrict = `性别(可以发挥想象进行补充，但一定要有)， 年龄(可以发挥想象进行补充，但一定要有)，
           肤色(可以发挥想象进行补充，但一定要有)， 衣服(可以发挥想象进行补充，但一定要有)， 发型(可以发挥想象进行补充，但一定要有)，
           发色(可以发挥想象进行补充，但一定要有)， 脸色(可以发挥想象进行补充，但一定要有)， 五官特点(可以发挥想象进行补充，但一定要有)`
        } else {
          let temp_restrict_pre = ''
          if (one_role.属性.includes('动物')) {
            temp_restrict_pre = `哪一种动物(可以发挥想象进行补充，但一定要有)，`
          }
          temp_restrict = `${temp_restrict_pre} 体型(可以发挥想象进行补充，但一定要有)， 颜色(可以发挥想象进行补充，但一定要有)，
           四肢(可以发挥想象进行补充，但一定要有)， 五官特点(可以发挥想象进行补充，但一定要有)，
           身体(皮毛，羽毛，鳞片，肤色等，可以发挥想象进行补充，没有就不提供)`
        }
        adapt_keyword_restrict = adapt_keyword_restrict + temp_restrict + '。回答限制在30个字左右。'
        let keywords = await text2videoService.submitLLM(
          utils.aesEncrypt(adapt_keyword_restrict),
          utils.aesEncrypt(role_keywords_llm.api),
          [],
          form.task_id,
          'true'
        )
        keywords = keywords.replace(/。/g, '').replace(/、/g, ',')
        one_role.角色关键词 = keywords

        await delay(100)
        // const adapt_attribute_restrict_en = `你现在扮演专业的英语翻译的角色。请将这段文字“${keywords}”翻译为英语。\n要求：只返回英语即可，不要返回其他内容。`;
        // let keywords_en = await text2videoService.submitLLM(adapt_attribute_restrict_en, role_keywords_llm.api);
        let keywords_en = await text2videoService.submitTranslateToEn(
          utils.aesEncrypt(keywords),
          form.task_id,
          'true'
        )
        // console.log(keywords_en)
        // keywords_en = utils.filterChineseAndPunctuation(keywords_en.replace(/"/g, ''));
        keywords_en = keywords_en.replace(/"/g, '')
        one_role.角色关键词英文 = keywords_en
      }
    }
    try {
      await processRoles()
      console.log(form.chatgpt_answer_roles)
    } catch (error) {
      ElMessage({
        message: String(error),
        type: 'error'
      })
    }
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    // 最终关闭loading（无论成功或失败）
    loading.value = false
  }
}

const onAdapt = async (type: string) => {
  if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
    ElMessage({
      message: '文案不能为空',
      type: 'error'
    })
    return
  }
  if (!form.task_id) {
    // 初始化task_id
    form.task_id = utils.genDateTimeStr()
    console.log('分镜，生成task_id=', form.task_id)
  }
  // 按标点拆分成分镜
  let sentences = utils.splitText(form.chatgpt_answer)
  if (type == 'more_scene' && sentences.length < 5) {
    sentences = utils.splitText(form.chatgpt_answer, type)
  }
  // console.log(sentences.length)
  // 分镜
  form.adapt_result_json = []
  let texts = []
  for (let i = 0; i < sentences.length; i++) {
    form.adapt_result_json.push({
      编号: (i + 1).toString(),
      场景描述: sentences[i].trim(),
      场景关键词: '',
      场景关键词英文: '',
      角色: '',
      角色关键词: '',
      角色关键词英文: '',
      画面描述词: '',
      本镜配图: 'src/assets/waiting.png',
      local_image_path: '',
      info: '',
      roles: [],
      info2: ''
    })
    texts.push({
      idx: (i + 1).toString(),
      text: sentences[i].trim()
    })
  }
  // 匹配产品图到最合适的场景
  if (update_and_modify_product.pic_local && update_and_modify_product.pic_local != '') {
    let para = {
      task_id: form.task_id,
      image_path: update_and_modify_product.pic_local,
      texts: texts
    }
    try {
      const result = await text2videoService.submitImgTextMatch(para)
      // 找到最高的分数
      const highestScoreObject = result.reduce(
        (maxObj, currObj) => {
          return currObj.score > maxObj.score ? currObj : maxObj
        },
        { score: -Infinity }
      )
      // 将最高的分数匹配到场景中
      for (const item of form.adapt_result_json) {
        if (item.编号 == highestScoreObject.idx) {
          item.本镜配图 = update_and_modify_product.pic
          item.local_image_path = update_and_modify_product.pic_local
          item.info2 = '产品图与场景匹配度：' + highestScoreObject.score
        }
        // 顺便将返回结果的分数都匹配到场景中
        const matchInResult = result.find((r) => item.编号 == r.idx)
        if (matchInResult) {
          item.info2 = '产品图与场景匹配度：' + matchInResult.score
        }
      }
    } catch (error) {
      ElMessage({
        message: String(error),
        type: 'error'
      })
    }
  }
  console.log(form.adapt_result_json)
}

const onAdaptScene = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: '分镜不能为空',
      type: 'error'
    })
    return
  }
  loading.value = true
  async function processScenes() {
    for (const item of form.adapt_result_json) {
      if (item.local_image_path == '') {
        await onAdaptOneScene(item)
      }
    }
  }
  try {
    await processScenes()
    ElMessage({
      message: 'all scene ok',
      type: 'success'
    })
    console.log(form.adapt_result_json)
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    loading.value = false // 最终关闭loading（无论成功或失败）
  }
}

const onAdaptOneScene = async (item: any) => {
  if (!item.场景描述) {
    ElMessage({
      message: `分镜 ${item.编号} 场景描述不能为空`,
      type: 'error'
    })
    return
  }
  // 推理场景
  // 人物(可以发挥想象进行补充，但一定要有),  暂时去掉
  try {
    // const adapt_restrict = `故事：\n${form.chatgpt_answer}\n
    // 指令：
    // 请理解这个故事，给出这个场景“${item.场景描述}”的关键词（年代(可以发挥想象进行补充，但一定要有),空间(可以发挥想象进行补充，但一定要有),
    // 时间段(可以发挥想象进行补充，但一定要有),地理环境(可以发挥想象进行补充，但一定要有),天气(可以发挥想象进行补充，但一定要有),
    // 物品(可以发挥想象进行补充，但一定要有),镜头角度(可以发挥想象进行补充，但一定要有)）。
    // 要求：
    // 关键词以逗号分隔。
    // 只要返回关键词，不需要其他的说明文字。`;

    // const adapt_restrict = `剧本：“${form.chatgpt_answer}” \n 作为资深作家，请阅读剧本，并严格按照以下表单：
    // [{"旁白":"${item.场景描述}",场景描述:""}]
    // 根据旁白，来构造场景描述，语言要简要和清晰。你填写的内容只包括根据剧本所构思的摄像机镜头内的场景描述，而不需要其他的内容。请将你完成的表单返回给我。`;

    const adapt_restrict = `剧本：“${form.chatgpt_answer}”
    指令：
    作为资深作家，请阅读这个剧本，给出这个场景：“${item.场景描述}”的描述，50个字左右。`
    const keywords = await text2videoService.submitLLM(
      utils.aesEncrypt(adapt_restrict),
      utils.aesEncrypt(tuili_llm.api),
      [],
      form.task_id,
      'true'
    )
    // console.log(adapt_restrict)
    // console.log(keywords)
    item.场景关键词 = keywords

    // const adapt_restrict_en = `你现在扮演专业的英语翻译的角色。请将这段文字“${item.场景描述}”翻译为英语。\n要求：只返回英语即可，不要返回其他内容。`;
    // const keywords_en = await text2videoService.submitLLM(adapt_restrict_en, tuili_llm.api);
    let keywords_en = await text2videoService.submitTranslateToEn(
      utils.aesEncrypt(keywords),
      form.task_id,
      'true'
    )
    // console.log(keywords_en)
    // item.场景关键词英文 = utils.filterChineseAndPunctuation(keywords_en.replace(/"/g, ''));
    item.场景关键词英文 = keywords_en.replace(/"/g, '')
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  }
}

const onAdaptSceneRoles = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: '分镜不能为空',
      type: 'error'
    })
    return
  }
  if (!form.all_roles) {
    ElMessage({
      message: `总角色不能为空`,
      type: 'error'
    })
    return
  }
  loading.value = true
  async function processScenes() {
    for (const item of form.adapt_result_json) {
      if (item.local_image_path == '') {
        await onAdaptOneSceneRoles(item)
      }
    }
  }
  try {
    await processScenes()
    console.log(form.adapt_result_json)
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    loading.value = false // 最终关闭loading（无论成功或失败）
  }
}

const onAdaptOneSceneRoles = async (item: any) => {
  if (!item.场景描述) {
    ElMessage({
      message: `分镜 ${item.编号} 场景描述不能为空`,
      type: 'error'
    })
    return
  }
  if (!form.all_roles) {
    ElMessage({
      message: `总角色不能为空`,
      type: 'error'
    })
    return
  }
  // 推理角色
  try {
    if (form.chatgpt_answer_roles.length === 0) {
      // 总角色为空
      item.角色 = ''
      item.角色关键词 = ''
    } else {
      // 总角色不为空
      // const adapt_role_restrict = `请理解这个故事：“${form.chatgpt_answer}”，针对其中的这个场景：“${item.场景描述}”，从所有角色：“${form.all_roles}”中选择本场景的角色，多个角色以逗号分隔。`;
      const adapt_role_restrict = `整个故事(“${form.chatgpt_answer})，\n\n本章节(${item.场景描述})，\n\n角色列表(${form.all_roles})，\n\n请返回给本章节出现的角色。注意：不要发挥想象，必须从角色列表中选出本章节出现过的角色，如果多个用逗号隔开。`
      const item_roles_answer = await text2videoService.submitLLM(
        utils.aesEncrypt(adapt_role_restrict),
        utils.aesEncrypt(tuili_keyword_llm.api),
        [],
        form.task_id,
        'true'
      )
      console.log(`==============${item.编号}===============`)
      console.log('form.all_roles = ', form.all_roles)
      item.info = `推理返回：${item_roles_answer}`
      let item_roles_answer_list = item_roles_answer.trim().split(/[，,、]/)
      item_roles_answer_list = item_roles_answer_list.map((item) => item.trim())
      // 过滤推理出来的角色，都要在总角色里
      item.roles = ['无角色']
      for (const y of form.chatgpt_answer_roles) {
        item.roles.push(y.角色)
      }

      item.角色 = '无角色'
      let filter_result = ''
      console.log('item_roles_answer_list = ', item_roles_answer_list)
      for (const x of item_roles_answer_list) {
        for (const y of form.chatgpt_answer_roles) {
          if (x == y.角色) {
            filter_result += x + ','
            console.log('filter_result = ', filter_result)
            // 下拉列表添加项目
            // item.roles.push(x);
          }
        }
      }
      if (filter_result.endsWith(',')) {
        filter_result = filter_result.slice(0, -1) // 去掉结尾的逗号
      }
      if (filter_result) {
        item.角色 = filter_result
      }
      console.log('过滤后 item.角色 = ', item.角色)

      ////// 加一段逻辑，本镜角色有且只能有一个，且尽量不与之前相同。【begin】
      const temp_arr = item.角色.split(/[，,、]/)
      const temp_arr_length = temp_arr.length
      ////// 如果本镜的角色大于1个，则只保留没有出现过的角色，且保证只有一个
      if (temp_arr_length > 1) {
        ////// 获取本镜之前的所有角色
        let role_history = ''
        form.adapt_result_json.forEach((scene) => {
          if (Number(scene.编号) < Number(item.编号)) {
            role_history += scene.角色 + ','
          }
        })
        role_history = role_history.replace(/,+$/, '')
        console.log(`role_history = ${role_history}`)
        for (const temp of temp_arr) {
          if (role_history.includes(temp)) {
            item.角色 = ''
            continue
          } else {
            item.角色 = temp
            break
          }
        }
        if (!item.角色) {
          const role_history_arr = role_history.split(',')
          const lastOne = role_history_arr[role_history_arr.length - 1]
          const remainingValues = role_history_arr.filter((i) => i !== lastOne)
          if (remainingValues.length >= 1) {
            item.角色 = remainingValues[remainingValues.length - 1]
          } else {
            item.角色 = item_roles_answer.trim()
          }
          console.log(`lalalalala item.角色 = ${item.角色}`)
        }
      }
      console.log(`item.角色 = ${item.角色}`)
      ////// 加一段逻辑，本镜角色有且只能有一个，且尽量不与之前相同。【end】

      // 开始匹配角色关键词
      let role_kws = ''
      let role_kws_en = ''
      const item_roles_arr = item.角色.split(/[，,、]/)
      item_roles_arr.forEach((one_item_role: string) => {
        let temp_role_kws = ''
        let temp_role_kws_en = ''
        // 人工匹配角色关键词，先找想同的
        for (const i of form.chatgpt_answer_roles) {
          if (i['角色'].trim() == one_item_role.trim()) {
            temp_role_kws = `${i['角色关键词']}`
            temp_role_kws_en = `${i['角色关键词英文']}`
            // 找到就ok
            break
          }
        }
        // 如果找不到相同的，则模糊匹配
        if (!temp_role_kws) {
          for (const i of form.chatgpt_answer_roles) {
            if (
              i['角色'].includes(one_item_role.trim()) ||
              one_item_role.includes(i['角色'].trim())
            ) {
              temp_role_kws = `${i['角色关键词']}`
              temp_role_kws_en = `${i['角色关键词英文']}`
              // 匹配到一个就ok
              break
            }
          }
        }
        role_kws = `${role_kws}${temp_role_kws}`
        role_kws_en = `${role_kws_en}${temp_role_kws_en}`
      })
      item.角色关键词 = role_kws
      item.角色关键词英文 = role_kws_en
    }
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  }
}

const onItemRolesChange = (item: any) => {
  console.log(item.编号, item.角色)
  if (item.角色 == '无角色') {
    item.角色关键词 = ''
    item.角色关键词英文 = ''
  } else {
    for (const y of form.chatgpt_answer_roles) {
      if (item.角色 == y.角色) {
        item.角色关键词 = y.角色关键词
        item.角色关键词英文 = y.角色关键词英文
        break
      }
    }
  }
}

const onDraw = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: '分镜不能为空',
      type: 'error'
    })
    return
  }
  let is_all_ok = true
  for (const item of form.adapt_result_json) {
    if (!item.场景关键词 && !item.角色关键词 && item.local_image_path == '') {
      ElMessage({
        message: `分镜 ${item.编号} 关键词为空，请重新推理本镜`,
        type: 'error'
      })
      is_all_ok = false
      break
    }
  }
  if (is_all_ok) {
    for (const item of form.adapt_result_json) {
      if (item.local_image_path == '') {
        // onDrawOne(item);
        // 因3090显存不够，暂时改成串行画图
        await onDrawOne(item)
      }
    }
  }
}

const onDrawOne = async (item: any) => {
  if (!item.场景关键词 && !item.角色关键词) {
    ElMessage({
      message: '本镜关键词为空，请重新推理本镜',
      type: 'error'
    })
    return
  }
  if (!form.task_id) {
    ElMessage({
      message: 'task_id不能为空，请刷新页面',
      type: 'error'
    })
    return
  }
  // 翻译+画图
  try {
    item.本镜配图 = 'src/assets/loading.gif'
    // let temp_prompt = ""
    // if (item.场景描述) {temp_prompt = temp_prompt + `场景描述为：${item.场景描述}\n`};
    // if (item.场景关键词) {temp_prompt = temp_prompt + `场景关键词为：${item.场景关键词}\n`};
    // if (item.角色) {temp_prompt = temp_prompt + `场景中的角色有：${item.角色}\n`};
    // if (item.角色关键词) {temp_prompt = temp_prompt + `角色关键词为：${item.角色关键词}\n`};
    // const sd_describe = await text2videoService.submitLLM(
    //   `${temp_prompt}
    //   指令：
    //   请理解以上内容，并返回一段英文的描述。`, fanyi_llm.api
    // );
    // item.画面描述词 = sd_describe;
    item.画面描述词 = item.场景关键词英文 + ',' + item.角色关键词英文

    const sd_prompt = item.画面描述词 + ',' + sd_prompt_prefix
    // console.log(sd_prompt);
    // console.log(sd_negative_prompt_prefix);
    const sampler_index = sd_model.sampler_index
    const seed = sd_model.seed
    const steps = sd_model.steps
    const cfg_scale = sd_model.cfg_scale
    const model = sd_model.model
    const sd_img = await text2videoService.submitSD(
      form.task_id,
      item.编号,
      utils.aesEncrypt(sd_prompt),
      utils.aesEncrypt(sd_negative_prompt_prefix),
      utils.aesEncrypt(form.img_size.width),
      utils.aesEncrypt(form.img_size.height),
      utils.aesEncrypt(sampler_index),
      utils.aesEncrypt(seed),
      utils.aesEncrypt(steps),
      utils.aesEncrypt(cfg_scale),
      'true',
      utils.aesEncrypt(model)
    )
    item.本镜配图 = sd_img.domain_image_path + '?v=' + utils.genDateTimeStr()
    item.local_image_path = sd_img.local_image_path
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
    item.本镜配图 = ''
    item.local_image_path = ''
  }
}

const onGenVideo = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: '分镜必要信息不能为空，请重新执行',
      type: 'error'
    })
    return
  }
  let is_all_ok = true
  form.adapt_result_json.map((item) => {
    if (item.编号 == '' || item.场景描述 == '' || item.local_image_path == '') {
      ElMessage({
        message: `分镜 ${item.编号} 的必要信息为空，请重新执行`,
        type: 'error'
      })
      is_all_ok = false
    }
  })
  if (!is_all_ok) return
  try {
    if (cover_backcover.if_need_cover_pic == 'true') {
      console.log('添加封面文字到图片')
      let res = await onMarketingTemplateAddTextToPic('cover')
      if (!res) {
        return
      }
    }
    if (cover_backcover.if_need_product_pic == 'true') {
      console.log('添加封底文字到图片')
      let res = await onMarketingTemplateAddTextToPic('product')
      if (!res) {
        return
      }
    }

    console.log(form.adapt_result_json)
    let video_param_detail = []
    // 封面
    if (cover_backcover.if_need_cover_pic == 'true' && cover_backcover.cover_pic_with_text_local) {
      video_param_detail.push({
        idx: '0',
        text: '',
        img_path: cover_backcover.cover_pic_with_text_local,
        no_text_duration: '0.1'
      })
    }
    // 分镜
    form.adapt_result_json.map((item) => {
      video_param_detail.push({
        idx: item.编号,
        text: item.场景描述,
        img_path: item.local_image_path
      })
    })
    // 封底
    if (
      cover_backcover.if_need_product_pic == 'true' &&
      cover_backcover.product_pic_with_text_local
    ) {
      // 如果text没有值，则时长默认5秒
      video_param_detail.push({
        idx: String(form.adapt_result_json.length + 1),
        text: cover_backcover.product_pic_speech,
        img_path: cover_backcover.product_pic_with_text_local,
        no_text_duration: '5'
      })
    }
    let para_rate = `${voice_rate.value}%`
    let para_volume = `${voice_volume.value}%`
    if (voice_rate.value >= 0) {
      para_rate = `+${para_rate}`
    }
    if (voice_volume.value >= 0) {
      para_volume = `+${para_volume}`
    }
    const video_param = {
      task_id: form.task_id,
      if_need_subtitle: form.if_need_subtitle,
      lang: 'zh',
      task_info: video_param_detail,
      rate: para_rate,
      volume: para_volume,
      voice: voice.value,
      bgm: bgm.value,
      bgm_volume: bgm_volume.value,
      sub_font_size: String(sub_font_size.value),
      sub_font_color: sub_font_color.value,
      sub_position: String(1 - sub_position.value),
      sub_bg_color: ''
    }
    if (sub_bg_color.value) {
      video_param.sub_bg_color = sub_bg_color.value
    }

    const result = await text2videoService.submitGenVideo(video_param)
    console.log(result)
    form.final_video = ''
    form.final_video = result + '?v=' + utils.genDateTimeStr()
  } catch (error: any) {
    // console.error(error);
    ElMessage({
      message: error,
      type: 'error'
    })
  }
}

const clean_data = () => {
  form.chatgpt_prompt = ''
  form.chatgpt_answer = ''
  form.chatgpt_answer_roles = <Wm.RolesItem[]>[]
  form.adapt_result_json = <Wm.ScriptsItem[]>[]
  form.task_id = ''
  form.final_video = ''

  cover_backcover.if_need_cover_pic = 'false'
  cover_backcover.cover_pic = 'src/assets/waiting.png'
  cover_backcover.cover_pic_local = ''
  cover_backcover.cover_pic_with_text = 'src/assets/waiting.png'
  cover_backcover.cover_pic_with_text_local = ''
  cover_backcover.cover_pic_titles = <Wm.PicText[]>[]
  cover_backcover.cover_pic_use_scene = ''

  cover_backcover.if_need_product_pic = 'false'
  cover_backcover.product_pic = 'src/assets/waiting.png'
  cover_backcover.product_pic_local = ''
  cover_backcover.product_pic_with_text = 'src/assets/waiting.png'
  cover_backcover.product_pic_with_text_local = ''
  cover_backcover.product_pic_titles = <Wm.PicText[]>[]
  cover_backcover.product_pic_speech = ''

  update_and_modify_product.pic = 'src/assets/waiting.png'
  update_and_modify_product.pic_local = ''
  update_and_modify_product.pic_preview = 'src/assets/waiting.png'
  update_and_modify_product.pic_preview_local = ''
}

const clean_roles = () => {
  form.chatgpt_answer_roles = <Wm.RolesItem[]>[]
}
const clean_scenes = () => {
  form.adapt_result_json = <Wm.ScriptsItem[]>[]
}

const onChangeScreen = (val: string) => {
  // 先清理数据
  clean_data()
  if (!form.task_id) {
    // 初始化task_id
    form.task_id = utils.genDateTimeStr()
    console.log('更改屏幕设置，task_id=', form.task_id)
  }

  if (debug.value == true) {
    if (val == '横屏') {
      form.task_id = default_data.horizontal_data.task_id
      form.chatgpt_prompt = default_data.horizontal_data.chatgpt_prompt
      form.chatgpt_answer = default_data.horizontal_data.chatgpt_answer
      form.chatgpt_answer_roles = default_data.horizontal_data.chatgpt_answer_roles
      form.all_roles = default_data.horizontal_data.all_roles
      form.adapt_result_json = default_data.horizontal_data.adapt_result_json
      form.final_video = default_data.horizontal_data.final_video
    } else {
      form.task_id = default_data.vertical_data.task_id
      form.chatgpt_prompt = default_data.vertical_data.chatgpt_prompt
      form.chatgpt_answer = default_data.vertical_data.chatgpt_answer
      form.chatgpt_answer_roles = default_data.vertical_data.chatgpt_answer_roles
      form.all_roles = default_data.vertical_data.all_roles
      form.adapt_result_json = default_data.vertical_data.adapt_result_json
      form.final_video = default_data.vertical_data.final_video
    }

    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

    // cover_backcover.if_need_product_pic = 'true';
    // cover_backcover.if_need_cover_pic = 'true';
    cover_backcover.product_pic_titles = default_data.cover_backcover.product_pic_titles
    cover_backcover.product_pic_speech = default_data.cover_backcover.product_pic_speech
    cover_backcover.cover_pic_titles = default_data.cover_backcover.cover_pic_titles

    // cover_backcover.product_pic = default_data.cover_backcover.product_pic;
    // cover_backcover.product_pic_local = default_data.cover_backcover.product_pic_local;
    // cover_backcover.product_pic_with_text = default_data.cover_backcover.product_pic_with_text;
    // cover_backcover.product_pic_with_text_local = default_data.cover_backcover.product_pic_with_text_local;

    // cover_backcover.cover_pic = default_data.cover_backcover.cover_pic;
    // cover_backcover.cover_pic_local = default_data.cover_backcover.cover_pic_local;
    // cover_backcover.cover_pic_with_text = default_data.cover_backcover.cover_pic_with_text;
    // cover_backcover.cover_pic_with_text_local = default_data.cover_backcover.cover_pic_with_text_local;

    update_and_modify_product.if_need = 'true'
    update_and_modify_product.pic =
      'http://wm-tools-backend.frp.wmdigit.com:8888/assets/2024/05/13/f60b2b58-10d8-11ef-a812-559c156fce46_resized.png'
    update_and_modify_product.pic_local =
      'assets/2024/05/13/f60b2b58-10d8-11ef-a812-559c156fce46_resized.png'
  }

  // 宽高
  if (val == '横屏') {
    form.img_size = default_data.horizontal_img_size
  } else {
    form.img_size = default_data.vertical_img_size
  }
}

const showsdprompt = (item: any) => {
  if (!item.画面描述词) {
    ElMessage({
      message: '还未绘图，请绘图后查看',
      type: 'error'
    })
    return
  }
  // alert(item.画面描述词)
  dialogData.value = `${item.画面描述词},${sd_prompt_prefix}===== 反向提示词 =====${sd_negative_prompt_prefix}`
  dialogVisible.value = true // 打开对话框
}

const upload = ref<UploadInstance>()

const actionUrl = ref(
  import.meta.env.MODE === 'production'
    ? '/file/upload_pic_and_modify'
    : import.meta.env.VITE_APP_BASE_API + '/file/upload_pic_and_modify'
)

// 在分镜自定义上传图片时发现个bug
// 第一次上传没问题，但重复进行上传，会更新到最后一行上去。
// 奇怪，没找到原因。暂时先通过迂回的方法来处理。
// 终于找到原因了，是handleUploadExceed的问题，它在超出limit后，清空已上传，并将新文件上传，但用的都是upload实例
let uploadItemId = 0
const onClickUpload = (val: any) => {
  uploadItemId = val.编号 - 1
  console.log(uploadItemId)
}
const handleUploadSuccess = (val: Wm.UploadResult) => {
  console.log(val)
  if (val.code == 0) {
    form.adapt_result_json[uploadItemId].本镜配图 = val.data[0].url + '?v=' + utils.genDateTimeStr()
    form.adapt_result_json[uploadItemId].local_image_path = val.data[0].path
    ElMessage({
      message: '上传成功',
      type: 'success'
    })
  } else {
    ElMessage({
      message: '上传失败：' + val.message,
      type: 'error'
    })
  }
}
const handleUploadExceed: UploadProps['onExceed'] = (files) => {
  // 清除已上传的文件
  upload.value!.clearFiles()
  // 获取超出限制的第一个文件
  const file = files[0] as UploadRawFile
  // 给文件分配一个新的唯一标识
  file.uid = genFileId()
  // 手动触发文件上传
  upload.value!.handleStart(file)
  // 提交上传
  upload.value!.submit()
}

const handleUploadError = (error: Error) => {
  ElMessage({
    message: String(error.message),
    type: 'error'
  })
}

const handleBeforeUpload = async (file: any) => {
  const isLt1M = file.size / 1024 / 1024 <= 1
  if (!isLt1M) {
    ElMessage.error('上传图片大小不能超过 1MB!')
    return false
  }
  return new Promise((resolve, reject) => {
    let is_size_ok = false
    const reader = new FileReader()
    reader.onload = (e: any) => {
      const dataURL = e.target.result
      const img = new Image()
      img.onload = () => {
        console.log('文件宽度:', img.width)
        console.log('文件高度:', img.height)
        if (
          (form.screen == '竖屏' && img.height >= img.width) ||
          (form.screen == '横屏' && img.width >= img.height)
        ) {
          is_size_ok = true
        }
        if (is_size_ok) {
          resolve(true) // 尺寸符合要求
        } else {
          reject('竖屏请上传竖屏图片，横屏请上传横屏图片!')
        }
      }
      img.src = dataURL
    }
    reader.readAsDataURL(file)
  }).catch((error) => {
    console.log('Error:', error)
    ElMessage.error(error)
    return false
  })
}

const onClearOnePic = (item: any) => {
  item.本镜配图 = ''
  item.local_image_path = ''
}

const onPwdCheckDialog = () => {
  text2videoService
    .submitPwdCheck(pwdCheckValue.value)
    .then((result: string) => {
      if (result == 'success') {
        pwdCheckDialogVisible.value = false
      } else {
        ElMessage({
          message: result,
          type: 'error'
        })
      }
    })
    .catch((error: any) => {
      ElMessage({
        message: error,
        type: 'error'
      })
    })
}

const onDeleteOne = (item: any) => {
  try {
    let delete_no = item.编号
    // 删除记录
    form.adapt_result_json = form.adapt_result_json.filter((item) => item.编号 !== delete_no)
    // 重新对记录进行编号
    form.adapt_result_json = form.adapt_result_json.map((item, index) => {
      return { ...item, 编号: (index + 1).toString() }
    })
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  }
}

// ///////  模板相关  ////////////

// const activeTab = ref("first");
// const goToNextPage = () => {
//   activeTab.value = "second";
// };

const upload_cover = ref<UploadInstance>()
const upload_product = ref<UploadInstance>()

const MarketingTemplateUploadProductPicSuccess = (val: Wm.UploadResult) => {
  // console.log(val)
  if (val.code == 0) {
    cover_backcover.product_pic = val.data[0].url + '?v=' + utils.genDateTimeStr()
    cover_backcover.product_pic_local = val.data[0].path
    cover_backcover.product_pic_with_text = 'src/assets/waiting.png'
    cover_backcover.product_pic_with_text_local = ''
    ElMessage({
      message: '上传成功',
      type: 'success'
    })
    // onMarketingTemplateAddTextToPic('product');
  } else {
    ElMessage({
      message: '上传失败：' + val.message,
      type: 'error'
    })
  }
}
const handleMarketingTemplateUploadProductPicExceed: UploadProps['onExceed'] = (files) => {
  // 清除已上传的文件
  upload_product.value!.clearFiles()
  // 获取超出限制的第一个文件
  const file = files[0] as UploadRawFile
  // 给文件分配一个新的唯一标识
  file.uid = genFileId()
  // 手动触发文件上传
  upload_product.value!.handleStart(file)
  // 提交上传
  upload_product.value!.submit()
}

const MarketingTemplateUploadCoverPicSuccess = (val: Wm.UploadResult) => {
  if (val.code == 0) {
    cover_backcover.cover_pic = val.data[0].url + '?v=' + utils.genDateTimeStr()
    cover_backcover.cover_pic_local = val.data[0].path
    cover_backcover.cover_pic_with_text = 'src/assets/waiting.png'
    cover_backcover.cover_pic_with_text_local = ''
    ElMessage({
      message: '上传成功',
      type: 'success'
    })
    // onMarketingTemplateAddTextToPic('cover');
  } else {
    ElMessage({
      message: '上传失败：' + val.message,
      type: 'error'
    })
  }
}
const handleMarketingTemplateUploadCoverPicExceed: UploadProps['onExceed'] = (files) => {
  // 清除已上传的文件
  upload_cover.value!.clearFiles()
  // 获取超出限制的第一个文件
  const file = files[0] as UploadRawFile
  // 给文件分配一个新的唯一标识
  file.uid = genFileId()
  // 手动触发文件上传
  upload_cover.value!.handleStart(file)
  // 提交上传
  upload_cover.value!.submit()
}

const onClearMarketingTemplatePic = (type: string) => {
  if (type == 'product') {
    cover_backcover.product_pic = 'src/assets/waiting.png'
    cover_backcover.product_pic_local = ''
    cover_backcover.product_pic_with_text = 'src/assets/waiting.png'
    cover_backcover.product_pic_with_text_local = ''
  }
  if (type == 'cover') {
    cover_backcover.cover_pic = 'src/assets/waiting.png'
    cover_backcover.cover_pic_local = ''
    cover_backcover.cover_pic_with_text = 'src/assets/waiting.png'
    cover_backcover.cover_pic_with_text_local = ''
    cover_backcover.cover_pic_use_scene = ''
  }
}

const check_if_has_pic = (type: string) => {
  if (
    (type == 'product' && !cover_backcover.product_pic_local) ||
    (type == 'cover' && !cover_backcover.cover_pic_local)
  ) {
    ElMessage({
      message: '请先设置图片',
      type: 'error'
    })
    return false
  }
  return true
}

const onAddMarketingTemplatePicText = async (type: string, action: string, index: number) => {
  if (action == 'add') {
    if (!check_if_has_pic(type)) {
      return
    }
    if (type == 'cover') {
      const newElement = {
        text: '新的文本',
        color: '#000000',
        bg_color: '#FFFFFF',
        font_size: 60,
        position: 0.37
      }
      cover_backcover.cover_pic_titles.push(newElement)
    }
    if (type == 'product') {
      const newElement = {
        text: '关注  点赞  评论',
        color: '#DAFB01',
        bg_color: '#000000',
        font_size: 60,
        position: 0.2
      }
      cover_backcover.product_pic_titles.push(newElement)
    }
  }
  if (action == 'del') {
    if (type == 'cover') {
      cover_backcover.cover_pic_titles.splice(index, 1)
    }
    if (type == 'product') {
      cover_backcover.product_pic_titles.splice(index, 1)
    }
  }
  await onMarketingTemplateAddTextToPic(type)
}

const onMarketingTemplateAddTextToPic = async (type: string) => {
  if (
    (type == 'product' && !cover_backcover.product_pic_local) ||
    (type == 'cover' && !cover_backcover.cover_pic_local)
  ) {
    ElMessage({
      message: '请先设置图片',
      type: 'error'
    })
    return false
  }
  if (type == 'product' && cover_backcover.product_pic_titles.length == 0) {
    cover_backcover.product_pic_with_text = cover_backcover.product_pic
    cover_backcover.product_pic_with_text_local = cover_backcover.product_pic_local
    return true
  }
  if (type == 'cover' && cover_backcover.cover_pic_titles.length == 0) {
    cover_backcover.cover_pic_with_text = cover_backcover.cover_pic
    cover_backcover.cover_pic_with_text_local = cover_backcover.cover_pic_local
    return true
  }
  let params = {
    image_path: '',
    image_texts: [
      {
        text: '',
        text_color: '',
        text_bg_color: '',
        font_size: '',
        position: '',
        lang: ''
      }
    ]
  }
  if (type == 'product') {
    const texts = cover_backcover.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'
      }
    })
    params = {
      image_path: cover_backcover.product_pic_local,
      image_texts: texts
    }
  }
  if (type == 'cover') {
    const texts = cover_backcover.cover_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'
      }
    })
    params = {
      image_path: cover_backcover.cover_pic_local,
      image_texts: texts
    }
  }
  params.image_texts.forEach((item, index) => {
    if (!item.text_color || item.text_color.trim() === '') {
      ElMessage({
        message: '字体颜色不能为空',
        type: 'error'
      })
      return false
    }
  })

  try {
    const result = await text2videoService.submitAddTextToImg(params)
    // console.log(result);
    if (type == 'product') {
      cover_backcover.product_pic_with_text =
        result.domain_image_path + '?v=' + utils.genDateTimeStr()
      cover_backcover.product_pic_with_text_local = result.local_image_path
    }
    if (type == 'cover') {
      cover_backcover.cover_pic_with_text =
        result.domain_image_path + '?v=' + utils.genDateTimeStr()
      cover_backcover.cover_pic_with_text_local = result.local_image_path
    }
    return true
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
    if (type == 'product') {
      cover_backcover.product_pic_with_text = ''
      cover_backcover.product_pic_with_text_local = ''
    }
    if (type == 'cover') {
      cover_backcover.cover_pic_with_text = ''
      cover_backcover.cover_pic_with_text_local = ''
    }
    return false
  }
}

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 {
    console.log('第一次提问')
    let result1 = await text2videoService.submitLLM(
      utils.aesEncrypt(marketing_template.prompt1),
      utils.aesEncrypt(wen_an_llm.api),
      [],
      form.task_id,
      'true'
    )
    marketing_template.result1 = result1
    // console.log(marketing_template.prompt1);
    // console.log(marketing_template.result1);

    console.log('第二次带历史提问')
    const history = [
      { role: utils.aesEncrypt('user'), content: utils.aesEncrypt(marketing_template.prompt1) },
      { role: utils.aesEncrypt('assistant'), content: utils.aesEncrypt(result1) }
    ]
    let result2 = await text2videoService.submitLLM(
      utils.aesEncrypt(marketing_template.prompt2),
      utils.aesEncrypt(wen_an_llm.api),
      history,
      form.task_id,
      'true'
    )
    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'
    })
  }
}

const onTest = () => {
  console.log(form.chatgpt_prompt)
  const encrypt_data = utils.aesEncrypt(form.chatgpt_prompt)
  console.log(encrypt_data)
  text2videoService
    .submitTest(encrypt_data)
    .then((result: string) => {
      console.log(result)
      form.chatgpt_answer = result
    })
    .catch((error: any) => {
      // console.error(error);
      ElMessage({
        message: error,
        type: 'error'
      })
    })
}

const onSelectCoverChange = (value: any) => {
  cover_backcover.cover_pic = form.adapt_result_json[parseInt(value) - 1].本镜配图
  cover_backcover.cover_pic_local = form.adapt_result_json[parseInt(value) - 1].local_image_path
  cover_backcover.cover_pic_with_text = 'src/assets/waiting.png'
  cover_backcover.cover_pic_with_text_local = ''
  onMarketingTemplateAddTextToPic('cover')
}

// 局部重绘Dialog
const showInPaintDialog = (type: string, item: any) => {
  let base_img_path = ''
  inPaintType.value = type
  inPaintItem.value = null
  inPaintPrompt.value = ''
  inPaintBaseImgData.value = ''
  inPaintMaskData.value = ''

  if (type == 'scene') {
    inPaintItem.value = item
    // inPaintPrompt.value = inPaintItem.value.场景关键词+' '+inPaintItem.value.角色关键词;
    inPaintPrompt.value = ''
    base_img_path = inPaintItem.value.本镜配图
  } else if (type == 'cover') {
    inPaintPrompt.value = ''
    base_img_path = cover_backcover.cover_pic
  } else if (type == 'product') {
    inPaintPrompt.value = ''
    base_img_path = cover_backcover.product_pic
  }

  if (!base_img_path || base_img_path.length == 0) {
    ElMessage({
      message: '没有基础图片，请确认',
      type: 'error'
    })
    return
  }

  inPaintVisible.value = true // 打开对话框

  // 等待元素加载完成
  nextTick(() => {
    // 局部重绘
    const base_canvas = document.getElementById('baseCanvas') as HTMLCanvasElement
    const mask_canvas = document.getElementById('maskCanvas') as HTMLCanvasElement
    if (base_canvas && mask_canvas) {
      let base_ctx = base_canvas.getContext('2d') as CanvasRenderingContext2D
      base_ctx.clearRect(0, 0, base_canvas.width, base_canvas.height)
      var img = new Image()
      img.crossOrigin = 'Anonymous' // 如果图片需要用于跨域，则需要设置这个属性
      img.onload = function () {
        base_canvas.width = img.width
        base_canvas.height = img.height
        base_ctx.drawImage(img, 0, 0, base_canvas.width, base_canvas.height)
      }
      img.src = base_img_path

      let mask_ctx = mask_canvas.getContext('2d') as CanvasRenderingContext2D
      mask_ctx.clearRect(0, 0, mask_canvas.width, mask_canvas.height)

      mask_ctx.lineWidth = 40 // 设置线条粗细
      mask_ctx.strokeStyle = 'rgba(255, 255, 255, 1)' // 设置线条颜色
      mask_ctx.lineCap = 'round' // 线头尾为圆形
      mask_ctx.lineJoin = 'round' // 拐点为圆形，默认是尖角
      // mask_ctx.globalCompositeOperation = 'destination-atop';  //避免线条重叠的时候透明度也重叠
      // mask_ctx.globalCompositeOperation = 'copy';  //避免线条重叠的时候透明度也重叠

      let isDrawing = false
      // 鼠标或触摸事件开始绘制
      mask_canvas.addEventListener('mousedown', startDrawing)
      mask_canvas.addEventListener('touchstart', startDrawing)

      // 鼠标或触摸事件绘制中
      mask_canvas.addEventListener('mousemove', draw)
      mask_canvas.addEventListener('touchmove', draw)

      // 鼠标或触摸事件结束绘制
      mask_canvas.addEventListener('mouseup', stopDrawing)
      mask_canvas.addEventListener('touchend', stopDrawing)
      mask_canvas.addEventListener('mouseout', stopDrawing)

      // 清除按钮点击事件
      const clearButton = document.getElementById('clearButton') as HTMLButtonElement
      clearButton.addEventListener('click', clearCanvas)

      // 开始绘制
      function startDrawing(e: any) {
        isDrawing = true
        mask_ctx.beginPath()
        const { offsetX, offsetY } = getOffset(e)
        mask_ctx.moveTo(offsetX, offsetY)
        draw(e)
      }

      // 绘制中
      function draw(e: any) {
        if (!isDrawing) return
        const { offsetX, offsetY } = getOffset(e)
        mask_ctx.lineTo(offsetX, offsetY)
        mask_ctx.stroke()
      }

      // 结束绘制
      function stopDrawing() {
        isDrawing = false
        inPaintBaseImgData.value = base_canvas.toDataURL('image/png')
        inPaintMaskData.value = mask_canvas.toDataURL('image/png')
      }

      // 清除画布
      function clearCanvas() {
        mask_ctx.clearRect(0, 0, mask_canvas.width, mask_canvas.height)
      }

      // 获取鼠标或触摸事件的偏移量
      function getOffset(e: any) {
        const rect = mask_canvas.getBoundingClientRect()
        let offsetX, offsetY
        if (e.type.includes('touch')) {
          offsetX = e.touches[0].clientX - rect.left
          offsetY = e.touches[0].clientY - rect.top
        } else {
          offsetX = e.offsetX
          offsetY = e.offsetY
        }
        return { offsetX, offsetY }
      }
    } else {
      console.error('Canvas element not found')
    }
  })
}

const onSubmitInPaint = async () => {
  if (!form.task_id) {
    ElMessage({
      message: 'task_id不能为空，请刷新页面',
      type: 'error'
    })
    return
  }
  if (!inPaintBaseImgData.value || !inPaintMaskData.value) {
    ElMessage({
      message: '请在图片上涂抹需要保留的部分！',
      type: 'error'
    })
    return
  }
  if (!inPaintPrompt.value || inPaintPrompt.value.length == 0) {
    ElMessage({
      message: '请填写画面描述！',
      type: 'error'
    })
    return
  }
  const sampler_index = sd_model.sampler_index
  const seed = sd_model.seed
  const steps = sd_model.steps
  const cfg_scale = sd_model.cfg_scale
  const model = sd_model.model
  const base_img = inPaintBaseImgData.value
  const mask = inPaintMaskData.value

  let sd_prompt = ''
  let img_id = ''
  let item = null

  if (inPaintType.value == 'scene') {
    item = inPaintItem.value
    item.本镜配图 = 'src/assets/loading.gif'
    img_id = item.编号
  } else if (inPaintType.value == 'cover') {
    img_id = 'cover'
    cover_backcover.cover_pic = 'src/assets/waiting.png'
    cover_backcover.cover_pic_local = ''
  } else if (inPaintType.value == 'product') {
    img_id = 'product'
    cover_backcover.product_pic = 'src/assets/waiting.png'
    cover_backcover.product_pic_local = ''
  }

  try {
    let keywords_en = await text2videoService.submitTranslateToEn(
      utils.aesEncrypt(inPaintPrompt.value),
      form.task_id,
      'true'
    )
    sd_prompt = keywords_en.replace(/"/g, '') + ',' + sd_prompt_prefix
    let sd_img
    if (debug.value == true) {
      sd_img = await text2videoService.submitSDInPaint(
        form.task_id,
        img_id,
        sd_prompt,
        sd_negative_prompt_prefix,
        form.img_size.width,
        form.img_size.height,
        sampler_index,
        seed,
        steps,
        cfg_scale,
        'false',
        model,
        base_img,
        mask,
        'img_data'
      )
    } else {
      sd_img = await text2videoService.submitSDInPaint(
        form.task_id,
        img_id,
        utils.aesEncrypt(sd_prompt),
        utils.aesEncrypt(sd_negative_prompt_prefix),
        utils.aesEncrypt(form.img_size.width),
        utils.aesEncrypt(form.img_size.height),
        utils.aesEncrypt(sampler_index),
        utils.aesEncrypt(seed),
        utils.aesEncrypt(steps),
        utils.aesEncrypt(cfg_scale),
        'true',
        utils.aesEncrypt(model),
        utils.aesEncrypt(base_img),
        utils.aesEncrypt(mask),
        'img_data'
      )
    }
    if (inPaintType.value == 'scene') {
      item.本镜配图 = sd_img.domain_image_path + '?v=' + utils.genDateTimeStr()
      item.local_image_path = sd_img.local_image_path
    } else if (inPaintType.value == 'cover') {
      cover_backcover.cover_pic = sd_img.domain_image_path + '?v=' + utils.genDateTimeStr()
      cover_backcover.cover_pic_local = sd_img.local_image_path
    } else if (inPaintType.value == 'product') {
      cover_backcover.product_pic = sd_img.domain_image_path + '?v=' + utils.genDateTimeStr()
      cover_backcover.product_pic_local = sd_img.local_image_path
    }
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    inPaintVisible.value = false // 关闭对话框
  }
}

//  上传自定义的产品图并重绘
const upload_update_and_modify_product = ref<UploadInstance>()
const UploadAndModifyProductPicSuccess = (val: Wm.UploadResult) => {
  if (val.code == 0) {
    update_and_modify_product.pic = val.data[0].url + '?v=' + utils.genDateTimeStr()
    update_and_modify_product.pic_local = val.data[0].path
    update_and_modify_product.pic_preview = val.data[0].url + '?v=' + utils.genDateTimeStr()
    update_and_modify_product.pic_preview_local = val.data[0].path
    ElMessage({
      message: '上传成功',
      type: 'success'
    })
  } else {
    ElMessage({
      message: '上传失败：' + val.message,
      type: 'error'
    })
  }
}
const onAnalyzeUploadAndModifyProductPic = () => {
  // 解析内容
  const param = {
    task_id: form.task_id,
    image_path: update_and_modify_product.pic_local,
    prompt: '找到图片中的所有文字，理解图片中的商品信息和背景信息'
  }
  text2videoService
    .submitImgToText(param)
    .then((result: string) => {
      if (form.chatgpt_prompt == '') {
        form.chatgpt_prompt = result + ' 根据以上信息，编写一段50字的小故事。'
      } else {
        form.chatgpt_prompt = result + ' 根据以上信息，' + form.chatgpt_prompt
      }
    })
    .catch((error: any) => {
      ElMessage({
        message: '解析失败：' + error,
        type: 'error'
      })
    })
}
const handleUploadAndModifyProductPicExceed: UploadProps['onExceed'] = (files) => {
  // 清除已上传的文件
  upload_update_and_modify_product.value!.clearFiles()
  // 获取超出限制的第一个文件
  const file = files[0] as UploadRawFile
  // 给文件分配一个新的唯一标识
  file.uid = genFileId()
  // 手动触发文件上传
  upload_update_and_modify_product.value!.handleStart(file)
  // 提交上传
  upload_update_and_modify_product.value!.submit()
}
const onClearUploadAndModifyProductPic = () => {
  update_and_modify_product.pic = 'src/assets/waiting.png'
  update_and_modify_product.pic_local = ''
  update_and_modify_product.pic_preview = 'src/assets/waiting.png'
  update_and_modify_product.pic_preview_local = ''
}
// 自定义产品图重绘Dialog
let if_binded_events = false
const showUploadAndModifyProductPicInPaintDialog = () => {
  update_and_modify_product.inPaintPrompt = ''
  update_and_modify_product.inPaintBaseImgData = ''
  update_and_modify_product.inPaintMaskData = ''
  update_and_modify_product.cutout_obj = <Wm.Coordinate[]>[]
  update_and_modify_product.cutout_no_obj = <Wm.Coordinate[]>[]

  let base_img_path = update_and_modify_product.pic
  if (!base_img_path || base_img_path.length == 0) {
    ElMessage({
      message: '没有基础图片，请确认',
      type: 'error'
    })
    return
  }
  let preview_img_path = update_and_modify_product.pic_preview
  update_and_modify_product.inPaintVisible = true // 打开对话框
  // 等待元素加载完成
  nextTick(() => {
    // 自定义产品图局部重绘
    const base_canvas = document.getElementById(
      'update_and_modify_product_baseCanvas'
    ) as HTMLCanvasElement
    const preview_canvas = document.getElementById(
      'update_and_modify_product_previewCanvas'
    ) as HTMLCanvasElement
    const mask_canvas = document.getElementById(
      'update_and_modify_product_maskCanvas'
    ) as HTMLCanvasElement
    const clearButton = document.getElementById(
      'update_and_modify_product_clearButton'
    ) as HTMLButtonElement
    const no_obj_checkbox = document.getElementById(
      'update_and_modify_product_noObjCheckbox'
    ) as HTMLInputElement
    const mask_canvas2 = document.getElementById(
      'update_and_modify_product_maskCanvas2'
    ) as HTMLCanvasElement
    // 初始化非产品层
    no_obj_checkbox.checked = false
    mask_canvas2.style.zIndex = '3'

    if (base_canvas && preview_canvas && mask_canvas) {
      // 基础图
      let base_ctx = base_canvas.getContext('2d') as CanvasRenderingContext2D
      base_ctx.clearRect(0, 0, base_canvas.width, base_canvas.height)
      var base_img = new Image()
      base_img.crossOrigin = 'Anonymous' // 如果图片需要用于跨域，则需要设置这个属性
      base_img.onload = function () {
        base_canvas.width = base_img.width
        base_canvas.height = base_img.height
        base_ctx.drawImage(base_img, 0, 0, base_canvas.width, base_canvas.height)
      }
      base_img.src = base_img_path

      // 预览图
      let preview_ctx = preview_canvas.getContext('2d') as CanvasRenderingContext2D
      preview_ctx.clearRect(0, 0, preview_canvas.width, preview_canvas.height)
      if (preview_img_path && preview_img_path.length != 0) {
        var preview_img = new Image()
        preview_img.crossOrigin = 'Anonymous' // 如果图片需要用于跨域，则需要设置这个属性
        preview_img.onload = function () {
          preview_canvas.width = preview_img.width
          preview_canvas.height = preview_img.height
          preview_ctx.drawImage(preview_img, 0, 0, preview_canvas.width, preview_canvas.height)
        }
        preview_img.src = preview_img_path
      }

      // 产品层mask
      let mask_ctx = mask_canvas.getContext('2d') as CanvasRenderingContext2D
      mask_ctx.clearRect(0, 0, mask_canvas.width, mask_canvas.height)
      mask_ctx.lineWidth = 40 // 设置线条粗细
      mask_ctx.strokeStyle = 'rgba(255, 255, 255, 1)' // 设置线条颜色
      mask_ctx.lineCap = 'round' // 线头尾为圆形
      mask_ctx.lineJoin = 'round' // 拐点为圆形，默认是尖角
      mask_ctx.globalCompositeOperation = 'copy'

      // 非产品层mask
      let mask_ctx2 = mask_canvas2.getContext('2d') as CanvasRenderingContext2D
      mask_ctx2.clearRect(0, 0, mask_canvas2.width, mask_canvas2.height)
      mask_ctx2.lineWidth = 40 // 设置线条粗细
      mask_ctx2.strokeStyle = 'rgba(255, 0, 0, 1)' // 设置线条颜色
      mask_ctx2.lineCap = 'round' // 线头尾为圆形
      mask_ctx2.lineJoin = 'round' // 拐点为圆形，默认是尖角
      mask_ctx2.globalCompositeOperation = 'copy'

      if (!if_binded_events) {
        // 点选产品事件
        mask_canvas.addEventListener('mousedown', onClickObj)
        // 重置按钮点击事件
        clearButton.addEventListener('click', resetCanvas)
        // 复选框事件
        no_obj_checkbox.addEventListener('click', onClickNoObjCheckbox)
        // 点选非产品事件
        mask_canvas2.addEventListener('mousedown', onClickNoObj)
        // 每次打开都会再绑定一次，这里防止多次绑定，否则数据会重复
        if_binded_events = true
      }

      // 点选产品
      function onClickObj(e: any) {
        mask_ctx.beginPath()
        const { offsetX, offsetY } = getOffset(e)
        mask_ctx.moveTo(offsetX, offsetY)
        mask_ctx.lineTo(offsetX, offsetY)
        mask_ctx.stroke()
        console.log('obj==>', offsetX, offsetY)
        // 先清空再push，保证里面只有一个点
        update_and_modify_product.cutout_obj = <Wm.Coordinate[]>[]
        update_and_modify_product.cutout_obj.push({ x: offsetX, y: offsetY })
      }

      // 点选产品
      function onClickNoObj(e: any) {
        mask_ctx2.beginPath()
        const { offsetX, offsetY } = getOffset(e)
        mask_ctx2.moveTo(offsetX, offsetY)
        mask_ctx2.lineTo(offsetX, offsetY)
        mask_ctx2.stroke()
        console.log('no-obj==>', offsetX, offsetY)
        // 先清空再push，保证里面只有一个点
        update_and_modify_product.cutout_no_obj = <Wm.Coordinate[]>[]
        update_and_modify_product.cutout_no_obj.push({ x: offsetX, y: offsetY })
      }

      // 重置
      function resetCanvas() {
        update_and_modify_product.pic_preview = ''
        update_and_modify_product.pic_preview_local = ''
        update_and_modify_product.inPaintVisible = false // 关闭对话框
        showUploadAndModifyProductPicInPaintDialog() // 再打开对话框进行预览
      }

      // checkbox点击事件
      function onClickNoObjCheckbox() {
        if (no_obj_checkbox.checked) {
          mask_canvas2.style.zIndex = '5'
        } else {
          mask_canvas2.style.zIndex = '3'
        }
        const computedStyle = window.getComputedStyle(mask_canvas2)
        const currentZIndex = computedStyle.getPropertyValue('z-index')
        console.log('Current z-index:', currentZIndex)
      }

      // 获取鼠标的偏移量
      function getOffset(e: any) {
        // console.log(e)
        let offsetX = e.offsetX
        let offsetY = e.offsetY
        // console.log({ offsetX, offsetY })
        return { offsetX, offsetY }
      }
    } else {
      ElMessage({
        message: 'Canvas element not found',
        type: 'error'
      })
      console.error('Canvas element not found')
    }
  })
}

const onSubmitUploadAndModifyProductPicCutOut = async () => {
  if (!form.task_id) {
    ElMessage({
      message: 'task_id不能为空，请刷新页面',
      type: 'error'
    })
    return
  }
  if (update_and_modify_product.cutout_obj.length == 0) {
    ElMessage({
      message: '没有产品坐标，至少要点击产品！',
      type: 'error'
    })
    return
  }
  let point_prompt: any[] = []
  let point_label: any[] = []
  // 产品坐标
  // console.log(update_and_modify_product.cutout_obj)
  update_and_modify_product.cutout_obj.forEach((item, index) => {
    point_prompt.push([item.x, item.y])
    point_label.push(1)
  })
  // 非产品坐标
  update_and_modify_product.cutout_no_obj.forEach((item, index) => {
    point_prompt.push([item.x, item.y])
    point_label.push(0)
  })
  // console.log(point_prompt, point_label)
  // console.log(JSON.stringify(point_prompt), JSON.stringify(point_label))
  // return;
  const param = {
    task_id: form.task_id,
    image_path: update_and_modify_product.pic_local,
    point_prompt: JSON.stringify(point_prompt),
    point_label: JSON.stringify(point_label)
  }
  // console.log(param)
  try {
    const cutout_result = await text2videoService.submitCutOutImg(param)
    update_and_modify_product.pic_preview =
      cutout_result.domain_image_path_preview + '?v=' + utils.genDateTimeStr()
    update_and_modify_product.pic_preview_local = cutout_result.local_image_path_preview
    update_and_modify_product.pic_mask =
      cutout_result.domain_image_path_mask + '?v=' + utils.genDateTimeStr()
    update_and_modify_product.pic_mask_local = cutout_result.local_image_path_mask
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    update_and_modify_product.inPaintVisible = false // 关闭对话框
    showUploadAndModifyProductPicInPaintDialog() // 再打开对话框进行预览
  }
}

const onSubmitUploadAndModifyProductPicInPaint = async () => {
  if (!form.task_id) {
    ElMessage({
      message: 'task_id不能为空，请刷新页面',
      type: 'error'
    })
    return
  }
  if (!update_and_modify_product.pic_local || !update_and_modify_product.pic_mask_local) {
    ElMessage({
      message: '缺少基本图片和mask图片！',
      type: 'error'
    })
    return
  }
  if (
    !update_and_modify_product.inPaintPrompt ||
    update_and_modify_product.inPaintPrompt.length == 0
  ) {
    ElMessage({
      message: '请填写画面描述！',
      type: 'error'
    })
    return
  }
  const sampler_index = sd_model.sampler_index
  const seed = sd_model.seed
  const steps = sd_model.steps
  const cfg_scale = sd_model.cfg_scale
  const model = sd_model.model
  const base_img = update_and_modify_product.pic_local
  const mask = update_and_modify_product.pic_mask_local
  let img_id = 'update_and_modify_product'
  update_and_modify_product.pic = 'src/assets/waiting.png'
  update_and_modify_product.pic_local = ''
  try {
    let keywords_en = await text2videoService.submitTranslateToEn(
      utils.aesEncrypt(update_and_modify_product.inPaintPrompt),
      form.task_id,
      'true'
    )
    let sd_prompt = keywords_en.replace(/"/g, '') + ',' + sd_prompt_prefix
    let sd_img
    if (debug.value == true) {
      sd_img = await text2videoService.submitSDInPaint(
        form.task_id,
        img_id,
        sd_prompt,
        sd_negative_prompt_prefix,
        form.img_size.width,
        form.img_size.height,
        sampler_index,
        seed,
        steps,
        cfg_scale,
        'false',
        model,
        base_img,
        mask,
        'img_path'
      )
    } else {
      sd_img = await text2videoService.submitSDInPaint(
        form.task_id,
        img_id,
        utils.aesEncrypt(sd_prompt),
        utils.aesEncrypt(sd_negative_prompt_prefix),
        utils.aesEncrypt(form.img_size.width),
        utils.aesEncrypt(form.img_size.height),
        utils.aesEncrypt(sampler_index),
        utils.aesEncrypt(seed),
        utils.aesEncrypt(steps),
        utils.aesEncrypt(cfg_scale),
        'true',
        utils.aesEncrypt(model),
        utils.aesEncrypt(base_img),
        utils.aesEncrypt(mask),
        utils.aesEncrypt('img_path')
      )
    }
    update_and_modify_product.pic = sd_img.domain_image_path + '?v=' + utils.genDateTimeStr()
    update_and_modify_product.pic_local = sd_img.local_image_path
  } catch (error) {
    ElMessage({
      message: String(error),
      type: 'error'
    })
  } finally {
    update_and_modify_product.inPaintVisible = false // 关闭对话框
  }
}
</script>

<template>
  <main class="home-container">
    <!-- 标题 -->
    <el-divider content-position="left">text2video</el-divider>
    <el-form :model="form" label-width="114px" v-loading="loading">
      <el-form-item>
        <div>
          <el-radio-group v-model="form.screen" @change="onChangeScreen">
            <el-radio label="横屏" size="large" border />
            <el-radio label="竖屏" size="large" border />
          </el-radio-group>
        </div>
      </el-form-item>
      <el-form-item>
        <el-button type="success" @click="clean_data">清除所有数据</el-button>
        <!-- <el-button type="danger" @click="onTest">测试</el-button> -->
      </el-form-item>
      <!-- 产品图 -->
      <el-form-item label="产品图">
        <el-switch
          v-model="update_and_modify_product.if_need"
          active-value="true"
          inactive-value="false"
        />
      </el-form-item>
      <div v-if="JSON.parse(update_and_modify_product.if_need.toLowerCase())">
        <el-form-item>
          <div
            :style="{ width: String(parseInt(form.img_size.width) / 3) + 'px' }"
            class="dashed-div"
          >
            <!-- <el-image :src="update_and_modify_product.pic" /> -->
            <el-image
              :src="update_and_modify_product.pic"
              :zoom-rate="1.0"
              :max-scale="1.5"
              :min-scale="1.5"
              :preview-src-list="[update_and_modify_product.pic]"
              fit="cover"
              :hide-on-click-modal="true"
            />
          </div>
          <!-- <div
            :style="{ width: String(parseInt(form.img_size.width) / 3) + 'px' }"
            class="dashed-div"
            style="margin-left: 20px"
          >
            <el-image :src="update_and_modify_product.pic_preview" />
          </div> -->
        </el-form-item>
        <el-form-item>
          <el-upload
            ref="upload_update_and_modify_product"
            :show-file-list="false"
            :limit="1"
            accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
            :action="actionUrl"
            :on-success="UploadAndModifyProductPicSuccess"
            :on-exceed="handleUploadAndModifyProductPicExceed"
            :on-error="handleUploadError"
            :data="{ width: form.img_size.width, height: form.img_size.height }"
            :before-upload="handleBeforeUpload"
          >
            <el-button type="primary" size="small">上传图片</el-button>
          </el-upload>
          <el-button
            type="primary"
            size="small"
            @click="showUploadAndModifyProductPicInPaintDialog"
            style="margin-left: 12px"
            >局部重绘</el-button
          >
          <el-button
            type="primary"
            size="small"
            @click="onAnalyzeUploadAndModifyProductPic"
            style="margin-left: 12px"
            >解析图片</el-button
          >
          <el-button
            plain
            size="small"
            @click="onClearUploadAndModifyProductPic"
            style="margin-left: 12px"
            >清除图片</el-button
          >
        </el-form-item>
      </div>
      <!-- Prompt到文案 -->
      <el-form-item label="Prompt">
        <el-input v-model="form.chatgpt_prompt" :autosize="true" type="textarea" />
      </el-form-item>
      <el-form-item>
        <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 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-form-item>
      <!-- 角色 -->
      <el-form-item>
        <el-button type="primary" @click="onAdaptRoles">推理角色（{{ role_llm.name }}）</el-button>
        <el-button type="primary" @click="onAdaptRolesKeywords"
          >推理角色关键词（{{ role_keywords_llm.name }}）</el-button
        >
        <el-button plain @click="clean_roles">清空总角色列表</el-button>
      </el-form-item>
      <el-form-item label="角色">
        <el-table
          :data="form.chatgpt_answer_roles"
          border
          style="width: 100%; z-index: calc(var(--el-table-index) -1)"
        >
          <el-table-column prop="角色" label="角色" width="300">
            <template v-slot="scope">
              <el-input v-model="scope.row.角色" :autosize="true" type="textarea"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="属性" label="属性" width="300">
            <template v-slot="scope">
              <el-select v-model="scope.row.属性" filterable allow-create :reserve-keyword="false">
                <el-option
                  v-for="item in default_data.role_attribute_options"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column prop="角色关键词" label="角色关键词">
            <template v-slot="scope">
              <el-input v-model="scope.row.角色关键词" :autosize="true" type="textarea"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="角色关键词英文" label="角色关键词英文">
            <template v-slot="scope">
              <el-input
                v-model="scope.row.角色关键词英文"
                :autosize="true"
                type="textarea"
              ></el-input>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <!-- 分镜 -->
      <el-form-item>
        <el-button type="primary" @click="onAdapt('default')">分镜：标准模式</el-button>
        <el-button type="success" @click="onAdapt('more_scene')">分镜：丰富场景模式</el-button>
        <el-button type="primary" @click="onAdaptScene">推理场景（{{ tuili_llm.name }}）</el-button>
        <el-button type="primary" @click="onAdaptSceneRoles"
          >推理场景中的角色（{{ tuili_keyword_llm.name }}）</el-button
        >
        <el-button type="primary" @click="onDraw">绘图</el-button>
        <el-button plain @click="clean_scenes">清空分镜列表</el-button>
      </el-form-item>
      <el-form-item label="分镜">
        <el-table
          :data="form.adapt_result_json"
          border
          style="width: 100%; z-index: calc(var(--el-table-index) -1)"
        >
          <el-table-column prop="编号" label="编号" width="55" />
          <el-table-column prop="场景描述" label="场景描述">
            <template v-slot="scope">
              <el-input v-model="scope.row.场景描述" :autosize="true" type="textarea"></el-input>
              <el-text class="mx-1" size="small">{{ scope.row.info2 }}</el-text>
            </template>
          </el-table-column>
          <el-table-column prop="场景关键词" label="场景关键词">
            <template v-slot="scope">
              <el-text class="mx-1" size="small">{{ scope.row.场景关键词 }}</el-text>
              <hr style="border: none; border-top: 1px dashed #999; margin: 5px 0" />
              <el-input
                v-model="scope.row.场景关键词英文"
                :autosize="true"
                type="textarea"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="角色" label="角色">
            <template v-slot="scope">
              <el-text class="mx-1" size="small">{{ scope.row.info }}</el-text>
              <hr style="border: none; border-top: 1px dashed #999; margin: 5px 0" />
              <el-select
                v-model="scope.row.角色"
                placeholder=""
                @change="onItemRolesChange(scope.row)"
              >
                <el-option v-for="item in scope.row.roles" :key="item" :label="item" :value="item">
                  <span style="float: left">{{ item }}</span>
                </el-option>
              </el-select>
              <!-- <el-text class="mx-1" size="small">{{ scope.row.角色 }}<br />（{{ scope.row.info }}）</el-text> -->
            </template>
          </el-table-column>
          <el-table-column prop="角色关键词" label="角色关键词">
            <template v-slot="scope">
              <el-text class="mx-1" size="small">{{ scope.row.角色关键词 }}</el-text>
              <hr style="border: none; border-top: 1px dashed #999; margin: 5px 0" />
              <el-input
                v-model="scope.row.角色关键词英文"
                :autosize="true"
                type="textarea"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="本镜配图" label="本镜配图" width="300">
            <template v-slot="scope">
              <div>
                <el-image
                  :src="scope.row.本镜配图"
                  :zoom-rate="1.0"
                  :max-scale="1.5"
                  :min-scale="1.5"
                  :preview-src-list="[scope.row.本镜配图]"
                  fit="cover"
                  :hide-on-click-modal="true"
                />
              </div>
            </template>
          </el-table-column>
          <el-table-column width="120" label="操作" align="center">
            <!-- 
            <template v-slot:header>
              <el-button type="danger" size="default" @click="">批量绘制所有图片</el-button>
            </template> 
            -->
            <template v-slot="scope">
              <div style="margin: 5px 0">
                <el-button type="primary" size="small" @click="onAdaptOneScene(scope.row)"
                  >推理场景</el-button
                >
              </div>
              <div style="margin: 5px 0">
                <el-button type="primary" size="small" @click="onAdaptOneSceneRoles(scope.row)"
                  >推理角色</el-button
                >
              </div>
              <div style="margin: 5px 0">
                <el-button type="primary" size="small" @click="onDrawOne(scope.row)"
                  >绘图</el-button
                >
              </div>
              <el-upload
                ref="upload"
                :show-file-list="false"
                :limit="1"
                accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
                :action="actionUrl"
                :on-success="handleUploadSuccess"
                :on-exceed="handleUploadExceed"
                :on-error="handleUploadError"
                :data="{ width: form.img_size.width, height: form.img_size.height }"
                :before-upload="handleBeforeUpload"
              >
                <el-button type="primary" size="small" @click="onClickUpload(scope.row)"
                  >上传图片</el-button
                >
              </el-upload>
              <!-- <div style="margin: 5px 0">
                <el-button
                  type="primary"
                  size="small"
                  @click="showInPaintDialog('scene', scope.row)"
                  >局部重绘</el-button
                >
              </div> -->
              <!-- <div style="margin: 5px 0"><el-button plain size="small" @click="onClearOnePic(scope.row)">清除图片</el-button></div> -->
              <div style="margin: 5px 0">
                <el-button plain size="small" @click="showsdprompt(scope.row)">debug</el-button>
              </div>
              <el-dialog v-model="dialogVisible" width="80%">
                <p>{{ dialogData }}</p>
                <template #footer>
                  <div class="dialog-footer">
                    <el-button type="primary" @click="dialogVisible = false">ok</el-button>
                  </div>
                </template>
              </el-dialog>
              <div style="margin: 10px 0">
                <el-button type="danger" size="small" @click="onDeleteOne(scope.row)"
                  >删除本镜</el-button
                >
              </div>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item label="封面图片">
        <el-switch
          v-model="cover_backcover.if_need_cover_pic"
          active-value="true"
          inactive-value="false"
        />
      </el-form-item>
      <div v-if="JSON.parse(cover_backcover.if_need_cover_pic.toLowerCase())">
        <el-form-item>
          <!-- :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="cover_backcover.cover_pic" />
          </div>
          <div
            :style="{ width: String(parseInt(form.img_size.width) / 3) + 'px' }"
            class="dashed-div"
            style="margin-left: 20px"
          >
            <el-image :src="cover_backcover.cover_pic_with_text" />
          </div>
        </el-form-item>
        <el-form-item>
          <el-upload
            ref="upload_cover"
            :show-file-list="false"
            :limit="1"
            accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
            :action="actionUrl"
            :on-success="MarketingTemplateUploadCoverPicSuccess"
            :on-exceed="handleMarketingTemplateUploadCoverPicExceed"
            :on-error="handleUploadError"
            :data="{ width: form.img_size.width, height: form.img_size.height }"
            :before-upload="handleBeforeUpload"
          >
            <el-button type="primary" size="small">上传图片</el-button>
          </el-upload>
          <span style="margin-left: 12px">或使用第</span>
          <el-select
            size="small"
            v-model="cover_backcover.cover_pic_use_scene"
            placeholder="选择"
            style="width: 60px"
            @change="onSelectCoverChange"
          >
            <el-option
              v-for="item in form.adapt_result_json"
              :key="item.编号"
              :label="item.编号"
              :value="item.编号"
            >
              <span style="float: left">{{ item.编号 }}</span>
            </el-option>
          </el-select>
          <span>帧做封面</span>
          <el-button
            plain
            size="small"
            @click="onClearMarketingTemplatePic('cover')"
            style="margin-left: 12px"
            >清除图片</el-button
          >
          <!-- <el-button
            type="primary"
            size="small"
            @click="showInPaintDialog('cover', '')"
            style="margin-left: 12px"
            >局部重绘</el-button
          > -->
        </el-form-item>
        <el-form-item>
          <div style="width: 100%">
            <el-button
              type="primary"
              size="small"
              @click="onAddMarketingTemplatePicText('cover', 'add', 0)"
              >增加文字</el-button
            >
            <!-- <el-button type="success" size="small" @click="onMarketingTemplateAddTextToPic('cover')">预览</el-button> -->
          </div>
          <div
            v-for="(pic_title, index) in cover_backcover.cover_pic_titles"
            :key="index"
            class="dashed-div"
            style="width: 100%"
          >
            <el-input
              v-model="pic_title.text"
              :autosize="true"
              type="textarea"
              @change="onMarketingTemplateAddTextToPic('cover')"
            ></el-input>
            <span style="margin-left: 10px">字体颜色：</span>
            <el-color-picker
              v-model="pic_title.color"
              @change="onMarketingTemplateAddTextToPic('cover')"
            />
            <span style="margin-left: 30px">字体背景：</span>
            <el-color-picker
              v-model="pic_title.bg_color"
              @change="onMarketingTemplateAddTextToPic('cover')"
            />
            <span style="margin-left: 30px">字体大小：</span>
            <el-input-number
              v-model="pic_title.font_size"
              :min="1"
              :max="100"
              controls-position="right"
              @change="onMarketingTemplateAddTextToPic('cover')"
            />
            <span style="margin-left: 30px">在图片上的位置：</span>
            <el-slider
              v-model="pic_title.position"
              :step="0.01"
              :min="0"
              :max="1"
              show-input
              vertical
              height="100px"
              style="margin-top: 10px"
              @change="onMarketingTemplateAddTextToPic('cover')"
            />
            <el-button
              type="danger"
              size="small"
              @click="onAddMarketingTemplatePicText('cover', 'del', index)"
              style="margin-left: 80px"
              >删除文字</el-button
            >
          </div>
        </el-form-item>
      </div>
      <el-form-item label="封底图片">
        <el-switch
          v-model="cover_backcover.if_need_product_pic"
          active-value="true"
          inactive-value="false"
        />
      </el-form-item>
      <div v-if="JSON.parse(cover_backcover.if_need_product_pic.toLowerCase())">
        <el-form-item>
          <!-- :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="cover_backcover.product_pic" />
          </div>
          <div
            :style="{ width: String(parseInt(form.img_size.width) / 3) + 'px' }"
            class="dashed-div"
            style="margin-left: 20px"
          >
            <el-image :src="cover_backcover.product_pic_with_text" />
          </div>
        </el-form-item>
        <el-form-item>
          <el-upload
            ref="upload_product"
            :show-file-list="false"
            :limit="1"
            accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
            :action="actionUrl"
            :on-success="MarketingTemplateUploadProductPicSuccess"
            :on-exceed="handleMarketingTemplateUploadProductPicExceed"
            :on-error="handleUploadError"
            :data="{ width: form.img_size.width, height: form.img_size.height }"
            :before-upload="handleBeforeUpload"
          >
            <el-button type="primary" size="small">上传图片</el-button>
          </el-upload>
          <el-button
            plain
            size="small"
            @click="onClearMarketingTemplatePic('product')"
            style="margin-left: 12px"
            >清除图片</el-button
          >
          <!-- <el-button
            type="primary"
            size="small"
            @click="showInPaintDialog('product', '')"
            style="margin-left: 12px"
            >局部重绘</el-button
          > -->
        </el-form-item>
        <el-form-item>
          <div style="width: 100%">
            <el-button
              type="primary"
              size="small"
              @click="onAddMarketingTemplatePicText('product', 'add', 0)"
              >增加文字</el-button
            >
            <!-- <el-button type="success" size="small" @click="onMarketingTemplateAddTextToPic('product')">预览</el-button> -->
          </div>
          <div
            v-for="(pic_title, index) in cover_backcover.product_pic_titles"
            :key="index"
            class="dashed-div"
            style="width: 100%"
          >
            <el-input
              v-model="pic_title.text"
              :autosize="true"
              type="textarea"
              @change="onMarketingTemplateAddTextToPic('product')"
            ></el-input>
            <span style="margin-left: 10px">字体颜色：</span>
            <el-color-picker
              v-model="pic_title.color"
              @change="onMarketingTemplateAddTextToPic('product')"
            />
            <span style="margin-left: 30px">字体背景：</span>
            <el-color-picker
              v-model="pic_title.bg_color"
              @change="onMarketingTemplateAddTextToPic('product')"
            />
            <span style="margin-left: 30px">字体大小：</span>
            <el-input-number
              v-model="pic_title.font_size"
              :min="1"
              :max="100"
              controls-position="right"
              @change="onMarketingTemplateAddTextToPic('product')"
            />
            <span style="margin-left: 30px">在图片上的位置：</span>
            <el-slider
              v-model="pic_title.position"
              :step="0.01"
              :min="0"
              :max="1"
              show-input
              vertical
              height="100px"
              style="margin-top: 10px"
              @change="onMarketingTemplateAddTextToPic('product')"
            />
            <el-button
              type="danger"
              size="small"
              @click="onAddMarketingTemplatePicText('product', 'del', index)"
              style="margin-left: 80px"
              >删除文字</el-button
            >
          </div>
        </el-form-item>
        <el-form-item label="封底旁白">
          <el-input
            v-model="cover_backcover.product_pic_speech"
            :autosize="true"
            type="textarea"
          ></el-input>
        </el-form-item>
      </div>
      <!-- 生成视频 -->
      <el-form-item label="视频设置">
        <span style="margin: 0 20px 0 0">TTS语速：</span>
        <el-slider
          v-model="voice_rate"
          show-input
          :min="-50"
          :max="50"
          :marks="default_data.marks"
          style="width: 900px"
        />
      </el-form-item>
      <el-form-item>
        <span style="margin: 0 20px 0 0">TTS音量：</span>
        <el-slider
          v-model="voice_volume"
          show-input
          :min="-80"
          :max="80"
          :marks="default_data.marks"
          style="width: 900px"
        />
      </el-form-item>
      <el-form-item>
        <span style="margin: 20px 20px 0 0">TTS语音：</span>
        <el-select v-model="voice" placeholder="Select" style="width: 400px; margin-top: 20px">
          <el-option
            v-for="item in default_data.voices"
            :key="item.value"
            :label="item.value"
            :value="item.value"
          >
            <span style="float: left">{{ item.value }}</span>
            <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">{{
              item.label
            }}</span>
          </el-option>
        </el-select>
        <audio
          :src="'src/assets/edge-tts-voices/' + voice + '.mp3'"
          controls
          style="height: 30px; margin: 20px 0 0 10px"
        ></audio>
      </el-form-item>
      <el-form-item>
        <span style="margin: 0 20px 0 0">背景音乐：</span>
        <el-select v-model="bgm" placeholder="无" style="width: 400px">
          <el-option
            v-for="item in default_data.bgm"
            :key="item.value"
            :label="item.value"
            :value="item.value"
          >
            <span style="float: left">{{ item.label }}</span>
            <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">{{
              item.value
            }}</span>
          </el-option>
        </el-select>
        <audio
          :src="'src/assets/bgm/' + bgm + '.mp3'"
          controls
          style="height: 30px; margin-left: 10px"
        ></audio>
      </el-form-item>
      <el-form-item>
        <span style="margin: 0 20px 0 0">背景音量：</span>
        <el-slider
          v-model="bgm_volume"
          show-input
          :step="0.1"
          :min="0"
          :max="2"
          :marks="default_data.bgm_volume_marks"
          style="width: 600px"
        />
      </el-form-item>
      <el-form-item>
        <span style="margin: 20px 20px 20px 0">字幕合成：</span>
        <el-switch v-model="form.if_need_subtitle" active-value="true" inactive-value="false" />
        <div v-if="JSON.parse(form.if_need_subtitle.toLowerCase())">
          <span style="margin-left: 30px">字体颜色：</span>
          <el-color-picker v-model="sub_font_color" />
          <span style="margin-left: 30px">字体背景：</span>
          <el-color-picker v-model="sub_bg_color" />
          <span style="margin-left: 30px">字体大小：</span>
          <el-input-number v-model="sub_font_size" :min="1" :max="50" controls-position="right" />
          <span style="margin-left: 30px">在屏幕上的位置：</span>
          <el-slider
            v-model="sub_position"
            :step="0.1"
            :min="0"
            :max="1"
            show-input
            vertical
            height="100px"
          />
        </div>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onGenVideo">生成视频</el-button>
      </el-form-item>
      <el-form-item>
        <video :src="form.final_video" controls></video>
      </el-form-item>
    </el-form>

    <!-- 授权密码框 -->
    <el-dialog
      v-model="pwdCheckDialogVisible"
      title="请输入密码"
      width="20%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <el-form :model="form">
        <el-form-item label="密码">
          <el-input
            v-model="pwdCheckValue"
            autocomplete="off"
            type="password"
            show-password
            @keyup.enter="onPwdCheckDialog()"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="onPwdCheckDialog()">ok</el-button>
        </div>
      </template>
    </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="100"
            :max="500"
            controls-position="right"
          />
        </el-form-item>
      </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>

    <!-- 局部重绘 -->
    <el-dialog
      v-model="inPaintVisible"
      :width="parseInt(form.img_size.width) + 40"
      :close-on-click-modal="false"
      :close-on-press-escape="true"
      :lock-scroll="true"
    >
      <div style="color: red">请在图片上涂抹需要保留的部分</div>
      <div
        ref="inpaint"
        :style="
          'position: relative; width: ' +
          form.img_size.width +
          'px; height: ' +
          form.img_size.height +
          'px; margin: 10px auto;'
        "
      >
        <canvas
          id="baseCanvas"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0"
        ></canvas>
        <canvas
          id="maskCanvas"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0; z-index: 1; background: none"
        ></canvas>
      </div>
      <button id="clearButton">清除涂抹</button>
      <div>
        <span>画面描述：</span>
        <el-input v-model="inPaintPrompt" :autosize="true" type="textarea"></el-input>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="inPaintVisible = false">取消</el-button>
          <el-button type="primary" @click="onSubmitInPaint">提交</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 自定义产品图局部重绘 -->
    <el-dialog
      v-model="update_and_modify_product.inPaintVisible"
      :width="parseInt(form.img_size.width) + 40"
      :close-on-click-modal="false"
      :close-on-press-escape="true"
      :lock-scroll="true"
    >
      <div style="color: red">
        先在图片上点击产品部分 ==> 点击智能抠图，预览效果 ==> 如效果不理想，则勾选此项
        <input type="checkbox" id="update_and_modify_product_noObjCheckbox" />
        ，再点击非产品部分，抠图，直到满意。
      </div>
      <div
        ref="update_and_modify_product_inpaint"
        :style="
          'position: relative; width: ' +
          form.img_size.width +
          'px; height: ' +
          form.img_size.height +
          'px; margin: 10px auto;'
        "
      >
        <canvas
          id="update_and_modify_product_baseCanvas"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0; z-index: 1; background: none"
        ></canvas>
        <canvas
          id="update_and_modify_product_previewCanvas"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0; z-index: 2; background: none"
        ></canvas>
        <canvas
          id="update_and_modify_product_maskCanvas2"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0; z-index: 3; background: none"
        ></canvas>
        <canvas
          id="update_and_modify_product_maskCanvas"
          :width="form.img_size.width"
          :height="form.img_size.height"
          style="position: absolute; left: 0; top: 0; z-index: 4; background: none"
        ></canvas>
      </div>
      <button id="update_and_modify_product_clearButton">重置</button>
      <el-button @click="onSubmitUploadAndModifyProductPicCutOut">智能抠图</el-button>
      <div>
        <span>画面描述：</span>
        <el-input
          v-model="update_and_modify_product.inPaintPrompt"
          :autosize="true"
          type="textarea"
        ></el-input>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="update_and_modify_product.inPaintVisible = false">取消</el-button>
          <el-button type="primary" @click="onSubmitUploadAndModifyProductPicInPaint"
            >重绘</el-button
          >
        </div>
      </template>
    </el-dialog>
  </main>
</template>

<style lang="scss" scoped>
.home-container {
  width: 100%;
}
</style>

<style lang="scss">
.home-container {
  .el-table .el-table__cell {
    z-index: calc(var(--el-table-index) -1);
  }
}
.dashed-div {
  border: 1px dashed #999;
  margin: 5px 0;
  padding: 2px;
}
</style>
