<template>
  <div class="app-container">
    <!-- 将声音选择器移到顶部右侧 -->
    <div class="header-controls">
      <h1>智能PPT生成器</h1>
      <div class="voice-selector">
        <label for="voiceSelect" class="form-label">选择声音:</label>
        <select id="voiceSelect" class="form-select">
          <option value="标准">标准</option>
          <option value="Trump">Trump</option>
          <option value="Trump">Leap</option>
          <option value="Trump">ZFQ</option>
         
        </select>
      </div>
    </div>

    <div class="tabs">
      <button
        :class="{ active: currentTab === 'text' }"
        @click="currentTab = 'text'"
      >
        智能PPT讲解生成器
      </button>
      <button
        :class="{ active: currentTab === 'video' }"
        @click="currentTab = 'video'"
      >
        智能有声PPT生成器
      </button>
    </div>

    <!-- 其余内容保持不变 -->
    <!-- 文本处理模块 -->
    <div v-if="currentTab === 'text'" class="upload-box">
      <p>选择PPT文件 (.pptx)</p>
      <input type="file" accept=".pptx" @change="uploadTextFile" ref="textFileInput" />
    </div>

    <!-- 视频处理模块 -->
    <div v-if="currentTab === 'video'" class="upload-box">
      <div class="file-group">
        <label>第一步:上传PPT文件 (.pptx)</label>
        <input type="file" accept=".pptx" @change="uploadPptFile" ref="pptFileInput" />
      </div>
      <div class="file-group">
        <label>第二步:上传讲解脚本 (.txt)</label>
        <input type="file" accept=".txt" @change="uploadScriptFile" ref="scriptFileInput" />
      </div>
      <button @click="startVideoProcessing">开始生成有声PPT</button>
    </div>

    <div v-if="showStatus" id="status">
      <h3>处理进度</h3>
      <div class="progress">
        <div class="progress-bar" :style="{ width: progress + '%' }"></div>
      </div>
      <p>{{ statusMessage }}</p>
      <a v-if="downloadLink" :href="downloadLink" target="_blank">下载生成结果</a>
    </div>
  </div>
</template>
 
<script>
  export default {
    name: 'PPTGenerator',
    data() {
      return {
        currentTab: 'text',
        showStatus: false,
        progress: 0,
        statusMessage: '',
        downloadLink: null,
        currentTaskId: null,
        pptFile: null,
        scriptFile: null
      }
    },
    methods: {
      async uploadTextFile(event) {
        const file = event.target.files[0]
        if (!file) return
 
        const formData = new FormData()
        formData.append('file', file)
 
        this.showStatus = true
        this.statusMessage = '开始上传文件...'
 
        try {
          const response = await fetch('http://localhost:7860/api/text/upload', {
            method: 'POST',
            body: formData
          })
          const data = await response.json()
          if (data.error) {
            this.updateStatus('error', data.error)
            return
          }
          this.currentTaskId = data.task_id
          this.checkTextProgress()
        } catch (error) {
          this.updateStatus('error', '上传失败')
        }
      },
      async startVideoProcessing() {
        if (!this.pptFile || !this.scriptFile) {
          alert('请同时上传PPT文件和讲解脚本')
          return
        }
 
        const formData = new FormData()
        formData.append('ppt', this.pptFile)
        formData.append('script', this.scriptFile)
 
        this.showStatus = true
        this.updateProgress(5, '开始上传文件...')

        try {
          const response = await fetch('http://localhost:7860/api/video/upload', {
            method: 'POST',
            body: formData
          })
          const data = await response.json()
          if (data.error) {
            this.updateStatus('error', data.error)
            return
          }
          this.currentTaskId = data.task_id
          this.checkVideoProgress()
        } catch (error) {
          this.updateStatus('error', error.message)
        }
      },
      async checkTextProgress() {
  try {
    const response = await fetch(`http://localhost:7860/api/text/status/${this.currentTaskId}`);
    const data = await response.json();
    this.updateProgress(data.progress, data.message);
    if (data.status === "processing") {
      setTimeout(this.checkTextProgress, 2000);
    } else if (data.status === "completed") {
      // 修改下载链接,移除 .txt 后缀
      this.downloadLink = `http://localhost:7860/api/text/download/${this.currentTaskId}`;
    } else if (data.status === "failed") {
      this.updateStatus("error", data.message);
    }
  } catch (error) {
    this.updateStatus("error", "状态查询失败");
  }
},

async checkVideoProgress() {
  try {
    const response = await fetch(`http://localhost:7860/api/video/status/${this.currentTaskId}`);
    const data = await response.json();
    this.updateProgress(data.progress, data.message);
    if (data.status === "processing") {
      setTimeout(this.checkVideoProgress, 2000);
    } else if (data.status === "completed") {
      // 修改下载链接,提供 PPTX 文件
      this.downloadLink = `http://localhost:7860/api/video/download/${this.currentTaskId}`;
    } else if (data.status === "failed") {
      this.updateStatus("error", data.message);
    }
  } catch (error) {
    this.updateStatus("error", "状态查询失败");
  }
},

      updateProgress(percent, message) {
        this.progress = percent
        this.statusMessage = message
        this.updateProgressBarColor()
      },
      updateStatus(type, message) {
        this.statusMessage = message
        this.updateProgressBarColor(type)
      },
      updateProgressBarColor(type = 'success') {
        const progressBar = this.$el.querySelector('.progress-bar')
        progressBar.style.backgroundColor = type === 'error' ? '#ff4444' : '#4CAF50'
      },
      uploadPptFile(event) {
        this.pptFile = event.target.files[0]
      },
      uploadScriptFile(event) {
        this.scriptFile = event.target.files[0]
      }
    }
  }
</script>
 
<style scoped>
 .app-container {
    max-width: 800px;
    margin: 20px auto;
    padding: 20px;
    font-family: Arial, sans-serif;
  }
 
  .header-controls {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }
 
  .voice-selector {
    display: flex;
    align-items: center;
    gap: 10px;
  }
 
  .voice-selector .form-select {
    width: 180px;
  }
 
  .tabs {
    display: flex;
    justify-content: center;
    margin-bottom: 20px;
  }
 
  .tabs button {
    padding: 10px 20px;
    margin: 0 10px;
    border: none;
    background: #f8f9fa;
    border-radius: 4px;
    cursor: pointer;
  }
 
  .tabs button.active {
    background: #4CAF50;
    color: white;
  }
 
  .upload-box {
    border: 2px dashed #ccc;
    padding: 30px;
    text-align: center;
    margin: 20px 0;
    display: grid;
    gap: 15px;
  }
 
  .progress {
    height: 20px;
    background: #f0f0f0;
    border-radius: 10px;
    overflow: hidden;
    margin: 10px 0;
  }
 
  .progress-bar {
    height: 100%;
    background: #4CAF50;
    transition: width 0.3s ease-in-out;
  }
 
  #status {
    margin: 20px 0;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 8px;
  }
 
  .file-group {
    margin: 15px 0;
    padding: 10px;
    border: 1px solid #eee;
    border-radius: 6px;
  }
 
  .file-group label {
    display: block;
    margin-bottom: 8px;
    font-weight: bold;
    color: #666;
  }
 
  a {
    text-decoration: none;
    color: #fff;
    background: #4CAF50;
    padding: 10px 20px;
    border-radius: 4px;
    transition: background 0.3s;
  }
 
  a:hover {
    background: #45a049;
  }
</style>
 
posted on 2025-04-23 23:16  leapss  阅读(23)  评论(0)    收藏  举报