login.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. import Vue from 'vue';
  2. import { hexMD5 } from '../pages/login/md5.js';
  3. // 登录超时时间配置(毫秒)
  4. const LOGIN_TIMEOUT = 15000;
  5. const SSO_TIMEOUT = 10000;
  6. // 错误处理包装器
  7. function safeResolve(promise) {
  8. return promise.catch(err => {
  9. console.error('登录流程异常:', err);
  10. return false;
  11. });
  12. }
  13. // 带超时的 Promise
  14. function withTimeout(promise, timeoutMs = 10000, fallback = false) {
  15. return Promise.race([
  16. promise,
  17. new Promise(resolve => setTimeout(() => resolve(fallback), timeoutMs))
  18. ]).catch(() => fallback);
  19. }
  20. /* 获取用户权限 - 带超时和错误处理 */
  21. function query_userauth() {
  22. return withTimeout(
  23. new Promise((resolve) => {
  24. Vue.prototype.$Http.basic({
  25. "classname": "sysmanage.develop.userauth.userauth",
  26. "method": "query_userauth",
  27. content: {
  28. nocache: true
  29. }
  30. }).then(res => {
  31. console.log("查询用户权限", res)
  32. if (Vue.prototype.cutoff(res.msg)) {
  33. resolve(false);
  34. return;
  35. }
  36. parsingAuth(res.data);
  37. resolve(true);
  38. }).catch(() => resolve(false));
  39. }),
  40. SSO_TIMEOUT,
  41. false
  42. );
  43. }
  44. /* 查询站点数据 - 带超时和错误处理 */
  45. function querySite_Parameter() {
  46. return withTimeout(
  47. new Promise((resolve) => {
  48. Vue.prototype.$Http.basic({
  49. "classname": "webmanage.site.site",
  50. "method": "querySite_Parameter",
  51. "content": {}
  52. }).then(res => {
  53. console.log("查询站点配置", res)
  54. if (Vue.prototype.cutoff(res.msg)) {
  55. resolve(false);
  56. return;
  57. }
  58. try {
  59. uni.removeStorageSync('siteP');
  60. uni.setStorageSync('siteP', res.data);
  61. } catch (e) {
  62. console.error('缓存站点数据失败:', e);
  63. }
  64. resolve(true);
  65. }).catch(() => resolve(false));
  66. }),
  67. SSO_TIMEOUT,
  68. false
  69. );
  70. }
  71. /* 格式化权限 */
  72. function parsingAuth(list) {
  73. let authList = {}
  74. list.forEach(system => {
  75. // let systemObj = {}
  76. system.modules.forEach(app => {
  77. let appObj = {}
  78. app.apps.forEach(m => {
  79. appObj[m.meta.title] = {
  80. path: m.path,
  81. pathDetail: m.path_index,
  82. pathDetail: m.path_index,
  83. name: m.name,
  84. remark: m.meta.title,
  85. remarks: m.remarks,
  86. cover: m.cover,
  87. option: m.meta.auth.map(v => v.option),
  88. forms: m.meta.forms,
  89. optionname: m.meta.auth.map(v => v.optionname)
  90. }
  91. })
  92. // systemObj[app.systemmodulename] = appObj;
  93. authList[app.systemmodulename] = appObj;
  94. })
  95. // authList[system.systemname] = systemObj;
  96. });
  97. uni.removeStorageSync({
  98. key: 'authList'
  99. })
  100. uni.setStorageSync('authList', authList)
  101. }
  102. class Login {
  103. // 防止重复登录标志
  104. _isLoggingIn = false;
  105. /* 使用缓存的账号密码登录 - 带超时 */
  106. cachedAccountLogin() {
  107. return new Promise((resolve) => {
  108. // 防止重复调用
  109. if (this._isLoggingIn) {
  110. resolve(false);
  111. return;
  112. }
  113. this._isLoggingIn = true;
  114. const cachedAccount = uni.getStorageSync('accountno');
  115. const cachedPassword = uni.getStorageSync('accountnoPwd');
  116. if (!cachedAccount || !cachedPassword) {
  117. console.log("无缓存的账号密码");
  118. this._isLoggingIn = false;
  119. return resolve(false);
  120. }
  121. console.log("使用缓存的账号密码登录", cachedAccount);
  122. // 判断是否需要先走门店登录
  123. if (Vue.prototype.$Http.baseUrl === "https://meida.cnyunl.com:888") {
  124. withTimeout(
  125. this.tryStoreLogin(cachedAccount, cachedPassword),
  126. LOGIN_TIMEOUT
  127. ).then(result => {
  128. this._isLoggingIn = false;
  129. resolve(result);
  130. }).catch(() => {
  131. this._isLoggingIn = false;
  132. resolve(false);
  133. });
  134. } else {
  135. withTimeout(
  136. this.tryNewSystemLogin(cachedAccount, cachedPassword),
  137. LOGIN_TIMEOUT
  138. ).then(result => {
  139. this._isLoggingIn = false;
  140. resolve(result);
  141. }).catch(() => {
  142. this._isLoggingIn = false;
  143. resolve(false);
  144. });
  145. }
  146. });
  147. }
  148. /* 门店登录 -> SSO -> SSO2 */
  149. tryStoreLogin(account, password) {
  150. return new Promise((resolve) => {
  151. Vue.prototype.$Http.OldLogin(`?username=${account}&password=${encodeURIComponent(password)}`)
  152. .then(oldLoginResult => {
  153. console.log("门店登录结果:", oldLoginResult);
  154. if (oldLoginResult.success === true) {
  155. console.log("门店登录成功,开始单点登录到CRM");
  156. return Vue.prototype.$Http.SSO({
  157. accountno: oldLoginResult.data.userinfo.username,
  158. password: oldLoginResult.data.cookie.split("=")[1],
  159. systemclient: getApp().globalData.systemclient
  160. });
  161. } else {
  162. console.log("门店登录失败,尝试E订单登录");
  163. throw new Error('STORE_LOGIN_FAILED');
  164. }
  165. })
  166. .then(ssoResult => {
  167. console.log("SSO单点登录到CRM结果:", ssoResult);
  168. if (ssoResult.code === 1) {
  169. return this.handleSSO2(ssoResult);
  170. } else {
  171. console.log("SSO失败:", ssoResult.msg);
  172. resolve(false);
  173. }
  174. })
  175. .catch(err => {
  176. if (err.message === 'STORE_LOGIN_FAILED') {
  177. this.tryNewSystemLogin(account, password).then(resolve);
  178. } else {
  179. console.log("门店登录异常,尝试E订单登录:", err);
  180. this.tryNewSystemLogin(account, password).then(resolve);
  181. }
  182. });
  183. });
  184. }
  185. /* E订单登录 -> SSO2 */
  186. tryNewSystemLogin(account, passwordMD5) {
  187. return new Promise((resolve) => {
  188. console.log("尝试E订单登录", account);
  189. Vue.prototype.$Http.login({
  190. accountno: account,
  191. password: hexMD5(passwordMD5),
  192. systemclient: 'mdyxb'
  193. }).then(res => {
  194. if (res.code === 1) {
  195. console.log("缓存登录成功,开始SSO2", res);
  196. return this.handleSSO2(res);
  197. } else {
  198. console.log("缓存登录失败", res.msg);
  199. resolve(false);
  200. }
  201. }).catch(err => {
  202. console.log("缓存登录异常", err);
  203. resolve(false);
  204. });
  205. });
  206. }
  207. /* 处理 SSO2 结果 */
  208. handleSSO2(acc) {
  209. return new Promise((resolve) => {
  210. console.log("开始SSO2登录", acc);
  211. Vue.prototype.$Http.SSO2({
  212. accountno: acc.account_list[0].accountno,
  213. password: acc.account_list[0].token,
  214. accesstoken: acc.account_list[0].token,
  215. systemclient: acc.account_list[0].systemclient
  216. }).then(sso2Res => {
  217. if (sso2Res.code === 1) {
  218. console.log("SSO2成功", sso2Res);
  219. const account = { ...sso2Res.account_list.find(v => v.siteid == 'MD') || sso2Res.account_list[0] };
  220. try {
  221. uni.removeStorageSync('userMsg');
  222. uni.setStorageSync('userMsg', account);
  223. } catch (e) {
  224. console.error('存储用户信息失败:', e);
  225. }
  226. // 异步加载用户权限和站点参数
  227. const initPromise = Promise.all([query_userauth(), querySite_Parameter()]);
  228. getApp().globalData.systemInitIsComplete = initPromise;
  229. initPromise.then(() => {
  230. getApp().globalData.systemInitIsComplete = true;
  231. getApp().globalData.HomePageStartRendering.forEach(v => {
  232. try {
  233. v();
  234. } catch (e) {
  235. console.error('HomePageStartRendering 回调执行失败:', e);
  236. }
  237. });
  238. uni.reLaunch({
  239. url: '/pages/index/index',
  240. fail: () => {
  241. // 跳转失败时静默处理
  242. console.warn('reLaunch 跳转失败');
  243. }
  244. });
  245. }).catch(err => {
  246. console.error('初始化失败:', err);
  247. getApp().globalData.systemInitIsComplete = true;
  248. });
  249. resolve(true);
  250. } else {
  251. console.log("SSO2失败", sso2Res.msg);
  252. resolve(false);
  253. }
  254. }).catch(err => {
  255. console.log("SSO2异常", err);
  256. resolve(false);
  257. });
  258. });
  259. }
  260. /* 微信游客登录 - 带超时和错误处理 */
  261. wechatLogin() {
  262. return new Promise((resolve) => {
  263. if (this._isLoggingIn) {
  264. resolve(false);
  265. return;
  266. }
  267. this._isLoggingIn = true;
  268. uni.login({
  269. timeout: 10000,
  270. success(res) {
  271. Vue.prototype.$Http.loginbywechat({
  272. wechat_code: res.code,
  273. systemclient: getApp().globalData.systemclient
  274. }).then(res => {
  275. Vue.prototype.$Http.systemclient = getApp().globalData.systemclient;
  276. console.log("微信登录", res);
  277. if (Vue.prototype.cutoff(res.msg)) {
  278. this._isLoggingIn = false;
  279. return resolve(false);
  280. }
  281. try {
  282. uni.removeStorageSync('userMsg');
  283. uni.setStorageSync('userMsg', res.account_list[0]);
  284. } catch (e) {
  285. console.error('存储微信登录信息失败:', e);
  286. }
  287. // 异步初始化权限和配置
  288. const initPromise = Promise.all([query_userauth(), querySite_Parameter()]);
  289. getApp().globalData.systemInitIsComplete = initPromise;
  290. initPromise.then(() => {
  291. getApp().globalData.systemInitIsComplete = true;
  292. getApp().globalData.HomePageStartRendering.forEach(v => {
  293. try {
  294. v();
  295. } catch (e) {
  296. console.error('HomePageStartRendering 回调执行失败:', e);
  297. }
  298. });
  299. if (uni.getStorageSync('accountnoPwd')) {
  300. uni.navigateTo({
  301. url: "/pages/login/login",
  302. fail: () => console.warn('跳转到登录页失败')
  303. });
  304. }
  305. this._isLoggingIn = false;
  306. resolve(res.account_list[0].token);
  307. }).catch(() => {
  308. this._isLoggingIn = false;
  309. resolve(false);
  310. });
  311. }).catch(() => {
  312. this._isLoggingIn = false;
  313. resolve(false);
  314. });
  315. },
  316. fail: () => {
  317. console.log("微信登录失败");
  318. this._isLoggingIn = false;
  319. resolve(false);
  320. }
  321. });
  322. });
  323. }
  324. /* 自动登录入口 - 带超时保护 */
  325. autoLogin() {
  326. return new Promise((resolve) => {
  327. // 设置登录超时
  328. const timeout = setTimeout(() => {
  329. console.warn('登录流程超时');
  330. this._isLoggingIn = false;
  331. resolve(false);
  332. }, LOGIN_TIMEOUT + 5000);
  333. this.cachedAccountLogin().then(isCacheLoginSuccess => {
  334. clearTimeout(timeout);
  335. if (isCacheLoginSuccess) {
  336. console.log("缓存登录成功");
  337. resolve(true);
  338. } else {
  339. console.log("缓存登录失败,尝试微信登录");
  340. this.wechatLogin().then(result => {
  341. resolve(result);
  342. });
  343. }
  344. });
  345. });
  346. }
  347. }
  348. export {
  349. Login
  350. }