Showing
6 changed files
with
116 additions
and
72 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-20 19:53:12 | 2 | * @Date: 2025-03-20 19:53:12 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-21 15:28:49 | 4 | + * @LastEditTime: 2025-03-24 09:55:15 |
| 5 | * @FilePath: /mlaj/src/App.vue | 5 | * @FilePath: /mlaj/src/App.vue |
| 6 | - * @Description: 文件描述 | 6 | + * @Description: 入口文件 |
| 7 | --> | 7 | --> |
| 8 | <script setup> | 8 | <script setup> |
| 9 | import { RouterView } from "vue-router"; | 9 | import { RouterView } from "vue-router"; |
| ... | @@ -18,12 +18,12 @@ import { wxJsAPI } from "@/api/wx/config"; | ... | @@ -18,12 +18,12 @@ import { wxJsAPI } from "@/api/wx/config"; |
| 18 | import { apiList } from "@/api/wx/jsApiList.js"; | 18 | import { apiList } from "@/api/wx/jsApiList.js"; |
| 19 | import { wxInfo, getUrlParams, stringifyQuery } from "@/utils/tools"; | 19 | import { wxInfo, getUrlParams, stringifyQuery } from "@/utils/tools"; |
| 20 | 20 | ||
| 21 | -// 提供认证和购物车上下文 | 21 | +provideAuth(); // 提供全局认证状态 |
| 22 | -provideAuth(); | 22 | +provideCart(); // 提供全局购物车状态 |
| 23 | -provideCart(); | ||
| 24 | </script> | 23 | </script> |
| 25 | 24 | ||
| 26 | <template> | 25 | <template> |
| 26 | + <!-- 通过v-slot获取当前路由组件。使用component是为了实现动态组件渲染和加载状态的控制:当Component存在时渲染路由组件,不存在时显示加载动画。直接使用 --> | ||
| 27 | <router-view v-slot="{ Component }"> | 27 | <router-view v-slot="{ Component }"> |
| 28 | <div v-if="Component"> | 28 | <div v-if="Component"> |
| 29 | <component :is="Component" /> | 29 | <component :is="Component" /> | ... | ... |
src/api/data.js
deleted
100644 → 0
| 1 | -/* | ||
| 2 | - * @Date: 2022-06-17 14:54:29 | ||
| 3 | - * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | - * @LastEditTime: 2024-07-04 17:05:30 | ||
| 5 | - * @FilePath: /data-table/src/api/data.js | ||
| 6 | - * @Description: 表单数据接口 | ||
| 7 | - */ | ||
| 8 | -import { fn, fetch } from '@/api/fn'; | ||
| 9 | - | ||
| 10 | -const Api = { | ||
| 11 | - ADD_FORM_DATA: '/srv/?a=add_formdata', | ||
| 12 | - QUERY_FORM_DATA: '/srv/?a=query_formdata', | ||
| 13 | - MODI_FORM_DATA: '/srv/?a=modi_formdata', | ||
| 14 | - FLOW_FORM_DATA: '/srv/?a=flow_formdata', | ||
| 15 | -} | ||
| 16 | -/** | ||
| 17 | - * @description: 添加表单数据 | ||
| 18 | - * @param: form_code 表单唯一标识 | ||
| 19 | - * @param: data 待添加的数据,json对象结构;键值对记录变更的字段和值; | ||
| 20 | - */ | ||
| 21 | -export const addFormDataAPI = (params) => fn(fetch.post(Api.ADD_FORM_DATA, params)); | ||
| 22 | - | ||
| 23 | -/** | ||
| 24 | - * @description: 查询表单数据 | ||
| 25 | - * @param: form_code 表单唯一标识 | ||
| 26 | - * @param: id 数据ID | ||
| 27 | - */ | ||
| 28 | -export const queryFormDataAPI = (params) => fn(fetch.get(Api.QUERY_FORM_DATA, params)); | ||
| 29 | - | ||
| 30 | -/** | ||
| 31 | - * @description: 修改表单数据 | ||
| 32 | - * @param: form_code 表单唯一标识 | ||
| 33 | - * @param: id 数据ID | ||
| 34 | - * @param: data 待添加的数据,json对象结构;键值对记录变更的字段和值; | ||
| 35 | - */ | ||
| 36 | -export const modiFormDataAPI = (params) => fn(fetch.post(Api.MODI_FORM_DATA, params)); | ||
| 37 | - | ||
| 38 | -/** | ||
| 39 | - * @description: 流程表单数据 | ||
| 40 | - * @param: form_code 表单唯一标识 | ||
| 41 | - * @param: data_id 数据ID | ||
| 42 | - * @param: data 待添加的数据,json对象结构;键值对记录变更的字段和值; | ||
| 43 | - * @param: flow_node_code 流程节点 | ||
| 44 | - * @param: flow_node_action_id 用户点击的流程节点按钮ID | ||
| 45 | - * @param: flow_content 流程审批的文本意见 | ||
| 46 | - */ | ||
| 47 | -export const flowFormDataAPI = (params) => fn(fetch.post(Api.FLOW_FORM_DATA, params)); |
src/api/users.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-03-23 23:45:53 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-23 23:45:54 | ||
| 5 | + * @FilePath: /mlaj/src/api/users.js | ||
| 6 | + * @Description: 用户相关接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from './fn'; | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + USER_LOGIN: '/users/login', | ||
| 12 | + USER_REGISTER: '/users/register', | ||
| 13 | + USER_INFO: '/users/info', | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * @description: 用户登录 | ||
| 18 | + * @param: email 用户邮箱 | ||
| 19 | + * @param: password 用户密码 | ||
| 20 | + */ | ||
| 21 | +export const loginAPI = (params) => fn(fetch.post(Api.USER_LOGIN, params)); | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * @description: 用户注册 | ||
| 25 | + * @param: name 用户名称 | ||
| 26 | + * @param: email 用户邮箱 | ||
| 27 | + * @param: password 用户密码 | ||
| 28 | + */ | ||
| 29 | +export const registerAPI = (params) => fn(fetch.post(Api.USER_REGISTER, params)); | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * @description: 获取用户信息 | ||
| 33 | + */ | ||
| 34 | +export const getUserInfoAPI = () => fn(fetch.get(Api.USER_INFO)); |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-03-20 21:11:31 | 2 | * @Date: 2025-03-20 21:11:31 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-22 10:08:20 | 4 | + * @LastEditTime: 2025-03-24 01:10:13 |
| 5 | * @FilePath: /mlaj/src/contexts/auth.js | 5 | * @FilePath: /mlaj/src/contexts/auth.js |
| 6 | - * @Description: 文件描述 | 6 | + * @Description: 认证上下文管理模块,提供用户认证状态管理、登录登出功能 |
| 7 | */ | 7 | */ |
| 8 | + | ||
| 9 | +// 导入Vue的组合式API相关函数 | ||
| 8 | import { ref, provide, inject, onMounted } from 'vue' | 10 | import { ref, provide, inject, onMounted } from 'vue' |
| 9 | 11 | ||
| 10 | -// 创建认证上下文的key | 12 | +// 创建认证上下文的Symbol key,用于provide/inject依赖注入 |
| 13 | +// 使用Symbol确保key的唯一性,避免命名冲突 | ||
| 11 | const authKey = Symbol('auth') | 14 | const authKey = Symbol('auth') |
| 12 | 15 | ||
| 13 | /** | 16 | /** |
| 14 | * 提供认证功能的组合式函数 | 17 | * 提供认证功能的组合式函数 |
| 18 | + * 该函数创建并提供认证上下文,包含: | ||
| 19 | + * 1. 用户状态管理(currentUser) | ||
| 20 | + * 2. 加载状态管理(loading) | ||
| 21 | + * 3. 登录登出功能 | ||
| 22 | + * 4. Token过期检查 | ||
| 15 | */ | 23 | */ |
| 16 | export function provideAuth() { | 24 | export function provideAuth() { |
| 25 | + // 当前用户状态,初始为null表示未登录 | ||
| 17 | const currentUser = ref(null) | 26 | const currentUser = ref(null) |
| 27 | + // 加载状态标志,用于控制加载动画等UI展示 | ||
| 18 | const loading = ref(true) | 28 | const loading = ref(true) |
| 19 | 29 | ||
| 20 | - // 检查token是否过期(24小时) | 30 | + /** |
| 31 | + * 检查登录token是否过期 | ||
| 32 | + * @returns {boolean} true表示token有效,false表示token已过期 | ||
| 33 | + */ | ||
| 21 | const checkTokenExpiration = () => { | 34 | const checkTokenExpiration = () => { |
| 22 | const loginTimestamp = localStorage.getItem('loginTimestamp') | 35 | const loginTimestamp = localStorage.getItem('loginTimestamp') |
| 23 | if (loginTimestamp) { | 36 | if (loginTimestamp) { |
| 24 | const now = Date.now() | 37 | const now = Date.now() |
| 25 | const diff = now - parseInt(loginTimestamp) | 38 | const diff = now - parseInt(loginTimestamp) |
| 26 | - if (diff > 24 * 60 * 60 * 1000) { // 24小时 | 39 | + // 检查是否超过24小时(24 * 60 * 60 * 1000 毫秒) |
| 27 | - // 清理登录状态并返回false表示token已过期 | 40 | + if (diff > 24 * 60 * 60 * 1000) { |
| 41 | + // token过期,清理登录状态并返回false | ||
| 28 | logout() | 42 | logout() |
| 29 | return false | 43 | return false |
| 30 | } | 44 | } |
| ... | @@ -32,34 +46,64 @@ export function provideAuth() { | ... | @@ -32,34 +46,64 @@ export function provideAuth() { |
| 32 | return true | 46 | return true |
| 33 | } | 47 | } |
| 34 | 48 | ||
| 35 | - // 初始化时检查本地存储的用户信息 | 49 | + /** |
| 50 | + * 组件挂载时初始化用户状态 | ||
| 51 | + * 1. 从localStorage读取保存的用户信息 | ||
| 52 | + * 2. 检查token是否过期 | ||
| 53 | + * 3. 恢复用户状态或保持登出状态 | ||
| 54 | + */ | ||
| 36 | onMounted(() => { | 55 | onMounted(() => { |
| 37 | const savedUser = localStorage.getItem('currentUser') | 56 | const savedUser = localStorage.getItem('currentUser') |
| 38 | if (savedUser) { | 57 | if (savedUser) { |
| 39 | - // 只有在token未过期的情况下才恢复用户信息 | 58 | + // 检查token是否有效,有效则恢复用户状态 |
| 40 | if (checkTokenExpiration()) { | 59 | if (checkTokenExpiration()) { |
| 41 | currentUser.value = JSON.parse(savedUser) | 60 | currentUser.value = JSON.parse(savedUser) |
| 42 | } | 61 | } |
| 43 | } | 62 | } |
| 63 | + // 初始化完成,关闭加载状态 | ||
| 44 | loading.value = false | 64 | loading.value = false |
| 45 | }) | 65 | }) |
| 46 | 66 | ||
| 47 | - // 登录函数 | 67 | + /** |
| 68 | + * 用户登录函数 | ||
| 69 | + * @param {Object} userData - 用户数据对象,包含用户基本信息 | ||
| 70 | + * @returns {boolean} 登录是否成功 | ||
| 71 | + */ | ||
| 48 | const login = (userData) => { | 72 | const login = (userData) => { |
| 73 | + // 更新当前用户状态 | ||
| 49 | currentUser.value = userData | 74 | currentUser.value = userData |
| 75 | + if (currentUser.value) { | ||
| 76 | + try { | ||
| 77 | + // 持久化存储用户信息和登录时间戳 | ||
| 50 | localStorage.setItem('currentUser', JSON.stringify(userData)) | 78 | localStorage.setItem('currentUser', JSON.stringify(userData)) |
| 51 | localStorage.setItem('loginTimestamp', Date.now().toString()) | 79 | localStorage.setItem('loginTimestamp', Date.now().toString()) |
| 80 | + } catch (error) { | ||
| 81 | + console.error('Failed to save user data to localStorage:', error) | ||
| 82 | + } | ||
| 83 | + } | ||
| 52 | return true | 84 | return true |
| 53 | } | 85 | } |
| 54 | 86 | ||
| 55 | - // 登出函数 | 87 | + /** |
| 88 | + * 用户登出函数 | ||
| 89 | + * 清理用户状态和本地存储的认证信息 | ||
| 90 | + */ | ||
| 56 | const logout = () => { | 91 | const logout = () => { |
| 92 | + // 清空当前用户状态 | ||
| 57 | currentUser.value = null | 93 | currentUser.value = null |
| 94 | + // 清理本地存储的用户信息和登录时间戳 | ||
| 58 | localStorage.removeItem('currentUser') | 95 | localStorage.removeItem('currentUser') |
| 59 | localStorage.removeItem('loginTimestamp') | 96 | localStorage.removeItem('loginTimestamp') |
| 60 | } | 97 | } |
| 61 | 98 | ||
| 62 | - // 提供认证上下文 | 99 | + /** |
| 100 | + * 提供认证上下文给子组件使用 | ||
| 101 | + * 包含: | ||
| 102 | + * - currentUser: 当前用户状态 | ||
| 103 | + * - loading: 加载状态 | ||
| 104 | + * - login: 登录函数 | ||
| 105 | + * - logout: 登出函数 | ||
| 106 | + */ | ||
| 63 | provide(authKey, { | 107 | provide(authKey, { |
| 64 | currentUser, | 108 | currentUser, |
| 65 | loading, | 109 | loading, |
| ... | @@ -67,6 +111,7 @@ export function provideAuth() { | ... | @@ -67,6 +111,7 @@ export function provideAuth() { |
| 67 | logout | 111 | logout |
| 68 | }) | 112 | }) |
| 69 | 113 | ||
| 114 | + // 返回认证相关的状态和方法,供组件直接使用 | ||
| 70 | return { | 115 | return { |
| 71 | currentUser, | 116 | currentUser, |
| 72 | loading, | 117 | loading, |
| ... | @@ -76,11 +121,14 @@ export function provideAuth() { | ... | @@ -76,11 +121,14 @@ export function provideAuth() { |
| 76 | } | 121 | } |
| 77 | 122 | ||
| 78 | /** | 123 | /** |
| 79 | - * 使用认证功能的组合式函数 | 124 | + * 在子组件中使用认证功能的组合式函数 |
| 80 | - * @returns {Object} 认证上下文值 | 125 | + * @returns {Object} 认证上下文对象,包含用户状态和认证方法 |
| 126 | + * @throws {Error} 如果在provideAuth范围外使用则抛出错误 | ||
| 81 | */ | 127 | */ |
| 82 | export function useAuth() { | 128 | export function useAuth() { |
| 129 | + // 注入认证上下文 | ||
| 83 | const auth = inject(authKey) | 130 | const auth = inject(authKey) |
| 131 | + // 确保在provideAuth的范围内使用 | ||
| 84 | if (!auth) { | 132 | if (!auth) { |
| 85 | throw new Error('useAuth 必须在 provideAuth 的范围内使用') | 133 | throw new Error('useAuth 必须在 provideAuth 的范围内使用') |
| 86 | } | 134 | } | ... | ... |
| ... | @@ -12,6 +12,7 @@ import qs from 'Qs' | ... | @@ -12,6 +12,7 @@ import qs from 'Qs' |
| 12 | import { strExist } from '@/utils/tools' | 12 | import { strExist } from '@/utils/tools' |
| 13 | // import { parseQueryString } from '@/utils/tools' | 13 | // import { parseQueryString } from '@/utils/tools' |
| 14 | 14 | ||
| 15 | +axios.defaults.baseURL = 'http://localhost:3000/api'; | ||
| 15 | axios.defaults.params = { | 16 | axios.defaults.params = { |
| 16 | f: 'good', | 17 | f: 'good', |
| 17 | }; | 18 | }; | ... | ... |
| ... | @@ -114,15 +114,16 @@ import { ref } from 'vue' | ... | @@ -114,15 +114,16 @@ import { ref } from 'vue' |
| 114 | import { useRoute, useRouter } from 'vue-router' | 114 | import { useRoute, useRouter } from 'vue-router' |
| 115 | import FrostedGlass from '@/components/ui/FrostedGlass.vue' | 115 | import FrostedGlass from '@/components/ui/FrostedGlass.vue' |
| 116 | import { useAuth } from '@/contexts/auth' | 116 | import { useAuth } from '@/contexts/auth' |
| 117 | -import { useTitle } from '@vueuse/core'; | 117 | +import { useTitle } from '@vueuse/core' |
| 118 | +import { loginAPI } from '@/api/users' | ||
| 118 | const $route = useRoute(); | 119 | const $route = useRoute(); |
| 119 | const $router = useRouter(); | 120 | const $router = useRouter(); |
| 120 | useTitle($route.meta.title); | 121 | useTitle($route.meta.title); |
| 121 | const router = useRouter() | 122 | const router = useRouter() |
| 122 | const { login } = useAuth() | 123 | const { login } = useAuth() |
| 123 | 124 | ||
| 124 | -const email = ref('') | 125 | +const email = ref('user1@example.com') |
| 125 | -const password = ref('') | 126 | +const password = ref('password123') |
| 126 | const error = ref('') | 127 | const error = ref('') |
| 127 | const loading = ref(false) | 128 | const loading = ref(false) |
| 128 | 129 | ||
| ... | @@ -136,13 +137,20 @@ const handleSubmit = async () => { | ... | @@ -136,13 +137,20 @@ const handleSubmit = async () => { |
| 136 | error.value = '' | 137 | error.value = '' |
| 137 | loading.value = true | 138 | loading.value = true |
| 138 | 139 | ||
| 139 | - // 使用auth.js中的login函数 | 140 | + // 调用登录接口 |
| 140 | - const success = login({ | 141 | + const response = await loginAPI({ |
| 141 | email: email.value, | 142 | email: email.value, |
| 142 | - name: '李玉红', | 143 | + password: password.value |
| 143 | - avatar: 'https://cdn.ipadbiz.cn/mlaj/images/user-avatar-1.jpg' | ||
| 144 | }) | 144 | }) |
| 145 | 145 | ||
| 146 | + if (response.code !== 1) { | ||
| 147 | + error.value = response.msg || '登录失败,请检查您的凭据' | ||
| 148 | + return | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + // 登录成功,更新auth状态 | ||
| 152 | + const success = login(response.data) | ||
| 153 | + | ||
| 146 | if (success) { | 154 | if (success) { |
| 147 | // 如果有重定向参数,登录成功后跳转到对应页面 | 155 | // 如果有重定向参数,登录成功后跳转到对应页面 |
| 148 | const redirect = $route.query.redirect | 156 | const redirect = $route.query.redirect | ... | ... |
-
Please register or login to post a comment