feat:注册接口对接

This commit is contained in:
小张 2025-09-11 23:12:18 +08:00
parent 7911565249
commit 7551571f0a
9 changed files with 289 additions and 38 deletions

View File

@ -21,7 +21,7 @@ export const API_ENDPOINTS = {
AUTH: {
LOGIN: '/aiol/aiolUser/login',
USER_INFO: '/aiol/aiolUser/info',
REGISTER: '/auth/register',
REGISTER: '/aiol/aiolUser/register',
LOGOUT: '/auth/logout',
REFRESH: '/auth/refresh',
ME: '/auth/me',

View File

@ -7,6 +7,7 @@ import type {
LoginResponse,
// BackendLoginResponse,
RegisterRequest,
BackendRegisterRequest,
UserProfile,
BackendUserInfo,
UserInfoResponse,
@ -198,8 +199,59 @@ export class AuthApi {
}
// 用户注册
static register(data: RegisterRequest): Promise<ApiResponse<User>> {
return ApiRequest.post('/auth/register', data)
static async register(data: RegisterRequest): Promise<ApiResponse<User>> {
try {
// 转换为后端接口格式
const registerData: BackendRegisterRequest = {
studentNumber: data.email || data.phone || data.username,
inviteCode: data.inviteCode || '',
password: data.password
}
console.log('🚀 发送注册请求:', { url: '/aiol/aiolUser/register', data: { ...registerData, password: '***' } })
// 调用后端注册API
const response = await ApiRequest.post<any>('/aiol/aiolUser/register', registerData)
console.log('🔍 Register API Response:', response)
// 处理响应格式
let actualCode = response.code
let actualMessage = response.message
// 如果响应被包装在data中
if (response.data && typeof response.data === 'object' && 'code' in response.data) {
actualCode = response.data.code
actualMessage = response.data.message
}
// 检查注册是否成功
if (actualCode === 200 || actualCode === 0) {
// 注册成功,返回标准格式
const adaptedResponse: ApiResponse<User> = {
code: 200,
message: actualMessage || '注册成功',
data: {
id: Date.now(), // 临时ID
username: registerData.studentNumber,
email: data.email || '',
phone: data.phone || '',
nickname: registerData.studentNumber,
avatar: '',
role: 'student',
status: 'active',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
}
}
return adaptedResponse
} else {
throw new Error(actualMessage || '注册失败')
}
} catch (error) {
console.error('🚨 Register API Error:', error)
throw error
}
}
// 用户登出
@ -266,6 +318,10 @@ export class AuthApi {
static convertBackendUserToUser(backendUser: BackendUserInfo): User {
const { baseInfo, roles, extendedInfo } = backendUser
console.log('🔄 convertBackendUserToUser - 原始后端数据:', backendUser)
console.log('🔄 convertBackendUserToUser - baseInfo.avatar:', baseInfo.avatar)
console.log('🔄 convertBackendUserToUser - baseInfo.realname:', baseInfo.realname)
// 转换性别
let gender: 'male' | 'female' | 'other' = 'other'
if (baseInfo.sex === 1) gender = 'male'
@ -282,7 +338,7 @@ export class AuthApi {
role = 'teacher'
}
return {
const convertedUser = {
id: parseInt(baseInfo.id) || 0,
username: baseInfo.username,
email: baseInfo.email,
@ -303,6 +359,11 @@ export class AuthApi {
socialLinks: {}
}
}
console.log('✅ convertBackendUserToUser - 转换后的用户数据:', convertedUser)
console.log('✅ convertBackendUserToUser - 转换后的头像:', convertedUser.avatar)
return convertedUser
}
// 更新用户资料

View File

@ -127,7 +127,20 @@ export class ExamApi {
*/
static async createQuestion(data: CreateQuestionRequest): Promise<ApiResponse<string>> {
console.log('🚀 添加题目:', data)
const response = await ApiRequest.post<string>('/aiol/aiolQuestion/add', data)
// 提取repoId作为查询参数其他数据作为请求体
const { repoId, ...questionData } = data
// 构建查询参数只有repoId
const params: any = {}
if (repoId) {
params.repoId = repoId
}
console.log('🔍 API查询参数:', params)
console.log('🔍 API请求体:', questionData)
const response = await ApiRequest.post<string>('/aiol/aiolQuestion/add', questionData, { params })
console.log('✅ 添加题目成功:', response)
return response
}
@ -161,7 +174,7 @@ export class ExamApi {
*/
static async createQuestionOption(data: CreateQuestionOptionRequest): Promise<ApiResponse<string>> {
console.log('🚀 添加题目选项:', data)
const response = await ApiRequest.post<string>('/gen/questionoption/questionOption/add', data)
const response = await ApiRequest.post<string>('/aiol/aiolQuestionOption/add', data)
console.log('✅ 添加题目选项成功:', response)
return response
}

View File

@ -123,6 +123,13 @@ export interface RegisterRequest {
inviteCode?: string
}
// 后端注册接口请求格式
export interface BackendRegisterRequest {
studentNumber: string
inviteCode?: string
password: string
}
// 课程相关类型
export interface Course {
id: string // 改为string类型保持后端ID的原始格式
@ -773,12 +780,15 @@ export interface UpdateRepoRequest {
}
export interface CreateQuestionRequest {
repoId?: string
parentId?: string
type: number
content: string
analysis?: string
difficulty: number
score: number
degree?: number
ability?: number
}
export interface UpdateQuestionRequest {

View File

@ -12,6 +12,8 @@
:alt="alt"
@error="handleImageError"
@load="handleImageLoad"
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<div v-else class="avatar-placeholder">
<span class="avatar-text">{{ avatarText }}</span>
@ -20,7 +22,7 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref, computed, watch } from 'vue'
interface Props {
src?: string
@ -38,6 +40,15 @@ const props = withDefaults(defineProps<Props>(), {
const imageError = ref(false)
// src
watch(() => props.src, (newSrc) => {
console.log('🖼️ SafeAvatar - 头像URL变化:', newSrc)
console.log('🖼️ SafeAvatar - 头像URL类型:', typeof newSrc)
console.log('🖼️ SafeAvatar - 头像URL长度:', newSrc?.length)
//
imageError.value = false
}, { immediate: true })
//
const avatarText = computed(() => {
if (props.name) {
@ -51,11 +62,13 @@ const avatarText = computed(() => {
return '用'
})
const handleImageError = () => {
const handleImageError = (event: Event) => {
console.error('🚨 SafeAvatar - 头像加载失败:', props.src, event)
imageError.value = true
}
const handleImageLoad = () => {
console.log('✅ SafeAvatar - 头像加载成功:', props.src)
imageError.value = false
}
</script>

View File

@ -162,6 +162,7 @@ const userStore = useUserStore()
console.log('🔍 AppHeader - 当前用户信息:', userStore.user)
console.log('🔍 AppHeader - 用户真实姓名:', userStore.user?.profile?.realName)
console.log('🔍 AppHeader - 用户头像:', userStore.user?.avatar)
console.log('🔍 AppHeader - 用户头像类型:', typeof userStore.user?.avatar)
//
watch(() => userStore.user, (newUser) => {
@ -169,9 +170,15 @@ watch(() => userStore.user, (newUser) => {
if (newUser) {
console.log('🔄 AppHeader - 新的真实姓名:', newUser.profile?.realName)
console.log('🔄 AppHeader - 新的头像:', newUser.avatar)
console.log('🔄 AppHeader - 新的头像类型:', typeof newUser.avatar)
}
}, { deep: true })
//
watch(() => userStore.user?.avatar, (newAvatar) => {
console.log('🖼️ AppHeader - 头像URL变化:', newAvatar)
}, { immediate: true })
//
const mobileMenuOpen = ref(false)

View File

@ -143,6 +143,7 @@ export const useUserStore = defineStore('user', () => {
// 强制刷新用户信息
const refreshUserInfo = async () => {
console.log('🔄 强制刷新用户信息...')
return await getCurrentUser(true)
}
@ -181,9 +182,35 @@ export const useUserStore = defineStore('user', () => {
user.value = JSON.parse(savedUser)
token.value = savedToken
// 不强制刷新用户信息避免API超时导致白屏
// 如果需要验证token有效性可以在用户操作时进行
console.log('✅ 用户认证状态已恢复')
// 验证token有效性并获取最新用户信息
try {
console.log('🔍 验证token有效性并获取最新用户信息...')
const userInfoResponse = await AuthApi.getUserInfo()
if (userInfoResponse.success && userInfoResponse.result) {
// 将后端用户信息转换为前端格式
const convertedUser = AuthApi.convertBackendUserToUser(userInfoResponse.result)
// 更新用户信息
user.value = convertedUser
localStorage.setItem('user', JSON.stringify(convertedUser))
console.log('✅ 用户信息已更新:', convertedUser)
} else {
console.warn('⚠️ 获取用户信息失败,保持本地缓存的用户信息')
}
} catch (error: any) {
console.warn('⚠️ 验证token或获取用户信息失败:', error)
// 如果是401错误说明token已过期清除认证状态
if (error.response?.status === 401) {
console.log('🔄 Token已过期清除认证状态')
await logout()
}
// 其他错误(如网络错误)保持本地缓存的用户信息
}
} catch (error) {
console.error('Failed to parse saved user data:', error)
await logout()

View File

@ -210,6 +210,25 @@ const handleSubmit = async () => {
//
userStore.isLoading = true
if (isRegisterMode.value) {
//
await handleRegister()
} else {
//
await handleLogin()
}
} catch (error: any) {
console.error('表单提交失败:', error)
if (error.message) {
message.error(error.message)
}
} finally {
userStore.isLoading = false
}
}
//
const handleLogin = async () => {
console.log('🚀 开始登录:', { account: formData.studentId, password: '***' })
console.log('🔍 表单密码长度:', formData.password?.length)
@ -315,25 +334,52 @@ const handleSubmit = async () => {
console.error('❌ 登录失败,响应码:', response.code)
message.error(response.message || '登录失败')
}
}
//
const handleRegister = async () => {
console.log('🚀 开始注册:', { account: formData.studentId, inviteCode: formData.inviteCode })
try {
// API
const response = await AuthApi.register({
username: formData.studentId,
email: formData.studentId.includes('@') ? formData.studentId : '',
phone: /^[0-9]+$/.test(formData.studentId) ? formData.studentId : '',
password: formData.password,
confirmPassword: formData.password,
captcha: '', //
inviteCode: formData.inviteCode
})
console.log('✅ 注册响应:', response)
if (response.code === 200 || response.code === 0) {
message.success('注册成功!请使用您的账号登录')
//
isRegisterMode.value = false
// 便
formData.inviteCode = ''
} else {
message.error(response.message || '注册失败')
}
} catch (error: any) {
console.error('登录失败:', error)
console.error('注册失败:', error)
//
if (error.response?.status === 401) {
message.error('邮箱或密码错误')
} else if (error.response?.status === 429) {
message.error('登录尝试过于频繁,请稍后再试')
if (error.response?.status === 400) {
message.error('请求参数错误,请检查输入信息')
} else if (error.response?.status === 409) {
message.error('账号已被注册,请使用其他账号')
} else if (error.response?.data?.message) {
//
message.error(error.response.data.message)
} else if (error.message) {
//
message.error(error.message)
} else {
message.error('网络错误,请检查网络连接')
}
} finally {
userStore.isLoading = false
}
}

View File

@ -511,12 +511,15 @@ const createNewQuestion = async (bankId: string) => {
try {
// API
const questionData = {
repoId: bankId, // ID
parentId: undefined, // IDundefined
type: getQuestionTypeNumber(questionForm.type),
content: questionForm.title,
analysis: questionForm.explanation || '',
difficulty: getDifficultyNumber(questionForm.difficulty),
score: questionForm.score
score: questionForm.score,
degree: 1, // 1
ability: 1 // 1
};
console.log('🚀 创建题目,数据:', questionData);
@ -541,31 +544,102 @@ const createNewQuestion = async (bankId: string) => {
}
}
if (!success) {
throw new Error('创建题目失败');
if (!success || !questionId) {
throw new Error('创建题目失败未获取到题目ID');
}
console.log('✅ 题目创建成功题目ID:', questionId);
message.success('题目保存成功');
//
const currentRoute = route.path;
if (currentRoute.includes('/course-editor/')) {
//
const courseId = route.params.id || route.params.courseId;
router.push(`/teacher/course-editor/${courseId}/question-bank/${bankId}/questions`);
} else {
//
router.push(`/teacher/exam-management/question-bank/${bankId}/questions`);
//
const questionType = getQuestionTypeNumber(questionForm.type);
if (questionType === 0 || questionType === 1 || questionType === 2) { //
await createQuestionOptions(questionId, questionType);
}
message.success('题目创建成功!');
router.back();
} catch (error: any) {
console.error('创建题目流程失败:', error);
console.error('❌ 创建题目失败:', error);
message.error(error.message || '创建题目失败');
throw error;
}
};
//
const createQuestionOptions = async (questionId: string, questionType: number) => {
try {
console.log('🚀 开始创建题目选项题目ID:', questionId, '题目类型:', questionType);
let optionsToCreate: Array<{
content: string;
izCorrent: number;
orderNo: number;
}> = [];
if (questionType === 0) { //
//
const options = questionForm.options || [];
const correctAnswer = questionForm.correctAnswer;
optionsToCreate = options.map((option: any, index: number) => ({
content: option.content || option.text || '',
izCorrent: option.letter === correctAnswer ? 1 : 0,
orderNo: index
}));
} else if (questionType === 1) { //
const options = questionForm.options || [];
const correctAnswers = questionForm.correctAnswers || [];
optionsToCreate = options.map((option: any, index: number) => ({
content: option.content || option.text || '',
izCorrent: correctAnswers.includes(option.letter) ? 1 : 0,
orderNo: index
}));
} else if (questionType === 2) { //
//
const correctAnswer = questionForm.correctAnswer;
const isCorrectTrue = String(correctAnswer) === 'true' || correctAnswer === 1;
optionsToCreate = [
{
content: '正确',
izCorrent: isCorrectTrue ? 1 : 0,
orderNo: 0
},
{
content: '错误',
izCorrent: isCorrectTrue ? 0 : 1,
orderNo: 1
}
];
}
console.log('📊 准备创建的选项:', optionsToCreate);
//
for (const option of optionsToCreate) {
const optionData = {
questionId: questionId,
content: option.content,
izCorrent: option.izCorrent,
orderNo: option.orderNo
};
console.log('🚀 创建选项:', optionData);
const optionResponse = await ExamApi.createQuestionOption(optionData);
console.log('✅ 选项创建成功:', optionResponse);
}
console.log('✅ 所有选项创建完成');
} catch (error: any) {
console.error('❌ 创建题目选项失败:', error);
throw new Error('创建题目选项失败:' + (error.message || '未知错误'));
}
};
//