hookehuyr

Merge branch 'feature/后端测试' into develop

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" />
......
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));
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
......