fix auth
This commit is contained in:
@@ -462,7 +462,28 @@ class ApiManager {
|
||||
async smartLogin(forceRefresh: boolean = false): Promise<ILoginResponse | null> {
|
||||
if (USE_CLOUD) {
|
||||
const app = getApp<IAppOption>()
|
||||
const dictLevel = wx.getStorageSync('dictLevel') || 'PRIMARY'
|
||||
let dictLevel = wx.getStorageSync('dictLevel') || 'LEVEL1'
|
||||
try {
|
||||
const resp = await this.request<{ user: IUserInfo; dict_level?: string; session_uuid?: string; settings?: { dict_level?: string }; points?: { balance: number; expired_time: string } }>(
|
||||
'/api/v1/wx/user',
|
||||
'GET',
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
const data = (resp as any)?.data || resp
|
||||
if (data.user) {
|
||||
app.globalData.userInfo = data.user
|
||||
wx.setStorageSync('userInfo', data.user)
|
||||
}
|
||||
const dl = data.dict_level || 'LEVEL1'
|
||||
if (dl) {
|
||||
dictLevel = dl
|
||||
wx.setStorageSync('dictLevel', dictLevel)
|
||||
}
|
||||
if (data.session_uuid) {
|
||||
wx.setStorageSync('sessionUuid', data.session_uuid)
|
||||
}
|
||||
} catch (e) {}
|
||||
app.globalData.isLoggedIn = true
|
||||
app.globalData.dictLevel = dictLevel
|
||||
return {
|
||||
@@ -483,12 +504,12 @@ class ApiManager {
|
||||
if (!isExpired) {
|
||||
app.globalData.isLoggedIn = true
|
||||
app.globalData.token = authInfo.token
|
||||
app.globalData.dictLevel = authInfo.dictLevel || 'PRIMARY'
|
||||
app.globalData.dictLevel = authInfo.dictLevel || 'LEVEL1'
|
||||
return {
|
||||
access_token: authInfo.token,
|
||||
access_token_expire_time: new Date(authInfo.tokenExpiry).toISOString(),
|
||||
session_uuid: authInfo.sessionUuid || '',
|
||||
dict_level: authInfo.dictLevel || 'PRIMARY'
|
||||
dict_level: authInfo.dictLevel || 'LEVEL1'
|
||||
}
|
||||
} else {
|
||||
this.clearAuthData()
|
||||
@@ -641,67 +662,89 @@ class ApiManager {
|
||||
|
||||
// 上传文件(第一步:上传文件获取ID)
|
||||
async uploadFile(filePath: string, retryCount: number = 0): Promise<string> {
|
||||
const maxRetries = 1 // 最多重试1次
|
||||
|
||||
if (USE_CLOUD) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = wx.getFileSystemManager()
|
||||
fs.getFileInfo({
|
||||
filePath,
|
||||
success: async (infoRes) => {
|
||||
try {
|
||||
const filename = this.extractFileName(filePath)
|
||||
const mime = this.getMimeType(filePath)
|
||||
const initResp = await this.wx_request<{ file_id: string; cloud_path: string; env: string }>(
|
||||
'/api/v1/file/upload/init',
|
||||
'POST',
|
||||
{ filename, size: infoRes.size, mime, biz_type: 'file' }
|
||||
)
|
||||
const initData = (initResp as any).data || initResp
|
||||
const file_id = initData.file_id
|
||||
const cloud_path = initData.cloud_path
|
||||
const env = initData.env
|
||||
const task = wx.cloud.uploadFile({
|
||||
cloudPath: cloud_path,
|
||||
filePath,
|
||||
config: { env },
|
||||
success: async (upRes) => {
|
||||
try {
|
||||
const completeResp = await this.wx_request<{ id: string; url?: string }>(
|
||||
'/api/v1/file/upload/complete',
|
||||
'POST',
|
||||
{ file_id, cloud_path, fileID: upRes.fileID, size: infoRes.size, mime }
|
||||
)
|
||||
resolve(file_id)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
},
|
||||
fail: (e) => {
|
||||
const info = String(e)
|
||||
if (info.indexOf('abort') !== -1) {
|
||||
reject(new Error('上传中断'))
|
||||
} else {
|
||||
reject(new Error('上传失败'))
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
const maxRetries = 1
|
||||
return new Promise(async (resolve, reject) => {
|
||||
console.log('上传文件请求:', { filePath, retryCount })
|
||||
|
||||
wx.uploadFile({
|
||||
url: `${BASE_URL}/api/v1/file/upload`,
|
||||
filePath,
|
||||
name: 'file', // 根据API要求调整参数名
|
||||
name: 'file',
|
||||
header: this.getHeaders(),
|
||||
success: async (res) => {
|
||||
console.log('上传文件响应:', {
|
||||
statusCode: res.statusCode,
|
||||
data: res.data,
|
||||
retryCount
|
||||
})
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
try {
|
||||
const response = JSON.parse(res.data) as IApiResponse<{ id: string }>
|
||||
if (response.code === 0 || response.code === 200) {
|
||||
if (response.data?.id) {
|
||||
console.log('文件上传成功,获得ID:', response.data.id)
|
||||
resolve(response.data.id)
|
||||
} else {
|
||||
reject(new Error('服务器返回数据中缺少文件ID'))
|
||||
}
|
||||
} else {
|
||||
const errorMsg = response.message || response.msg || '文件上传失败'
|
||||
console.error('文件上传业务错误:', errorMsg, response)
|
||||
wx.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: errorMsg, icon: 'none' })
|
||||
reject(new Error(errorMsg))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('文件上传响应解析错误:', error)
|
||||
wx.showToast({
|
||||
title: '数据解析错误',
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: '数据解析错误', icon: 'none' })
|
||||
reject(error)
|
||||
}
|
||||
} else if (res.statusCode === 401) {
|
||||
console.warn('文件上传401认证失败,尝试自动登录', { retryCount, maxRetries })
|
||||
|
||||
// 如果还有重试机会,尝试自动登录并重试请求
|
||||
if (retryCount < maxRetries) {
|
||||
try {
|
||||
console.log('开始文件上传401自动登录重试')
|
||||
|
||||
// 清理过期的认证数据
|
||||
this.clearAuthData()
|
||||
|
||||
// 进行智能登录
|
||||
const loginResult = await this.smartLogin(true) // 强制刷新token
|
||||
|
||||
const loginResult = await this.smartLogin(true)
|
||||
if (loginResult) {
|
||||
console.log('文件上传401自动登录成功,重试请求')
|
||||
// 登录成功后重试原请求
|
||||
try {
|
||||
const retryResult = await this.uploadFile(filePath, retryCount + 1)
|
||||
resolve(retryResult)
|
||||
@@ -709,64 +752,24 @@ class ApiManager {
|
||||
reject(retryError)
|
||||
}
|
||||
} else {
|
||||
console.error('文件上传401自动登录失败')
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} catch (loginError) {
|
||||
console.error('文件上传401自动登录发生错误:', loginError)
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} else {
|
||||
// 重试次数耗尽,直接处理token过期
|
||||
console.error('文件上传401重试次数耗尽,跳转登录页')
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} else {
|
||||
// Check for 413 Request Entity Too Large error
|
||||
if (res.statusCode === 413) {
|
||||
// Get file size for debugging
|
||||
const fs = wx.getFileSystemManager();
|
||||
fs.getFileInfo({
|
||||
filePath: filePath,
|
||||
success: (infoRes) => {
|
||||
const fileSizeInMB = (infoRes.size / (1024 * 1024)).toFixed(4);
|
||||
console.error('文件上传413错误 - 请求实体过大:', {
|
||||
statusCode: res.statusCode,
|
||||
fileSize: `${fileSizeInMB} MB`,
|
||||
fileSizeInBytes: infoRes.size,
|
||||
filePath: filePath,
|
||||
data: res.data
|
||||
});
|
||||
},
|
||||
fail: (infoError) => {
|
||||
console.error('文件上传413错误 - 无法获取文件大小:', {
|
||||
statusCode: res.statusCode,
|
||||
filePath: filePath,
|
||||
fileInfoError: infoError,
|
||||
data: res.data
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('文件上传HTTP错误:', res.statusCode, res.data);
|
||||
}
|
||||
|
||||
wx.showToast({
|
||||
title: '文件上传失败',
|
||||
icon: 'none'
|
||||
});
|
||||
reject(new Error(`HTTP ${res.statusCode}`));
|
||||
wx.showToast({ title: '文件上传失败', icon: 'none' })
|
||||
reject(new Error(`HTTP ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('文件上传请求失败:', error)
|
||||
wx.showToast({
|
||||
title: '文件上传失败',
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: '文件上传失败', icon: 'none' })
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
@@ -775,67 +778,89 @@ class ApiManager {
|
||||
|
||||
// 上传文件(第一步:上传文件获取ID)
|
||||
async uploadImageFile(filePath: string, retryCount: number = 0): Promise<string> {
|
||||
const maxRetries = 1 // 最多重试1次
|
||||
|
||||
if (USE_CLOUD) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = wx.getFileSystemManager()
|
||||
fs.getFileInfo({
|
||||
filePath,
|
||||
success: async (infoRes) => {
|
||||
try {
|
||||
const filename = this.extractFileName(filePath)
|
||||
const mime = this.getMimeType(filePath)
|
||||
const initResp = await this.wx_request<{ file_id: string; cloud_path: string; env: string }>(
|
||||
'/api/v1/file/upload/init',
|
||||
'POST',
|
||||
{ filename, size: infoRes.size, mime, biz_type: 'image' }
|
||||
)
|
||||
const initData = (initResp as any).data || initResp
|
||||
const file_id = initData.file_id
|
||||
const cloud_path = initData.cloud_path
|
||||
const env = initData.env
|
||||
const task = wx.cloud.uploadFile({
|
||||
cloudPath: cloud_path,
|
||||
filePath,
|
||||
config: { env },
|
||||
success: async (upRes) => {
|
||||
try {
|
||||
const completeResp = await this.wx_request<{ id: string; url?: string }>(
|
||||
'/api/v1/file/upload/complete',
|
||||
'POST',
|
||||
{ file_id, cloud_path, fileID: upRes.fileID, size: infoRes.size, mime }
|
||||
)
|
||||
resolve(file_id)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
},
|
||||
fail: (e) => {
|
||||
const info = String(e)
|
||||
if (info.indexOf('abort') !== -1) {
|
||||
reject(new Error('上传中断'))
|
||||
} else {
|
||||
reject(new Error('上传失败'))
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
const maxRetries = 1
|
||||
return new Promise(async (resolve, reject) => {
|
||||
console.log('上传文件请求:', { filePath, retryCount })
|
||||
|
||||
wx.uploadFile({
|
||||
url: `${BASE_URL}/api/v1/file/upload_image`,
|
||||
filePath,
|
||||
name: 'file', // 根据API要求调整参数名
|
||||
name: 'file',
|
||||
header: this.getHeaders(),
|
||||
success: async (res) => {
|
||||
console.log('上传文件响应:', {
|
||||
statusCode: res.statusCode,
|
||||
data: res.data,
|
||||
retryCount
|
||||
})
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
try {
|
||||
const response = JSON.parse(res.data) as IApiResponse<{ id: string }>
|
||||
if (response.code === 0 || response.code === 200) {
|
||||
if (response.data?.id) {
|
||||
console.log('文件上传成功,获得ID:', response.data.id)
|
||||
resolve(response.data.id)
|
||||
} else {
|
||||
reject(new Error('服务器返回数据中缺少文件ID'))
|
||||
}
|
||||
} else {
|
||||
const errorMsg = response.message || response.msg || '文件上传失败'
|
||||
console.error('文件上传业务错误:', errorMsg, response)
|
||||
wx.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: errorMsg, icon: 'none' })
|
||||
reject(new Error(errorMsg))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('文件上传响应解析错误:', error)
|
||||
wx.showToast({
|
||||
title: '数据解析错误',
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: '数据解析错误', icon: 'none' })
|
||||
reject(error)
|
||||
}
|
||||
} else if (res.statusCode === 401) {
|
||||
console.warn('文件上传401认证失败,尝试自动登录', { retryCount, maxRetries })
|
||||
|
||||
// 如果还有重试机会,尝试自动登录并重试请求
|
||||
if (retryCount < maxRetries) {
|
||||
try {
|
||||
console.log('开始文件上传401自动登录重试')
|
||||
|
||||
// 清理过期的认证数据
|
||||
this.clearAuthData()
|
||||
|
||||
// 进行智能登录
|
||||
const loginResult = await this.smartLogin(true) // 强制刷新token
|
||||
|
||||
const loginResult = await this.smartLogin(true)
|
||||
if (loginResult) {
|
||||
console.log('文件上传401自动登录成功,重试请求')
|
||||
// 登录成功后重试原请求
|
||||
try {
|
||||
const retryResult = await this.uploadFile(filePath, retryCount + 1)
|
||||
resolve(retryResult)
|
||||
@@ -843,78 +868,57 @@ class ApiManager {
|
||||
reject(retryError)
|
||||
}
|
||||
} else {
|
||||
console.error('文件上传401自动登录失败')
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} catch (loginError) {
|
||||
console.error('文件上传401自动登录发生错误:', loginError)
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} else {
|
||||
// 重试次数耗尽,直接处理token过期
|
||||
console.error('文件上传401重试次数耗尽,跳转登录页')
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('登录已过期'))
|
||||
}
|
||||
} else {
|
||||
// Check for 413 Request Entity Too Large error
|
||||
if (res.statusCode === 413) {
|
||||
// Get file size for debugging
|
||||
const fs = wx.getFileSystemManager();
|
||||
fs.getFileInfo({
|
||||
filePath: filePath,
|
||||
success: (infoRes) => {
|
||||
const fileSizeInMB = (infoRes.size / (1024 * 1024)).toFixed(4);
|
||||
console.error('文件上传413错误 - 请求实体过大:', {
|
||||
statusCode: res.statusCode,
|
||||
fileSize: `${fileSizeInMB} MB`,
|
||||
fileSizeInBytes: infoRes.size,
|
||||
filePath: filePath,
|
||||
data: res.data
|
||||
});
|
||||
},
|
||||
fail: (infoError) => {
|
||||
console.error('文件上传413错误 - 无法获取文件大小:', {
|
||||
statusCode: res.statusCode,
|
||||
filePath: filePath,
|
||||
fileInfoError: infoError,
|
||||
data: res.data
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('文件上传HTTP错误:', res.statusCode, res.data);
|
||||
}
|
||||
|
||||
wx.showToast({
|
||||
title: '文件上传失败',
|
||||
icon: 'none'
|
||||
});
|
||||
reject(new Error(`HTTP ${res.statusCode}`));
|
||||
wx.showToast({ title: '文件上传失败', icon: 'none' })
|
||||
reject(new Error(`HTTP ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('文件上传请求失败:', error)
|
||||
wx.showToast({
|
||||
title: '文件上传失败',
|
||||
icon: 'none'
|
||||
})
|
||||
wx.showToast({ title: '文件上传失败', icon: 'none' })
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private extractFileName(path: string): string {
|
||||
const i = path.lastIndexOf('/')
|
||||
return i >= 0 ? path.substring(i + 1) : path
|
||||
}
|
||||
|
||||
private getMimeType(path: string): string {
|
||||
const i = path.lastIndexOf('.')
|
||||
const ext = i >= 0 ? path.substring(i + 1).toLowerCase() : ''
|
||||
const map: Record<string, string> = {
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
bmp: 'image/bmp'
|
||||
}
|
||||
return map[ext] || 'application/octet-stream'
|
||||
}
|
||||
|
||||
// 图片识别(第二步:通过文件ID进行识别)
|
||||
async recognizeImageAsync(fileId: string, type: string = 'word'): Promise<{task_id: string, status: string, message: string}> {
|
||||
console.log('开始图片识别请求:', { fileId, type })
|
||||
|
||||
// 获取当前的词典等级配置
|
||||
const app = getApp<IAppOption>()
|
||||
const dictLevel = app.globalData.dictLevel || wx.getStorageSync('dictLevel') || 'PRIMARY'
|
||||
const dictLevel = app.globalData.dictLevel || wx.getStorageSync('dictLevel') || 'LEVEL1'
|
||||
|
||||
console.log('开始图片识别请求:', { fileId, type, dictLevel })
|
||||
const response = await this.request<{task_id: string, status: string, message: string}>('/api/v1/image/recognize/async', 'POST', {
|
||||
file_id: fileId,
|
||||
type: type,
|
||||
@@ -1578,56 +1582,77 @@ class ApiManager {
|
||||
|
||||
// 安全下载文件接口
|
||||
async downloadFile(fileId: string): Promise<string> {
|
||||
if (USE_CLOUD) {
|
||||
try {
|
||||
const resp = await this.wx_request<{ url: string }>(`/api/v1/file/temp_url/${fileId}`, 'GET')
|
||||
const tempUrl = (resp as any)?.data?.url || (resp as any)?.url
|
||||
if (!tempUrl) {
|
||||
throw new Error('无法获取临时下载链接')
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.downloadFile({
|
||||
url: tempUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
const fs = wx.getFileSystemManager()
|
||||
const tempPath = res.tempFilePath
|
||||
const extMatch = tempPath && tempPath.match(/\.[a-zA-Z0-9]+$/)
|
||||
if (!extMatch) {
|
||||
resolve(tempPath)
|
||||
return
|
||||
}
|
||||
const ext = extMatch[0]
|
||||
const filePath = `${wx.env.USER_DATA_PATH}/${fileId}${ext}`
|
||||
fs.saveFile({
|
||||
tempFilePath: tempPath,
|
||||
filePath,
|
||||
success: () => resolve(filePath),
|
||||
fail: () => resolve(tempPath)
|
||||
})
|
||||
} else {
|
||||
reject(new Error(`文件下载失败,状态码: ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (error) => reject(new Error('文件下载失败'))
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
// console.log('开始安全下载文件:', fileId);
|
||||
|
||||
// 构建文件下载URL
|
||||
const fileUrl = `${BASE_URL}/api/v1/file/${fileId}`;
|
||||
|
||||
// 获取认证头
|
||||
const headers = this.getHeaders();
|
||||
|
||||
// 使用微信的下载文件API
|
||||
const fileUrl = `${BASE_URL}/api/v1/file/${fileId}`
|
||||
const headers = this.getHeaders()
|
||||
wx.downloadFile({
|
||||
url: fileUrl,
|
||||
header: headers,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
const fs = wx.getFileSystemManager();
|
||||
const tempPath = res.tempFilePath;
|
||||
const extMatch = tempPath && tempPath.match(/\.[a-zA-Z0-9]+$/);
|
||||
const fs = wx.getFileSystemManager()
|
||||
const tempPath = res.tempFilePath
|
||||
const extMatch = tempPath && tempPath.match(/\.[a-zA-Z0-9]+$/)
|
||||
if (!extMatch) {
|
||||
resolve(tempPath);
|
||||
return;
|
||||
resolve(tempPath)
|
||||
return
|
||||
}
|
||||
const ext = extMatch[0];
|
||||
const filePath = `${wx.env.USER_DATA_PATH}/${fileId}${ext}`;
|
||||
const ext = extMatch[0]
|
||||
const filePath = `${wx.env.USER_DATA_PATH}/${fileId}${ext}`
|
||||
fs.saveFile({
|
||||
tempFilePath: tempPath,
|
||||
filePath,
|
||||
success: () => {
|
||||
resolve(filePath);
|
||||
},
|
||||
fail: () => {
|
||||
resolve(tempPath);
|
||||
}
|
||||
});
|
||||
success: () => resolve(filePath),
|
||||
fail: () => resolve(tempPath)
|
||||
})
|
||||
} else if (res.statusCode === 401) {
|
||||
// 处理认证失败
|
||||
console.error('文件下载认证失败');
|
||||
this.handleTokenExpired();
|
||||
reject(new Error('认证失败,请重新登录'));
|
||||
this.handleTokenExpired()
|
||||
reject(new Error('认证失败,请重新登录'))
|
||||
} else {
|
||||
console.error('文件下载失败,状态码:', res.statusCode);
|
||||
reject(new Error(`文件下载失败,状态码: ${res.statusCode}`));
|
||||
reject(new Error(`文件下载失败,状态码: ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('文件下载请求失败:', error);
|
||||
reject(new Error('文件下载失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
fail: (error) => reject(new Error('文件下载失败'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 将文件ID转换为可显示的图片URL
|
||||
|
||||
Reference in New Issue
Block a user