forked from 77media/video-flow
Merge branch 'zxx_dev' into dev
This commit is contained in:
commit
4680f2229a
@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Modal, Button, Spin, QRCode } from 'antd';
|
import { Modal, Button, Spin, QRCode, message } from 'antd';
|
||||||
import {
|
import {
|
||||||
Youtube,
|
Youtube,
|
||||||
Instagram,
|
Instagram,
|
||||||
@ -11,6 +11,7 @@ import {
|
|||||||
Loader2
|
Loader2
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { shareApiUrl } from '@/lib/env';
|
import { shareApiUrl } from '@/lib/env';
|
||||||
|
import { VideoShareForm } from './VideoShareForm';
|
||||||
|
|
||||||
interface ShareModalProps {
|
interface ShareModalProps {
|
||||||
/** 是否显示弹框 */
|
/** 是否显示弹框 */
|
||||||
@ -88,6 +89,42 @@ const sharePlatforms: SharePlatform[] = [
|
|||||||
|
|
||||||
export default function ShareModal({ visible, onClose, project }: ShareModalProps) {
|
export default function ShareModal({ visible, onClose, project }: ShareModalProps) {
|
||||||
const [loadingPlatform, setLoadingPlatform] = useState<string | null>(null);
|
const [loadingPlatform, setLoadingPlatform] = useState<string | null>(null);
|
||||||
|
const [showShareForm, setShowShareForm] = useState(false);
|
||||||
|
const [authError, setAuthError] = useState<string | null>(null);
|
||||||
|
const [selectedPlatform, setSelectedPlatform] = useState<string>('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听 URL 参数变化,处理授权回调
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible) return;
|
||||||
|
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const platform = urlParams.get('platform');
|
||||||
|
const status = urlParams.get('status');
|
||||||
|
const error = urlParams.get('error');
|
||||||
|
|
||||||
|
if (platform && status) {
|
||||||
|
// 统一转换成小写
|
||||||
|
const normalizedPlatform = platform.toLowerCase();
|
||||||
|
setSelectedPlatform(normalizedPlatform);
|
||||||
|
|
||||||
|
if (status === 'success') {
|
||||||
|
setAuthError(null);
|
||||||
|
setShowShareForm(true);
|
||||||
|
message.success(`${platform} 授权成功!`);
|
||||||
|
} else if (status === 'error') {
|
||||||
|
setAuthError(error || '授权失败,请重试');
|
||||||
|
setShowShareForm(true);
|
||||||
|
message.error(`${platform} 授权失败`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理 URL 参数
|
||||||
|
const newUrl = window.location.pathname;
|
||||||
|
window.history.replaceState({}, '', newUrl);
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户ID
|
* 获取用户ID
|
||||||
*/
|
*/
|
||||||
@ -99,11 +136,11 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
/**
|
/**
|
||||||
* 通用平台授权检查
|
* 通用平台授权检查
|
||||||
*/
|
*/
|
||||||
const checkPlatformAuth = async (apiPath: string, platformName: string) => {
|
const checkPlatformAuth = async (apiPath: string, platformName: string, platformId: string) => {
|
||||||
const userId = getUserId();
|
const userId = getUserId();
|
||||||
|
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
console.error('用户ID不存在,请先登录');
|
message.error('用户ID不存在,请先登录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,25 +148,29 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${localStorage.getItem('token') || ''}`
|
'Authorization': `Bearer ${localStorage.getItem('token') || ''}`,
|
||||||
|
'ngrok-skip-browser-warning': 'true'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.successful && data.code === 0) {
|
if (data.successful && data.code === 0) {
|
||||||
const { has_valid_token, auth_url, access_token } = data.data;
|
const { has_valid_token, auth_url } = data.data;
|
||||||
|
|
||||||
if (!has_valid_token) {
|
if (!has_valid_token) {
|
||||||
// 需要用户授权,跳转到授权页面
|
// 需要用户授权,跳转到授权页面
|
||||||
window.open(auth_url, '_blank');
|
window.open(auth_url, '_blank');
|
||||||
|
message.info('请在新窗口完成授权');
|
||||||
} else {
|
} else {
|
||||||
// 用户已授权,直接使用access_token进行第三方登录
|
// 用户已授权,直接显示上传表单
|
||||||
console.log(`${platformName}用户已授权,access_token:`, access_token);
|
setSelectedPlatform(platformId);
|
||||||
// TODO: 实现视频上传逻辑
|
setAuthError(null);
|
||||||
|
setShowShareForm(true);
|
||||||
|
message.success(`${platformName} 已授权,可以直接上传视频`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(`获取${platformName}授权信息失败:`, data.message);
|
message.error(data.message || `获取${platformName}授权信息失败`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -146,14 +187,15 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
if (platformId === 'copy') {
|
if (platformId === 'copy') {
|
||||||
await handleCopyLink();
|
await handleCopyLink();
|
||||||
} else if (platformId === 'instagram') {
|
} else if (platformId === 'instagram') {
|
||||||
alert('Instagram分享功能正在开发中,敬请期待!');
|
message.info('Instagram分享功能正在开发中,敬请期待!');
|
||||||
} else if (platform.apiPath) {
|
} else if (platform.apiPath) {
|
||||||
await checkPlatformAuth(platform.apiPath, platform.name);
|
await checkPlatformAuth(platform.apiPath, platform.name, platformId);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Share to ${platformId} not implemented yet`);
|
console.log(`Share to ${platformId} not implemented yet`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Share to ${platformId} failed:`, error);
|
console.error(`Share to ${platformId} failed:`, error);
|
||||||
|
message.error(`操作失败:${error instanceof Error ? error.message : '未知错误'}`);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingPlatform(null);
|
setLoadingPlatform(null);
|
||||||
}
|
}
|
||||||
@ -168,13 +210,13 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
const videoUrl = project.final_video_url || project.final_simple_video_url;
|
const videoUrl = project.final_video_url || project.final_simple_video_url;
|
||||||
if (videoUrl) {
|
if (videoUrl) {
|
||||||
await navigator.clipboard.writeText(videoUrl);
|
await navigator.clipboard.writeText(videoUrl);
|
||||||
console.log('视频链接已复制到剪贴板');
|
message.success('视频链接已复制到剪贴板');
|
||||||
// TODO: 显示复制成功提示
|
|
||||||
} else {
|
} else {
|
||||||
console.error('视频链接不存在');
|
message.error('视频链接不存在');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('复制链接失败:', error);
|
console.error('复制链接失败:', error);
|
||||||
|
message.error('复制链接失败,请手动复制');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,18 +225,44 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
return project.final_video_url || project.final_simple_video_url || '';
|
return project.final_video_url || project.final_simple_video_url || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频分享提交成功
|
||||||
|
*/
|
||||||
|
const handleVideoShare = (videoUrl: string, videoName: string) => {
|
||||||
|
// 上传成功后的处理
|
||||||
|
setShowShareForm(false);
|
||||||
|
setSelectedPlatform('');
|
||||||
|
setAuthError(null);
|
||||||
|
|
||||||
|
// 延迟关闭主对话框,让用户看到成功提示
|
||||||
|
setTimeout(() => {
|
||||||
|
onClose();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭分享表单
|
||||||
|
*/
|
||||||
|
const handleCancelShareForm = () => {
|
||||||
|
setShowShareForm(false);
|
||||||
|
setAuthError(null);
|
||||||
|
setSelectedPlatform('');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Share2 className="w-5 h-5 text-white" />
|
<Share2 className="w-5 h-5 text-white" />
|
||||||
<span className="text-white font-medium">Share Video</span>
|
<span className="text-white font-medium">
|
||||||
|
{showShareForm ? `分享到 ${selectedPlatform}` : 'Share Video'}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
open={visible}
|
open={visible}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
footer={null}
|
footer={null}
|
||||||
width={720}
|
width={showShareForm ? 500 : 720}
|
||||||
className="share-modal"
|
className="share-modal"
|
||||||
styles={{
|
styles={{
|
||||||
content: {
|
content: {
|
||||||
@ -212,6 +280,18 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{showShareForm ? (
|
||||||
|
/* 显示视频分享表单 */
|
||||||
|
<VideoShareForm
|
||||||
|
onCancel={handleCancelShareForm}
|
||||||
|
onShare={handleVideoShare}
|
||||||
|
error={authError}
|
||||||
|
platform={selectedPlatform}
|
||||||
|
videoUrl={getVideoUrl()}
|
||||||
|
videoName={project.name || ''}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
/* 显示平台选择界面 */
|
||||||
<div className="flex gap-6">
|
<div className="flex gap-6">
|
||||||
{/* 左侧:二维码区域 */}
|
{/* 左侧:二维码区域 */}
|
||||||
<div className="flex-1 flex flex-col items-center justify-center space-y-4">
|
<div className="flex-1 flex flex-col items-center justify-center space-y-4">
|
||||||
@ -265,7 +345,7 @@ export default function ShareModal({ visible, onClose, project }: ShareModalProp
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,154 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { AlertCircle, Loader2 } from 'lucide-react';
|
||||||
|
import { shareApiUrl } from '@/lib/env';
|
||||||
|
import { message } from 'antd';
|
||||||
|
|
||||||
export const VideoShareForm: React.FC<{ onCancel: () => void; onShare: (videoUrl: string, videoName: string) => void }> = ({ onCancel, onShare }) => {
|
interface VideoShareFormProps {
|
||||||
const [videoUrl, setVideoUrl] = useState('');
|
onCancel: () => void;
|
||||||
const [videoName, setVideoName] = useState('');
|
onShare: (videoUrl: string, videoName: string) => void;
|
||||||
|
error?: string | null;
|
||||||
|
platform?: string;
|
||||||
|
videoUrl?: string;
|
||||||
|
videoName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const handleShare = () => {
|
// 平台上传接口映射(统一使用小写 key)
|
||||||
|
const PLATFORM_UPLOAD_API: Record<string, string> = {
|
||||||
|
'youtube': '/api/video-share/youtube/upload',
|
||||||
|
'tiktok': '/api/video-share/tiktok/upload',
|
||||||
|
'reddit': '/api/video-share/reddit/upload',
|
||||||
|
'twitter': '/api/video-share/x/upload',
|
||||||
|
// Instagram 开发中,暂不支持
|
||||||
|
// 'instagram': '/api/video-share/instagram/upload',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VideoShareForm: React.FC<VideoShareFormProps> = ({
|
||||||
|
onCancel,
|
||||||
|
onShare,
|
||||||
|
error = null,
|
||||||
|
platform = '',
|
||||||
|
videoUrl: initialVideoUrl = '',
|
||||||
|
videoName: initialVideoName = ''
|
||||||
|
}) => {
|
||||||
|
const [videoUrl, setVideoUrl] = useState(initialVideoUrl);
|
||||||
|
const [videoName, setVideoName] = useState(initialVideoName);
|
||||||
|
const [uploading, setUploading] = useState(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户ID
|
||||||
|
*/
|
||||||
|
const getUserId = () => {
|
||||||
|
const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}');
|
||||||
|
return currentUser.id || currentUser.userId;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传视频到指定平台
|
||||||
|
*/
|
||||||
|
const uploadVideoToPlatform = async (platformName: string, contentUrl: string, title: string) => {
|
||||||
|
const userId = getUserId();
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
message.error('用户ID不存在,请先登录');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一转换成小写后查找 API 路径
|
||||||
|
const normalizedPlatform = platformName.toLowerCase().replace(/\s+/g, '').replace(/[()]/g, '');
|
||||||
|
const apiPath = PLATFORM_UPLOAD_API[normalizedPlatform];
|
||||||
|
if (!apiPath) {
|
||||||
|
message.error(`平台 ${platformName} 暂不支持或正在开发中`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${shareApiUrl}${apiPath}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('token') || ''}`,
|
||||||
|
'ngrok-skip-browser-warning': 'true'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
user_id: userId,
|
||||||
|
content_url: contentUrl,
|
||||||
|
title: title
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.successful && data.code === 0) {
|
||||||
|
message.success(`视频已成功上传到 ${platformName}!`);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
message.error(data.message || `上传到 ${platformName} 失败`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`上传到 ${platformName} 失败:`, error);
|
||||||
|
message.error(`上传失败:${error instanceof Error ? error.message : '网络错误'}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleShare = async () => {
|
||||||
|
if (!videoUrl || !videoName) {
|
||||||
|
message.warning('请填写完整的视频信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUploading(true);
|
||||||
|
try {
|
||||||
|
const success = await uploadVideoToPlatform(platform, videoUrl, videoName);
|
||||||
|
if (success) {
|
||||||
onShare(videoUrl, videoName);
|
onShare(videoUrl, videoName);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setUploading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-alt="video-share-form-container" className="backdrop-blur-lg bg-white/30 dark:bg-slate-900/30 rounded-lg p-6 shadow-lg">
|
<div data-alt="video-share-form-container" className="backdrop-blur-lg bg-white/10 dark:bg-slate-900/30 rounded-lg p-6 shadow-lg">
|
||||||
<h2 data-alt="form-title" className="text-2xl font-bold mb-4 text-slate-800 dark:text-slate-200">转发视频</h2>
|
<h2 data-alt="form-title" className="text-2xl font-bold mb-4 text-white">
|
||||||
|
转发视频{platform && ` - ${platform}`}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{/* 错误信息显示 */}
|
||||||
|
{error && (
|
||||||
|
<div className="mb-4 p-3 bg-red-500/20 border border-red-500/50 rounded-lg flex items-start gap-2">
|
||||||
|
<AlertCircle className="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5" />
|
||||||
|
<div className="flex-1">
|
||||||
|
<p className="text-red-200 text-sm font-medium">授权失败</p>
|
||||||
|
<p className="text-red-300 text-xs mt-1">{error}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div data-alt="form-fields" className="space-y-4">
|
<div data-alt="form-fields" className="space-y-4">
|
||||||
<div data-alt="video-url-field" className="flex flex-col gap-2">
|
<div data-alt="video-url-field" className="flex flex-col gap-2">
|
||||||
<label htmlFor="videoUrl" className="text-sm font-medium text-slate-700 dark:text-slate-300">视频链接</label>
|
<label htmlFor="videoUrl" className="text-sm font-medium text-white/90">视频链接</label>
|
||||||
<Input
|
<Input
|
||||||
id="videoUrl"
|
id="videoUrl"
|
||||||
value={videoUrl}
|
value={videoUrl}
|
||||||
onChange={(e) => setVideoUrl(e.target.value)}
|
onChange={(e) => setVideoUrl(e.target.value)}
|
||||||
placeholder="请输入视频链接"
|
placeholder="请输入视频链接"
|
||||||
className="bg-white/50 dark:bg-slate-800/50 border-slate-300 dark:border-slate-700 text-slate-900 dark:text-slate-100"
|
className="bg-white/10 border-white/20 text-white placeholder:text-white/50"
|
||||||
|
disabled={!!error}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div data-alt="video-name-field" className="flex flex-col gap-2">
|
<div data-alt="video-name-field" className="flex flex-col gap-2">
|
||||||
<label htmlFor="videoName" className="text-sm font-medium text-slate-700 dark:text-slate-300">视频名称</label>
|
<label htmlFor="videoName" className="text-sm font-medium text-white/90">视频名称</label>
|
||||||
<Input
|
<Input
|
||||||
id="videoName"
|
id="videoName"
|
||||||
value={videoName}
|
value={videoName}
|
||||||
onChange={(e) => setVideoName(e.target.value)}
|
onChange={(e) => setVideoName(e.target.value)}
|
||||||
placeholder="请输入视频名称"
|
placeholder="请输入视频名称"
|
||||||
className="bg-white/50 dark:bg-slate-800/50 border-slate-300 dark:border-slate-700 text-slate-900 dark:text-slate-100"
|
className="bg-white/10 border-white/20 text-white placeholder:text-white/50"
|
||||||
|
disabled={!!error}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -40,17 +157,38 @@ export const VideoShareForm: React.FC<{ onCancel: () => void; onShare: (videoUrl
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={onCancel}
|
onClick={onCancel}
|
||||||
data-alt="cancel-button"
|
data-alt="cancel-button"
|
||||||
className="border-slate-400 dark:border-slate-600 text-slate-800 dark:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800"
|
className="border-white/30 text-white hover:bg-white/10"
|
||||||
|
disabled={uploading}
|
||||||
>
|
>
|
||||||
取消
|
{error ? '关闭' : '取消'}
|
||||||
</Button>
|
</Button>
|
||||||
|
{!error && (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleShare}
|
onClick={handleShare}
|
||||||
data-alt="share-button"
|
data-alt="share-button"
|
||||||
className="bg-blue-500 hover:bg-blue-600 text-white"
|
className="
|
||||||
|
relative overflow-hidden
|
||||||
|
bg-gradient-to-r from-[#6AF4F9] to-[#C039F6]
|
||||||
|
hover:from-[#5ee3e8] hover:to-[#b028e5]
|
||||||
|
text-white font-medium
|
||||||
|
shadow-lg shadow-purple-500/30
|
||||||
|
hover:shadow-xl hover:shadow-purple-500/50
|
||||||
|
transition-all duration-300
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed
|
||||||
|
disabled:shadow-none
|
||||||
|
"
|
||||||
|
disabled={!videoUrl || !videoName || uploading}
|
||||||
>
|
>
|
||||||
一键转发
|
{uploading ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||||
|
上传中...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
'一键转发'
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -375,7 +375,7 @@ export default function CreateToVideo2() {
|
|||||||
{(project.final_video_url || project.final_simple_video_url) && (
|
{(project.final_video_url || project.final_simple_video_url) && (
|
||||||
<div className="absolute top-1 right-1 flex items-center gap-1">
|
<div className="absolute top-1 right-1 flex items-center gap-1">
|
||||||
{/* 转发按钮 */}
|
{/* 转发按钮 */}
|
||||||
{/* <Tooltip placement="top" title="Share">
|
<Tooltip placement="top" title="Share">
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="text"
|
type="text"
|
||||||
@ -384,7 +384,7 @@ export default function CreateToVideo2() {
|
|||||||
>
|
>
|
||||||
<Send className="w-4 h-4 text-white" />
|
<Send className="w-4 h-4 text-white" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip> */}
|
</Tooltip>
|
||||||
{/* 下载按钮 */}
|
{/* 下载按钮 */}
|
||||||
<Tooltip placement="top" title="Download">
|
<Tooltip placement="top" title="Download">
|
||||||
<Button size="small" type="text" disabled={isLoadingDownloadBtn} className="w-[2.5rem] h-[2.5rem] rounded-full items-center justify-center p-0 hidden group-hover:flex transition-all duration-300 hover:bg-white/15" onClick={(e) => handleDownloadClick(e, project)}>
|
<Button size="small" type="text" disabled={isLoadingDownloadBtn} className="w-[2.5rem] h-[2.5rem] rounded-full items-center justify-center p-0 hidden group-hover:flex transition-all duration-300 hover:bg-white/15" onClick={(e) => handleDownloadClick(e, project)}>
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export const getEnvConfig = (): EnvConfig => {
|
|||||||
javaUrl: process.env.NEXT_PUBLIC_JAVA_URL || 'https://77.app.java.auth.qikongjian.com',
|
javaUrl: process.env.NEXT_PUBLIC_JAVA_URL || 'https://77.app.java.auth.qikongjian.com',
|
||||||
cutUrl: process.env.NEXT_PUBLIC_CUT_URL || 'https://smartcut.api.movieflow.ai',
|
cutUrl: process.env.NEXT_PUBLIC_CUT_URL || 'https://smartcut.api.movieflow.ai',
|
||||||
cutUrlTo: process.env.NEXT_PUBLIC_CUT_URL_TO || 'https://smartcut.api.movieflow.ai',
|
cutUrlTo: process.env.NEXT_PUBLIC_CUT_URL_TO || 'https://smartcut.api.movieflow.ai',
|
||||||
shareApiUrl: process.env.NEXT_PUBLIC_SHARE_API_URL || 'http://39.97.48.225:8000',
|
shareApiUrl: process.env.NEXT_PUBLIC_SHARE_API_URL || 'https://nebuly-tish-metapsychological.ngrok-free.dev',
|
||||||
|
|
||||||
// Google OAuth 配置
|
// Google OAuth 配置
|
||||||
googleClientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '847079918888-o1nne8d3ij80dn20qurivo987pv07225.apps.googleusercontent.com',
|
googleClientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '847079918888-o1nne8d3ij80dn20qurivo987pv07225.apps.googleusercontent.com',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user