4 Commits

Author SHA1 Message Date
hzm
8fdbd2505b feat:重新上线登录测试版功能 2026-02-07 22:25:48 +08:00
hzm
1049719e3f feat:发布 0.1.1 紧急修复版本 2026-02-07 20:44:57 +08:00
hzm
6b5c69ee53 feat:临时关闭登录功能 2026-02-07 20:44:31 +08:00
hzm
8a62e7383d feat:完善版本更新检查逻辑 2026-02-07 16:03:33 +08:00
2 changed files with 65 additions and 21 deletions

View File

@@ -472,7 +472,7 @@ function Stat({ label, value, delta }) {
); );
} }
function FeedbackModal({ onClose }) { function FeedbackModal({ onClose, user }) {
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [succeeded, setSucceeded] = useState(false); const [succeeded, setSucceeded] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
@@ -563,7 +563,7 @@ function FeedbackModal({ onClose }) {
style={{ width: '100%' }} style={{ width: '100%' }}
/> />
</div> </div>
<input type="hidden" name="email" value={user?.email || ''} />
<div className="form-group" style={{ marginBottom: 20 }}> <div className="form-group" style={{ marginBottom: 20 }}>
<label htmlFor="message" className="muted" style={{ display: 'block', marginBottom: 8, fontSize: '14px' }}> <label htmlFor="message" className="muted" style={{ display: 'block', marginBottom: 8, fontSize: '14px' }}>
反馈内容 反馈内容
@@ -1232,7 +1232,7 @@ function CloudConfigModal({ onConfirm, onCancel, type = 'empty' }) {
</div> </div>
<p className="muted" style={{ marginBottom: 20, fontSize: '14px', lineHeight: '1.6' }}> <p className="muted" style={{ marginBottom: 20, fontSize: '14px', lineHeight: '1.6' }}>
{isConflict {isConflict
? '检测到本地配置云端更新,请选择操作:' ? '检测到本地配置云端不一致,请选择操作:'
: '是否将本地配置同步到云端?'} : '是否将本地配置同步到云端?'}
</p> </p>
<div className="row" style={{ flexDirection: 'column', gap: 12 }}> <div className="row" style={{ flexDirection: 'column', gap: 12 }}>
@@ -1856,12 +1856,12 @@ export default function HomePage() {
// 检查更新 // 检查更新
const [hasUpdate, setHasUpdate] = useState(false); const [hasUpdate, setHasUpdate] = useState(false);
const [latestVersion, setLatestVersion] = useState(''); const [latestVersion, setLatestVersion] = useState('');
const [updateContent, setUpdateContent] = useState('');
useEffect(() => { useEffect(() => {
const checkUpdate = async () => { const checkUpdate = async () => {
try { try {
const res = await fetch('https://api.github.com/repos/hzm0321/real-time-fund/releases/latest'); const res = await fetch('https://api.github.com/repos/hzm0321/real-time-fund/releases/latest');
console.log(packageJson.version)
if (!res.ok) return; if (!res.ok) return;
const data = await res.json(); const data = await res.json();
if (data.tag_name) { if (data.tag_name) {
@@ -1869,6 +1869,7 @@ export default function HomePage() {
if (remoteVersion !== packageJson.version) { if (remoteVersion !== packageJson.version) {
setHasUpdate(true); setHasUpdate(true);
setLatestVersion(remoteVersion); setLatestVersion(remoteVersion);
setUpdateContent(data.body || '');
} }
} }
} catch (e) { } catch (e) {
@@ -3224,7 +3225,6 @@ export default function HomePage() {
})) }))
: []; : [];
return { return {
version: 1,
funds, funds,
favorites: cleanedFavorites, favorites: cleanedFavorites,
groups: cleanedGroups, groups: cleanedGroups,
@@ -3235,7 +3235,6 @@ export default function HomePage() {
}; };
} catch { } catch {
return { return {
version: 1,
funds: [], funds: [],
favorites: [], favorites: [],
groups: [], groups: [],
@@ -3313,6 +3312,11 @@ export default function HomePage() {
return; return;
} }
if (data?.data && typeof data.data === 'object' && Object.keys(data.data).length > 0) { if (data?.data && typeof data.data === 'object' && Object.keys(data.data).length > 0) {
const localPayload = collectLocalPayload();
const localComparable = getComparablePayload(localPayload);
const cloudComparable = getComparablePayload(data.data);
if (localComparable !== cloudComparable) {
const cloudTime = new Date(data.updated_at || 0).getTime(); const cloudTime = new Date(data.updated_at || 0).getTime();
const localTime = new Date(localStorage.getItem('localUpdatedAt') || 0).getTime(); const localTime = new Date(localStorage.getItem('localUpdatedAt') || 0).getTime();
@@ -3320,6 +3324,7 @@ export default function HomePage() {
setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: data.data }); setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: data.data });
return; return;
} }
}
await applyCloudConfig(data.data, data.updated_at); await applyCloudConfig(data.data, data.updated_at);
return; return;
@@ -3366,13 +3371,11 @@ export default function HomePage() {
const exportLocalData = async () => { const exportLocalData = async () => {
try { try {
const payload = { const payload = {
version: 1,
funds: JSON.parse(localStorage.getItem('funds') || '[]'), funds: JSON.parse(localStorage.getItem('funds') || '[]'),
favorites: JSON.parse(localStorage.getItem('favorites') || '[]'), favorites: JSON.parse(localStorage.getItem('favorites') || '[]'),
groups: JSON.parse(localStorage.getItem('groups') || '[]'), groups: JSON.parse(localStorage.getItem('groups') || '[]'),
collapsedCodes: JSON.parse(localStorage.getItem('collapsedCodes') || '[]'), collapsedCodes: JSON.parse(localStorage.getItem('collapsedCodes') || '[]'),
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10), refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
viewMode,
holdings: JSON.parse(localStorage.getItem('holdings') || '{}'), holdings: JSON.parse(localStorage.getItem('holdings') || '{}'),
exportedAt: new Date().toISOString() exportedAt: new Date().toISOString()
}; };
@@ -3579,7 +3582,6 @@ export default function HomePage() {
<span>基估宝</span> <span>基估宝</span>
</div> </div>
<div className="actions"> <div className="actions">
<img alt="项目Github地址" src={githubImg.src} style={{ width: '30px', height: '30px', cursor: 'pointer' }} onClick={() => window.open("https://github.com/hzm0321/real-time-fund")} />
{hasUpdate && ( {hasUpdate && (
<div <div
className="badge" className="badge"
@@ -3590,6 +3592,7 @@ export default function HomePage() {
<UpdateIcon width="14" height="14" /> <UpdateIcon width="14" height="14" />
</div> </div>
)} )}
<img alt="项目Github地址" src={githubImg.src} style={{ width: '30px', height: '30px', cursor: 'pointer' }} onClick={() => window.open("https://github.com/hzm0321/real-time-fund")} />
<div className="badge" title="当前刷新频率"> <div className="badge" title="当前刷新频率">
<span>刷新</span> <span>刷新</span>
<strong>{Math.round(refreshMs / 1000)}</strong> <strong>{Math.round(refreshMs / 1000)}</strong>
@@ -3604,6 +3607,15 @@ export default function HomePage() {
> >
<RefreshIcon className={refreshing ? 'spin' : ''} width="18" height="18" /> <RefreshIcon className={refreshing ? 'spin' : ''} width="18" height="18" />
</button> </button>
{/*<button*/}
{/* className="icon-button"*/}
{/* aria-label="打开设置"*/}
{/* onClick={() => setSettingsOpen(true)}*/}
{/* title="设置"*/}
{/* hidden*/}
{/*>*/}
{/* <SettingsIcon width="18" height="18" />*/}
{/*</button>*/}
{/* 用户菜单 */} {/* 用户菜单 */}
<div className="user-menu-container" ref={userMenuRef}> <div className="user-menu-container" ref={userMenuRef}>
<button <button
@@ -4599,6 +4611,7 @@ export default function HomePage() {
<FeedbackModal <FeedbackModal
key={feedbackNonce} key={feedbackNonce}
onClose={() => setFeedbackOpen(false)} onClose={() => setFeedbackOpen(false)}
user={user}
/> />
)} )}
</AnimatePresence> </AnimatePresence>
@@ -4837,9 +4850,28 @@ export default function HomePage() {
<UpdateIcon width="20" height="20" style={{color: 'var(--success)'}} /> <UpdateIcon width="20" height="20" style={{color: 'var(--success)'}} />
<span>更新提示</span> <span>更新提示</span>
</div> </div>
<p className="muted" style={{ marginBottom: 24, fontSize: '14px', lineHeight: '1.6' }}> <div style={{ marginBottom: 24 }}>
检测到新版本是否刷新浏览器以更新 <p className="muted" style={{ fontSize: '14px', lineHeight: '1.6', marginBottom: 12 }}>
检测到新版本是否刷新浏览器以更新
<br/>
更新内容如下
</p> </p>
{updateContent && (
<div style={{
background: 'rgba(0,0,0,0.2)',
padding: '12px',
borderRadius: '8px',
fontSize: '13px',
lineHeight: '1.5',
maxHeight: '200px',
overflowY: 'auto',
whiteSpace: 'pre-wrap',
border: '1px solid rgba(255,255,255,0.1)'
}}>
{updateContent}
</div>
)}
</div>
<div className="row" style={{ gap: 12 }}> <div className="row" style={{ gap: 12 }}>
<button <button
className="button secondary" className="button secondary"
@@ -4884,6 +4916,18 @@ export default function HomePage() {
<form onSubmit={handleSendOtp}> <form onSubmit={handleSendOtp}>
<div className="form-group" style={{ marginBottom: 16 }}> <div className="form-group" style={{ marginBottom: 16 }}>
<div style={{
marginBottom: 12,
padding: '8px 12px',
background: 'rgba(230, 162, 60, 0.1)',
border: '1px solid rgba(230, 162, 60, 0.2)',
borderRadius: '4px',
fontSize: '0.8rem',
color: '#e6a23c',
lineHeight: '1.4'
}}>
登录功能目前正在测试使用过程中如遇到问题欢迎大家在 <a href="https://github.com/hzm0321/real-time-fund/issues" target="_blank" style={{ textDecoration: 'underline', color: 'inherit' }}>Github</a> 上反馈
</div>
<div className="muted" style={{ marginBottom: 8, fontSize: '0.8rem' }}> <div className="muted" style={{ marginBottom: 8, fontSize: '0.8rem' }}>
请输入邮箱我们将发送验证码到您的邮箱 请输入邮箱我们将发送验证码到您的邮箱
</div> </div>

View File

@@ -1,6 +1,6 @@
{ {
"name": "real-time-fund", "name": "real-time-fund",
"version": "0.1.0", "version": "0.1.2",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",