useEnterpriseAuth.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { ref, computed } from 'vue';
  2. import { fetchEnterpriseInfo, fetchEnterpriseLogin, type EnterpriseInfo } from '@/network/api/enterprise';
  3. const TEMP_HISTORY_KEY = 'ba_temp_chat_history';
  4. const AUTH_HISTORY_KEY = 'ba_chat_history';
  5. const AUTH_CURRENT_SESSION_KEY = 'ba_current_session_id';
  6. const ENTERPRISE_INFO_KEY = 'ba_enterprise_info';
  7. const AUTH_TOKEN_KEY = 'ba_auth_token';
  8. export const enterpriseInfo = ref<EnterpriseInfo | null>(null);
  9. const authLoading = ref(false);
  10. const authError = ref(false);
  11. // Global fetch interceptor: any 401 response → clear enterprise info (logout)
  12. (function setupFetchInterceptor() {
  13. if (typeof window === 'undefined') return;
  14. const originalFetch = window.fetch.bind(window);
  15. window.fetch = async (...args: Parameters<typeof fetch>) => {
  16. const response = await originalFetch(...args);
  17. if (response.status === 401 && enterpriseInfo.value) {
  18. enterpriseInfo.value = null;
  19. globalThis.authToken = undefined;
  20. globalThis.token = undefined;
  21. localStorage.removeItem(ENTERPRISE_INFO_KEY);
  22. localStorage.removeItem(AUTH_TOKEN_KEY);
  23. }
  24. return response;
  25. };
  26. })();
  27. export function getQueryParamUniversal(key: string): string | null {
  28. const searchParams = new URLSearchParams(window.location.search);
  29. if (searchParams.has(key)) {
  30. return searchParams.get(key);
  31. }
  32. const hash = window.location.hash;
  33. const queryIndex = hash.indexOf('?');
  34. if (queryIndex !== -1) {
  35. const hashQuery = hash.substring(queryIndex + 1);
  36. const hashParams = new URLSearchParams(hashQuery);
  37. return hashParams.get(key);
  38. }
  39. return null;
  40. }
  41. export function getChatHistoryStorageKey(): string {
  42. return enterpriseInfo.value ? AUTH_HISTORY_KEY : TEMP_HISTORY_KEY;
  43. }
  44. export function getCurrentSessionStorageKey(): string {
  45. return AUTH_CURRENT_SESSION_KEY;
  46. }
  47. export function useEnterpriseAuth() {
  48. const isLoggedIn = computed(() => !!enterpriseInfo.value);
  49. const enterpriseName = computed(() => enterpriseInfo.value?.name || '');
  50. const creditCode = computed(() => enterpriseInfo.value?.credit_code || '');
  51. const initAuth = async () => {
  52. const creditCodeParam = getQueryParamUniversal('credit_code');
  53. const accessToken = getQueryParamUniversal('access_token');
  54. // 跟随 querystring 的 policyMode:A/B 测试变体(如 zhaoshang_staging_1)也需体现在 source 中
  55. globalThis.source = globalThis.policyMode || "zhaoshang";
  56. // 1. access_token 存在: 换取 credit_code + authToken, 再拉企业信息
  57. // (要企业态就显式带 ?access_token=<token> 或 ?credit_code=<代码>)
  58. if (accessToken && !creditCodeParam) {
  59. authLoading.value = true;
  60. authError.value = false;
  61. try {
  62. const loginResult = await fetchEnterpriseLogin(accessToken);
  63. if (loginResult) {
  64. globalThis.authToken = loginResult.authToken;
  65. globalThis.token = loginResult.authToken;
  66. localStorage.setItem(AUTH_TOKEN_KEY, loginResult.authToken);
  67. authLoading.value = false;
  68. return await initAuthWithCreditCode(loginResult.creditCode);
  69. }
  70. } catch {
  71. authError.value = true;
  72. } finally {
  73. authLoading.value = false;
  74. }
  75. return;
  76. }
  77. // 2. credit_code 存在: 直接拉企业信息
  78. if (creditCodeParam) {
  79. return await initAuthWithCreditCode(creditCodeParam);
  80. }
  81. // 3. 无参数: 保持未登录状态
  82. };
  83. const initAuthWithCreditCode = async (creditCodeParam: string) => {
  84. authLoading.value = true;
  85. authError.value = false;
  86. try {
  87. const info = await fetchEnterpriseInfo(creditCodeParam);
  88. if (info) {
  89. enterpriseInfo.value = info;
  90. const cc = info.credit_code || creditCodeParam;
  91. (globalThis as any).credit_code = cc;
  92. (globalThis as any).transmission = {
  93. ...((globalThis as any).transmission || {}),
  94. credit_code: cc,
  95. };
  96. localStorage.setItem(ENTERPRISE_INFO_KEY, JSON.stringify(info));
  97. }
  98. } catch {
  99. authError.value = true;
  100. } finally {
  101. authLoading.value = false;
  102. }
  103. };
  104. const logout = () => {
  105. enterpriseInfo.value = null;
  106. globalThis.authToken = undefined;
  107. globalThis.token = undefined;
  108. localStorage.removeItem(ENTERPRISE_INFO_KEY);
  109. localStorage.removeItem(AUTH_TOKEN_KEY);
  110. };
  111. const redirectToLogin = () => {
  112. // 回跳到本页;一网通办 redirect_uri 白名单后续自行对接
  113. const mode = globalThis.policyMode || "zhaoshang";
  114. const currentUrl = `${window.location.origin}${window.location.pathname}#/?mode=${mode}`;
  115. const sourceLink = `https://zwdtuser.sh.gov.cn/uc/login/login.jsp?sendPost=false&type=2&redirect_uri=${encodeURIComponent(currentUrl)}`;
  116. window.location.href = sourceLink;
  117. };
  118. return {
  119. isLoggedIn,
  120. enterpriseName,
  121. creditCode,
  122. enterpriseInfo,
  123. authLoading,
  124. authError,
  125. initAuth,
  126. logout,
  127. redirectToLogin,
  128. };
  129. }