|
|
@@ -114,14 +114,14 @@ export class App implements OnInit {
|
|
|
// 2. URL 没有 user → 检查 localStorage 缓存
|
|
|
const cachedUserId = localStorage.getItem('apig_user_id');
|
|
|
const cachedToken = localStorage.getItem('apig_session_token');
|
|
|
+ const cachedName = localStorage.getItem('apig_display_name');
|
|
|
if (cachedUserId && cachedToken) {
|
|
|
console.log('[AUTH] 从 localStorage 恢复用户:', cachedUserId);
|
|
|
this.userId = cachedUserId;
|
|
|
- this.loggedInUser = cachedUserId;
|
|
|
+ this.loggedInUser = cachedName || cachedUserId;
|
|
|
this.sessionToken = cachedToken;
|
|
|
- // 后台验证 token 是否还有效
|
|
|
- this.validateCachedToken(cachedToken, cachedUserId);
|
|
|
- this.loadApig();
|
|
|
+ // 先验证 token,验证通过再加载数据
|
|
|
+ this.validateAndLoad(cachedToken, cachedUserId);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -130,7 +130,7 @@ export class App implements OnInit {
|
|
|
this.needLogin = true;
|
|
|
}
|
|
|
|
|
|
- async validateCachedToken(token: string, userId: string): Promise<void> {
|
|
|
+ async validateAndLoad(token: string, userId: string): Promise<void> {
|
|
|
try {
|
|
|
const resp = await fetch(`${API_BASE}/parse/users/me`, {
|
|
|
headers: {
|
|
|
@@ -143,17 +143,37 @@ export class App implements OnInit {
|
|
|
console.warn('[AUTH] 缓存 token 已失效,需要重新登录');
|
|
|
localStorage.removeItem('apig_user_id');
|
|
|
localStorage.removeItem('apig_session_token');
|
|
|
+ localStorage.removeItem('apig_display_name');
|
|
|
this.needLogin = true;
|
|
|
+ this.cdr.detectChanges();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // token 有效 — 更新 displayName(可能 localStorage 里是旧的)
|
|
|
+ const serverName = data.nickname || data.username || data.mobilePhoneNumber || userId;
|
|
|
+ if (serverName && serverName !== this.loggedInUser) {
|
|
|
+ this.loggedInUser = serverName;
|
|
|
+ localStorage.setItem('apig_display_name', serverName);
|
|
|
+ }
|
|
|
+ // userId 可能变化(极端情况:session 对应不同用户)
|
|
|
+ if (data.objectId !== userId) {
|
|
|
+ console.warn('[AUTH] session 对应用户不匹配,纠正:', userId, '→', data.objectId);
|
|
|
+ this.userId = data.objectId;
|
|
|
+ localStorage.setItem('apig_user_id', data.objectId);
|
|
|
}
|
|
|
+ console.log('[AUTH] token 验证通过, user:', data.objectId, data.username || '');
|
|
|
+ this.cdr.detectChanges();
|
|
|
+ this.loadApig();
|
|
|
} catch (e) {
|
|
|
console.warn('[AUTH] 验证 token 失败:', e);
|
|
|
+ // 网络错误时仍然尝试加载(可能离线缓存能用)
|
|
|
+ this.loadApig();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- onLoginSuccess(event: { userId: string; sessionToken: string }): void {
|
|
|
- console.log('[AUTH] 登录成功, userId:', event.userId);
|
|
|
+ onLoginSuccess(event: { userId: string; sessionToken: string; displayName: string }): void {
|
|
|
+ console.log('[AUTH] 登录成功, userId:', event.userId, 'display:', event.displayName);
|
|
|
this.userId = event.userId;
|
|
|
- this.loggedInUser = event.userId;
|
|
|
+ this.loggedInUser = event.displayName || event.userId;
|
|
|
this.sessionToken = event.sessionToken;
|
|
|
this.needLogin = false;
|
|
|
this.errorMsg = '';
|
|
|
@@ -161,6 +181,23 @@ export class App implements OnInit {
|
|
|
this.loadApig();
|
|
|
}
|
|
|
|
|
|
+ logout(): void {
|
|
|
+ console.log('[AUTH] 退出登录');
|
|
|
+ localStorage.removeItem('apig_user_id');
|
|
|
+ localStorage.removeItem('apig_session_token');
|
|
|
+ localStorage.removeItem('apig_display_name');
|
|
|
+ this.userId = '';
|
|
|
+ this.loggedInUser = '';
|
|
|
+ this.sessionToken = '';
|
|
|
+ this.authId = '';
|
|
|
+ this.apig = null;
|
|
|
+ this.orders = [];
|
|
|
+ this.errorMsg = '';
|
|
|
+ this.showSuccess = false;
|
|
|
+ this.needLogin = true;
|
|
|
+ this.cdr.detectChanges();
|
|
|
+ }
|
|
|
+
|
|
|
// ─── Load available APIG list (when no apigId) ───
|
|
|
async loadApigList(): Promise<void> {
|
|
|
this.apigListLoading = true;
|
|
|
@@ -214,6 +251,7 @@ export class App implements OnInit {
|
|
|
const resolved = await this.resolveAuthId(this.userId, this.apigId);
|
|
|
if (!resolved) {
|
|
|
this.errorMsg = '无法获取或创建计费账套,请联系管理员。';
|
|
|
+ this.cdr.detectChanges();
|
|
|
return;
|
|
|
}
|
|
|
this.authId = resolved;
|
|
|
@@ -254,14 +292,19 @@ export class App implements OnInit {
|
|
|
}
|
|
|
|
|
|
this.errorMsg = '无法加载接口信息。请确认参数正确。';
|
|
|
+ this.cdr.detectChanges();
|
|
|
} catch (e: any) {
|
|
|
this.errorMsg = '网络错误: ' + e.message;
|
|
|
+ this.cdr.detectChanges();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─── 通过 user+apigid 查询或创建 APIGAuth ───
|
|
|
async resolveAuthId(user: string, apig: string): Promise<string | null> {
|
|
|
- // 1. 查询已有 APIGAuth(按 user 指针)
|
|
|
+ const authHeaders: any = { 'X-Parse-Application-Id': APP_ID };
|
|
|
+ if (this.sessionToken) authHeaders['X-Parse-Session-Token'] = this.sessionToken;
|
|
|
+
|
|
|
+ // 1. 精确查询:按 user + api 指针
|
|
|
try {
|
|
|
const query: any = {
|
|
|
where: JSON.stringify({
|
|
|
@@ -271,96 +314,45 @@ export class App implements OnInit {
|
|
|
limit: '1'
|
|
|
};
|
|
|
const resp = await fetch(API_BASE + '/parse/classes/APIGAuth?' + new URLSearchParams(query), {
|
|
|
- headers: { 'X-Parse-Application-Id': APP_ID }
|
|
|
+ headers: authHeaders
|
|
|
});
|
|
|
const data = await resp.json();
|
|
|
if (data.results?.length > 0) {
|
|
|
- console.log('[resolveAuthId] 找到已有 APIGAuth:', data.results[0].objectId);
|
|
|
+ console.log('[resolveAuthId] 找到已有 APIGAuth:', data.results[0].objectId, 'count:', data.results[0].count);
|
|
|
return data.results[0].objectId;
|
|
|
}
|
|
|
} catch (e: any) {
|
|
|
console.warn('[resolveAuthId] 查询失败:', e.message);
|
|
|
}
|
|
|
|
|
|
- // 2. 回退:按 api 查询所有记录(兼容旧 company / 不同 user 的记录)
|
|
|
- // 合并所有记录的 count 和 used 到一条主记录,绑定当前 user,删除多余记录
|
|
|
+ // 2. 未找到 → 为当前用户创建新 APIGAuth(余额=0,需充值)
|
|
|
try {
|
|
|
- const fallbackQuery: any = {
|
|
|
- where: JSON.stringify({
|
|
|
- api: { __type: 'Pointer', className: 'APIG', objectId: apig }
|
|
|
- }),
|
|
|
- order: '-count',
|
|
|
- limit: '20'
|
|
|
- };
|
|
|
- const fbResp = await fetch(API_BASE + '/parse/classes/APIGAuth?' + new URLSearchParams(fallbackQuery), {
|
|
|
- headers: { 'X-Parse-Application-Id': APP_ID }
|
|
|
- });
|
|
|
- const fbData = await fbResp.json();
|
|
|
- const records = fbData.results || [];
|
|
|
-
|
|
|
- if (records.length > 0) {
|
|
|
- // 汇总所有记录的 count 和 used
|
|
|
- let totalCount = 0;
|
|
|
- let totalUsed = 0;
|
|
|
- for (const r of records) {
|
|
|
- totalCount += (r.count || 0);
|
|
|
- totalUsed += (r.used || 0);
|
|
|
- }
|
|
|
-
|
|
|
- // 选第一条(count 最高)作为主记录
|
|
|
- const primary = records[0];
|
|
|
- console.log(`[resolveAuthId] 找到 ${records.length} 条旧记录,合并余额: count=${totalCount}, used=${totalUsed}`);
|
|
|
-
|
|
|
- // 更新主记录:绑定当前 user + 合并余额
|
|
|
- try {
|
|
|
- await fetch(API_BASE + '/parse/classes/APIGAuth/' + primary.objectId, {
|
|
|
- method: 'PUT',
|
|
|
- headers: { 'X-Parse-Application-Id': APP_ID, 'Content-Type': 'application/json' },
|
|
|
- body: JSON.stringify({
|
|
|
- user: { __type: 'Pointer', className: '_User', objectId: user },
|
|
|
- count: totalCount,
|
|
|
- used: totalUsed
|
|
|
- })
|
|
|
- });
|
|
|
- console.log('[resolveAuthId] 主记录已更新:', primary.objectId);
|
|
|
- } catch (e: any) {
|
|
|
- console.warn('[resolveAuthId] 更新主记录失败:', e.message);
|
|
|
- }
|
|
|
+ console.log('[resolveAuthId] 未找到该用户的 APIGAuth,创建新记录(余额=0)...');
|
|
|
|
|
|
- // 删除多余记录
|
|
|
- for (let i = 1; i < records.length; i++) {
|
|
|
- try {
|
|
|
- await fetch(API_BASE + '/parse/classes/APIGAuth/' + records[i].objectId, {
|
|
|
- method: 'DELETE',
|
|
|
- headers: { 'X-Parse-Application-Id': APP_ID }
|
|
|
- });
|
|
|
- console.log('[resolveAuthId] 删除重复记录:', records[i].objectId);
|
|
|
- } catch (e: any) {
|
|
|
- console.warn('[resolveAuthId] 删除失败:', records[i].objectId, e.message);
|
|
|
- }
|
|
|
+ // 获取用户的 company 指针(ensureCompany 已在登录时创建)
|
|
|
+ let companyPointer: any = undefined;
|
|
|
+ try {
|
|
|
+ const meResp = await fetch(API_BASE + '/parse/users/me', { headers: authHeaders });
|
|
|
+ const meData = await meResp.json();
|
|
|
+ if (meData.company?.objectId) {
|
|
|
+ companyPointer = { __type: 'Pointer', className: 'Company', objectId: meData.company.objectId };
|
|
|
}
|
|
|
-
|
|
|
- return primary.objectId;
|
|
|
+ } catch (e: any) {
|
|
|
+ console.warn('[resolveAuthId] 获取 company 失败:', e.message);
|
|
|
}
|
|
|
- } catch (e: any) {
|
|
|
- console.warn('[resolveAuthId] 回退查询失败:', e.message);
|
|
|
- }
|
|
|
|
|
|
- // 3. 创建新 APIGAuth
|
|
|
- try {
|
|
|
- console.log('[resolveAuthId] 未找到任何 APIGAuth,创建新记录...');
|
|
|
+ const body: any = {
|
|
|
+ api: { __type: 'Pointer', className: 'APIG', objectId: apig },
|
|
|
+ user: { __type: 'Pointer', className: '_User', objectId: user },
|
|
|
+ count: 0,
|
|
|
+ used: 0
|
|
|
+ };
|
|
|
+ if (companyPointer) body.company = companyPointer;
|
|
|
+
|
|
|
const createResp = await fetch(API_BASE + '/parse/classes/APIGAuth', {
|
|
|
method: 'POST',
|
|
|
- headers: {
|
|
|
- 'X-Parse-Application-Id': APP_ID,
|
|
|
- 'Content-Type': 'application/json'
|
|
|
- },
|
|
|
- body: JSON.stringify({
|
|
|
- api: { __type: 'Pointer', className: 'APIG', objectId: apig },
|
|
|
- user: { __type: 'Pointer', className: '_User', objectId: user },
|
|
|
- count: 0,
|
|
|
- used: 0
|
|
|
- })
|
|
|
+ headers: { ...authHeaders, 'Content-Type': 'application/json' },
|
|
|
+ body: JSON.stringify(body)
|
|
|
});
|
|
|
const created = await createResp.json();
|
|
|
if (created.objectId) {
|