修改登录,绑定学生相关界面
This commit is contained in:
+12
-3
@@ -85,7 +85,10 @@ export type RefreshTokenResponse = {
|
||||
* 密码登录
|
||||
*/
|
||||
export function apiLogin(params: LoginParams): Promise<ApiResponse<UserInfo> | null> {
|
||||
return post<UserInfo>('/api/auth/login', params)
|
||||
return post<any>('/api/v1/Parents/Login', { phone: params.phone, password: params.password, loginType: 0 }).then((res) => {
|
||||
if (!res || !res.data) return null
|
||||
return { code: res.code, message: res.message, data: { userId: String(res.data.parentId), phone: res.data.phone, nickname: res.data.name, avatar: '', token: res.data.token, refreshToken: '' } }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +109,13 @@ export function apiSendCode(params: SendCodeParams): Promise<ApiResponse<SendCod
|
||||
* 注册
|
||||
*/
|
||||
export function apiRegister(params: RegisterParams): Promise<ApiResponse<UserInfo> | null> {
|
||||
return post<UserInfo>('/api/auth/register', params)
|
||||
const relations = ['爸爸', '妈妈', '爷爷', '奶奶', '外公', '外婆', '其他亲属']
|
||||
return post<any>('/api/v1/Parents/Bind', {
|
||||
name: params.parentName,
|
||||
phone: params.phone,
|
||||
password: params.password,
|
||||
students: params.students.map((id) => ({ userId: Number(id), relation: relations.indexOf(params.relationship) + 1 }))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,5 +143,5 @@ export function apiRefreshToken(params: RefreshTokenParams): Promise<ApiResponse
|
||||
* 退出登录
|
||||
*/
|
||||
export function apiLogout(): Promise<ApiResponse<null> | null> {
|
||||
return post<null>('/api/auth/logout')
|
||||
return post<null>('/api/v1/Parents/Logout')
|
||||
}
|
||||
|
||||
+5
-2
@@ -268,14 +268,17 @@ export type VerifyAccountParams = {
|
||||
* 验证学生二维码
|
||||
*/
|
||||
export function apiVerifyStudentQRCode(params: VerifyQRCodeParams): Promise<ApiResponse<StudentInfo> | null> {
|
||||
return post<StudentInfo>('/api/student/verify-qrcode', params)
|
||||
return apiVerifyStudentAccount({ account: params.account, name: params.name })
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证学生账号
|
||||
*/
|
||||
export function apiVerifyStudentAccount(params: VerifyAccountParams): Promise<ApiResponse<StudentInfo> | null> {
|
||||
return post<StudentInfo>('/api/student/verify-account', params)
|
||||
return get<any>('/api/v1/Parents/VerifyStudent', { RealName: params.name, Account: params.account }).then((res) => {
|
||||
if (!res || !res.data) return null
|
||||
return { code: res.code, message: res.message, data: { id: String(res.data.userId), name: res.data.name, account: res.data.account, avatar: res.data.avatar || '', grade: res.data.gradeLevel || '', class: res.data.className || '' } }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
return
|
||||
}
|
||||
const res = await apiSendCode({ phone: p, type: 'forgot-password' })
|
||||
if (res && res.code === 0) {
|
||||
if (res && res.code === 200) {
|
||||
uni.showToast({ title: '验证码已发送', icon: 'success' })
|
||||
countdownBtnRef.value?.startCountdown()
|
||||
}
|
||||
@@ -171,7 +171,7 @@
|
||||
resetToken: resetToken.value
|
||||
})
|
||||
|
||||
if (res && res.code === 0) {
|
||||
if (res && res.code === 200) {
|
||||
step.value = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,6 @@
|
||||
<text class="btn-text">登录</text>
|
||||
</view>
|
||||
|
||||
<!-- 切换验证码登录 -->
|
||||
<text class="switch-text" @tap="handleSwitchToCodeLogin">验证码登录</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部注册入口 -->
|
||||
@@ -131,15 +129,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到验证码登录
|
||||
*/
|
||||
function handleSwitchToCodeLogin() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/verify-code'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码
|
||||
*/
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
}
|
||||
|
||||
const res = await apiSendCode({ phone: p, type: 'login' })
|
||||
if (res && res.code === 0) {
|
||||
if (res && res.code === 200) {
|
||||
uni.showToast({ title: '验证码已发送', icon: 'success' })
|
||||
countdownBtnRef.value?.startCountdown()
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
listFailed.value = false
|
||||
try {
|
||||
const res = await apiGetBoundStudents()
|
||||
if (res && res.code === 0 && res.data) {
|
||||
if (res && res.code === 200 && res.data) {
|
||||
students.value = res.data.students
|
||||
if (!selectedStudentId.value) selectedStudentId.value = res.data.currentStudentId ?? ''
|
||||
} else listFailed.value = true
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
loadFailed.value = false
|
||||
try {
|
||||
const res = await apiGetBoundStudents()
|
||||
if (res && res.code === 0 && res.data) students.value = res.data.students
|
||||
if (res && res.code === 200 && res.data) students.value = res.data.students
|
||||
else loadFailed.value = true
|
||||
} catch (_error) { loadFailed.value = true }
|
||||
finally { loading.value = false }
|
||||
@@ -93,7 +93,7 @@
|
||||
verifying.value = true
|
||||
try {
|
||||
const res = qrCode ? await apiVerifyStudentQRCode({ qrCode, account: studentAccount, name: studentName }) : await apiVerifyStudentAccount({ account: studentAccount, name: studentName })
|
||||
if (res && res.code === 0 && res.data) {
|
||||
if (res && res.code === 200 && res.data) {
|
||||
if (students.value.some(item => item.id === res.data!.id || item.account === res.data!.account)) uni.showToast({ title: '该学生已绑定', icon: 'none' })
|
||||
else verified.value = res.data
|
||||
}
|
||||
|
||||
@@ -50,9 +50,6 @@
|
||||
<view class="btn-primary" @tap="handleGoHome">
|
||||
<text class="btn-primary-text">去登录</text>
|
||||
</view>
|
||||
<view class="btn-secondary" @tap="handleGoLogin">
|
||||
<text class="btn-secondary-text">返回首页</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
if (res && res.code === 0 && res.data) {
|
||||
if (res && res.code === 200 && res.data) {
|
||||
// 检查是否重复绑定
|
||||
const exists = studentList.value.find(s => s.account === res.data!.account)
|
||||
if (exists) {
|
||||
|
||||
@@ -112,9 +112,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { apiRegister } from '../../api/auth'
|
||||
import { apiCheckPhone } from '../../api/student'
|
||||
import { registrationStudents } from '../../store/registration'
|
||||
import { setUserInfo } from '../../store/user'
|
||||
|
||||
type ParentAccountForm = {
|
||||
parentName: string
|
||||
@@ -177,17 +175,8 @@
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查手机号是否已注册
|
||||
uni.showLoading({ title: '检查中...' })
|
||||
const checkRes = await apiCheckPhone(form.phone)
|
||||
uni.hideLoading()
|
||||
|
||||
if (checkRes && checkRes.data && checkRes.data.exists) {
|
||||
uni.showToast({
|
||||
title: '该手机号已注册,请直接登录',
|
||||
icon: 'none'
|
||||
})
|
||||
if (students.value.length === 0 || students.value.some((student) => !Number.isSafeInteger(Number(student.id)) || Number(student.id) <= 0)) {
|
||||
uni.showToast({ title: '学生信息无效,请重新验证', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -195,20 +184,23 @@
|
||||
uni.showLoading({ title: '注册中...' })
|
||||
|
||||
const studentIds = students.value.map(s => s.id)
|
||||
const res = await apiRegister({
|
||||
let res
|
||||
try {
|
||||
res = await apiRegister({
|
||||
parentName: form.parentName,
|
||||
phone: form.phone,
|
||||
relationship: form.relationship,
|
||||
password: form.password,
|
||||
students: studentIds
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('注册请求失败', error)
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
uni.hideLoading()
|
||||
|
||||
if (res && res.code === 0 && res.data) {
|
||||
// 保存用户信息
|
||||
setUserInfo(res.data)
|
||||
|
||||
if (res && res.code === 200 && res.data) {
|
||||
// 跳转到注册完成页
|
||||
uni.redirectTo({
|
||||
url: '/pages/register/complete'
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
if (res && res.code === 0 && res.data) {
|
||||
if (res && res.code === 200 && res.data) {
|
||||
// 检查是否重复绑定
|
||||
const exists = studentList.value.find(s => s.account === res.data!.account)
|
||||
if (exists) {
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 计算 MD5 摘要。
|
||||
* 服务端当前要求登录密码以小写 32 位 MD5 字符串传输。
|
||||
*/
|
||||
export function md5(value: string): string {
|
||||
const bytes = unescape(encodeURIComponent(value))
|
||||
const words: number[] = []
|
||||
const bitLength = bytes.length * 8
|
||||
|
||||
for (let index = 0; index < bytes.length; index++) {
|
||||
words[index >> 2] = (words[index >> 2] || 0) | (bytes.charCodeAt(index) << ((index % 4) * 8))
|
||||
}
|
||||
words[bitLength >> 5] = (words[bitLength >> 5] || 0) | (0x80 << (bitLength % 32))
|
||||
words[(((bitLength + 64) >>> 9) << 4) + 14] = bitLength
|
||||
|
||||
let a = 0x67452301
|
||||
let b = 0xefcdab89
|
||||
let c = 0x98badcfe
|
||||
let d = 0x10325476
|
||||
|
||||
for (let offset = 0; offset < words.length; offset += 16) {
|
||||
const oldA = a
|
||||
const oldB = b
|
||||
const oldC = c
|
||||
const oldD = d
|
||||
|
||||
a = md5Round(a, b, c, d, words[offset] || 0, 7, -680876936)
|
||||
d = md5Round(d, a, b, c, words[offset + 1] || 0, 12, -389564586)
|
||||
c = md5Round(c, d, a, b, words[offset + 2] || 0, 17, 606105819)
|
||||
b = md5Round(b, c, d, a, words[offset + 3] || 0, 22, -1044525330)
|
||||
a = md5Round(a, b, c, d, words[offset + 4] || 0, 7, -176418897)
|
||||
d = md5Round(d, a, b, c, words[offset + 5] || 0, 12, 1200080426)
|
||||
c = md5Round(c, d, a, b, words[offset + 6] || 0, 17, -1473231341)
|
||||
b = md5Round(b, c, d, a, words[offset + 7] || 0, 22, -45705983)
|
||||
a = md5Round(a, b, c, d, words[offset + 8] || 0, 7, 1770035416)
|
||||
d = md5Round(d, a, b, c, words[offset + 9] || 0, 12, -1958414417)
|
||||
c = md5Round(c, d, a, b, words[offset + 10] || 0, 17, -42063)
|
||||
b = md5Round(b, c, d, a, words[offset + 11] || 0, 22, -1990404162)
|
||||
a = md5Round(a, b, c, d, words[offset + 12] || 0, 7, 1804603682)
|
||||
d = md5Round(d, a, b, c, words[offset + 13] || 0, 12, -40341101)
|
||||
c = md5Round(c, d, a, b, words[offset + 14] || 0, 17, -1502002290)
|
||||
b = md5Round(b, c, d, a, words[offset + 15] || 0, 22, 1236535329)
|
||||
|
||||
a = md5Round2(a, b, c, d, words[offset + 1] || 0, 5, -165796510)
|
||||
d = md5Round2(d, a, b, c, words[offset + 6] || 0, 9, -1069501632)
|
||||
c = md5Round2(c, d, a, b, words[offset + 11] || 0, 14, 643717713)
|
||||
b = md5Round2(b, c, d, a, words[offset] || 0, 20, -373897302)
|
||||
a = md5Round2(a, b, c, d, words[offset + 5] || 0, 5, -701558691)
|
||||
d = md5Round2(d, a, b, c, words[offset + 10] || 0, 9, 38016083)
|
||||
c = md5Round2(c, d, a, b, words[offset + 15] || 0, 14, -660478335)
|
||||
b = md5Round2(b, c, d, a, words[offset + 4] || 0, 20, -405537848)
|
||||
a = md5Round2(a, b, c, d, words[offset + 9] || 0, 5, 568446438)
|
||||
d = md5Round2(d, a, b, c, words[offset + 14] || 0, 9, -1019803690)
|
||||
c = md5Round2(c, d, a, b, words[offset + 3] || 0, 14, -187363961)
|
||||
b = md5Round2(b, c, d, a, words[offset + 8] || 0, 20, 1163531501)
|
||||
a = md5Round2(a, b, c, d, words[offset + 13] || 0, 5, -1444681467)
|
||||
d = md5Round2(d, a, b, c, words[offset + 2] || 0, 9, -51403784)
|
||||
c = md5Round2(c, d, a, b, words[offset + 7] || 0, 14, 1735328473)
|
||||
b = md5Round2(b, c, d, a, words[offset + 12] || 0, 20, -1926607734)
|
||||
|
||||
a = md5Round3(a, b, c, d, words[offset + 5] || 0, 4, -378558)
|
||||
d = md5Round3(d, a, b, c, words[offset + 8] || 0, 11, -2022574463)
|
||||
c = md5Round3(c, d, a, b, words[offset + 11] || 0, 16, 1839030562)
|
||||
b = md5Round3(b, c, d, a, words[offset + 14] || 0, 23, -35309556)
|
||||
a = md5Round3(a, b, c, d, words[offset + 1] || 0, 4, -1530992060)
|
||||
d = md5Round3(d, a, b, c, words[offset + 4] || 0, 11, 1272893353)
|
||||
c = md5Round3(c, d, a, b, words[offset + 7] || 0, 16, -155497632)
|
||||
b = md5Round3(b, c, d, a, words[offset + 10] || 0, 23, -1094730640)
|
||||
a = md5Round3(a, b, c, d, words[offset + 13] || 0, 4, 681279174)
|
||||
d = md5Round3(d, a, b, c, words[offset] || 0, 11, -358537222)
|
||||
c = md5Round3(c, d, a, b, words[offset + 3] || 0, 16, -722521979)
|
||||
b = md5Round3(b, c, d, a, words[offset + 6] || 0, 23, 76029189)
|
||||
a = md5Round3(a, b, c, d, words[offset + 9] || 0, 4, -640364487)
|
||||
d = md5Round3(d, a, b, c, words[offset + 12] || 0, 11, -421815835)
|
||||
c = md5Round3(c, d, a, b, words[offset + 15] || 0, 16, 530742520)
|
||||
b = md5Round3(b, c, d, a, words[offset + 2] || 0, 23, -995338651)
|
||||
|
||||
a = md5Round4(a, b, c, d, words[offset] || 0, 6, -198630844)
|
||||
d = md5Round4(d, a, b, c, words[offset + 7] || 0, 10, 1126891415)
|
||||
c = md5Round4(c, d, a, b, words[offset + 14] || 0, 15, -1416354905)
|
||||
b = md5Round4(b, c, d, a, words[offset + 5] || 0, 21, -57434055)
|
||||
a = md5Round4(a, b, c, d, words[offset + 12] || 0, 6, 1700485571)
|
||||
d = md5Round4(d, a, b, c, words[offset + 3] || 0, 10, -1894986606)
|
||||
c = md5Round4(c, d, a, b, words[offset + 10] || 0, 15, -1051523)
|
||||
b = md5Round4(b, c, d, a, words[offset + 1] || 0, 21, -2054922799)
|
||||
a = md5Round4(a, b, c, d, words[offset + 8] || 0, 6, 1873313359)
|
||||
d = md5Round4(d, a, b, c, words[offset + 15] || 0, 10, -30611744)
|
||||
c = md5Round4(c, d, a, b, words[offset + 6] || 0, 15, -1560198380)
|
||||
b = md5Round4(b, c, d, a, words[offset + 13] || 0, 21, 1309151649)
|
||||
a = md5Round4(a, b, c, d, words[offset + 4] || 0, 6, -145523070)
|
||||
d = md5Round4(d, a, b, c, words[offset + 11] || 0, 10, -1120210379)
|
||||
c = md5Round4(c, d, a, b, words[offset + 2] || 0, 15, 718787259)
|
||||
b = md5Round4(b, c, d, a, words[offset + 9] || 0, 21, -343485551)
|
||||
|
||||
a = (a + oldA) | 0
|
||||
b = (b + oldB) | 0
|
||||
c = (c + oldC) | 0
|
||||
d = (d + oldD) | 0
|
||||
}
|
||||
|
||||
return [a, b, c, d].map((word) => {
|
||||
let result = ''
|
||||
for (let index = 0; index < 4; index++) {
|
||||
result += ((word >> (index * 8)) & 0xff).toString(16).padStart(2, '0')
|
||||
}
|
||||
return result
|
||||
}).join('')
|
||||
}
|
||||
|
||||
function md5Round(a: number, b: number, c: number, d: number, value: number, shift: number, constant: number): number {
|
||||
return md5Rotate((a + ((b & c) | (~b & d)) + value + constant) | 0, shift) + b | 0
|
||||
}
|
||||
|
||||
function md5Round2(a: number, b: number, c: number, d: number, value: number, shift: number, constant: number): number {
|
||||
return md5Rotate((a + ((b & d) | (c & ~d)) + value + constant) | 0, shift) + b | 0
|
||||
}
|
||||
|
||||
function md5Round3(a: number, b: number, c: number, d: number, value: number, shift: number, constant: number): number {
|
||||
return md5Rotate((a + (b ^ c ^ d) + value + constant) | 0, shift) + b | 0
|
||||
}
|
||||
|
||||
function md5Round4(a: number, b: number, c: number, d: number, value: number, shift: number, constant: number): number {
|
||||
return md5Rotate((a + (c ^ (b | ~d)) + value + constant) | 0, shift) + b | 0
|
||||
}
|
||||
|
||||
function md5Rotate(value: number, shift: number): number {
|
||||
return (value << shift) | (value >>> (32 - shift))
|
||||
}
|
||||
+6
-5
@@ -22,7 +22,7 @@ export type RequestConfig = {
|
||||
}
|
||||
|
||||
// 基础URL配置 - 虚拟接口
|
||||
const BASE_URL = 'https://mock-api.example.com'
|
||||
const BASE_URL = 'https://localhost:7145'
|
||||
|
||||
// 请求超时时间
|
||||
const TIMEOUT = 10000
|
||||
@@ -112,7 +112,7 @@ function responseInterceptor<T>(response: UniNamespace.RequestSuccessCallbackRes
|
||||
const result = response.data as ApiResponse<T>
|
||||
|
||||
// 业务状态码检查
|
||||
if (result.code !== 0) {
|
||||
if (result.code !== 200) {
|
||||
handleError(result.code, result.message, config.showError)
|
||||
return null
|
||||
}
|
||||
@@ -371,7 +371,7 @@ function createMockResponse<T>(config: RequestConfig): ApiResponse<T> {
|
||||
}
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
code: 200,
|
||||
message: 'success',
|
||||
data: data as T
|
||||
}
|
||||
@@ -385,7 +385,7 @@ export function request<T>(config: RequestConfig): Promise<ApiResponse<T> | null
|
||||
// 请求拦截
|
||||
const finalConfig = requestInterceptor(config)
|
||||
|
||||
if (USE_MOCK_API) {
|
||||
if (USE_MOCK_API && !finalConfig.url.includes('/api/v1/Parents/')) {
|
||||
const delay = Math.floor(Math.random() * (MOCK_RESPONSE_MAX_DELAY + 1))
|
||||
setTimeout(() => {
|
||||
if (finalConfig.showLoading !== false) {
|
||||
@@ -416,7 +416,8 @@ export function request<T>(config: RequestConfig): Promise<ApiResponse<T> | null
|
||||
|
||||
// 网络错误处理
|
||||
handleError(-1, err.errMsg ?? '网络连接失败', finalConfig.showError)
|
||||
reject(err)
|
||||
// 将网络失败转换为统一的空响应,避免页面事件中出现未处理 Promise 异常。
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user