@@ -9,6 +9,13 @@ export interface User {
99 permissions ?: string [ ] ;
1010}
1111
12+ export interface Account {
13+ id : string ;
14+ label : string ;
15+ token : string ;
16+ user : User ;
17+ }
18+
1219// 标准权限列表
1320export const PERMISSIONS = {
1421 // 仪表盘
@@ -55,16 +62,24 @@ export const ROLES = {
5562
5663const AUTH_TOKEN_KEY = 'auth_token' ;
5764const AUTH_USER_KEY = 'auth_user' ;
65+ const AUTH_ACCOUNTS_KEY = 'auth_accounts' ;
66+ const AUTH_ACTIVE_ACCOUNT_KEY = 'auth_active_account' ;
5867
5968@Injectable ( { providedIn : 'root' } )
6069export class AuthService {
6170 private readonly tokenSignal = signal < string | null > ( this . getStoredToken ( ) ) ;
6271 private readonly userSignal = signal < User | null > ( this . getStoredUser ( ) ) ;
6372 private readonly loadingSignal = signal ( false ) ;
73+ private readonly accountsSignal = signal < Account [ ] > ( this . getStoredAccounts ( ) ) ;
74+ private readonly activeAccountIdSignal = signal < string | null > ( this . getStoredActiveAccountId ( ) ) ;
6475
6576 readonly isAuthenticated = computed ( ( ) => ! ! this . tokenSignal ( ) ) ;
6677 readonly user = computed ( ( ) => this . userSignal ( ) ) ;
6778 readonly loading = computed ( ( ) => this . loadingSignal ( ) ) ;
79+ readonly accounts = this . accountsSignal . asReadonly ( ) ;
80+ readonly activeAccount = computed ( ( ) =>
81+ this . accountsSignal ( ) . find ( ( acc ) => acc . id === this . activeAccountIdSignal ( ) ) || null
82+ ) ;
6883
6984 constructor ( ) {
7085 // Sync token changes to localStorage
@@ -85,6 +100,30 @@ export class AuthService {
85100 localStorage . removeItem ( AUTH_USER_KEY ) ;
86101 }
87102 } ) ;
103+
104+ effect ( ( ) => {
105+ if ( typeof localStorage === 'undefined' ) return ;
106+ localStorage . setItem ( AUTH_ACCOUNTS_KEY , JSON . stringify ( this . accountsSignal ( ) ) ) ;
107+ } ) ;
108+
109+ effect ( ( ) => {
110+ if ( typeof localStorage === 'undefined' ) return ;
111+ const activeId = this . activeAccountIdSignal ( ) ;
112+ if ( activeId ) {
113+ localStorage . setItem ( AUTH_ACTIVE_ACCOUNT_KEY , activeId ) ;
114+ } else {
115+ localStorage . removeItem ( AUTH_ACTIVE_ACCOUNT_KEY ) ;
116+ }
117+ } ) ;
118+
119+ // Keep token/user in sync with active account
120+ effect ( ( ) => {
121+ const active = this . activeAccount ( ) ;
122+ if ( active ) {
123+ this . tokenSignal . set ( active . token ) ;
124+ this . userSignal . set ( active . user ) ;
125+ }
126+ } ) ;
88127 }
89128
90129 get token ( ) : string | null {
@@ -94,6 +133,19 @@ export class AuthService {
94133 setAuth ( token : string , user : User ) : void {
95134 this . tokenSignal . set ( token ) ;
96135 this . userSignal . set ( user ) ;
136+
137+ const existing = this . accountsSignal ( ) ;
138+ const account : Account = {
139+ id : user . id ,
140+ label : user . name || user . email ,
141+ token,
142+ user,
143+ } ;
144+ const next = existing . some ( ( a ) => a . id === account . id )
145+ ? existing . map ( ( a ) => ( a . id === account . id ? account : a ) )
146+ : [ ...existing , account ] ;
147+ this . accountsSignal . set ( next ) ;
148+ this . activeAccountIdSignal . set ( account . id ) ;
97149 }
98150
99151 setLoading ( loading : boolean ) : void {
@@ -103,6 +155,7 @@ export class AuthService {
103155 logout ( ) : void {
104156 this . tokenSignal . set ( null ) ;
105157 this . userSignal . set ( null ) ;
158+ this . activeAccountIdSignal . set ( null ) ;
106159 }
107160
108161 /**
@@ -163,4 +216,35 @@ export class AuthService {
163216 return null ;
164217 }
165218 }
219+
220+ private getStoredAccounts ( ) : Account [ ] {
221+ if ( typeof localStorage === 'undefined' ) return [ ] ;
222+ const stored = localStorage . getItem ( AUTH_ACCOUNTS_KEY ) ;
223+ if ( ! stored ) return [ ] ;
224+ try {
225+ return JSON . parse ( stored ) as Account [ ] ;
226+ } catch {
227+ return [ ] ;
228+ }
229+ }
230+
231+ private getStoredActiveAccountId ( ) : string | null {
232+ if ( typeof localStorage === 'undefined' ) return null ;
233+ return localStorage . getItem ( AUTH_ACTIVE_ACCOUNT_KEY ) ;
234+ }
235+
236+ switchAccount ( accountId : string ) : void {
237+ const target = this . accountsSignal ( ) . find ( ( acc ) => acc . id === accountId ) ;
238+ if ( ! target ) return ;
239+ this . activeAccountIdSignal . set ( accountId ) ;
240+ this . tokenSignal . set ( target . token ) ;
241+ this . userSignal . set ( target . user ) ;
242+ }
243+
244+ removeAccount ( accountId : string ) : void {
245+ this . accountsSignal . update ( ( accounts ) => accounts . filter ( ( a ) => a . id !== accountId ) ) ;
246+ if ( this . activeAccountIdSignal ( ) === accountId ) {
247+ this . activeAccountIdSignal . set ( this . accountsSignal ( ) [ 0 ] ?. id ?? null ) ;
248+ }
249+ }
166250}
0 commit comments