fix(client): migrate digital storage keys

This commit is contained in:
baiyanyun
2026-06-07 18:21:24 +08:00
parent fa5522e32e
commit 09d65701a3
11 changed files with 64 additions and 46 deletions

View File

@@ -7,8 +7,10 @@
<script>
window.__QIMINGCLAW_EMBEDDED_DIGITAL__ = true;
try {
window.localStorage.setItem("zeroclaw_token", "qimingclaw_embedded_digital_employee");
window.sessionStorage.setItem("sgrobot_logged_in", "1");
window.localStorage.setItem("qimingclaw_digital_token", "qimingclaw_embedded_digital_employee");
window.localStorage.removeItem("zeroclaw_token");
window.sessionStorage.setItem("qimingclaw_digital_logged_in", "1");
window.sessionStorage.removeItem("sgrobot_logged_in");
} catch (error) {
console.warn("[qimingclaw] digital employee auth bootstrap skipped", error);
}

View File

@@ -122,11 +122,12 @@ interface RoleContextValue {
const RoleContext = createContext<RoleContextValue | null>(null);
const STORAGE_KEY = 'sgrobot-console-role';
const STORAGE_KEY = 'qimingclaw:digital-console-role';
const LEGACY_STORAGE_KEY = 'sgrobot-console-role';
function getStoredRole(): ConsoleRole {
try {
const stored = localStorage.getItem(STORAGE_KEY);
const stored = localStorage.getItem(STORAGE_KEY) ?? localStorage.getItem(LEGACY_STORAGE_KEY);
if (stored && stored in ROLE_PROFILES) return stored as ConsoleRole;
} catch { /* localStorage blocked */ }
return 'sales';
@@ -137,7 +138,10 @@ export function RoleProvider({ children }: { children: ReactNode }) {
const setRole = useCallback((newRole: ConsoleRole) => {
setRoleState(newRole);
try { localStorage.setItem(STORAGE_KEY, newRole); } catch { /* noop */ }
try {
localStorage.setItem(STORAGE_KEY, newRole);
localStorage.removeItem(LEGACY_STORAGE_KEY);
} catch { /* noop */ }
}, []);
const profile = ROLE_PROFILES[role];

View File

@@ -111,7 +111,7 @@ export async function apiFetch<T = unknown>(
if (response.status === 401) {
clearToken();
window.dispatchEvent(new Event('zeroclaw-unauthorized'));
window.dispatchEvent(new Event('qimingclaw-digital-unauthorized'));
throw new UnauthorizedError();
}

View File

@@ -1,11 +1,12 @@
const TOKEN_KEY = 'zeroclaw_token';
const TOKEN_KEY = 'qimingclaw_digital_token';
const LEGACY_TOKEN_KEY = 'zeroclaw_token';
/**
* Retrieve the stored authentication token.
*/
export function getToken(): string | null {
try {
return localStorage.getItem(TOKEN_KEY);
return localStorage.getItem(TOKEN_KEY) ?? localStorage.getItem(LEGACY_TOKEN_KEY);
} catch {
return null;
}
@@ -17,6 +18,7 @@ export function getToken(): string | null {
export function setToken(token: string): void {
try {
localStorage.setItem(TOKEN_KEY, token);
localStorage.removeItem(LEGACY_TOKEN_KEY);
} catch {
// localStorage may be unavailable (e.g. in some private browsing modes)
}
@@ -28,6 +30,7 @@ export function setToken(token: string): void {
export function clearToken(): void {
try {
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(LEGACY_TOKEN_KEY);
} catch {
// Ignore
}

View File

@@ -1,6 +1,5 @@
declare global {
interface Window {
__SGROBOT_BASE__?: string;
__QIMINGCLAW_DIGITAL_API_BASE__?: string;
}
}

View File

@@ -116,7 +116,8 @@ const EVENT_STATUS_FILTERS: Array<{ id: EventStatusFilter; label: string }> = [
{ id: 'success', label: '已完成' },
{ id: 'danger', label: '异常' },
];
const WORKDAY_GUIDE_DISMISSED_STORAGE_KEY = 'sgrobot:digital-workday-guide-dismissed-date';
const WORKDAY_GUIDE_DISMISSED_STORAGE_KEY = 'qimingclaw:digital-workday-guide-dismissed-date';
const LEGACY_WORKDAY_GUIDE_DISMISSED_STORAGE_KEY = 'sgrobot:digital-workday-guide-dismissed-date';
const MAIN_RUN_DETAIL_LIMIT = 80;
const EVENT_HISTORY_RENDER_LIMIT = 300;
const WORKDAY_GUIDE_STEPS = [
@@ -778,7 +779,8 @@ function resolveEmployeeVisualState(args: {
function readGuideDismissedDate(): string | null {
if (typeof window === 'undefined') return null;
try {
return window.sessionStorage.getItem(WORKDAY_GUIDE_DISMISSED_STORAGE_KEY);
return window.sessionStorage.getItem(WORKDAY_GUIDE_DISMISSED_STORAGE_KEY)
?? window.sessionStorage.getItem(LEGACY_WORKDAY_GUIDE_DISMISSED_STORAGE_KEY);
} catch {
return null;
}
@@ -788,6 +790,7 @@ function rememberGuideDismissedDate(date: string): void {
if (typeof window === 'undefined') return;
try {
window.sessionStorage.setItem(WORKDAY_GUIDE_DISMISSED_STORAGE_KEY, date);
window.sessionStorage.removeItem(LEGACY_WORKDAY_GUIDE_DISMISSED_STORAGE_KEY);
} catch {
// Session storage can be unavailable in restricted browser contexts.
}

View File

@@ -16,7 +16,7 @@ const TABS: { id: DigitalTab; label: string }[] = [
{ id: 'reports', label: '日报' },
{ id: 'settings', label: '设置' },
];
const DIGITAL_EMPLOYEE_CLOSE_MESSAGE = 'sgrobot:digital-close';
const DIGITAL_EMPLOYEE_CLOSE_MESSAGE = 'qimingclaw:digital-close';
function isDigitalTab(value: string | null): value is DigitalTab {
return Boolean(value && TABS.some(tab => tab.id === value));

View File

@@ -5,7 +5,8 @@ import { useRole, ROLE_PROFILES, type ConsoleRole } from '@/contexts/RoleContext
import { t } from '@/lib/i18n';
const ROLES: ConsoleRole[] = ['sales', 'engineering', 'hr', 'finance', 'executive'];
const STORAGE_KEY = 'sgrobot-role-preferences';
const STORAGE_KEY = 'qimingclaw:digital-role-preferences';
const LEGACY_STORAGE_KEY = 'sgrobot-role-preferences';
type RolePreferences = {
workStart: string;
@@ -58,7 +59,7 @@ const inputStyle: CSSProperties = {
function loadPreferences(): RolePreferences {
try {
const raw = localStorage.getItem(STORAGE_KEY);
const raw = localStorage.getItem(STORAGE_KEY) ?? localStorage.getItem(LEGACY_STORAGE_KEY);
if (!raw) return defaultPreferences;
return { ...defaultPreferences, ...JSON.parse(raw) };
} catch {
@@ -84,7 +85,10 @@ export default function OpsSettings() {
const savePreferences = (next: RolePreferences) => {
setPreferences(next);
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(next)); } catch { /* localStorage blocked */ }
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
localStorage.removeItem(LEGACY_STORAGE_KEY);
} catch { /* localStorage blocked */ }
markSaved();
};