Commit 1f7f2977 authored by Administrator's avatar Administrator
Browse files

added StudentView page to handle CURD operations.

parent 38326bc5
......@@ -22,6 +22,9 @@ export const apiEndpoints = {
// 学生相关
STUDENTS: {
LIST: '/api/student/',
CREATE: '/api/student/',
UPDATE: (studentId) => `/api/student/${studentId}/`,
DELETE: (studentId) => `/api/student/${studentId}/`,
},
}
......
import apiClient, { apiEndpoints } from './index.js'
// 获取学生列表
// Get student list
export const getStudents = async () => {
try {
const response = await apiClient.get(apiEndpoints.STUDENTS.LIST)
......@@ -9,3 +9,118 @@ export const getStudents = async () => {
throw new Error(error?.response?.data?.detail || error?.message || 'Failed to fetch students')
}
}
// Update student information
export const updateStudent = async (studentId, studentData) => {
try {
// Convert data format to match API requirements
const apiData = {
student_name: studentData.student_name || '',
enabled: studentData.enabled ? 'Y' : 'N',
grade: studentData.grade || '',
age: parseInt(studentData.age) || 0,
}
// If avatar data is included, add avatar-related fields
if (studentData.avatar && studentData.avatar_mime_type) {
apiData.avatar_base64 = studentData.avatar
apiData.avatar_mime_type = studentData.avatar_mime_type
apiData.avatar_file_name = studentData.avatar_file_name || ''
}
console.log('Sending update request:', {
studentId,
url: apiEndpoints.STUDENTS.UPDATE(studentId),
data: { ...apiData, avatar_base64: apiData.avatar_base64 ? '[base64 data]' : undefined } // Don't print full base64
})
const response = await apiClient.patch(apiEndpoints.STUDENTS.UPDATE(studentId), apiData)
return response.data
} catch (error) {
console.error('API error details:', {
status: error?.response?.status,
statusText: error?.response?.statusText,
data: error?.response?.data,
headers: error?.response?.headers
})
const errorMessage = error?.response?.data?.detail ||
error?.response?.data?.message ||
error?.response?.data?.error ||
`HTTP ${error?.response?.status}: ${error?.response?.statusText}` ||
error.message ||
'Failed to update student'
throw new Error(errorMessage)
}
}
// Create student
export const createStudent = async (studentData) => {
try {
// Convert data format to match API requirements
const apiData = {
student_name: studentData.student_name || '',
enabled: studentData.enabled ? 'Y' : 'N',
grade: studentData.grade || '',
age: parseInt(studentData.age) || 0,
}
// If avatar data is included, add avatar-related fields
if (studentData.avatar && studentData.avatar_mime_type) {
apiData.avatar_base64 = studentData.avatar
apiData.avatar_mime_type = studentData.avatar_mime_type
apiData.avatar_file_name = studentData.avatar_file_name || ''
}
console.log('Sending create request:', {
url: apiEndpoints.STUDENTS.CREATE,
data: { ...apiData, avatar_base64: apiData.avatar_base64 ? '[base64 data]' : undefined }
})
const response = await apiClient.post(apiEndpoints.STUDENTS.CREATE, apiData)
return response.data
} catch (error) {
console.error('API error details:', {
status: error?.response?.status,
statusText: error?.response?.statusText,
data: error?.response?.data,
headers: error?.response?.headers
})
const errorMessage = error?.response?.data?.detail ||
error?.response?.data?.message ||
error?.response?.data?.error ||
`HTTP ${error?.response?.status}: ${error?.response?.statusText}` ||
error.message ||
'Failed to create student'
throw new Error(errorMessage)
}
}
// Delete student
export const deleteStudent = async (studentId) => {
try {
console.log('Sending delete request:', {
studentId,
url: apiEndpoints.STUDENTS.DELETE(studentId)
})
const response = await apiClient.delete(apiEndpoints.STUDENTS.DELETE(studentId))
return response.data
} catch (error) {
console.error('API error details:', {
status: error?.response?.status,
statusText: error?.response?.statusText,
data: error?.response?.data,
headers: error?.response?.headers
})
const errorMessage = error?.response?.data?.detail ||
error?.response?.data?.message ||
error?.response?.data?.error ||
`HTTP ${error?.response?.status}: ${error?.response?.statusText}` ||
error.message ||
'Failed to delete student'
throw new Error(errorMessage)
}
}
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import { useRouter } from 'vue-router'
import axios from 'axios'
import apiClient from '@/api/index.js'
import { login as authLogin, refreshAccessToken as authRefreshToken } from '@/api/authService.js'
export const useAuthStore = defineStore('auth', () => {
......@@ -58,9 +58,10 @@ export const useAuthStore = defineStore('auth', () => {
const setAxiosAuthHeader = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`
// 设置apiClient默认headers
apiClient.defaults.headers.common.Authorization = `Bearer ${token}`
} else {
delete axios.defaults.headers.common.Authorization
delete apiClient.defaults.headers.common.Authorization
}
}
......@@ -92,8 +93,8 @@ export const useAuthStore = defineStore('auth', () => {
const setupAxiosInterceptors = () => {
if (interceptorsInitialized.value) return
// 请求拦截:总是携带最新的访问令牌
axios.interceptors.request.use((config) => {
// 请求拦截:总是携带最新的访问令牌
apiClient.interceptors.request.use((config) => {
if (accessToken.value) {
config.headers = config.headers || {}
config.headers.Authorization = `Bearer ${accessToken.value}`
......@@ -101,8 +102,8 @@ export const useAuthStore = defineStore('auth', () => {
return config
})
// 响应拦截:遇到 401 尝试刷新一次并重试原请求
axios.interceptors.response.use(
// 响应拦截:遇到 401 尝试刷新一次并重试原请求
apiClient.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config || {}
......@@ -121,7 +122,7 @@ export const useAuthStore = defineStore('auth', () => {
await refreshAccessToken()
originalRequest.headers = originalRequest.headers || {}
originalRequest.headers.Authorization = `Bearer ${accessToken.value}`
return axios(originalRequest)
return apiClient(originalRequest)
} catch (e) {
logout()
return Promise.reject(e)
......
<script setup>
import { ref } from 'vue'
import { useAuthStore } from '../stores/auth'
import loginImage from '@/assets/images/login.jpg'
const authStore = useAuthStore()
const username = ref('')
......@@ -84,6 +83,14 @@ const handleLogin = async () => {
variant="outlined"
density="comfortable"
/>
<v-alert
v-if="error"
type="error"
variant="tonal"
class="mb-4"
>
{{ error }}
</v-alert>
<v-btn
color="primary"
block
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment