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
-613
File diff suppressed because one or more lines are too long
Vendored
+1
-3
@@ -28,12 +28,10 @@
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script type="module" crossorigin src="/assets/index-CnKJ4EKg.js"></script>
|
||||
|
||||
<script type="module" crossorigin src="/assets/index-C4uOdbc7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Bsz_Xon-.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Generated
+82
@@ -17,6 +17,7 @@
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-quill-new": "^3.8.3",
|
||||
"react-router-dom": "^7.15.0",
|
||||
"three": "^0.184.0",
|
||||
"uuid": "^14.0.0",
|
||||
@@ -2826,6 +2827,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
|
||||
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -2833,6 +2840,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-diff": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
@@ -3615,6 +3628,25 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.18.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
|
||||
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@@ -3822,6 +3854,12 @@
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parchment": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
|
||||
"integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -4138,6 +4176,35 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/quill": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz",
|
||||
"integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^5.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"parchment": "^3.0.0",
|
||||
"quill-delta": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=8.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-delta": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
|
||||
"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-diff": "^1.3.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rangetouch": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz",
|
||||
@@ -4189,6 +4256,21 @@
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-quill-new": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/react-quill-new/-/react-quill-new-3.8.3.tgz",
|
||||
"integrity": "sha512-c96PYqFTo0pI4R3e79B3rH9LUIce1kIQbmTBu/imJQZk8305ogyLyBqKKjG2UoInDlquXqePSzmBo2aVia3ttw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21",
|
||||
"quill": "~2.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"quill-delta": "^5.1.0",
|
||||
"react": "^16 || ^17 || ^18 || ^19",
|
||||
"react-dom": "^16 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.15.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.0.tgz",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-quill-new": "^3.8.3",
|
||||
"react-router-dom": "^7.15.0",
|
||||
"three": "^0.184.0",
|
||||
"uuid": "^14.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Tag, Button } from 'antd';
|
||||
import { BellOutlined, ThunderboltOutlined, GiftOutlined, StarOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { BellOutlined, ThunderboltOutlined, GiftOutlined, StarOutlined, CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { getNotifications, markNotificationRead } from '../api';
|
||||
import { useAuthStore } from '../store/useAuthStore';
|
||||
|
||||
@@ -105,94 +105,61 @@ const NotificationPopup: React.FC = () => {
|
||||
background: 'rgba(0,0,0,0.45)', backdropFilter: 'blur(6px)',
|
||||
}} onClick={handleClose}>
|
||||
<div onClick={e => e.stopPropagation()} style={{
|
||||
width: 420,
|
||||
borderRadius: 24,
|
||||
width: 520,
|
||||
borderRadius: 24,
|
||||
overflow: 'hidden',
|
||||
boxShadow: '0 25px 80px rgba(0,0,0,0.15)',
|
||||
boxShadow: '0 30px 100px rgba(0,0,0,0.2)',
|
||||
animation: 'notificationPop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1)',
|
||||
background: '#ffffff',
|
||||
}}>
|
||||
{/* Header */}
|
||||
<div style={{
|
||||
background: tc.gradient,
|
||||
padding: '24px 28px 20px',
|
||||
position: 'relative',
|
||||
padding: '16px 28px 14px',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
right: -50,
|
||||
top: -50,
|
||||
width: 200,
|
||||
height: 200,
|
||||
borderRadius: '50%',
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
right: -50,
|
||||
top: -50,
|
||||
width: 200,
|
||||
height: 200,
|
||||
borderRadius: '50%',
|
||||
background: 'radial-gradient(circle, rgba(255,255,255,0.15) 0%, transparent 60%)',
|
||||
filter: 'blur(30px)',
|
||||
}} />
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
right: 30,
|
||||
top: 10,
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: '50%',
|
||||
background: 'rgba(255,255,255,0.06)',
|
||||
filter: 'blur(15px)',
|
||||
}} />
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', position: 'relative' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<div style={{
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 14,
|
||||
background: 'rgba(255,255,255,0.15)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: 20,
|
||||
color: '#fff',
|
||||
}}>{tc.icon}</div>
|
||||
<div>
|
||||
<div style={{
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12,
|
||||
marginBottom: 4,
|
||||
fontWeight: 500,
|
||||
}}>新消息通知</div>
|
||||
<div style={{
|
||||
color: '#fff',
|
||||
fontSize: 28,
|
||||
fontWeight: 700,
|
||||
letterSpacing: '-1px',
|
||||
}}>{current.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleClose}
|
||||
{/* Top row: type badge + close */}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
|
||||
<Tag style={{ background: 'rgba(255,255,255,0.2)', border: 'none', color: '#fff', borderRadius: 6, padding: '2px 10px', fontSize: 11, fontWeight: 500 }}>
|
||||
{tc.icon} {tc.label}
|
||||
</Tag>
|
||||
<button
|
||||
onClick={handleClose}
|
||||
style={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
borderRadius: '50%',
|
||||
background: 'rgba(255,255,255,0.1)',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
transition: 'all 0.2s ease',
|
||||
outline: 'none',
|
||||
}}
|
||||
onMouseEnter={e => {
|
||||
e.currentTarget.style.background = 'rgba(255,255,255,0.2)';
|
||||
}}
|
||||
onMouseLeave={e => {
|
||||
e.currentTarget.style.background = 'rgba(255,255,255,0.1)';
|
||||
width: 28, height: 28, borderRadius: '50%',
|
||||
background: 'rgba(255,255,255,0.1)',
|
||||
border: 'none', cursor: 'pointer',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
transition: 'all 0.2s ease', outline: 'none',
|
||||
}}
|
||||
onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.2)'; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.1)'; }}
|
||||
>
|
||||
<CloseOutlined style={{ color: '#fff', fontSize: 14 }} />
|
||||
<CloseOutlined style={{ color: '#fff', fontSize: 12 }} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Title + time row */}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12 }}>
|
||||
<div style={{ color: '#fff', fontSize: 22, fontWeight: 700, letterSpacing: '-0.5px' }}>
|
||||
{current.title}
|
||||
</div>
|
||||
<div style={{ color: 'rgba(255,255,255,0.6)', fontSize: 11, whiteSpace: 'nowrap', flexShrink: 0 }}>
|
||||
{current.createdAt ? new Date(current.createdAt).toLocaleString('zh-CN') : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
@@ -201,48 +168,67 @@ const NotificationPopup: React.FC = () => {
|
||||
padding: '24px 28px 28px',
|
||||
}}>
|
||||
<div style={{
|
||||
padding: '18px 20px',
|
||||
background: '#f8fafc',
|
||||
padding: '18px 20px',
|
||||
background: '#f8fafc',
|
||||
borderRadius: 16,
|
||||
marginBottom: 20,
|
||||
marginBottom: 20,
|
||||
border: '1px solid #f1f5f9',
|
||||
}}>
|
||||
<div style={{
|
||||
fontSize: 14,
|
||||
color: '#475569',
|
||||
<div style={{
|
||||
fontSize: 14,
|
||||
color: '#475569',
|
||||
lineHeight: 1.7,
|
||||
}}>
|
||||
{current.content}
|
||||
</div>
|
||||
}} dangerouslySetInnerHTML={{ __html: current.content }} />
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
{/* Left: navigation with left/right buttons */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<Tag
|
||||
color={tc.gradient.includes('#6366f1') ? '#6366f1' : tc.gradient.includes('#f59e0b') ? '#f59e0b' : '#8b5cf6'}
|
||||
style={{
|
||||
borderRadius: 6,
|
||||
border: 'none',
|
||||
padding: '3px 10px',
|
||||
fontSize: 11,
|
||||
fontWeight: 500,
|
||||
background: '#f1f5f9',
|
||||
color: '#64748b',
|
||||
}}
|
||||
>
|
||||
{tc.label}
|
||||
</Tag>
|
||||
{notifications.length > 1 && (
|
||||
<>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); setCurrentIndex(currentIndex > 0 ? currentIndex - 1 : notifications.length - 1); }}
|
||||
style={{
|
||||
width: 30, height: 30, borderRadius: '50%',
|
||||
background: '#f1f5f9', border: 'none', cursor: 'pointer',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
transition: 'all 0.2s', outline: 'none',
|
||||
}}
|
||||
onMouseEnter={e => { e.currentTarget.style.background = '#e2e8f0'; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.background = '#f1f5f9'; }}
|
||||
>
|
||||
<LeftOutlined style={{ color: '#64748b', fontSize: 12 }} />
|
||||
</button>
|
||||
<span style={{ fontSize: 12, color: '#64748b', fontWeight: 500, minWidth: 36, textAlign: 'center' }}>
|
||||
{currentIndex + 1}/{notifications.length}
|
||||
</span>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); setCurrentIndex(currentIndex < notifications.length - 1 ? currentIndex + 1 : 0); }}
|
||||
style={{
|
||||
width: 30, height: 30, borderRadius: '50%',
|
||||
background: '#f1f5f9', border: 'none', cursor: 'pointer',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
transition: 'all 0.2s', outline: 'none',
|
||||
}}
|
||||
onMouseEnter={e => { e.currentTarget.style.background = '#e2e8f0'; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.background = '#f1f5f9'; }}
|
||||
>
|
||||
<RightOutlined style={{ color: '#64748b', fontSize: 12 }} />
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleAcknowledge}
|
||||
{/* Right: acknowledge button */}
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleAcknowledge}
|
||||
style={{
|
||||
borderRadius: 12,
|
||||
fontWeight: 600,
|
||||
borderRadius: 12,
|
||||
fontWeight: 600,
|
||||
height: 40,
|
||||
background: tc.gradient,
|
||||
background: tc.gradient,
|
||||
border: 'none',
|
||||
paddingLeft: 28,
|
||||
paddingLeft: 28,
|
||||
paddingRight: 28,
|
||||
boxShadow: `0 6px 16px ${tc.glowColor}`,
|
||||
transition: 'all 0.2s ease',
|
||||
@@ -261,28 +247,6 @@ const NotificationPopup: React.FC = () => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{notifications.length > 1 && (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: 6, marginTop: 20 }}>
|
||||
{notifications.map((_, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setCurrentIndex(i)}
|
||||
style={{
|
||||
width: i === currentIndex ? 20 : 5,
|
||||
height: 5,
|
||||
borderRadius: 3,
|
||||
background: i === currentIndex
|
||||
? (tc.gradient.includes('#6366f1') ? '#6366f1' : tc.gradient.includes('#f59e0b') ? '#f59e0b' : '#8b5cf6')
|
||||
: '#e2e8f0',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.3s ease',
|
||||
outline: 'none',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<style>{`
|
||||
|
||||
@@ -81,6 +81,7 @@ const MessagesPage: React.FC = () => {
|
||||
dataIndex: 'content',
|
||||
key: 'content',
|
||||
ellipsis: true,
|
||||
render: (v: string) => <div style={{ maxWidth: 300 }} dangerouslySetInnerHTML={{ __html: v }} />,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
|
||||
Reference in New Issue
Block a user