App.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <script>
  2. export default {
  3. onLaunch: function() {
  4. // console.log('App Launch');
  5. // 检查登录状态
  6. this.checkLoginStatus();
  7. },
  8. onShow: function() {
  9. // console.log('App Show');
  10. // 每次显示应用时检查登录状态
  11. this.checkLoginStatus();
  12. },
  13. onHide: function() {
  14. // console.log('App Hide');
  15. // 应用进入后台时释放资源
  16. this.releaseGlobalResources();
  17. },
  18. // 全局错误捕获
  19. onError: function(error) {
  20. this.handleGlobalError(error);
  21. },
  22. methods: {
  23. // 释放全局资源
  24. releaseGlobalResources: function() {
  25. console.log('Releasing global resources');
  26. // 清除可能存在的定时器
  27. try {
  28. // 这里可以添加更多的资源释放逻辑
  29. } catch (e) {
  30. console.error('Error releasing resources:', e);
  31. }
  32. },
  33. // 全局错误处理
  34. handleGlobalError: function(error) {
  35. console.error('Global error captured:', error);
  36. // 处理特定类型的错误
  37. if (error.message && error.message.includes('Failed to receiveTasks')) {
  38. // 提取实例ID
  39. const instanceIdMatch = error.message.match(/instance \((\d+)\)/);
  40. const instanceId = instanceIdMatch ? instanceIdMatch[1] : 'unknown';
  41. // 记录详细错误信息
  42. console.error(`UHF plugin instance (${instanceId}) error: Failed to receiveTasks`);
  43. // 显示错误提示
  44. uni.showToast({
  45. title: `设备通信错误(实例${instanceId}),请重试`,
  46. icon: 'none',
  47. duration: 3000
  48. });
  49. // 尝试重置插件实例
  50. setTimeout(() => {
  51. this.resetPluginInstance();
  52. }, 1000);
  53. }
  54. },
  55. // 重置应用状态
  56. resetAppState: function() {
  57. console.log('Resetting app state due to plugin error');
  58. try {
  59. // 清除所有相关缓存数据
  60. uni.removeStorageSync('uhf_plugin_state');
  61. uni.removeStorageSync('equipment_token');
  62. // 重新加载当前页面
  63. const pages = getCurrentPages();
  64. if (pages && pages.length > 0) {
  65. const currentPage = pages[pages.length - 1];
  66. // 如果当前是首页,则刷新页面
  67. if (currentPage.route === 'pages/index/index') {
  68. currentPage.$vm.$destroy();
  69. uni.redirectTo({
  70. url: '/pages/index/index'
  71. });
  72. } else {
  73. // 否则跳转到首页
  74. uni.redirectTo({
  75. url: '/pages/index/index'
  76. });
  77. }
  78. } else {
  79. // 如果没有页面,跳转到首页
  80. uni.redirectTo({
  81. url: '/pages/index/index'
  82. });
  83. }
  84. } catch (e) {
  85. console.error('Error resetting app state:', e);
  86. }
  87. },
  88. // 检查并清理插件实例
  89. checkAndCleanupPluginInstance: function() {
  90. console.log('Checking and cleaning up plugin instance');
  91. try {
  92. // 如果存在页面实例
  93. const pages = getCurrentPages();
  94. if (pages && pages.length > 0) {
  95. const currentPage = pages[pages.length - 1];
  96. if (currentPage && currentPage.$vm) {
  97. // 如果页面有uhfSFHelper实例,尝试释放设备
  98. if (currentPage.$vm.uhfSFHelper) {
  99. try {
  100. console.log('Releasing device from current page');
  101. currentPage.$vm.releaseDevice();
  102. } catch (e) {
  103. console.error('Error releasing device:', e);
  104. }
  105. // 清除插件实例
  106. currentPage.$vm.uhfSFHelper = null;
  107. console.log('Plugin instance cleared from current page');
  108. }
  109. }
  110. }
  111. // 清除全局插件相关缓存
  112. uni.removeStorageSync('uhf_plugin_instance');
  113. console.log('Plugin related storage cleared');
  114. } catch (e) {
  115. console.error('Error checking and cleaning up plugin instance:', e);
  116. }
  117. },
  118. // Vue2风格的checkLoginStatus方法实现 - 优化版
  119. checkLoginStatus: function() {
  120. // 防止短时间内重复导航到登录页面
  121. if (this.isNavigatingToLogin) {
  122. console.log('正在导航到登录页面,忽略重复调用');
  123. return;
  124. }
  125. try {
  126. // 1. 首先尝试从全局数据获取
  127. let token = this.globalData.token;
  128. let expireAt = this.globalData.expireAt;
  129. let userInfo = this.globalData.userInfo;
  130. // 2. 如果全局数据不可用,尝试从本地存储恢复
  131. if (!token || !expireAt) {
  132. token = uni.getStorageSync('equipment_token');
  133. expireAt = uni.getStorageSync('token_expire_time');
  134. userInfo = uni.getStorageSync('user_info');
  135. // 添加详细日志,帮助调试
  136. console.log('从本地存储获取登录信息 - token:', !!token, 'expireAt:', !!expireAt);
  137. // 如果从本地存储恢复成功,更新全局数据
  138. if (token && expireAt) {
  139. this.globalData.token = token;
  140. this.globalData.expireAt = expireAt;
  141. this.globalData.userInfo = userInfo;
  142. this.globalData.isLoggedIn = true;
  143. console.log('从本地存储恢复登录信息成功');
  144. }
  145. }
  146. // 获取当前页面路径
  147. const pages = getCurrentPages();
  148. let currentPath = '';
  149. if (pages && pages.length > 0) {
  150. const currentPage = pages[pages.length - 1];
  151. currentPath = currentPage.route;
  152. console.log('当前页面路径:', currentPath);
  153. }
  154. // 移除特殊账号处理逻辑,统一按token和过期时间判断
  155. if (!token || !expireAt) {
  156. // 未登录或缺少过期时间,跳转到登录页面
  157. // 检查当前是否已经在登录页面,避免重复跳转
  158. if (currentPath !== 'pages/login/login') {
  159. console.log('未登录或缺少过期时间,跳转到登录页面');
  160. this.isNavigatingToLogin = true;
  161. uni.redirectTo({
  162. url: '/pages/login/login',
  163. success: function() {
  164. console.log('导航到登录页面成功');
  165. // 导航成功后重置标志
  166. setTimeout(function() {
  167. this.isNavigatingToLogin = false;
  168. }.bind(this), 1000);
  169. }.bind(this),
  170. fail: function(err) {
  171. console.error('导航到登录页面失败:', err);
  172. this.isNavigatingToLogin = false;
  173. }.bind(this)
  174. });
  175. } else {
  176. console.log('已经在登录页面,无需跳转');
  177. }
  178. } else {
  179. // 检查token是否过期
  180. let expireTime;
  181. try {
  182. // 健壮的过期时间解析逻辑
  183. if (typeof expireAt === 'string') {
  184. // 尝试直接解析为数字
  185. const timestamp = parseInt(expireAt);
  186. if (!isNaN(timestamp)) {
  187. expireTime = timestamp;
  188. } else {
  189. // 如果不是数字字符串,尝试作为日期字符串解析
  190. expireTime = new Date(expireAt).getTime();
  191. }
  192. } else if (typeof expireAt === 'number') {
  193. // 如果已经是数字类型,直接使用
  194. expireTime = expireAt;
  195. }
  196. } catch (e) {
  197. console.error('解析过期时间失败:', e);
  198. }
  199. // 添加详细日志,记录过期时间解析结果
  200. console.log('过期时间解析结果 - expireAt:', expireAt, 'expireTime:', expireTime);
  201. // 确保过期时间有效
  202. if (isNaN(expireTime)) {
  203. console.error('无效的过期时间:', expireAt);
  204. // 跳转到登录页
  205. if (currentPath !== 'pages/login/login') {
  206. this.isNavigatingToLogin = true;
  207. uni.redirectTo({
  208. url: '/pages/login/login',
  209. success: function() {
  210. setTimeout(function() {
  211. this.isNavigatingToLogin = false;
  212. }.bind(this), 1000);
  213. }.bind(this),
  214. fail: function(err) {
  215. console.error('导航到登录页面失败:', err);
  216. this.isNavigatingToLogin = false;
  217. }.bind(this)
  218. });
  219. }
  220. return;
  221. }
  222. const currentTime = new Date().getTime();
  223. // 提前1分钟检查过期,给用户预留时间
  224. if (currentTime + 60 * 1000 > expireTime) {
  225. console.log('登录即将过期或已过期,需要重新登录 - 当前时间:', currentTime, '过期时间:', expireTime);
  226. // 清除登录信息
  227. this.globalData.token = '';
  228. this.globalData.expireAt = '';
  229. this.globalData.userInfo = {};
  230. this.globalData.isLoggedIn = false;
  231. uni.removeStorageSync('equipment_token');
  232. uni.removeStorageSync('token_expire_time');
  233. uni.removeStorageSync('user_info');
  234. // 跳转到登录页面
  235. if (currentPath !== 'pages/login/login') {
  236. this.isNavigatingToLogin = true;
  237. uni.redirectTo({
  238. url: '/pages/login/login',
  239. success: function() {
  240. console.log('导航到登录页面成功');
  241. // 导航成功后重置标志
  242. setTimeout(function() {
  243. this.isNavigatingToLogin = false;
  244. }.bind(this), 1000);
  245. }.bind(this),
  246. fail: function(err) {
  247. console.error('导航到登录页面失败:', err);
  248. this.isNavigatingToLogin = false;
  249. }.bind(this)
  250. });
  251. }
  252. } else {
  253. // 已登录且token有效,设置全局登录状态
  254. this.globalData.isLoggedIn = true;
  255. this.globalData.token = token;
  256. this.globalData.expireAt = expireAt;
  257. this.globalData.equipmentManage = this.globalData.equipmentManage || 0;
  258. this.globalData.userInfo = userInfo;
  259. // 计算剩余时间并记录日志,帮助调试
  260. const remainingTime = (expireTime - currentTime) / 1000 / 60; // 转换为分钟
  261. console.log('登录状态有效,无需重新登录 - 剩余时间约:', Math.round(remainingTime), '分钟');
  262. // 如果已经在登录页面,自动跳转到首页
  263. if (currentPath === 'pages/login/login') {
  264. console.log('登录状态有效但当前在登录页面,自动跳转到首页');
  265. this.isNavigatingToLogin = true;
  266. setTimeout(function() {
  267. uni.switchTab({
  268. url: '/pages/index/index',
  269. success: function() {
  270. console.log('从登录页跳转到首页成功');
  271. this.isNavigatingToLogin = false;
  272. }.bind(this),
  273. fail: function(err) {
  274. console.error('从登录页跳转到首页失败:', err);
  275. this.isNavigatingToLogin = false;
  276. }.bind(this)
  277. });
  278. }.bind(this), 500);
  279. }
  280. }
  281. }
  282. } catch (e) {
  283. console.error('检查登录状态时发生错误:', e);
  284. }
  285. },
  286. // 重置插件实例
  287. resetPluginInstance: function() {
  288. console.log('Resetting plugin instance globally');
  289. try {
  290. this.checkAndCleanupPluginInstance();
  291. // 延迟一段时间后重置应用状态
  292. setTimeout(() => {
  293. this.resetAppState();
  294. }, 1000);
  295. } catch (e) {
  296. console.error('Error resetting plugin instance:', e);
  297. }
  298. }
  299. },
  300. globalData: {
  301. isLoggedIn: false,
  302. token: '',
  303. expireAt: '',
  304. equipmentManage: 0,
  305. userInfo: {}
  306. },
  307. // 导航状态控制
  308. data() {
  309. return {
  310. isNavigatingToLogin: false
  311. }
  312. }
  313. }
  314. </script>
  315. <style>
  316. /*每个页面公共css */
  317. @import "components/colorui/main.css";
  318. @import "components/colorui/icon.css";
  319. </style>