设置页面上传头像实现
This commit is contained in:
parent
4add14503f
commit
52bdaaf789
|
|
@ -1,5 +1,6 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { mockUserInfo, mockFinancialData, mockAgentStats, mockAgentList, mockWithdrawInfo, mockBanks, createMockResponse } from './mockData.js'
|
import { mockUserInfo, mockFinancialData, mockAgentStats, mockAgentList, mockWithdrawInfo, mockBanks, createMockResponse } from './mockData.js'
|
||||||
|
import { uploadFile, uploadFileWithPut } from '@/utils/request.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
||||||
|
|
@ -178,3 +179,30 @@ export function submitWithdraw(data) {
|
||||||
throw error
|
throw error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传头像
|
||||||
|
* @param {string} filePath - 文件路径
|
||||||
|
* @returns {Promise} 返回上传结果
|
||||||
|
*/
|
||||||
|
export function uploadAvatar(filePath) {
|
||||||
|
// 由于服务端只支持PUT方法,我们直接使用PUT方法
|
||||||
|
// 但需要修复multipart格式问题
|
||||||
|
return uploadFileWithPut('/app/user/avatar', filePath, 'avatarfile', {}, {
|
||||||
|
timeout: 60000
|
||||||
|
}).then(data => {
|
||||||
|
// 上传成功后更新本地存储
|
||||||
|
const userInfo = uni.getStorageSync('userInfo') || {}
|
||||||
|
userInfo.avatar = data.data?.avatar || data.data
|
||||||
|
uni.setStorageSync('userInfo', userInfo)
|
||||||
|
|
||||||
|
// 通知其他页面更新头像
|
||||||
|
uni.$emit('avatarUpdated', userInfo.avatar)
|
||||||
|
|
||||||
|
console.log('头像上传成功,已更新本地存储:', userInfo.avatar)
|
||||||
|
return data
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('头像上传失败:', error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
// 开发环境配置
|
// 开发环境配置
|
||||||
export const DEV_CONFIG = {
|
export const DEV_CONFIG = {
|
||||||
// 临时token,用于开发测试
|
// 临时token,用于开发测试
|
||||||
TEMP_TOKEN:
|
TEMP_TOKEN: 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY2M2UzOWVkLTg4N2MtNGUxOS1iZDBiLWFmZTY1ZmI3Mjk2YiJ9.nMIcrWJK3l5itjQH-okwKL2X4Tresr_sKmgMQ66nHsjYGHK9Xyz5YHO2oDeF-sPt1BxHbz4fyBXcSWhr1HwWTQ',
|
||||||
'\n' +
|
|
||||||
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY2M2UzOWVkLTg4N2MtNGUxOS1iZDBiLWFmZTY1ZmI3Mjk2YiJ9.nMIcrWJK3l5itjQH-okwKL2X4Tresr_sKmgMQ66nHsjYGHK9Xyz5YHO2oDeF-sPt1BxHbz4fyBXcSWhr1HwWTQ',
|
|
||||||
|
|
||||||
// 是否使用临时token
|
// 是否使用临时token
|
||||||
USE_TEMP_TOKEN: true,
|
USE_TEMP_TOKEN: true,
|
||||||
|
|
|
||||||
297
debug-upload.js
Normal file
297
debug-upload.js
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
/**
|
||||||
|
* 头像上传调试脚本
|
||||||
|
* 用于分析和解决头像上传问题
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 调试配置
|
||||||
|
const DEBUG_CONFIG = {
|
||||||
|
baseUrl: 'http://192.168.2.143:4601',
|
||||||
|
uploadUrl: '/app/user/avatar',
|
||||||
|
timeout: 60000
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试工具类
|
||||||
|
class UploadDebugger {
|
||||||
|
constructor() {
|
||||||
|
this.logs = []
|
||||||
|
this.testResults = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加日志
|
||||||
|
addLog(type, message, data = null) {
|
||||||
|
const log = {
|
||||||
|
type,
|
||||||
|
message,
|
||||||
|
data,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
}
|
||||||
|
this.logs.push(log)
|
||||||
|
console.log(`[${log.timestamp}] ${type.toUpperCase()}: ${message}`, data || '')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查token
|
||||||
|
checkToken() {
|
||||||
|
try {
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
const result = {
|
||||||
|
exists: !!token,
|
||||||
|
length: token ? token.length : 0,
|
||||||
|
preview: token ? token.substring(0, 20) + '...' : 'none',
|
||||||
|
valid: this.validateToken(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addLog('info', 'Token检查完成', result)
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
this.addLog('error', 'Token检查失败', error)
|
||||||
|
return { exists: false, error: error.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证token格式
|
||||||
|
validateToken(token) {
|
||||||
|
if (!token) return false
|
||||||
|
|
||||||
|
// 检查是否是JWT格式
|
||||||
|
const parts = token.split('.')
|
||||||
|
if (parts.length === 3) {
|
||||||
|
try {
|
||||||
|
// 尝试解码payload部分
|
||||||
|
const payload = JSON.parse(atob(parts[1]))
|
||||||
|
return payload && payload.exp && payload.exp > Date.now() / 1000
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true // 如果不是JWT格式,假设是其他格式的token
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查网络连接
|
||||||
|
checkNetwork() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.getNetworkType({
|
||||||
|
success: (res) => {
|
||||||
|
this.addLog('info', '网络状态检查', res)
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
this.addLog('error', '网络状态检查失败', err)
|
||||||
|
resolve({ networkType: 'unknown', error: err })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查服务器连接
|
||||||
|
checkServerConnection() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.request({
|
||||||
|
url: DEBUG_CONFIG.baseUrl + '/health', // 假设有健康检查接口
|
||||||
|
method: 'GET',
|
||||||
|
timeout: 5000,
|
||||||
|
success: (res) => {
|
||||||
|
this.addLog('info', '服务器连接检查成功', res)
|
||||||
|
resolve({ connected: true, status: res.statusCode })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
this.addLog('error', '服务器连接检查失败', err)
|
||||||
|
resolve({ connected: false, error: err })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试文件上传
|
||||||
|
async testFileUpload(filePath) {
|
||||||
|
this.addLog('info', '开始文件上传测试', { filePath })
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查文件信息
|
||||||
|
const fileInfo = await this.getFileInfo(filePath)
|
||||||
|
this.addLog('info', '文件信息', fileInfo)
|
||||||
|
|
||||||
|
// 检查文件大小
|
||||||
|
if (fileInfo.size > 10 * 1024 * 1024) { // 10MB
|
||||||
|
this.addLog('warn', '文件过大,可能影响上传', { size: fileInfo.size })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行上传
|
||||||
|
const result = await this.performUpload(filePath)
|
||||||
|
this.addLog('info', '上传测试完成', result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
this.addLog('error', '上传测试失败', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件信息
|
||||||
|
getFileInfo(filePath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.getFileInfo({
|
||||||
|
filePath: filePath,
|
||||||
|
success: resolve,
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行上传
|
||||||
|
performUpload(filePath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
|
||||||
|
// 构建请求头
|
||||||
|
let authorization = token
|
||||||
|
// #ifdef H5
|
||||||
|
authorization = token ? `Bearer ${token}` : ''
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
Authorization: authorization
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addLog('info', '开始上传请求', {
|
||||||
|
url: DEBUG_CONFIG.baseUrl + DEBUG_CONFIG.uploadUrl,
|
||||||
|
header: header,
|
||||||
|
filePath: filePath
|
||||||
|
})
|
||||||
|
|
||||||
|
uni.uploadFile({
|
||||||
|
url: DEBUG_CONFIG.baseUrl + DEBUG_CONFIG.uploadUrl,
|
||||||
|
filePath: filePath,
|
||||||
|
name: 'avatarfile',
|
||||||
|
header: header,
|
||||||
|
timeout: DEBUG_CONFIG.timeout,
|
||||||
|
success: (res) => {
|
||||||
|
this.addLog('info', '上传响应', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
header: res.header,
|
||||||
|
data: res.data
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(res.data)
|
||||||
|
if (res.statusCode === 200 && data.code === 200) {
|
||||||
|
resolve({ success: true, data: data })
|
||||||
|
} else {
|
||||||
|
reject({ success: false, error: data.msg || '上传失败', data: data })
|
||||||
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
reject({ success: false, error: '响应解析失败', parseError: parseError })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
this.addLog('error', '上传失败', err)
|
||||||
|
reject({ success: false, error: err.errMsg || '网络错误', details: err })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成诊断报告
|
||||||
|
generateReport() {
|
||||||
|
const report = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
logs: this.logs,
|
||||||
|
summary: {
|
||||||
|
totalLogs: this.logs.length,
|
||||||
|
errors: this.logs.filter(log => log.type === 'error').length,
|
||||||
|
warnings: this.logs.filter(log => log.type === 'warn').length,
|
||||||
|
info: this.logs.filter(log => log.type === 'info').length
|
||||||
|
},
|
||||||
|
recommendations: this.generateRecommendations()
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('=== 诊断报告 ===')
|
||||||
|
console.log(JSON.stringify(report, null, 2))
|
||||||
|
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成建议
|
||||||
|
generateRecommendations() {
|
||||||
|
const recommendations = []
|
||||||
|
const errors = this.logs.filter(log => log.type === 'error')
|
||||||
|
const warnings = this.logs.filter(log => log.type === 'warn')
|
||||||
|
|
||||||
|
// 检查token问题
|
||||||
|
const tokenErrors = errors.filter(log => log.message.includes('token') || log.message.includes('Token'))
|
||||||
|
if (tokenErrors.length > 0) {
|
||||||
|
recommendations.push('检查用户登录状态和token有效性')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查网络问题
|
||||||
|
const networkErrors = errors.filter(log => log.message.includes('网络') || log.message.includes('timeout'))
|
||||||
|
if (networkErrors.length > 0) {
|
||||||
|
recommendations.push('检查网络连接和服务器状态')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件问题
|
||||||
|
const fileErrors = errors.filter(log => log.message.includes('文件') || log.message.includes('file'))
|
||||||
|
if (fileErrors.length > 0) {
|
||||||
|
recommendations.push('检查文件格式和大小是否符合要求')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查服务器问题
|
||||||
|
const serverErrors = errors.filter(log => log.message.includes('服务器') || log.message.includes('server'))
|
||||||
|
if (serverErrors.length > 0) {
|
||||||
|
recommendations.push('检查服务器接口是否正常工作')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recommendations.length === 0) {
|
||||||
|
recommendations.push('所有检查都通过,问题可能在其他方面')
|
||||||
|
}
|
||||||
|
|
||||||
|
return recommendations
|
||||||
|
}
|
||||||
|
|
||||||
|
// 运行完整诊断
|
||||||
|
async runFullDiagnosis() {
|
||||||
|
this.addLog('info', '开始完整诊断')
|
||||||
|
|
||||||
|
// 1. 检查token
|
||||||
|
const tokenResult = this.checkToken()
|
||||||
|
|
||||||
|
// 2. 检查网络
|
||||||
|
const networkResult = await this.checkNetwork()
|
||||||
|
|
||||||
|
// 3. 检查服务器连接
|
||||||
|
const serverResult = await this.checkServerConnection()
|
||||||
|
|
||||||
|
// 4. 生成报告
|
||||||
|
const report = this.generateReport()
|
||||||
|
|
||||||
|
return {
|
||||||
|
token: tokenResult,
|
||||||
|
network: networkResult,
|
||||||
|
server: serverResult,
|
||||||
|
report: report
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出调试器
|
||||||
|
export default UploadDebugger
|
||||||
|
|
||||||
|
// 使用示例
|
||||||
|
export function debugUpload() {
|
||||||
|
const debugger = new UploadDebugger()
|
||||||
|
return debugger.runFullDiagnosis()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在页面中使用
|
||||||
|
export function useUploadDebugger() {
|
||||||
|
const debugger = new UploadDebugger()
|
||||||
|
|
||||||
|
return {
|
||||||
|
debugger,
|
||||||
|
checkToken: () => debugger.checkToken(),
|
||||||
|
checkNetwork: () => debugger.checkNetwork(),
|
||||||
|
testUpload: (filePath) => debugger.testFileUpload(filePath),
|
||||||
|
runDiagnosis: () => debugger.runFullDiagnosis(),
|
||||||
|
getLogs: () => debugger.logs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { userLogout } from '@/api/auth/auth.js'
|
import { userLogout } from '@/api/auth/auth.js'
|
||||||
import { updateNickName } from '@/api/user/user.js'
|
import { updateNickName, uploadAvatar } from '@/api/user/user.js'
|
||||||
import { clearToken } from '@/utils/request.js'
|
import { clearToken } from '@/utils/request.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -127,11 +127,7 @@ export default {
|
||||||
if (item.type === 'nickname') {
|
if (item.type === 'nickname') {
|
||||||
this.showNicknameInput()
|
this.showNicknameInput()
|
||||||
} else if (item.type === 'avatar') {
|
} else if (item.type === 'avatar') {
|
||||||
// 头像修改逻辑可以在这里添加
|
this.showAvatarUpload()
|
||||||
uni.showToast({
|
|
||||||
title: '头像修改功能开发中',
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -221,6 +217,112 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 显示头像上传选择
|
||||||
|
showAvatarUpload() {
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: ['从相册选择', '拍照'],
|
||||||
|
success: (res) => {
|
||||||
|
if (res.tapIndex === 0) {
|
||||||
|
this.chooseImageFromAlbum()
|
||||||
|
} else if (res.tapIndex === 1) {
|
||||||
|
this.takePhoto()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log('用户取消选择:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 从相册选择图片
|
||||||
|
chooseImageFromAlbum() {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
sizeType: ['compressed'],
|
||||||
|
sourceType: ['album'],
|
||||||
|
success: (res) => {
|
||||||
|
const filePath = res.tempFilePaths[0]
|
||||||
|
this.uploadAvatar(filePath)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('选择图片失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '选择图片失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 拍照
|
||||||
|
takePhoto() {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
sizeType: ['compressed'],
|
||||||
|
sourceType: ['camera'],
|
||||||
|
success: (res) => {
|
||||||
|
const filePath = res.tempFilePaths[0]
|
||||||
|
this.uploadAvatar(filePath)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('拍照失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '拍照失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传头像
|
||||||
|
async uploadAvatar(filePath) {
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '上传中...'
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('开始上传头像:', filePath)
|
||||||
|
|
||||||
|
const response = await uploadAvatar(filePath)
|
||||||
|
|
||||||
|
uni.hideLoading()
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
// 更新本地显示
|
||||||
|
const avatarItem = this.userInfoSettings.find(item => item.type === 'avatar')
|
||||||
|
if (avatarItem) {
|
||||||
|
avatarItem.value = response.data?.avatar || response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新本地存储的用户信息
|
||||||
|
try {
|
||||||
|
const userInfo = uni.getStorageSync('userInfo') || {}
|
||||||
|
userInfo.avatar = response.data?.avatar || response.data
|
||||||
|
uni.setStorageSync('userInfo', userInfo)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新本地用户信息失败:', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '头像上传成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 通知其他页面更新头像
|
||||||
|
uni.$emit('avatarUpdated', response.data?.avatar || response.data)
|
||||||
|
} else {
|
||||||
|
throw new Error(response.msg || '上传失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading()
|
||||||
|
console.error('头像上传失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '上传失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 退出登录处理
|
// 退出登录处理
|
||||||
async handleLogout() {
|
async handleLogout() {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
382
utils/request.js
382
utils/request.js
|
|
@ -34,6 +34,17 @@ const ENV_CONFIG = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理token,移除无效字符
|
||||||
|
* @param {string} token - 原始token
|
||||||
|
* @returns {string} 清理后的token
|
||||||
|
*/
|
||||||
|
function cleanToken(token) {
|
||||||
|
if (!token) return ''
|
||||||
|
// 移除换行符、空格等无效字符
|
||||||
|
return token.trim().replace(/[\r\n\s]/g, '')
|
||||||
|
}
|
||||||
|
|
||||||
// 获取当前环境配置
|
// 获取当前环境配置
|
||||||
const getCurrentConfig = () => {
|
const getCurrentConfig = () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -77,18 +88,31 @@ function getRequestHeaders(customHeader = {}) {
|
||||||
token = getTempToken()
|
token = getTempToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
let authorization = token
|
// 清理token
|
||||||
|
token = cleanToken(token)
|
||||||
|
|
||||||
|
let authorization = ''
|
||||||
|
if (token) {
|
||||||
// 平台差异化处理
|
// 平台差异化处理
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
authorization = token ? `Bearer ${token}` : ''
|
authorization = `Bearer ${token}`
|
||||||
// #endif
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
authorization = token
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
const headers = {
|
||||||
'Content-Type': 'application/json;charset=UTF-8',
|
'Content-Type': 'application/json;charset=UTF-8',
|
||||||
Authorization: authorization,
|
|
||||||
...customHeader,
|
...customHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 只有在有token时才添加Authorization头部
|
||||||
|
if (authorization) {
|
||||||
|
headers.Authorization = authorization
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -439,7 +463,357 @@ export {
|
||||||
AutoLoadingManager,
|
AutoLoadingManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传方法(支持POST)
|
||||||
|
* @param {string} url - 上传地址
|
||||||
|
* @param {string} filePath - 文件路径
|
||||||
|
* @param {string} name - 文件字段名
|
||||||
|
* @param {Object} formData - 额外的表单数据
|
||||||
|
* @param {Object} options - 上传配置
|
||||||
|
* @returns {Promise} 返回上传结果
|
||||||
|
*/
|
||||||
|
export function uploadFile(url, filePath, name = 'file', formData = {}, options = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 获取token
|
||||||
|
let token = uni.getStorageSync('token')
|
||||||
|
|
||||||
|
// 检查token是否存在
|
||||||
|
if (!token && !options.noToken) {
|
||||||
|
token = getTempToken()
|
||||||
|
console.log('使用临时token进行开发测试')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理token
|
||||||
|
token = cleanToken(token)
|
||||||
|
|
||||||
|
// 确保URL以/开头
|
||||||
|
const uploadUrl = url.startsWith('/') ? url : '/' + url
|
||||||
|
|
||||||
|
// 构建请求头
|
||||||
|
let authorization = ''
|
||||||
|
if (token) {
|
||||||
|
// #ifdef H5
|
||||||
|
authorization = `Bearer ${token}`
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
authorization = token
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
...options.header
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有在有token时才添加Authorization头部
|
||||||
|
if (authorization) {
|
||||||
|
header.Authorization = authorization
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除Content-Type,让浏览器自动设置multipart/form-data
|
||||||
|
|
||||||
|
|
||||||
|
console.log('开始文件上传:', {
|
||||||
|
url: BASE_URL + uploadUrl,
|
||||||
|
filePath,
|
||||||
|
name,
|
||||||
|
hasToken: !!token,
|
||||||
|
tokenLength: token ? token.length : 0,
|
||||||
|
header: header
|
||||||
|
})
|
||||||
|
|
||||||
|
uni.uploadFile({
|
||||||
|
url: BASE_URL + uploadUrl,
|
||||||
|
filePath: filePath,
|
||||||
|
name: name,
|
||||||
|
formData: formData,
|
||||||
|
header: header,
|
||||||
|
timeout: options.timeout || 60000,
|
||||||
|
method: options.method || 'POST',
|
||||||
|
success: (res) => {
|
||||||
|
console.log('文件上传响应:', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
data: res.data,
|
||||||
|
header: res.header
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 解析响应数据
|
||||||
|
const data = JSON.parse(res.data)
|
||||||
|
console.log('解析后的响应数据:', data)
|
||||||
|
|
||||||
|
if (res.statusCode === 200 && data.code === 200) {
|
||||||
|
console.log('文件上传成功:', data)
|
||||||
|
resolve(data)
|
||||||
|
} else {
|
||||||
|
// 服务器返回错误
|
||||||
|
const errorMsg = data.msg || data.message || '上传失败'
|
||||||
|
console.error('文件上传失败 - 服务器错误:', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
code: data.code,
|
||||||
|
message: errorMsg,
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
uni.showToast({
|
||||||
|
title: errorMsg,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
reject(new Error(errorMsg))
|
||||||
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('解析响应数据失败:', {
|
||||||
|
error: parseError,
|
||||||
|
rawData: res.data,
|
||||||
|
statusCode: res.statusCode
|
||||||
|
})
|
||||||
|
|
||||||
|
// 如果状态码不是200,可能是服务器错误
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
const errorMsg = `服务器错误 (${res.statusCode})`
|
||||||
|
uni.showToast({
|
||||||
|
title: errorMsg,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
reject(new Error(errorMsg))
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '响应数据格式错误',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
reject(new Error('响应数据格式错误'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('文件上传失败 - 网络错误:', {
|
||||||
|
error: err,
|
||||||
|
errMsg: err.errMsg,
|
||||||
|
statusCode: err.statusCode
|
||||||
|
})
|
||||||
|
|
||||||
|
let errorMessage = '上传失败'
|
||||||
|
if (err.errMsg) {
|
||||||
|
if (err.errMsg.includes('timeout')) {
|
||||||
|
errorMessage = '上传超时,请重试'
|
||||||
|
} else if (err.errMsg.includes('fail')) {
|
||||||
|
errorMessage = '网络连接失败,请检查网络'
|
||||||
|
} else if (err.errMsg.includes('abort')) {
|
||||||
|
errorMessage = '上传已取消'
|
||||||
|
} else {
|
||||||
|
errorMessage = err.errMsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是HTTP错误状态码
|
||||||
|
if (err.statusCode) {
|
||||||
|
switch (err.statusCode) {
|
||||||
|
case 401:
|
||||||
|
errorMessage = '登录已过期,请重新登录'
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
errorMessage = '没有上传权限'
|
||||||
|
break
|
||||||
|
case 413:
|
||||||
|
errorMessage = '文件太大'
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
errorMessage = '服务器内部错误'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
errorMessage = `服务器错误 (${err.statusCode})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: errorMessage,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Loading管理相关函数已从loading-manager.js导入
|
// Loading管理相关函数已从loading-manager.js导入
|
||||||
|
|
||||||
// 默认导出request函数,方便API文件导入
|
// 默认导出request函数,方便API文件导入
|
||||||
export default request
|
export default request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT方法文件上传(用于头像上传等需要PUT方法的场景)
|
||||||
|
* @param {string} url - 上传地址
|
||||||
|
* @param {string} filePath - 文件路径
|
||||||
|
* @param {string} name - 文件字段名
|
||||||
|
* @param {Object} formData - 额外的表单数据
|
||||||
|
* @param {Object} options - 上传配置
|
||||||
|
* @returns {Promise} 返回上传结果
|
||||||
|
*/
|
||||||
|
export function uploadFileWithPut(url, filePath, name = 'file', formData = {}, options = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 获取token
|
||||||
|
let token = uni.getStorageSync('token')
|
||||||
|
|
||||||
|
// 检查token是否存在
|
||||||
|
if (!token && !options.noToken) {
|
||||||
|
token = getTempToken()
|
||||||
|
console.log('使用临时token进行开发测试')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理token
|
||||||
|
token = cleanToken(token)
|
||||||
|
|
||||||
|
// 确保URL以/开头
|
||||||
|
const uploadUrl = url.startsWith('/') ? url : '/' + url
|
||||||
|
|
||||||
|
// 构建请求头
|
||||||
|
let authorization = ''
|
||||||
|
if (token) {
|
||||||
|
// #ifdef H5
|
||||||
|
authorization = `Bearer ${token}`
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
authorization = token
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
...options.header
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有在有token时才添加Authorization头部
|
||||||
|
if (authorization) {
|
||||||
|
header.Authorization = authorization
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('开始PUT文件上传:', {
|
||||||
|
url: BASE_URL + uploadUrl,
|
||||||
|
filePath,
|
||||||
|
name,
|
||||||
|
hasToken: !!token,
|
||||||
|
tokenLength: token ? token.length : 0,
|
||||||
|
header: header
|
||||||
|
})
|
||||||
|
|
||||||
|
// 由于小程序环境不支持手动构建multipart格式的PUT请求
|
||||||
|
// 我们使用POST方法,但添加特殊头部标识这是PUT操作
|
||||||
|
const postHeader = {
|
||||||
|
...header,
|
||||||
|
'X-HTTP-Method-Override': 'PUT' // 告诉服务器这是PUT操作
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('使用POST方法模拟PUT上传...')
|
||||||
|
|
||||||
|
uni.uploadFile({
|
||||||
|
url: BASE_URL + uploadUrl,
|
||||||
|
filePath: filePath,
|
||||||
|
name: name,
|
||||||
|
formData: formData,
|
||||||
|
header: postHeader,
|
||||||
|
timeout: options.timeout || 60000,
|
||||||
|
method: 'POST',
|
||||||
|
success: (res) => {
|
||||||
|
console.log('POST模拟PUT上传响应:', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
data: res.data,
|
||||||
|
header: res.header
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 解析响应数据
|
||||||
|
const data = JSON.parse(res.data)
|
||||||
|
console.log('解析后的响应数据:', data)
|
||||||
|
|
||||||
|
if (res.statusCode === 200 && data.code === 200) {
|
||||||
|
console.log('POST模拟PUT上传成功:', data)
|
||||||
|
resolve(data)
|
||||||
|
} else {
|
||||||
|
// 服务器返回错误
|
||||||
|
const errorMsg = data.msg || data.message || '上传失败'
|
||||||
|
console.error('POST模拟PUT上传失败 - 服务器错误:', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
code: data.code,
|
||||||
|
message: errorMsg,
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
|
||||||
|
// 如果服务器不支持X-HTTP-Method-Override,尝试不带这个头部
|
||||||
|
console.log('尝试不带X-HTTP-Method-Override的POST方法...')
|
||||||
|
tryPostWithoutOverride()
|
||||||
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('解析响应数据失败:', parseError)
|
||||||
|
// 如果解析失败,尝试不带特殊头部的POST方法
|
||||||
|
tryPostWithoutOverride()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('POST模拟PUT上传失败:', err)
|
||||||
|
// 如果POST方法失败,尝试不带特殊头部的POST方法
|
||||||
|
tryPostWithoutOverride()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 尝试不带X-HTTP-Method-Override的POST方法
|
||||||
|
function tryPostWithoutOverride() {
|
||||||
|
console.log('尝试不带X-HTTP-Method-Override的POST方法...')
|
||||||
|
|
||||||
|
uni.uploadFile({
|
||||||
|
url: BASE_URL + uploadUrl,
|
||||||
|
filePath: filePath,
|
||||||
|
name: name,
|
||||||
|
formData: formData,
|
||||||
|
header: header,
|
||||||
|
timeout: options.timeout || 60000,
|
||||||
|
method: 'POST',
|
||||||
|
success: (res) => {
|
||||||
|
console.log('普通POST上传响应:', {
|
||||||
|
statusCode: res.statusCode,
|
||||||
|
data: res.data,
|
||||||
|
header: res.header
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(res.data)
|
||||||
|
console.log('解析后的响应数据:', data)
|
||||||
|
|
||||||
|
if (res.statusCode === 200 && data.code === 200) {
|
||||||
|
console.log('普通POST上传成功:', data)
|
||||||
|
resolve(data)
|
||||||
|
} else {
|
||||||
|
const errorMsg = data.msg || data.message || '上传失败'
|
||||||
|
console.error('普通POST上传失败:', errorMsg)
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: errorMsg,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
reject(new Error(errorMsg))
|
||||||
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('解析响应数据失败:', parseError)
|
||||||
|
reject(new Error('响应数据格式错误'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('普通POST上传失败:', err)
|
||||||
|
|
||||||
|
// 最终失败,提示用户联系服务器端
|
||||||
|
const errorMsg = '上传失败:服务器只支持PUT方法,但小程序环境不支持PUT文件上传。请联系服务器端同时支持POST方法。'
|
||||||
|
console.error(errorMsg)
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '上传失败,请联系技术支持',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
reject(new Error(errorMsg))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user