Merge branch 'main' of https://gitee.com/wg123/video-gen
This commit is contained in:
+117
-117
File diff suppressed because one or more lines are too long
Vendored
+35
-35
@@ -1,36 +1,36 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" id="favicon" />
|
||||
<script>
|
||||
// 立即从 localStorage 设置 favicon,避免闪烁
|
||||
(function() {
|
||||
try {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteLogo) {
|
||||
var link = document.getElementById('favicon');
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
})();
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script type="module" crossorigin src="/assets/index-CGl8RZCw.js"></script>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" id="favicon" />
|
||||
<script>
|
||||
// 立即从 localStorage 设置 favicon,避免闪烁
|
||||
(function() {
|
||||
try {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteLogo) {
|
||||
var link = document.getElementById('favicon');
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
})();
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script type="module" crossorigin src="/assets/index-8FIfOCqA.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DSYnuUvx.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -117,6 +117,7 @@ if (!res.ok) {
|
||||
// 检测"被踢出"错误 — 单设备登录互斥
|
||||
if (res.status === 401 && typeof parsed?.detail === 'string' && parsed.detail.includes('其他设备登录')) {
|
||||
window.dispatchEvent(new CustomEvent('kicked-out', { detail: { message: parsed.detail } }));
|
||||
throw new Error(parsed.detail); // 阻止后续自动跳转,由通知按钮处理
|
||||
}
|
||||
if (res.status === 401 && !options.skipAuthRedirect) {
|
||||
clearToken();
|
||||
|
||||
@@ -65,7 +65,6 @@ import { getMenuConfigs, getCreditProductCatalog, getPaymentMethods, createRecha
|
||||
import type { CreditProduct, CreditProductCatalog } from '../../types';
|
||||
import NotificationPopup from '../NotificationPopup';
|
||||
import ActivityBanner from './ActivityBanner';
|
||||
import KickedOutModal from '../KickedOutModal';
|
||||
import './AppLayout.css';
|
||||
|
||||
|
||||
@@ -530,7 +529,6 @@ const AppLayout: React.FC = () => {
|
||||
});
|
||||
const [siteInfoLoading, setSiteInfoLoading] = useState(!localStorage.getItem('siteInfo'));
|
||||
const [bannerVisible, setBannerVisible] = useState(false);
|
||||
const [kickedOutVisible, setKickedOutVisible] = useState(false);
|
||||
|
||||
// 资源存储容量(从 getUser().resource_capacity 获取)
|
||||
const [resourceCapacity, setResourceCapacity] = useState<{
|
||||
@@ -546,12 +544,15 @@ const AppLayout: React.FC = () => {
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const [operationManualUrl, setOperationManualUrl] = useState('');
|
||||
|
||||
// 监听"被踢出"事件 — 单设备登录互斥
|
||||
// 监听"被踢出"事件 — 单设备登录互斥,跳转登录页并带上标识
|
||||
useEffect(() => {
|
||||
const handler = () => setKickedOutVisible(true);
|
||||
window.addEventListener('kicked-out', handler);
|
||||
return () => window.removeEventListener('kicked-out', handler);
|
||||
}, []);
|
||||
const handleKickedOut = () => {
|
||||
localStorage.removeItem('token');
|
||||
navigate('/login?kicked_out=1');
|
||||
};
|
||||
window.addEventListener('kicked-out', handleKickedOut);
|
||||
return () => window.removeEventListener('kicked-out', handleKickedOut);
|
||||
}, [navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
getSiteInfo().then(info => {
|
||||
@@ -1123,7 +1124,6 @@ const AppLayout: React.FC = () => {
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<ActivityBanner onVisibilityChange={(v) => setBannerVisible(v)} />
|
||||
<KickedOutModal visible={kickedOutVisible} />
|
||||
<div style={{ display: 'flex', position: 'relative', padding: 4, gap: 12, flex: 1, minHeight: 0, overflow: 'hidden' }}>
|
||||
<div className="desktop-sidebar" style={{
|
||||
width: sidebarW, position: 'sticky', top: 4, alignSelf: 'flex-start', zIndex: 100,
|
||||
|
||||
@@ -74,6 +74,17 @@ const LoginPage: React.FC = () => {
|
||||
}
|
||||
}, [tabParam]);
|
||||
|
||||
// 单设备登录互斥 — 被踢出后显示提示
|
||||
useEffect(() => {
|
||||
if (searchParams.get('kicked_out') === '1') {
|
||||
message.warning('您的账号已在其他设备登录,请重新登录');
|
||||
// 清除参数,避免刷新重复提示
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.delete('kicked_out');
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
const goToRedirect = () => {
|
||||
if (redirect) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user