index.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import Vue from "vue";
  2. import VueRouter from "vue-router";
  3. import layout from "@/layout/index.vue";
  4. import { checkWxWorkEnvAndUserCache, getAgentFrom } from '@/utils/index'
  5. import { checkLoginStatus, initGuidInfo, doWecomLogin, getQyCode, getGuid, getMD5 } from '@/utils/wecomLogin.ts';
  6. import { doWxidLogin } from "@/api/indexAI";
  7. Vue.use(VueRouter);
  8. const router = new VueRouter({
  9. mode: process.env.NODE_ENV !== "development" ? "history" : "history",
  10. base: process.env.BASE_URL,
  11. scrollBehavior(to, from, savedPosition) {
  12. if (savedPosition) {
  13. return savedPosition;
  14. } else {
  15. return { x: 0, y: 0 };
  16. }
  17. },
  18. routes: [
  19. {
  20. path: "/",
  21. component: layout,
  22. redirect: "/AIDesign",
  23. children: [
  24. {
  25. path: "/AIDesign",
  26. component: () => import("../views/AIDesign/index.vue"),
  27. meta: { requiresAuth: true } // 标记需要登录的页面
  28. },
  29. {
  30. path: "/login",
  31. component: () => import("../views/login/index.vue"),
  32. meta: { title: "登录" }
  33. },
  34. {
  35. path: "/error/:code",
  36. component: () => import("../views/errorPage/index.vue")
  37. },
  38. {
  39. path: "/error",
  40. component: () => import("../views/errorPage/weixinerr.vue")
  41. },
  42. //设计页
  43. {
  44. path: "/AIDesign/design",
  45. component: () => import("../views/AIDesign/design.vue"),
  46. meta: { requiresAuth: true } // 标记需要登录的页面
  47. },
  48. //结果页
  49. {
  50. path: "/AIDesign/result",
  51. component: () => import("../views/AIDesign/result.vue"),
  52. meta: { requiresAuth: true } // 标记需要登录的页面
  53. },
  54. //历史页
  55. {
  56. path: "/AIDesign/history",
  57. component: () => import("../views/AIDesign/history.vue"),
  58. meta: { requiresAuth: true } // 标记需要登录的页面
  59. },
  60. //内墙-设计页
  61. {
  62. path: "/AIDesign/insideDesign",
  63. component: () => import("../views/AIDesign/insideDesign.vue"),
  64. meta: { requiresAuth: true } // 标记需要登录的页面
  65. },
  66. //一键诊断-生成页
  67. {
  68. path: "/AIDesign/diagnose",
  69. component: () => import("../views/AIDesign/diagnose.vue"),
  70. meta: { requiresAuth: true } // 标记需要登录的页面
  71. },
  72. //一键诊断-历史页
  73. {
  74. path: "/AIDesign/diagnoseHistory",
  75. component: () => import("../views/AIDesign/diagnoseHistory.vue"),
  76. meta: { requiresAuth: true } // 标记需要登录的页面
  77. },
  78. //一键诊断-结果页
  79. {
  80. path: "/AIDesign/diagnoseResult",
  81. component: () => import("../views/AIDesign/diagnoseResult.vue"),
  82. meta: { requiresAuth: true } // 标记需要登录的页面
  83. },
  84. //反馈页面
  85. {
  86. path: "/AIDesign/feedback",
  87. component: () => import("../views/AIDesign/feedback.vue"),
  88. meta: { requiresAuth: true }
  89. },
  90. // 生成方案
  91. {
  92. path: "/AIDesign/GeneratePlan",
  93. component: () => import("../views/AIDesign/GeneratePlan.vue"),
  94. meta: { requiresAuth: true }
  95. },
  96. ]
  97. },
  98. ]
  99. });
  100. // 全局前置守卫:只对需要登录的页面进行登录校验
  101. router.beforeEach(async (to, from, next) => {
  102. console.log("to=", to)
  103. if (!to.meta || (to.meta && !to.meta.requiresAuth)) {
  104. next();
  105. return;
  106. }
  107. try {
  108. //先判断企微环境
  109. // checkWxWorkEnvAndUserCache();
  110. const { loginType, wxid, WecomType } = to.query;
  111. // 初始化登录模式标识
  112. initLoginModeFlag(loginType);
  113. // 判断当前登录模式,分发处理逻辑
  114. const isNewLoginMode = sessionStorage.getItem('isNewLoginMode') === 'true';
  115. if (isNewLoginMode) {
  116. await handleWxidLoginMode(to, next, wxid, WecomType);
  117. } else {
  118. await handleCodeLoginMode(to, next);
  119. }
  120. } catch (error) {
  121. console.error("登录校验过程异常:", error);
  122. next({ path: "/error" });
  123. }
  124. });
  125. /**
  126. * 新登录方式处理:强制检测登录 → 获取Token → 缓存 → 放行/失败跳转
  127. * @param to 目标路由
  128. * @param next 路由放行方法
  129. */
  130. async function handleWxidLoginMode(to, next, wxid, WecomType) {
  131. try {
  132. window.localStorage.setItem('loginMode', 'wxidLogin');
  133. if (wxid) {
  134. window.localStorage.setItem('weChat', wxid);
  135. }
  136. if (WecomType) {
  137. const agentFrom = getAgentFrom(WecomType);
  138. window.localStorage.setItem('agentFrom', agentFrom);
  139. window.localStorage.setItem('agentFromAI', agentFrom);
  140. }
  141. // 3. 初始化鉴权信息,校验登录状态
  142. initGuidInfo();
  143. if (checkLoginStatus()) return next();
  144. // 4. wxid参数校验
  145. let wxId = wxid ? wxid : window.localStorage.getItem("weChat");
  146. if (!wxId) return redirectToError(next, "wxid参数缺失,无权限");
  147. const formData = new FormData();
  148. const timestamp = new Date().getTime().toString();
  149. const nonce = getGuid();
  150. const sign = getMD5(nonce, timestamp, wxId);
  151. formData.append('wxId', wxId);
  152. formData.append('timestamp', timestamp);
  153. formData.append('nonce', nonce);
  154. formData.append('sign', sign);
  155. doWxidLogin(formData)
  156. .then((res) => {
  157. if (res && res.StatusCode === 200 && res.Data && res.Data.token) {
  158. const userInfoV1 = JSON.stringify(res.Data);
  159. window.localStorage.setItem('userInfoV1', userInfoV1);
  160. window.localStorage.setItem('AIToken', res.Data.token);
  161. window.localStorage.setItem('isRefreshProvider', res.Data.isRefreshProvider);
  162. window.localStorage.setItem('weChat', res.Data.weChat);
  163. console.log(`新登录成功,Token已缓存,即将进入 ${to.path}`);
  164. // debugger
  165. next();
  166. } else {
  167. throw new Error('新登录失败,未获取到Token');
  168. }
  169. })
  170. .catch(() => {
  171. // 登录失败:跳转错误页
  172. next({ path: "/error", replace: true });
  173. });
  174. } catch (err) {
  175. console.error('新登录方式处理异常:', err);
  176. next({ path: "/error", replace: true });
  177. }
  178. }
  179. /**
  180. * 旧登录方式处理:原有企微code授权登录逻辑
  181. * @param to 目标路由
  182. * @param next 路由放行方法
  183. */
  184. function handleCodeLoginMode(to, next) {
  185. const org_loginMode = window.localStorage.getItem('loginMode');
  186. if (org_loginMode != 'codeLogin') {
  187. window.localStorage.clear();
  188. }
  189. window.localStorage.setItem('loginMode', 'codeLogin');
  190. //验证时间戳和token
  191. initGuidInfo();
  192. if (checkLoginStatus()) return next();
  193. const code = to.query.code as string;
  194. let finalCode;
  195. if (Array.isArray(code)) {
  196. finalCode = code.length > 0 ? code[code.length - 1] : null;
  197. } else {
  198. finalCode = code || null;
  199. }
  200. if (finalCode) {
  201. doWecomLogin(finalCode)
  202. .then(() => {
  203. // debugger
  204. next();
  205. console.log(`登录成功,即将进入 ${to.path}`);
  206. })
  207. .catch(() => {
  208. next({ path: "/error" });
  209. });
  210. } else {
  211. // debugger
  212. console.log(`访问 ${to.path} 需登录,正在跳转到授权页面`);
  213. getQyCode();
  214. }
  215. }
  216. /**
  217. * 初始化登录模式标识 - 保证会话内登录方式统一
  218. * @param {string} loginType 路由传参的登录类型
  219. */
  220. function initLoginModeFlag(loginType) {
  221. const isNewLoginMode = loginType && String(loginType) === '2';
  222. // 保证本次会话的登录方式不变
  223. if (isNewLoginMode) {
  224. sessionStorage.setItem("isNewLoginMode", 'true');
  225. }
  226. }
  227. /**
  228. * 跳转错误页并存储错误信息
  229. * @param {Function} next 路由放行函数
  230. * @param {string} msg 错误提示信息
  231. */
  232. function redirectToError(next, msg = '参数缺失,无权限') {
  233. sessionStorage.setItem("errorMsgTit", msg);
  234. next({ path: '/error', replace: true });
  235. }
  236. export default router;