From e97724337c7d25a2d0021f928cebe942cc131c2e Mon Sep 17 00:00:00 2001 From: luoyuehang <2830398107@qq.com> Date: Tue, 9 Dec 2025 23:18:21 +0800 Subject: [PATCH] =?UTF-8?q?app2=E7=99=BB=E5=BD=95=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E4=B8=8E=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/app2/src/main.js | 6 +- .../resources/app2/src/router/permission.js | 30 +++++++++ src/main/resources/app2/src/services/api.js | 36 +++++++++- .../app2/src/services/deviceService.js | 32 +++++++++ src/main/resources/app2/src/stores/auth.js | 30 +++++++++ src/main/resources/app2/src/stores/user.js | 67 +++++++++++++++++++ .../resources/app2/src/views/ProfilePage.vue | 32 +++++---- .../app2/src/views/StudentLoginPage.vue | 16 +++++ 8 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 src/main/resources/app2/src/router/permission.js create mode 100644 src/main/resources/app2/src/services/deviceService.js create mode 100644 src/main/resources/app2/src/stores/auth.js create mode 100644 src/main/resources/app2/src/stores/user.js diff --git a/src/main/resources/app2/src/main.js b/src/main/resources/app2/src/main.js index e04bef7..bb4cef0 100644 --- a/src/main/resources/app2/src/main.js +++ b/src/main/resources/app2/src/main.js @@ -1,15 +1,17 @@ +// src/main.js import './assets/main.css' -import './assets/mobile.css' // 添加这行 +import './assets/mobile.css' import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' +import './router/permission' // 确保引入了路由守卫 const app = createApp(App) app.use(createPinia()) app.use(router) -app.mount('#app') \ No newline at end of file +app.mount('#app') diff --git a/src/main/resources/app2/src/router/permission.js b/src/main/resources/app2/src/router/permission.js new file mode 100644 index 0000000..482c2a5 --- /dev/null +++ b/src/main/resources/app2/src/router/permission.js @@ -0,0 +1,30 @@ +// src/router/permission.js +import router from './index' + +// 不需要登录的白名单路由 +const whiteList = ['/', '/login', '/register'] + +router.beforeEach((to, from, next) => { + // 检查是否有有效的token + const token = localStorage.getItem('token') + + if (token) { + // 有token的情况下 + if (to.path === '/' || to.path === '/login') { + // 已登录用户访问登录页时重定向到首页 + next('/home') + } else { + // 访问其他需要权限的页面,允许通过 + next() + } + } else { + // 没有token的情况下 + if (whiteList.includes(to.path)) { + // 白名单路由可以直接访问 + next() + } else { + // 非白名单路由重定向到登录页 + next('/') + } + } +}) diff --git a/src/main/resources/app2/src/services/api.js b/src/main/resources/app2/src/services/api.js index f39f021..8df6d7e 100644 --- a/src/main/resources/app2/src/services/api.js +++ b/src/main/resources/app2/src/services/api.js @@ -2,10 +2,44 @@ import axios from 'axios' const apiClient = axios.create({ - baseURL: 'http://localhost:8080', // Adjust to your backend URL + baseURL: 'http://localhost:8080', headers: { 'Content-Type': 'application/json' } }) +// 请求拦截器 +apiClient.interceptors.request.use( + (config) => { + // 从本地存储获取token + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +apiClient.interceptors.response.use( + (response) => { + return response + }, + (error) => { + if (error.response?.status === 401) { + // token过期或无效,清除用户信息并跳转到登录页 + localStorage.removeItem('token') + localStorage.removeItem('userId') + localStorage.removeItem('username') + localStorage.removeItem('userType') + localStorage.removeItem('studentId') + window.location.href = '/' + } + return Promise.reject(error) + } +) + export default apiClient diff --git a/src/main/resources/app2/src/services/deviceService.js b/src/main/resources/app2/src/services/deviceService.js new file mode 100644 index 0000000..932cf1c --- /dev/null +++ b/src/main/resources/app2/src/services/deviceService.js @@ -0,0 +1,32 @@ +// src/services/deviceService.js +import api from './api' + +export const deviceService = { + // 获取终端设备信息 + async getTerminalInfo(terminalId) { + try { + const response = await api.get(`/api/water/terminal/${terminalId}`) + return response.data + } catch (error) { + // 更好的错误处理 + if (error.response?.status === 403) { + console.error('权限不足,请重新登录') + // 可以在这里触发重新登录逻辑 + } + throw error.response?.data || error.message + } + }, + + // 获取水质信息 + async getWaterQualityInfo(deviceId) { + try { + const response = await api.get(`/api/water/quality/${deviceId}`) + return response.data + } catch (error) { + if (error.response?.status === 403) { + console.error('权限不足,无法获取水质信息') + } + throw error.response?.data || error.message + } + } +} diff --git a/src/main/resources/app2/src/stores/auth.js b/src/main/resources/app2/src/stores/auth.js new file mode 100644 index 0000000..a06e5c8 --- /dev/null +++ b/src/main/resources/app2/src/stores/auth.js @@ -0,0 +1,30 @@ +// src/stores/auth.js +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' // 添加 computed 导入 + +export const useAuthStore = defineStore('auth', () => { + const user = ref(null) + const token = ref(localStorage.getItem('token')) + + const login = (userData, authToken) => { + user.value = userData + token.value = authToken + localStorage.setItem('token', authToken) + } + + const logout = () => { + user.value = null + token.value = null + localStorage.removeItem('token') + } + + const isAuthenticated = computed(() => !!token.value) // 使用 computed 包装 + + return { + user, + token, + isAuthenticated, + login, + logout + } +}) diff --git a/src/main/resources/app2/src/stores/user.js b/src/main/resources/app2/src/stores/user.js new file mode 100644 index 0000000..82c871a --- /dev/null +++ b/src/main/resources/app2/src/stores/user.js @@ -0,0 +1,67 @@ +// src/stores/user.js +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' + +export const useUserStore = defineStore('user', () => { + const token = ref(localStorage.getItem('token') || '') + const userId = ref(localStorage.getItem('userId') || '') + const username = ref(localStorage.getItem('username') || '') + const userType = ref(localStorage.getItem('userType') || '') + const studentId = ref(localStorage.getItem('studentId') || '') + + // 计算属性:是否已登录 + const isLoggedIn = computed(() => !!token.value) + + // 设置用户信息 + const setUser = (userInfo) => { + token.value = userInfo.token + userId.value = userInfo.userId + username.value = userInfo.username + userType.value = userInfo.userType + studentId.value = userInfo.studentId + + // 保存到本地存储 + localStorage.setItem('token', userInfo.token) + localStorage.setItem('userId', userInfo.userId) + localStorage.setItem('username', userInfo.username) + localStorage.setItem('userType', userInfo.userType) + localStorage.setItem('studentId', userInfo.studentId) + } + + // 清除用户信息 + const clearUser = () => { + token.value = '' + userId.value = '' + username.value = '' + userType.value = '' + studentId.value = '' + + // 清除本地存储 + localStorage.removeItem('token') + localStorage.removeItem('userId') + localStorage.removeItem('username') + localStorage.removeItem('userType') + localStorage.removeItem('studentId') + } + + // 从本地存储初始化用户信息 + const initFromStorage = () => { + token.value = localStorage.getItem('token') || '' + userId.value = localStorage.getItem('userId') || '' + username.value = localStorage.getItem('username') || '' + userType.value = localStorage.getItem('userType') || '' + studentId.value = localStorage.getItem('studentId') || '' + } + + return { + token, + userId, + username, + userType, + studentId, + isLoggedIn, + setUser, + clearUser, + initFromStorage + } +}) diff --git a/src/main/resources/app2/src/views/ProfilePage.vue b/src/main/resources/app2/src/views/ProfilePage.vue index 38222f6..0669cfb 100644 --- a/src/main/resources/app2/src/views/ProfilePage.vue +++ b/src/main/resources/app2/src/views/ProfilePage.vue @@ -152,20 +152,24 @@