diff --git a/client/mobile/api/auth.ts b/client/mobile/api/auth.ts new file mode 100644 index 0000000..8f1f82d --- /dev/null +++ b/client/mobile/api/auth.ts @@ -0,0 +1,118 @@ +import axios from 'axios'; +import type { User } from '../../share/types.ts'; + +// 从原api.ts导入基础配置 +const API_BASE_URL = '/api'; + +// 定义API返回数据类型 +interface AuthLoginResponse { + message: string; + token: string; + refreshToken?: string; + user: User; +} + +interface AuthResponse { + message: string; + [key: string]: any; +} + +// 定义Auth API接口类型 +interface AuthAPIType { + login: (username: string, password: string, latitude?: number, longitude?: number) => Promise; + register: (username: string, email: string, password: string) => Promise; + logout: () => Promise; + getCurrentUser: () => Promise; + updateUser: (userId: number, userData: Partial) => Promise; + changePassword: (oldPassword: string, newPassword: string) => Promise; + requestPasswordReset: (email: string) => Promise; + resetPassword: (token: string, newPassword: string) => Promise; +} + +// Auth相关API +export const AuthAPI: AuthAPIType = { + // 登录API + login: async (username: string, password: string, latitude?: number, longitude?: number) => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/login`, { + username, + password, + latitude, + longitude + }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 注册API + register: async (username: string, email: string, password: string) => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/register`, { username, email, password }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 登出API + logout: async () => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/logout`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取当前用户信息 + getCurrentUser: async () => { + try { + const response = await axios.get(`${API_BASE_URL}/auth/me`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新用户信息 + updateUser: async (userId: number, userData: Partial) => { + try { + const response = await axios.put(`${API_BASE_URL}/auth/users/${userId}`, userData); + return response.data; + } catch (error) { + throw error; + } + }, + + // 修改密码 + changePassword: async (oldPassword: string, newPassword: string) => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/change-password`, { oldPassword, newPassword }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 请求重置密码 + requestPasswordReset: async (email: string) => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/request-password-reset`, { email }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 重置密码 + resetPassword: async (token: string, newPassword: string) => { + try { + const response = await axios.post(`${API_BASE_URL}/auth/reset-password`, { token, newPassword }); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/chart.ts b/client/mobile/api/chart.ts new file mode 100644 index 0000000..f40212e --- /dev/null +++ b/client/mobile/api/chart.ts @@ -0,0 +1,74 @@ +import axios from 'axios'; + +const API_BASE_URL = '/api'; + +// 图表数据API接口类型 +interface ChartDataResponse { + message: string; + data: T; +} + +interface UserActivityData { + date: string; + count: number; +} + +interface FileUploadsData { + month: string; + count: number; +} + +interface FileTypesData { + type: string; + value: number; +} + +interface DashboardOverviewData { + userCount: number; + fileCount: number; + articleCount: number; + todayLoginCount: number; +} + +// 图表数据API +export const ChartAPI = { + // 获取用户活跃度数据 + getUserActivity: async (): Promise> => { + try { + const response = await axios.get(`${API_BASE_URL}/charts/user-activity`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取文件上传统计数据 + getFileUploads: async (): Promise> => { + try { + const response = await axios.get(`${API_BASE_URL}/charts/file-uploads`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取文件类型分布数据 + getFileTypes: async (): Promise> => { + try { + const response = await axios.get(`${API_BASE_URL}/charts/file-types`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取仪表盘概览数据 + getDashboardOverview: async (): Promise> => { + try { + const response = await axios.get(`${API_BASE_URL}/charts/dashboard-overview`); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/file.ts b/client/mobile/api/file.ts new file mode 100644 index 0000000..cb66a20 --- /dev/null +++ b/client/mobile/api/file.ts @@ -0,0 +1,175 @@ +import axios from 'axios'; +import type { MinioUploadPolicy, OSSUploadPolicy } from '@d8d-appcontainer/types'; +import type { + FileLibrary, FileCategory +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +interface FileUploadPolicyResponse { + message: string; + data: MinioUploadPolicy | OSSUploadPolicy; +} + +interface FileListResponse { + message: string; + data: { + list: FileLibrary[]; + pagination: { + current: number; + pageSize: number; + total: number; + }; + }; +} + +interface FileSaveResponse { + message: string; + data: FileLibrary; +} + +interface FileInfoResponse { + message: string; + data: FileLibrary; +} + +interface FileDeleteResponse { + message: string; +} + + +interface FileCategoryListResponse { + data: FileCategory[]; + total: number; + page: number; + pageSize: number; +} + +interface FileCategoryCreateResponse { + message: string; + data: FileCategory; +} + +interface FileCategoryUpdateResponse { + message: string; + data: FileCategory; +} + +interface FileCategoryDeleteResponse { + message: string; +} + +// 文件管理API +export const FileAPI = { + // 获取文件上传策略 + getUploadPolicy: async (filename: string, prefix: string = 'uploads/', maxSize: number = 10 * 1024 * 1024): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/upload/policy`, { + params: { filename, prefix, maxSize } + }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 保存文件信息 + saveFileInfo: async (fileData: Partial): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/upload/save`, fileData); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取文件列表 + getFileList: async (params?: { + page?: number, + pageSize?: number, + category_id?: number, + fileType?: string, + keyword?: string + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/upload/list`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取单个文件信息 + getFileInfo: async (id: number): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/upload/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新文件下载计数 + updateDownloadCount: async (id: number): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/upload/${id}/download`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 删除文件 + deleteFile: async (id: number): Promise => { + try { + const response = await axios.delete(`${API_BASE_URL}/upload/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取文件分类列表 + getCategories: async (params?: { + page?: number, + pageSize?: number, + search?: string + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/file-categories`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 创建文件分类 + createCategory: async (data: Partial): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/file-categories`, data); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新文件分类 + updateCategory: async (id: number, data: Partial): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/file-categories/${id}`, data); + return response.data; + } catch (error) { + throw error; + } + }, + + // 删除文件分类 + deleteCategory: async (id: number): Promise => { + try { + const response = await axios.delete(`${API_BASE_URL}/file-categories/${id}`); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/home.ts b/client/mobile/api/home.ts new file mode 100644 index 0000000..a144f10 --- /dev/null +++ b/client/mobile/api/home.ts @@ -0,0 +1,79 @@ +import axios from 'axios'; +import type { + KnowInfo +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +// 首页数据相关类型定义 +interface HomeBannersResponse { + message: string; + data: KnowInfo[]; +} + +interface HomeNewsResponse { + message: string; + data: KnowInfo[]; + pagination: { + total: number; + current: number; + pageSize: number; + totalPages: number; + }; +} + +interface HomeNoticesResponse { + message: string; + data: { + id: number; + title: string; + content: string; + created_at: string; + }[]; + pagination: { + total: number; + current: number; + pageSize: number; + totalPages: number; + }; +} + +// 首页API +export const HomeAPI = { + // 获取轮播图 + getBanners: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/home/banners`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取新闻列表 + getNews: async (params?: { + page?: number, + pageSize?: number, + category?: string + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/home/news`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取通知列表 + getNotices: async (params?: { + page?: number, + pageSize?: number + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/home/notices`, { params }); + return response.data; + } catch (error) { + throw error; + } + } +}; diff --git a/client/mobile/api/index.ts b/client/mobile/api/index.ts new file mode 100644 index 0000000..6f357bb --- /dev/null +++ b/client/mobile/api/index.ts @@ -0,0 +1,9 @@ +export * from './auth.ts'; +export * from './user.ts'; +export * from './file.ts'; +export * from './theme.ts'; +export * from './chart.ts'; +export * from './home.ts'; +export * from './map.ts'; +export * from './system.ts'; +export * from './message.ts'; \ No newline at end of file diff --git a/client/mobile/api/map.ts b/client/mobile/api/map.ts new file mode 100644 index 0000000..7092d29 --- /dev/null +++ b/client/mobile/api/map.ts @@ -0,0 +1,64 @@ +import axios from 'axios'; +import type { + LoginLocation, LoginLocationDetail, +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + + +// 地图相关API的接口类型定义 +export interface LoginLocationResponse { + message: string; + data: LoginLocation[]; +} + +export interface LoginLocationDetailResponse { + message: string; + data: LoginLocationDetail; +} + +export interface LoginLocationUpdateResponse { + message: string; + data: LoginLocationDetail; +} + +// 地图相关API +export const MapAPI = { + // 获取地图标记点数据 + getMarkers: async (params?: { + startTime?: string; + endTime?: string; + userId?: number + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/map/markers`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取登录位置详情 + getLocationDetail: async (locationId: number): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/map/location/${locationId}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新登录位置信息 + updateLocation: async (locationId: number, data: { + longitude: number; + latitude: number; + location_name?: string; + }): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/map/location/${locationId}`, data); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/message.ts b/client/mobile/api/message.ts new file mode 100644 index 0000000..c3e7bd7 --- /dev/null +++ b/client/mobile/api/message.ts @@ -0,0 +1,99 @@ +import axios from 'axios'; +import type { + MessageType, MessageStatus, UserMessage +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +// 消息API响应类型 +export interface MessageResponse { + message: string; + data?: any; +} + +export interface MessagesResponse { + data: UserMessage[]; + pagination: { + total: number; + current: number; + pageSize: number; + totalPages: number; + }; +} + +export interface UnreadCountResponse { + count: number; +} + +// 消息API +export const MessageAPI = { + // 获取消息列表 + getMessages: async (params?: { + page?: number, + pageSize?: number, + type?: MessageType, + status?: MessageStatus + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取消息详情 + getMessage: async (id: number): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 发送消息 + sendMessage: async (data: { + title: string, + content: string, + type: MessageType, + receiver_ids: number[] + }): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/messages`, data); + return response.data; + } catch (error) { + throw error; + } + }, + + // 删除消息(软删除) + deleteMessage: async (id: number): Promise => { + try { + const response = await axios.delete(`${API_BASE_URL}/messages/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取未读消息数量 + getUnreadCount: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages/count/unread`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 标记消息为已读 + markAsRead: async (id: number): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/messages/${id}/read`); + return response.data; + } catch (error) { + throw error; + } + } +}; diff --git a/client/mobile/api/system.ts b/client/mobile/api/system.ts new file mode 100644 index 0000000..9efab9e --- /dev/null +++ b/client/mobile/api/system.ts @@ -0,0 +1,50 @@ +import axios from 'axios'; +import type { + SystemSetting, SystemSettingGroupData, +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +// 系统设置API +export const SystemAPI = { + // 获取所有系统设置 + getSettings: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/settings`); + return response.data.data; + } catch (error) { + throw error; + } + }, + + // 获取指定分组的系统设置 + getSettingsByGroup: async (group: string): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/settings/group/${group}`); + return response.data.data; + } catch (error) { + throw error; + } + + }, + + // 更新系统设置 + updateSettings: async (settings: Partial[]): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/settings`, settings); + return response.data.data; + } catch (error) { + throw error; + } + }, + + // 重置系统设置 + resetSettings: async (): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/settings/reset`); + return response.data.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/theme.ts b/client/mobile/api/theme.ts new file mode 100644 index 0000000..27cd7cf --- /dev/null +++ b/client/mobile/api/theme.ts @@ -0,0 +1,39 @@ +import axios from 'axios'; +import type { + ThemeSettings +} from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +// Theme API 定义 +export const ThemeAPI = { + // 获取主题设置 + getThemeSettings: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/theme`); + return response.data.data; + } catch (error) { + throw error; + } + }, + + // 更新主题设置 + updateThemeSettings: async (themeData: Partial): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/theme`, themeData); + return response.data.data; + } catch (error) { + throw error; + } + }, + + // 重置主题设置 + resetThemeSettings: async (): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/theme/reset`); + return response.data.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/api/user.ts b/client/mobile/api/user.ts new file mode 100644 index 0000000..8f1aed5 --- /dev/null +++ b/client/mobile/api/user.ts @@ -0,0 +1,108 @@ +import axios from 'axios'; +import type { User } from '../../share/types.ts'; + +const API_BASE_URL = '/api'; + +// 为UserAPI添加的接口响应类型 +interface UsersResponse { + data: User[]; + pagination: { + total: number; + current: number; + pageSize: number; + totalPages: number; + }; +} + +export interface UserResponse { + data: User; + message?: string; +} + +interface UserCreateResponse { + message: string; + data: User; +} + +interface UserUpdateResponse { + message: string; + data: User; +} + +interface UserDeleteResponse { + message: string; + id: number; +} + +// 用户管理API +export const UserAPI = { + // 获取用户列表 + getUsers: async (params?: { page?: number, limit?: number, search?: string }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/users`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取单个用户详情 + getUser: async (userId: number): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/users/${userId}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 创建用户 + createUser: async (userData: Partial): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/users`, userData); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新用户信息 + updateUser: async (userId: number, userData: Partial): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/users/${userId}`, userData); + return response.data; + } catch (error) { + throw error; + } + }, + + // 删除用户 + deleteUser: async (userId: number): Promise => { + try { + const response = await axios.delete(`${API_BASE_URL}/users/${userId}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取当前用户信息 + getCurrentUser: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/users/me/profile`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 更新当前用户信息 + updateCurrentUser: async (userData: Partial): Promise => { + try { + const response = await axios.put(`${API_BASE_URL}/users/me/profile`, userData); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/components_uploader.tsx b/client/mobile/components_uploader.tsx index 464a787..00a3f27 100644 --- a/client/mobile/components_uploader.tsx +++ b/client/mobile/components_uploader.tsx @@ -15,7 +15,7 @@ import type { MinioUploadPolicy, OSSUploadPolicy } from '@d8d-appcontainer/types import 'dayjs/locale/zh-cn'; import { OssType } from '../share/types.ts'; -import { FileAPI } from './api.ts'; +import { FileAPI } from './api/index.ts'; // MinIO文件上传组件 export const Uploader = ({ diff --git a/client/mobile/hooks.tsx b/client/mobile/hooks.tsx index 7d22e62..4291a3e 100644 --- a/client/mobile/hooks.tsx +++ b/client/mobile/hooks.tsx @@ -4,7 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { getLocalStorageWithExpiry, setLocalStorageWithExpiry } from './utils.ts'; import type { User, AuthContextType, ThemeContextType, ThemeSettings } from '../share/types.ts'; import { ThemeMode, FontSize, CompactMode } from '../share/types.ts'; -import { AuthAPI, ThemeAPI } from './api.ts'; +import { AuthAPI, ThemeAPI } from './api/index.ts'; // 默认主题设置 const defaultThemeSettings: ThemeSettings = { diff --git a/client/mobile/pages_index.tsx b/client/mobile/pages_index.tsx index d24d316..ce15845 100644 --- a/client/mobile/pages_index.tsx +++ b/client/mobile/pages_index.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate, useLocation } from 'react-router'; -import { HomeAPI } from './api.ts'; -import { MessageAPI } from './api.ts'; +import { HomeAPI } from './api/index.ts'; +import { MessageAPI } from './api/index.ts'; import { HomeIcon, UserIcon, diff --git a/client/mobile/pages_messages.tsx b/client/mobile/pages_messages.tsx index b4b711f..a476c41 100644 --- a/client/mobile/pages_messages.tsx +++ b/client/mobile/pages_messages.tsx @@ -7,7 +7,7 @@ import { MessageStatus } from '../share/types.ts'; // 添加通知页面组件 -import { MessageAPI } from './api.ts'; +import { MessageAPI } from './api/index.ts'; export const NotificationsPage = () => { const queryClient = useQueryClient(); diff --git a/client/mobile/pages_profile.tsx b/client/mobile/pages_profile.tsx index 681fb13..d22bc77 100644 --- a/client/mobile/pages_profile.tsx +++ b/client/mobile/pages_profile.tsx @@ -2,7 +2,7 @@ import React from 'react' import { useNavigate } from 'react-router' import { useForm } from 'react-hook-form' import { useQuery, useMutation } from '@tanstack/react-query' -import { UserAPI } from './api.ts' +import { UserAPI } from './api/index.ts' import type { User } from '../share/types.ts' import { useAuth } from './hooks.tsx' diff --git a/client/mobile/pages_register.tsx b/client/mobile/pages_register.tsx index 263310e..d3f104a 100644 --- a/client/mobile/pages_register.tsx +++ b/client/mobile/pages_register.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useNavigate } from 'react-router'; import { ArrowRightIcon, EnvelopeIcon, LockClosedIcon, UserIcon } from '@heroicons/react/24/outline'; -import { AuthAPI } from './api.ts'; +import { AuthAPI } from './api/index.ts'; import { handleApiError } from './utils.ts'; const RegisterPage: React.FC = () => { diff --git a/client/mobile/pages_settings.tsx b/client/mobile/pages_settings.tsx index 8a581e4..2e61fd5 100644 --- a/client/mobile/pages_settings.tsx +++ b/client/mobile/pages_settings.tsx @@ -1,9 +1,9 @@ import React from 'react' import { useForm } from 'react-hook-form' import { useMutation, useQuery } from '@tanstack/react-query' -import { UserAPI } from './api.ts' +import { UserAPI } from './api/index.ts' import type { User } from '../share/types.ts' -import type { UserResponse } from './api.ts' +import type { UserResponse } from './api/index.ts' export default function SettingsPage() { const { data: userResponse, isLoading } = useQuery({