| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- <!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/text_to_image')}">
- <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>
- <input type="text" value="{$user.id}" id="user_id" disabled style="display: none">
- <!-- 提示词示例 -->
- <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');
- const user_id = document.getElementById('user_id');
- // 验证模板名称
- 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: "文生视频",
- user_id:user_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>
|