@@ -1007,31 +1007,40 @@ export default function PcFundTable({
|
|||||||
--row-bg: var(--bg);
|
--row-bg: var(--bg);
|
||||||
background-color: var(--row-bg) !important;
|
background-color: var(--row-bg) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 斑马纹行背景(非 hover 状态) */
|
|
||||||
.table-row-scroll:nth-child(even),
|
.table-row-scroll:nth-child(even),
|
||||||
.table-row-scroll.row-even {
|
.table-row-scroll.row-even {
|
||||||
background-color: var(--table-row-alt-bg) !important;
|
background-color: var(--table-row-alt-bg) !important;
|
||||||
}
|
}
|
||||||
|
.table-row-scroll:hover {
|
||||||
|
--row-bg: var(--table-row-hover-bg);
|
||||||
|
background-color: var(--row-bg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pinned cells 继承所在行的背景(非 hover 状态) */
|
/* Pinned cells inherit from parent row */
|
||||||
.table-row-scroll .pinned-cell {
|
.table-row-scroll .pinned-cell {
|
||||||
background-color: var(--row-bg) !important;
|
background-color: var(--row-bg) !important;
|
||||||
}
|
}
|
||||||
.table-row-scroll:nth-child(even) .pinned-cell,
|
.table-row-scroll:nth-child(even) .pinned-cell,
|
||||||
.table-row-scroll.row-even .pinned-cell,
|
.table-row-scroll.row-even .pinned-cell {
|
||||||
|
background-color: var(--table-row-alt-bg) !important;
|
||||||
|
}
|
||||||
|
.table-row-scroll:hover .pinned-cell {
|
||||||
|
background-color: var(--table-row-hover-bg) !important;
|
||||||
|
}
|
||||||
|
.table-row-scroll:nth-child(even) {
|
||||||
|
background-color: var(--table-row-alt-bg);
|
||||||
|
}
|
||||||
|
.table-row-scroll:hover {
|
||||||
|
--row-bg: var(--table-row-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pinned cells in even rows */
|
||||||
.row-even .pinned-cell {
|
.row-even .pinned-cell {
|
||||||
background-color: var(--table-row-alt-bg) !important;
|
background-color: var(--table-row-alt-bg) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hover 状态优先级最高,覆盖斑马纹和 pinned 背景 */
|
/* Pinned cells on hover */
|
||||||
.table-row-scroll:hover,
|
.table-row-scroll:hover .pinned-cell {
|
||||||
.table-row-scroll.row-even:hover {
|
|
||||||
--row-bg: var(--table-row-hover-bg);
|
|
||||||
background-color: var(--table-row-hover-bg) !important;
|
|
||||||
}
|
|
||||||
.table-row-scroll:hover .pinned-cell,
|
|
||||||
.table-row-scroll.row-even:hover .pinned-cell {
|
|
||||||
background-color: var(--table-row-hover-bg) !important;
|
background-color: var(--table-row-hover-bg) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
57
app/page.jsx
57
app/page.jsx
@@ -3109,6 +3109,25 @@ export default function HomePage() {
|
|||||||
if (nextFunds.length) {
|
if (nextFunds.length) {
|
||||||
const codes = Array.from(new Set(nextFunds.map((f) => f.code)));
|
const codes = Array.from(new Set(nextFunds.map((f) => f.code)));
|
||||||
if (codes.length) await refreshAll(codes);
|
if (codes.length) await refreshAll(codes);
|
||||||
|
// 刷新完成后,强制同步本地localStorage 的 funds 数据到云端
|
||||||
|
const currentUserId = userIdRef.current || user?.id;
|
||||||
|
if (currentUserId) {
|
||||||
|
try {
|
||||||
|
const latestFunds = JSON.parse(localStorage.getItem('funds') || '[]');
|
||||||
|
const localSig = getFundCodesSignature(latestFunds, ['gztime']);
|
||||||
|
const cloudSig = getFundCodesSignature(Array.isArray(cloudData.funds) ? cloudData.funds : [], ['gztime']);
|
||||||
|
if (localSig !== cloudSig) {
|
||||||
|
await syncUserConfig(
|
||||||
|
currentUserId,
|
||||||
|
false,
|
||||||
|
{ funds: Array.isArray(latestFunds) ? latestFunds : [] },
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('刷新后强制同步 funds 到云端失败', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = collectLocalPayload();
|
const payload = collectLocalPayload();
|
||||||
@@ -3121,10 +3140,9 @@ export default function HomePage() {
|
|||||||
const fetchCloudConfig = async (userId, checkConflict = false) => {
|
const fetchCloudConfig = async (userId, checkConflict = false) => {
|
||||||
if (!userId) return;
|
if (!userId) return;
|
||||||
try {
|
try {
|
||||||
// 一次查询同时拿到 meta 与 data,方便两种模式复用
|
|
||||||
const { data: meta, error: metaError } = await supabase
|
const { data: meta, error: metaError } = await supabase
|
||||||
.from('user_configs')
|
.from('user_configs')
|
||||||
.select('id, data, updated_at')
|
.select(`id, updated_at${checkConflict ? ', data' : ''}`)
|
||||||
.eq('user_id', userId)
|
.eq('user_id', userId)
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
@@ -3138,19 +3156,44 @@ export default function HomePage() {
|
|||||||
setCloudConfigModal({ open: true, userId, type: 'empty' });
|
setCloudConfigModal({ open: true, userId, type: 'empty' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 冲突检查模式:使用 meta.data 弹出冲突确认弹窗
|
|
||||||
if (checkConflict) {
|
if (checkConflict) {
|
||||||
setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: meta.data });
|
setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: meta.data });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 非冲突检查模式:直接复用上方查询到的 meta 数据,覆盖本地
|
const localUpdatedAt = window.localStorage.getItem('localUpdatedAt');
|
||||||
if (meta.data && isPlainObject(meta.data) && Object.keys(meta.data).length > 0) {
|
if (localUpdatedAt && meta.updated_at && new Date(meta.updated_at) < new Date(localUpdatedAt)) {
|
||||||
await applyCloudConfig(meta.data, meta.updated_at);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('user_configs')
|
||||||
|
.select('id, data, updated_at')
|
||||||
|
.eq('user_id', userId)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
if (data?.data && isPlainObject(data.data) && Object.keys(data.data).length > 0) {
|
||||||
|
const localPayload = collectLocalPayload();
|
||||||
|
const localComparable = getComparablePayload(localPayload);
|
||||||
|
const cloudComparable = getComparablePayload(data.data);
|
||||||
|
|
||||||
|
if (localComparable !== cloudComparable) {
|
||||||
|
// 如果数据不一致
|
||||||
|
if (checkConflict) {
|
||||||
|
// 只有明确要求检查冲突时才提示(例如刚登录时)
|
||||||
|
setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: data.data });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 否则直接覆盖本地(例如已登录状态下的刷新)
|
||||||
|
await applyCloudConfig(data.data, data.updated_at);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await applyCloudConfig(data.data, data.updated_at);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setCloudConfigModal({ open: true, userId, type: 'empty' });
|
setCloudConfigModal({ open: true, userId, type: 'empty' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('获取云端配置失败', e);
|
console.error('获取云端配置失败', e);
|
||||||
|
|||||||
Reference in New Issue
Block a user