| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143 |
- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>生成模板 - 文生视频</title>
- <!-- 引入Font Awesome图标 -->
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
- <!-- 引入自定义CSS -->
- <link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico"/>
- <style>
- /* 自定义提示框样式 */
- .custom-alert {
- position: fixed;
- top: 10%;
- left: 50%;
- transform: translate(-50%, -50%);
- padding: 15px 25px;
- border-radius: 8px;
- color: white;
- font-size: 14px;
- font-weight: 500;
- z-index: 10000;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
- opacity: 0;
- visibility: hidden;
- transition: all 0.3s ease;
- max-width: 80%;
- text-align: center;
- }
- .custom-alert.show {
- opacity: 1;
- visibility: visible;
- }
- .custom-alert.error {
- background-color: #e74c3c;
- }
- .custom-alert.success {
- background-color: #28a745;
- }
- .custom-alert.warning {
- background-color: #ffc107;
- color: #333;
- }
- .custom-alert.info {
- background-color: #17a2b8;
- }
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- /* 标题样式 */
- .page-title {
- font-size: 24px;
- font-weight: bold;
- margin-bottom: 25px;
- color: #333;
- }
- /* 内容区域 */
- .content-area {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 30px;
- }
- /* 左侧输入区域 */
- .input-section {
- background-color: #fff;
- border-radius: 8px;
- padding: 20px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- }
- /* 右侧预览区域 */
- .preview-section {
- background-color: #fff;
- border-radius: 8px;
- padding: 20px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- }
- /* 表单组样式 */
- .form-group {
- margin-bottom: 20px;
- }
- .form-group label {
- display: block;
- font-size: 14px;
- font-weight: bold;
- color: #333;
- margin-bottom: 8px;
- }
- /* 文本输入区域 */
- .prompt-textarea {
- width: 100%;
- height: 150px;
- padding: 12px;
- border: 1px solid #ddd;
- border-radius: 8px;
- resize: vertical;
- font-size: 14px;
- line-height: 1.5;
- }
- /* 参数设置区域 */
- .params-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
- gap: 15px;
- }
- .param-item {
- margin-bottom: 15px;
- }
- .param-item label {
- display: block;
- font-size: 13px;
- font-weight: bold;
- color: #333;
- margin-bottom: 5px;
- }
- .param-item select, .param-item input[type="number"] {
- width: 100%;
- padding: 8px 12px;
- border: 1px solid #ddd;
- border-radius: 4px;
- font-size: 14px;
- }
- /* 提示词示例 */
- .prompt-examples {
- background-color: #f8f9fa;
- border-radius: 8px;
- padding: 15px;
- margin-bottom: 20px;
- }
- .prompt-examples h4 {
- font-size: 14px;
- font-weight: bold;
- margin-bottom: 10px;
- color: #333;
- }
- .example-list {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- }
- .example-tag {
- font-size: 12px;
- background-color: #e9ecef;
- color: #666;
- padding: 4px 10px;
- border-radius: 4px;
- cursor: pointer;
- transition: background-color 0.2s;
- }
- .example-tag:hover {
- background-color: #dee2e6;
- }
- /* 按钮样式 */
- .button-group {
- display: flex;
- gap: 10px;
- }
- .btn {
- padding: 12px 24px;
- border: none;
- border-radius: 8px;
- font-size: 14px;
- cursor: pointer;
- transition: background-color 0.2s;
- }
- .btn-primary {
- background-color: #007bff;
- color: #fff;
- }
- .btn-primary:hover {
- background-color: #0056b3;
- }
- .btn-secondary {
- background-color: #6c757d;
- color: #fff;
- }
- .btn-secondary:hover {
- background-color: #545b62;
- }
- /* 预览区域 */
- .preview-container {
- width: 100%;
- min-height: 300px;
- background-color: #f8f9fa;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 20px;
- overflow: hidden;
- }
- .preview-image {
- max-width: 100%;
- max-height: 100%;
- object-fit: contain;
- }
- .preview-placeholder {
- font-size: 14px;
- color: #666;
- text-align: center;
- }
- /* 模板信息 */
- .template-info {
- margin-bottom: 20px;
- }
- .template-info h4 {
- font-size: 14px;
- font-weight: bold;
- margin-bottom: 10px;
- color: #333;
- }
- .template-form input {
- width: 100%;
- padding: 10px 12px;
- border: 1px solid #ddd;
- border-radius: 8px;
- font-size: 14px;
- margin-bottom: 10px;
- }
- /* 响应式设计 */
- @media (max-width: 768px) {
- .content-area {
- grid-template-columns: 1fr;
- }
- .clear-btn, .optimize-btn, .arrow-btn {
- flex: 1;
- }
- }
- .optimize-btn {
- background-color: #ffffff;
- color: #4b5563;
- padding: 10px 18px;
- border: 1px solid #d1d5db;
- border-radius: 8px;
- font-size: 14px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- gap: 6px;
- }
- .optimize-btn:hover {
- background-color: #f9fafb;
- border-color: #9ca3af;
- transform: translateY(-1px);
- }
- .clear-btn {
- background-color: #ffffff;
- color: #dc3545;
- border: 1px solid #f87171;
- border-radius: 8px;
- font-size: 14px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- gap: 6px;
- }
- .clear-btn:hover {
- background-color: #fee2e2;
- border-color: #ef4444;
- transform: translateY(-1px);
- }
- /* 操作按钮 */
- .prompt-actions {
- gap: 8px;
- }
- .clear-btn, .optimize-btn {
- padding: 8px 12px;
- font-size: 13px;
- }
- /* 菜单样式 */
- .menu-container {
- background-color: #f5f7fa;
- border-radius: 8px;
- padding: 10px;
- margin-bottom: 20px;
- display: flex;
- gap: 10px;
- }
- .menu-item {
- flex: 1;
- }
- .menu-item a {
- display: block;
- padding: 12px;
- background-color: white;
- border: 1px solid #e1e8ed;
- border-radius: 6px;
- text-align: center;
- text-decoration: none;
- color: #657786;
- font-size: 14px;
- font-weight: 500;
- transition: all 0.3s ease;
- }
- .menu-item a:hover {
- background-color: #e8f0fe;
- border-color: #1da1f2;
- color: #1da1f2;
- }
- .menu-item.active a {
- background-color: #1da1f2;
- border-color: #1da1f2;
- color: white;
- }
- .menu-item i {
- margin-right: 6px;
- font-size: 16px;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <!-- 菜单功能区 -->
- <div class="menu-container">
- <div class="menu-item">
- <a href="{:url('user/index')}">
- <i class="fas fa-image"></i>
- 文生图
- </a>
- </div>
- <div class="menu-item active">
- <a href="{:url('user/text_to_video')}">
- <i class="fas fa-video"></i>
- 文生视频
- </a>
- </div>
- </div>
- <div class="content-area">
- <!-- 左侧输入区域 -->
- <div class="input-section">
- <h3 style="font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333;">文生视频生成参数设置</h3>
- <!-- 提示词示例 -->
- <div class="prompt-examples">
- <label for="prompt">提示词</label>
- <textarea id="prompt" class="prompt-textarea" placeholder="请输入您想要生成的视频描述,越详细越好..."></textarea>
- </div>
- <!-- 生成参数 -->
- <div class="form-group">
- <label>生成参数</label>
- <div class="params-grid">
- <div class="param-item">
- <label for="style">风格</label>
- <select id="style">
- <option value="">默认</option>
- <option value="anime">动漫</option>
- <option value="realistic">写实</option>
- <option value="cartoon">卡通</option>
- <option value="fantasy">奇幻</option>
- </select>
- </div>
- <div class="param-item">
- <label for="duration">时长</label>
- <select id="duration">
- <option value="4">4秒</option>
- <option value="8">8秒</option>
- <option value="12">12秒</option>
- </select>
- </div>
- <div class="param-item">
- <label for="videoSize">尺寸</label>
- <select id="videoSize">
- <option value="1280x720">1280x720</option>
- <option value="720x1280">720x1280</option>
- </select>
- </div>
- </div>
- </div>
- <div class="button-group">
- <button class="clear-btn">
- <i class="fas fa-trash"></i>
- 清空
- </button>
- <button class="optimize-btn">
- <i class="fas fa-magic"></i>
- 一键优化
- </button>
- <button class="btn btn-primary" id="generateBtn">
- <i class="fas fa-arrow-up"></i>
- 生成视频
- </button>
- </div>
- </div>
- <!-- 右侧预览区域 -->
- <div class="preview-section">
- <h3 style="font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333;">视频预览</h3>
- <!-- 预览容器 -->
- <div id="videoResult" class="preview-container">
- <div class="preview-placeholder">
- <p>点击"生成视频"按钮开始创建您的视频</p>
- <p style="font-size: 12px; margin-top: 10px; color: #999;">生成时间可能需要几十秒到数分钟不等</p>
- </div>
- </div>
- <!-- 模板信息 -->
- <div class="template-info">
- <h4>模板信息</h4>
- <div class="template-form">
- <input type="text" id="templateName" placeholder="请输入模板名称">
- </div>
- </div>
- <!-- 保存按钮 -->
- <div class="button-group">
- <button class="btn btn-primary" id="saveBtn" disabled>保存为视频模板</button>
- <button class="btn btn-secondary" id="downloadBtn" disabled>下载视频</button>
- </div>
- </div>
- </div>
- </div>
- <script>
- // 自定义提示框函数
- function showAlert(message, type = 'info', duration = 3000) {
- // 检查是否已存在提示框容器,如果不存在则创建
- let alertElement = document.getElementById('customAlert');
- if (!alertElement) {
- alertElement = document.createElement('div');
- alertElement.id = 'customAlert';
- alertElement.className = 'custom-alert';
- document.body.appendChild(alertElement);
- }
- alertElement.textContent = message;
- alertElement.className = `custom-alert ${type}`;
- // 显示提示框
- alertElement.classList.add('show');
- // 自动隐藏
- setTimeout(() => {
- alertElement.classList.remove('show');
- }, duration);
- }
- // 生成视频函数
- function generateVideo() {
- const promptText = document.getElementById('prompt').value.trim();
- const videoStyle = document.getElementById('style').value;
- const videoDuration = document.getElementById('duration').value;
- const videoSize = document.getElementById('videoSize').value;
- const videoResultDiv = document.getElementById('videoResult');
- // 检查是否有提示词
- if (!promptText) {
- alert('请先输入视频描述');
- return;
- }
- // 显示加载状态
- videoResultDiv.innerHTML = `
- <div class="video-loading">
- <i class="fas fa-spinner fa-spin"></i>
- <p>正在生成视频,请稍候...</p>
- <p style="font-size: 12px; margin-top: 10px; color: #999;">生成时间可能需要几十秒到数分钟不等</p>
- </div>
- `;
- // 拼接风格、时长和尺寸到提示词末尾
- let fullPrompt = promptText;
- if (videoStyle) {
- fullPrompt += '风格:' + videoStyle;
- }
- if (videoDuration) {
- fullPrompt += '时长:' + videoDuration + '秒';
- }
- if (videoSize) {
- fullPrompt += '尺寸比例:' + videoSize;
- }
- // 发送请求到文生视频接口
- $.ajax({
- url: '/index.php/api/work_order/GetTxtToVideo',
- type: 'POST',
- dataType: 'json',
- data: {
- status_val: '文生视频',
- prompt: fullPrompt,
- model: 'sora-2',
- style: videoStyle,
- duration: videoDuration,
- size: videoSize
- },
- success: function(response) {
- // 处理成功响应
- if (response.code === 0 && response.data && response.data.web_url) {
- // 视频生成完成
- let videoUrl = response.data.web_url;
-
- // 确保web_url格式正确,添加根路径前缀
- if (videoUrl && !videoUrl.startsWith('/')) {
- videoUrl = '/' + videoUrl;
- }
-
- // 显示生成的视频
- videoResultDiv.innerHTML = `
- <div class="video-container">
- <video src="${videoUrl}" alt="生成的视频" class="generated-video" id="previewVideo" style="max-width: 100%; height: auto; max-height: 600px; cursor: pointer;" controls>
- 您的浏览器不支持视频播放
- </video>
- </div>
- `;
- // 更新视频信息到全局变量
- videoInfo = {
- style: videoStyle,
- duration: videoDuration,
- size: videoSize,
- web_url: videoUrl,
- video_id: response.data.video_id || response.data.id || ''
- };
-
- // 启用下载按钮和保存模板按钮
- document.getElementById('downloadBtn').disabled = false;
- document.getElementById('saveBtn').disabled = false;
- // 添加视频放大模态框(如果还不存在)
- if (!document.getElementById('videoModal')) {
- const modal = document.createElement('div');
- modal.id = 'videoModal';
- modal.style.cssText = `
- display: none;
- position: fixed;
- z-index: 9999;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: auto;
- background-color: rgba(0, 0, 0, 0.9);
- justify-content: center;
- align-items: center;
- `;
- modal.style.display = 'flex';
- modal.style.display = 'none';
- const modalContent = document.createElement('video');
- modalContent.id = 'modalVideo';
- modalContent.style.cssText = `
- max-width: 90%;
- max-height: 90%;
- margin: auto;
- `;
- modalContent.setAttribute('controls', 'controls');
- const closeBtn = document.createElement('span');
- closeBtn.innerHTML = '×';
- closeBtn.style.cssText = `
- position: absolute;
- top: 20px;
- right: 35px;
- color: #f1f1f1;
- font-size: 40px;
- font-weight: bold;
- transition: 0.3s;
- cursor: pointer;
- `;
- closeBtn.onclick = function() {
- modal.style.display = 'none';
- };
- modal.appendChild(closeBtn);
- modal.appendChild(modalContent);
- document.body.appendChild(modal);
- // 点击模态框背景关闭
- modal.onclick = function(event) {
- if (event.target.id === 'videoModal') {
- this.style.display = 'none';
- }
- };
- }
- // 为生成的视频添加点击事件
- const generatedVideo = videoResultDiv.querySelector('.generated-video');
- generatedVideo.onclick = function() {
- const modal = document.getElementById('videoModal');
- const modalVideo = document.getElementById('modalVideo');
- modalVideo.src = this.src;
- modal.style.display = 'flex';
- };
- } else if (response.code === 202 && response.data && response.data.video_id) {
- // 视频正在生成中,显示状态信息并开始轮询
- const videoId = response.data.video_id;
- const status = response.data.status;
- const progress = response.data.progress || 0;
-
- // 显示接口返回的message信息
- const message = response.msg || response.data.message || '';
- // <p style="font-size: 12px; margin-top: 10px; color: #999;">视频ID: ${videoId}</p>
- videoResultDiv.innerHTML = `
- <div class="video-processing">
- <i class="fas fa-hourglass-half fa-spin"></i>
- <p>正在生成视频,请稍候...</p>
- ${message ? `<p style="font-size: 12px; margin-top: 5px; color: #666;">${message}</p>` : ''}
- <p style="font-size: 12px; margin-top: 5px; color: #999;">当前状态: ${status === 'queued' ? '排队中' : '处理中'}</p>
- <div class="progress-bar-container" style="width: 200px; height: 8px; background-color: #eee; border-radius: 4px; margin: 10px auto;">
- <div class="progress-bar" style="width: ${progress}%; height: 100%; background-color: #4CAF50; border-radius: 4px; transition: width 0.3s;"></div>
- </div>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">系统正在自动检查视频生成状态...</p>
- </div>
- `;
-
- // 开始轮询检查视频状态
- startVideoPolling(videoId, videoStyle, videoDuration, videoSize);
- } else {
- // 显示错误信息
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>视频生成失败:${response.msg || '未知错误'}</p>
- </div>
- `;
- }
- },
- error: function(xhr, status, error) {
- // 处理网络错误
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>视频生成失败:网络错误</p>
- </div>
- `;
- }
- });
- }
- // 页面加载完成后绑定事件
- $(document).ready(function() {
- // 绑定生成视频按钮点击事件
- $('#generateBtn').click(generateVideo);
- // 绑定保存模板按钮点击事件
- $('#saveBtn').click(saveTemplate);
- // 绑定下载视频按钮点击事件
- $('#downloadBtn').click(downloadVideo);
- // 绑定清空按钮点击事件
- $('.clear-btn').click(clearPrompt);
- // 绑定一键优化按钮点击事件
- $('.optimize-btn').click(optimizePrompt);
-
- // 键盘ESC键关闭模态框事件
- document.addEventListener('keydown', function(event) {
- if (event.key === 'Escape') {
- const modal = document.getElementById('videoModal');
- if (modal && modal.style.display === 'flex') {
- modal.style.display = 'none';
- }
- }
- });
- });
- // 一键优化提示词功能
- function optimizePrompt() {
- const textarea = document.getElementById('prompt');
- const optimizeBtn = document.querySelector('.optimize-btn');
- if (textarea && textarea.value.trim() !== '') {
- // 显示加载状态
- const originalBtnText = optimizeBtn.innerHTML;
- optimizeBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 优化中...';
- optimizeBtn.disabled = true;
- // 构造请求参数
- const params = {
- status_val: '文生文',
- prompt: textarea.value,
- model: 'gemini-2.0-flash'
- };
- // 发送AJAX请求
- $.ajax({
- url: '/index.php/api/work_order/GetTxtToTxt',
- type: 'POST',
- data: params,
- dataType: 'json',
- success: function(data) {
- console.log(data);
- // 恢复按钮状态
- optimizeBtn.innerHTML = originalBtnText;
- optimizeBtn.disabled = false;
- // 优化成功,更新文本框内容
- textarea.value = data.content;
- textarea.scrollTop = textarea.scrollHeight;
- updateCharCount();
- // 显示优化成功提示
- const alert = document.createElement('div');
- alert.className = 'alert alert-success';
- alert.innerHTML = '提示词已优化!';
- alert.style.position = 'fixed';
- alert.style.top = '20px';
- alert.style.right = '20px';
- alert.style.zIndex = '9999';
- document.body.appendChild(alert);
- // 3秒后移除提示
- setTimeout(() => {
- alert.remove();
- }, 3000);
- }
- });
- } else {
- alert('请先输入提示词!');
- }
- }
- // 清空提示词功能
- function clearPrompt() {
- const textarea = document.getElementById('prompt');
- if (textarea) {
- textarea.value = '';
- textarea.focus();
- }
- }
- // 轮询检查视频状态函数
- function startVideoPolling(videoId, videoStyle, videoDuration, videoSize) {
- let pollingCount = 0;
- const maxPollingCount = 60; // 最大轮询次数 (30次 * 5秒 = 2.5分钟)
- const pollingInterval = 6000; // 轮询间隔 (5秒)
-
- // 轮询检查视频状态
- const pollingTimer = setInterval(function() {
- $.ajax({
- url: '/index.php/api/work_order/Getvideo_id',
- type: 'GET',
- dataType: 'json',
- data: {
- video_id: videoId
- },
- success: function(response) {
- if (response.code === 0 && response.data && response.data.web_url) {
- // 视频生成完成
- clearInterval(pollingTimer);
-
- const videoResultDiv = document.getElementById('videoResult');
- let videoUrl = response.data.web_url;
-
- // 确保web_url格式正确,添加根路径前缀
- if (videoUrl && !videoUrl.startsWith('/')) {
- videoUrl = '/' + videoUrl;
- }
-
- // 显示生成的视频
- videoResultDiv.innerHTML = `
- <div class="video-container">
- <video src="${videoUrl}" alt="生成的视频" class="generated-video" id="previewVideo" style="max-width: 100%; height: auto; max-height: 600px; cursor: pointer;" controls>
- 您的浏览器不支持视频播放
- </video>
- </div>
- `;
-
- // 更新视频信息到全局变量
- videoInfo = {
- style: videoStyle,
- duration: videoDuration,
- size: videoSize,
- web_url: videoUrl,
- video_id: response.data.video_id || videoId
- };
-
- // 启用下载按钮和保存模板按钮
- document.getElementById('downloadBtn').disabled = false;
- document.getElementById('saveBtn').disabled = false;
-
- // 添加视频放大模态框(如果还不存在)
- if (!document.getElementById('videoModal')) {
- const modal = document.createElement('div');
- modal.id = 'videoModal';
- modal.style.cssText = `
- display: none;
- position: fixed;
- z-index: 9999;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: auto;
- background-color: rgba(0, 0, 0, 0.9);
- justify-content: center;
- align-items: center;
- `;
- modal.style.display = 'flex';
- modal.style.display = 'none';
- const modalContent = document.createElement('video');
- modalContent.id = 'modalVideo';
- modalContent.style.cssText = `
- max-width: 90%;
- max-height: 90%;
- margin: auto;
- `;
- modalContent.setAttribute('controls', 'controls');
- const closeBtn = document.createElement('span');
- closeBtn.innerHTML = '×';
- closeBtn.style.cssText = `
- position: absolute;
- top: 20px;
- right: 35px;
- color: #f1f1f1;
- font-size: 40px;
- font-weight: bold;
- transition: 0.3s;
- cursor: pointer;
- `;
- closeBtn.onclick = function() {
- modal.style.display = 'none';
- };
- modal.appendChild(closeBtn);
- modal.appendChild(modalContent);
- document.body.appendChild(modal);
- // 点击模态框背景关闭
- modal.onclick = function(event) {
- if (event.target.id === 'videoModal') {
- this.style.display = 'none';
- }
- };
- }
- // 为生成的视频添加点击事件
- const generatedVideo = videoResultDiv.querySelector('.generated-video');
- generatedVideo.onclick = function() {
- const modal = document.getElementById('videoModal');
- const modalVideo = document.getElementById('modalVideo');
- modalVideo.src = this.src;
- modal.style.display = 'flex';
- };
- } else if (response.code === 202 && response.data) {
- // 视频仍在生成中,更新状态信息
- const status = response.data.status;
- const progress = response.data.progress || 0;
-
- const progressBar = videoResultDiv.querySelector('.progress-bar');
- const statusText = videoResultDiv.querySelector('.video-processing p:nth-child(3)');
- const progressText = videoResultDiv.querySelector('.video-processing p:nth-child(4)');
-
- if (progressBar) {
- progressBar.style.width = `${progress}%`;
- }
- if (statusText) {
- statusText.textContent = `当前状态: ${status === 'queued' ? '排队中' : '处理中'}`;
- }
- // if (progressText) {
- // progressText.textContent = `进度: ${progress}%`;
- // }
- } else {
- // 视频生成失败
- clearInterval(pollingTimer);
- const videoResultDiv = document.getElementById('videoResult');
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>视频生成失败:${response.msg || '未知错误'}</p>
- </div>
- `;
- }
- },
- error: function(xhr, status, error) {
- // 网络错误
- clearInterval(pollingTimer);
- const videoResultDiv = document.getElementById('videoResult');
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>检查视频状态失败:网络错误</p>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">请稍后手动刷新页面查看结果</p>
- <div style="margin-top: 10px;">
- <button onclick="startVideoPolling('${videoId}', '${videoStyle}', '${videoDuration}', '${videoSize}')" style="padding: 5px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer;">
- 重新检查视频状态
- </button>
- </div>
- </div>
- `;
- }
- });
-
- // 检查是否达到最大轮询次数
- pollingCount++;
- if (pollingCount >= maxPollingCount) {
- clearInterval(pollingTimer);
- const videoResultDiv = document.getElementById('videoResult');
- const manualCheckDiv = document.createElement('div');
- manualCheckDiv.style.cssText = 'text-align: center; margin-top: 10px;';
- manualCheckDiv.innerHTML = `
- <button onclick="checkVideoStatus('${videoId}')" style="padding: 5px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer;">
- 手动检查视频状态
- </button>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">或稍后刷新页面查看结果</p>
- `;
- videoResultDiv.appendChild(manualCheckDiv);
- }
- }, pollingInterval);
- }
-
- // 手动检查视频状态函数
- function checkVideoStatus(videoId) {
- $.ajax({
- url: '/index.php/api/work_order/Getvideo_id',
- type: 'GET',
- dataType: 'json',
- data: {
- video_id: videoId
- },
- success: function(response) {
- if (response.code === 0 && response.data && response.data.web_url) {
- // 视频生成完成,直接显示结果
- const videoResultDiv = document.getElementById('videoResult');
- let videoUrl = response.data.web_url;
-
- // 确保web_url格式正确,添加根路径前缀
- if (videoUrl && !videoUrl.startsWith('/')) {
- videoUrl = '/' + videoUrl;
- }
-
- // 显示生成的视频
- videoResultDiv.innerHTML = `
- <div class="video-container">
- <video src="${videoUrl}" alt="生成的视频" class="generated-video" id="previewVideo" style="max-width: 100%; height: auto; max-height: 600px; cursor: pointer;" controls>
- 您的浏览器不支持视频播放
- </video>
- </div>
- `;
-
- // 更新视频信息到全局变量
- videoInfo = {
- video_id: response.data.video_id || videoId,
- web_url: videoUrl
- };
-
- // 启用下载按钮和保存模板按钮
- document.getElementById('downloadBtn').disabled = false;
- document.getElementById('saveBtn').disabled = false;
-
- // 添加视频放大模态框(如果还不存在)
- if (!document.getElementById('videoModal')) {
- const modal = document.createElement('div');
- modal.id = 'videoModal';
- modal.style.cssText = `
- display: none;
- position: fixed;
- z-index: 9999;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: auto;
- background-color: rgba(0, 0, 0, 0.9);
- justify-content: center;
- align-items: center;
- `;
- modal.style.display = 'flex';
- modal.style.display = 'none';
- const modalContent = document.createElement('video');
- modalContent.id = 'modalVideo';
- modalContent.style.cssText = `
- max-width: 90%;
- max-height: 90%;
- margin: auto;
- `;
- modalContent.setAttribute('controls', 'controls');
- const closeBtn = document.createElement('span');
- closeBtn.innerHTML = '×';
- closeBtn.style.cssText = `
- position: absolute;
- top: 20px;
- right: 35px;
- color: #f1f1f1;
- font-size: 40px;
- font-weight: bold;
- transition: 0.3s;
- cursor: pointer;
- `;
- closeBtn.onclick = function() {
- modal.style.display = 'none';
- };
- modal.appendChild(closeBtn);
- modal.appendChild(modalContent);
- document.body.appendChild(modal);
- // 点击模态框背景关闭
- modal.onclick = function(event) {
- if (event.target.id === 'videoModal') {
- this.style.display = 'none';
- }
- };
- }
- // 为生成的视频添加点击事件
- const generatedVideo = videoResultDiv.querySelector('.generated-video');
- generatedVideo.onclick = function() {
- const modal = document.getElementById('videoModal');
- const modalVideo = document.getElementById('modalVideo');
- modalVideo.src = this.src;
- modal.style.display = 'flex';
- };
- } else {
- // 视频仍在生成中或失败
- const videoResultDiv = document.getElementById('videoResult');
- if (response.code === 202) {
- const progress = response.data.progress || 0;
- const message = response.msg || response.data.message || '';
- videoResultDiv.innerHTML = `
- <div class="video-processing">
- <i class="fas fa-hourglass-half fa-spin"></i>
- <p>${message || '视频正在生成中...'}</p>
- <p style="font-size: 12px; margin-top: 10px; color: #999;">视频ID: ${videoId}</p>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">当前状态: ${response.data.status === 'queued' ? '排队中' : '处理中'}</p>
- <div class="progress-container" style="width: 100%; background-color: #eee; margin-top: 15px;">
- <div class="progress-bar" style="width: ${progress}%; height: 20px; background-color: #4CAF50;"></div>
- </div>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">请稍后再次手动检查</p>
- </div>
- `;
- } else {
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>视频生成失败:${response.msg || '未知错误'}</p>
- </div>
- `;
- }
- }
- },
- error: function(xhr, status, error) {
- // 网络错误
- const videoResultDiv = document.getElementById('videoResult');
- videoResultDiv.innerHTML = `
- <div class="video-error">
- <i class="fas fa-exclamation-triangle"></i>
- <p>检查视频状态失败:网络错误</p>
- <p style="font-size: 12px; margin-top: 5px; color: #999;">请稍后再次尝试</p>
- </div>
- `;
- }
- });
- }
-
- // 保存模板函数
- function saveTemplate() {
- // 获取模板名称
- const templateName = document.getElementById('templateName').value.trim();
- const textarea = document.getElementById('prompt');
- // 验证模板名称
- if (!templateName) {
- showAlert('模板名称不能为空');
- return;
- }
-
- // 检查是否有视频信息
- if (!videoInfo || !videoInfo.web_url) {
- showAlert('请先生成视频');
- return;
- }
-
- // 构建请求参数
- const params = {
- chinese_description: textarea.value.trim(),
- template_image_url: videoInfo.web_url,
- template_name: templateName,
- size: videoInfo.size,
- style: videoInfo.style,
- type: "文生视频",
- sys_id:"管理员",
- seconds: videoInfo.duration,
- video_id: videoInfo.video_id
- };
-
- // 发送请求保存模板
- $.ajax({
- url: '/index.php/api/work_order/Add_Product_Template',
- type: 'POST',
- dataType: 'json',
- data: params,
- success: function(response) {
- if (response.code === 0) {
- showAlert('模板保存成功');
- // 清空模板名称输入框
- document.getElementById('templateName').value = '';
- } else {
- showAlert('模板保存失败: ' + response.msg, 'error');
- }
- },
- error: function(xhr, status, error) {
- showAlert('保存模板时发生错误: ' + error, 'error');
- }
- });
- }
- // 下载视频函数
- function downloadVideo() {
- const previewVideo = document.getElementById('previewVideo');
- if (previewVideo && previewVideo.src) {
- // 创建临时链接下载视频
- const link = document.createElement('a');
- link.href = previewVideo.src;
- // 生成更有意义的文件名
- const timestamp = new Date().getTime();
- const promptText = document.getElementById('prompt').value.trim();
- // 从提示词中提取前20个字符作为文件名的一部分
- const promptPart = promptText.substring(0, 20).replace(/[^\w\u4e00-\u9fa5]/g, '') || 'video';
- // 组合文件名:提示词部分_时间戳.mp4
- const fileName = `${promptPart}_${timestamp}.mp4`;
- link.download = fileName;
- link.click();
- }
- }
- </script>
- </body>
- </html>
|