667 lines
15 KiB
JavaScript
667 lines
15 KiB
JavaScript
import axios from 'axios'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
// 创建axios实例
|
||
const api = axios.create({
|
||
timeout: 10000
|
||
})
|
||
|
||
// 请求拦截器
|
||
api.interceptors.request.use(
|
||
config => {
|
||
// 动态设置baseURL
|
||
if (window.electronAPI) {
|
||
config.baseURL = window.electronAPI.getBackendUrl()
|
||
} else {
|
||
config.baseURL = 'http://192.168.1.58:5000'
|
||
}
|
||
|
||
// 为需要发送数据的请求设置Content-Type(避免覆盖FormData)
|
||
if (['post', 'put', 'patch'].includes((config.method || '').toLowerCase())) {
|
||
const isFormData = typeof FormData !== 'undefined' && config.data instanceof FormData
|
||
if (!isFormData && !config.headers['Content-Type']) {
|
||
config.headers['Content-Type'] = 'application/json'
|
||
}
|
||
}
|
||
|
||
// 添加认证token
|
||
const token = localStorage.getItem('authToken')
|
||
if (token) {
|
||
config.headers['Authorization'] = `Bearer ${token}`
|
||
}
|
||
|
||
// 添加时间戳防止缓存
|
||
if (config.method === 'get') {
|
||
config.params = {
|
||
...config.params,
|
||
_t: Date.now()
|
||
}
|
||
}
|
||
|
||
return config
|
||
},
|
||
error => {
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
// 响应拦截器
|
||
api.interceptors.response.use(
|
||
response => {
|
||
return response.data
|
||
},
|
||
error => {
|
||
let message = '请求失败'
|
||
|
||
if (error.response) {
|
||
// 服务器响应错误
|
||
const { status, data } = error.response
|
||
switch (status) {
|
||
case 400:
|
||
message = data.message || '请求参数错误'
|
||
break
|
||
case 401:
|
||
message = '未授权访问'
|
||
break
|
||
case 403:
|
||
message = '禁止访问'
|
||
break
|
||
case 404:
|
||
message = '请求的资源不存在'
|
||
break
|
||
case 500:
|
||
message = '服务器内部错误'
|
||
break
|
||
default:
|
||
message = data.message || `请求失败 (${status})`
|
||
}
|
||
} else if (error.request) {
|
||
// 网络错误
|
||
message = '网络连接失败,请检查后端服务是否启动'
|
||
} else {
|
||
// 其他错误
|
||
message = error.message || '未知错误'
|
||
}
|
||
|
||
// ElMessage.error(message)
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
// 系统API
|
||
export const systemAPI = {
|
||
// 健康检查
|
||
health() {
|
||
return api.get('/health')
|
||
},
|
||
|
||
// 获取系统信息
|
||
getSystemInfo() {
|
||
return api.get('/api/system/info')
|
||
},
|
||
|
||
// 获取系统状态
|
||
getSystemStatus() {
|
||
return api.get('/api/system/status')
|
||
}
|
||
}
|
||
|
||
// 设备API
|
||
export const deviceAPI = {
|
||
// 获取设备状态
|
||
getDeviceStatus() {
|
||
return api.get('/api/devices/status')
|
||
},
|
||
|
||
// 刷新设备
|
||
refreshDevices() {
|
||
return api.post('/api/devices/refresh')
|
||
},
|
||
|
||
// 校准设备
|
||
calibrateDevice() {
|
||
return api.post('/api/devices/calibrate')
|
||
},
|
||
|
||
// 校准IMU头部姿态传感器
|
||
calibrateIMU() {
|
||
return api.post('/api/devices/calibrate/imu')
|
||
},
|
||
|
||
// 测试设备
|
||
testDevice() {
|
||
return api.post('/api/devices/test')
|
||
}
|
||
}
|
||
|
||
// 用户认证API
|
||
export const authAPI = {
|
||
// 用户登录
|
||
login(credentials) {
|
||
return api.post('/api/auth/login', credentials)
|
||
},
|
||
|
||
// 用户注册
|
||
register(userData) {
|
||
return api.post('/api/auth/register', userData)
|
||
},
|
||
|
||
// 忘记密码
|
||
forgotPassword(email) {
|
||
return api.post('/api/auth/forgot-password', { email })
|
||
},
|
||
|
||
// 重置密码
|
||
resetPassword(token, newPassword) {
|
||
return api.post('/api/auth/reset-password', { token, password: newPassword })
|
||
},
|
||
|
||
// 退出登录
|
||
logout() {
|
||
return api.post('/api/auth/logout')
|
||
},
|
||
|
||
// 验证token
|
||
verifyToken() {
|
||
return api.get('/api/auth/verify')
|
||
}
|
||
}
|
||
|
||
// 患者API
|
||
export const patientAPI = {
|
||
// 获取患者列表
|
||
getPatients(params = {}) {
|
||
return api.get('/api/patients', { params })
|
||
},
|
||
|
||
// 获取患者详情
|
||
getPatient(id) {
|
||
return api.get(`/api/patients/${id}`)
|
||
},
|
||
|
||
// 根据ID获取患者(别名方法)
|
||
getById(id) {
|
||
return this.getPatient(id)
|
||
},
|
||
|
||
// 创建患者
|
||
createPatient(data) {
|
||
return api.post('/api/patients', data)
|
||
},
|
||
|
||
// 创建患者(别名方法)
|
||
create(data) {
|
||
return this.createPatient(data)
|
||
},
|
||
|
||
// 更新患者
|
||
updatePatient(id, data) {
|
||
return api.put(`/api/patients/${id}`, data)
|
||
},
|
||
|
||
// 更新患者(别名方法)
|
||
update(id, data) {
|
||
return this.updatePatient(id, data)
|
||
},
|
||
|
||
// 删除患者
|
||
deletePatient(id) {
|
||
return api.delete(`/api/patients/${id}`)
|
||
},
|
||
|
||
// 搜索患者
|
||
searchPatients(query) {
|
||
return api.get('/api/patients/search', { params: { q: query } })
|
||
},
|
||
|
||
// 获取患者统计信息
|
||
getStatistics() {
|
||
return api.get('/api/patients/statistics')
|
||
}
|
||
}
|
||
|
||
// 检测API
|
||
export const detectionAPI = {
|
||
// 开始检测
|
||
startDetection(config) {
|
||
return api.post('/api/detection/start', config)
|
||
},
|
||
|
||
// 停止检测
|
||
stopDetection(sessionId) {
|
||
return api.post(`/api/detection/${sessionId}/stop`)
|
||
},
|
||
|
||
// 获取检测状态
|
||
getDetectionStatus(sessionId) {
|
||
return api.get(`/api/detection/${sessionId}/status`)
|
||
},
|
||
|
||
// 获取实时数据
|
||
getRealTimeData(sessionId) {
|
||
return api.get(`/api/detection/${sessionId}/realtime`)
|
||
},
|
||
|
||
// 获取检测结果
|
||
getDetectionResults(sessionId) {
|
||
return api.get(`/api/detection/${sessionId}/results`)
|
||
},
|
||
|
||
// 保存检测结果
|
||
saveDetectionResults(sessionId, data) {
|
||
return api.post(`/api/detection/${sessionId}/save`, data)
|
||
},
|
||
|
||
// 创建检测记录
|
||
create(data) {
|
||
return api.post('/api/detection', data)
|
||
},
|
||
|
||
// 获取检测记录列表
|
||
getList(params = {}) {
|
||
return api.get('/api/detection', { params })
|
||
},
|
||
|
||
// 根据患者ID获取检测记录
|
||
getByPatient(patientId) {
|
||
return api.get(`/api/patients/${patientId}/detections`)
|
||
}
|
||
}
|
||
|
||
// 授权API
|
||
export const licenseAPI = {
|
||
info() {
|
||
return api.get('/api/license/info')
|
||
},
|
||
generateActivationRequest(company_name, contact_info) {
|
||
return api.post('/api/license/activation-request', { company_name, contact_info })
|
||
},
|
||
verifyLicense(licenseFile) {
|
||
const formData = new FormData()
|
||
formData.append('license_file', licenseFile)
|
||
return api.post('/api/license/verify', formData)
|
||
},
|
||
activatePackage(zipFile) {
|
||
const formData = new FormData()
|
||
formData.append('package_zip', zipFile)
|
||
return api.post('/api/license/activate-package', formData)
|
||
}
|
||
}
|
||
|
||
// 录制API
|
||
export const recordingAPI = {
|
||
// 创建录制
|
||
create(data) {
|
||
return api.post('/api/recordings', data)
|
||
},
|
||
|
||
// 获取录制列表
|
||
getList(params = {}) {
|
||
return api.get('/api/recordings', { params })
|
||
},
|
||
|
||
// 根据患者ID获取录制
|
||
getByPatient(patientId) {
|
||
return api.get(`/api/patients/${patientId}/recordings`)
|
||
},
|
||
|
||
// 获取录制详情
|
||
getById(id) {
|
||
return api.get(`/api/recordings/${id}`)
|
||
},
|
||
|
||
// 更新录制
|
||
update(id, data) {
|
||
return api.put(`/api/recordings/${id}`, data)
|
||
},
|
||
|
||
// 删除录制
|
||
delete(id) {
|
||
return api.delete(`/api/recordings/${id}`)
|
||
},
|
||
|
||
// 上传录制文件
|
||
upload(file, onProgress) {
|
||
const formData = new FormData()
|
||
formData.append('file', file)
|
||
|
||
return api.post('/api/recordings/upload', formData, {
|
||
headers: {
|
||
'Content-Type': 'multipart/form-data'
|
||
},
|
||
onUploadProgress: (progressEvent) => {
|
||
if (onProgress) {
|
||
const percentCompleted = Math.round(
|
||
(progressEvent.loaded * 100) / progressEvent.total
|
||
)
|
||
onProgress(percentCompleted)
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 会话API
|
||
export const sessionAPI = {
|
||
// 获取会话列表
|
||
getSessions(params = {}) {
|
||
return api.get('/api/sessions', { params })
|
||
},
|
||
|
||
// 获取会话详情
|
||
getSession(id) {
|
||
return api.get(`/api/sessions/${id}`)
|
||
},
|
||
|
||
// 删除会话
|
||
deleteSession(id) {
|
||
return api.delete(`/api/sessions/${id}`)
|
||
},
|
||
|
||
// 获取患者的会话历史
|
||
getPatientSessions(patientId, params = {}) {
|
||
return api.get(`/api/patients/${patientId}/sessions`, { params })
|
||
}
|
||
}
|
||
|
||
// 数据分析API
|
||
export const analysisAPI = {
|
||
// 分析会话数据
|
||
analyzeSession(sessionId) {
|
||
return api.post(`/api/analysis/session/${sessionId}`)
|
||
},
|
||
|
||
// 获取分析结果
|
||
getAnalysisResult(sessionId) {
|
||
return api.get(`/api/analysis/session/${sessionId}/result`)
|
||
},
|
||
|
||
// 比较多个会话
|
||
compareSessions(sessionIds) {
|
||
return api.post('/api/analysis/compare', { session_ids: sessionIds })
|
||
},
|
||
|
||
// 获取统计数据
|
||
getStatistics(params = {}) {
|
||
return api.get('/api/analysis/statistics', { params })
|
||
},
|
||
|
||
// 生成趋势报告
|
||
generateTrendReport(patientId, params = {}) {
|
||
return api.post(`/api/analysis/trend/${patientId}`, params)
|
||
}
|
||
}
|
||
|
||
// 报告API
|
||
export const reportAPI = {
|
||
// 生成PDF报告
|
||
generatePDFReport(sessionId) {
|
||
return api.post(`/api/reports/pdf/${sessionId}`, {}, {
|
||
responseType: 'blob'
|
||
})
|
||
},
|
||
|
||
// 导出数据
|
||
exportData(sessionId, format = 'csv') {
|
||
return api.get(`/api/reports/export/${sessionId}`, {
|
||
params: { format },
|
||
responseType: 'blob'
|
||
})
|
||
},
|
||
|
||
// 批量导出
|
||
batchExport(sessionIds, format = 'csv') {
|
||
return api.post('/api/reports/batch-export', {
|
||
session_ids: sessionIds,
|
||
format
|
||
}, {
|
||
responseType: 'blob'
|
||
})
|
||
},
|
||
|
||
// 获取报告列表
|
||
getReports(params = {}) {
|
||
return api.get('/api/reports', { params })
|
||
},
|
||
|
||
// 删除报告
|
||
deleteReport(reportId) {
|
||
return api.delete(`/api/reports/${reportId}`)
|
||
}
|
||
}
|
||
|
||
// 设置API
|
||
export const settingsAPI = {
|
||
// 获取系统设置
|
||
getSettings() {
|
||
return api.get('/api/settings')
|
||
},
|
||
|
||
// 更新系统设置
|
||
updateSettings(settings) {
|
||
return api.put('/api/settings', settings)
|
||
},
|
||
|
||
// 重置设置
|
||
resetSettings() {
|
||
return api.post('/api/settings/reset')
|
||
},
|
||
|
||
// 备份设置
|
||
backupSettings() {
|
||
return api.post('/api/settings/backup', {}, {
|
||
responseType: 'blob'
|
||
})
|
||
},
|
||
|
||
// 恢复设置
|
||
restoreSettings(file) {
|
||
const formData = new FormData()
|
||
formData.append('file', file)
|
||
return api.post('/api/settings/restore', formData, {
|
||
headers: {
|
||
'Content-Type': 'multipart/form-data'
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// WebSocket连接管理
|
||
export class WebSocketManager {
|
||
constructor() {
|
||
this.socket = null
|
||
this.reconnectAttempts = 0
|
||
this.maxReconnectAttempts = 5
|
||
this.reconnectInterval = 3000
|
||
this.listeners = new Map()
|
||
}
|
||
|
||
connect(url) {
|
||
try {
|
||
this.socket = new WebSocket(url)
|
||
|
||
this.socket.onopen = () => {
|
||
console.log('WebSocket连接已建立')
|
||
this.reconnectAttempts = 0
|
||
this.emit('connected')
|
||
}
|
||
|
||
this.socket.onmessage = (event) => {
|
||
try {
|
||
const data = JSON.parse(event.data)
|
||
this.emit('message', data)
|
||
|
||
// 根据消息类型分发
|
||
if (data.type) {
|
||
this.emit(data.type, data.payload)
|
||
}
|
||
} catch (error) {
|
||
console.error('WebSocket消息解析失败:', error)
|
||
}
|
||
}
|
||
|
||
this.socket.onclose = () => {
|
||
console.log('WebSocket连接已关闭')
|
||
this.emit('disconnected')
|
||
this.attemptReconnect()
|
||
}
|
||
|
||
this.socket.onerror = (error) => {
|
||
console.error('WebSocket错误:', error)
|
||
this.emit('error', error)
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('WebSocket连接失败:', error)
|
||
this.emit('error', error)
|
||
}
|
||
}
|
||
|
||
disconnect() {
|
||
if (this.socket) {
|
||
this.socket.close()
|
||
this.socket = null
|
||
}
|
||
}
|
||
|
||
send(data) {
|
||
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||
this.socket.send(JSON.stringify(data))
|
||
} else {
|
||
console.warn('WebSocket未连接,无法发送消息')
|
||
}
|
||
}
|
||
|
||
on(event, callback) {
|
||
if (!this.listeners.has(event)) {
|
||
this.listeners.set(event, [])
|
||
}
|
||
this.listeners.get(event).push(callback)
|
||
}
|
||
|
||
off(event, callback) {
|
||
if (this.listeners.has(event)) {
|
||
const callbacks = this.listeners.get(event)
|
||
const index = callbacks.indexOf(callback)
|
||
if (index > -1) {
|
||
callbacks.splice(index, 1)
|
||
}
|
||
}
|
||
}
|
||
|
||
emit(event, data) {
|
||
if (this.listeners.has(event)) {
|
||
this.listeners.get(event).forEach(callback => {
|
||
try {
|
||
callback(data)
|
||
} catch (error) {
|
||
console.error(`WebSocket事件处理错误 [${event}]:`, error)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
attemptReconnect() {
|
||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||
this.reconnectAttempts++
|
||
console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`)
|
||
|
||
setTimeout(() => {
|
||
if (window.electronAPI) {
|
||
const backendUrl = window.electronAPI.getBackendUrl()
|
||
const wsUrl = backendUrl.replace('http', 'ws') + '/ws'
|
||
this.connect(wsUrl)
|
||
}
|
||
}, this.reconnectInterval)
|
||
} else {
|
||
console.error('WebSocket重连失败,已达到最大重试次数')
|
||
this.emit('reconnect_failed')
|
||
}
|
||
}
|
||
}
|
||
|
||
// 创建WebSocket管理器实例
|
||
export const wsManager = new WebSocketManager()
|
||
|
||
// 文件上传工具
|
||
export const uploadFile = (file, onProgress) => {
|
||
return new Promise((resolve, reject) => {
|
||
const formData = new FormData()
|
||
formData.append('file', file)
|
||
|
||
const config = {
|
||
headers: {
|
||
'Content-Type': 'multipart/form-data'
|
||
},
|
||
onUploadProgress: (progressEvent) => {
|
||
if (onProgress) {
|
||
const percentCompleted = Math.round(
|
||
(progressEvent.loaded * 100) / progressEvent.total
|
||
)
|
||
onProgress(percentCompleted)
|
||
}
|
||
}
|
||
}
|
||
|
||
api.post('/api/upload', formData, config)
|
||
.then(resolve)
|
||
.catch(reject)
|
||
})
|
||
}
|
||
|
||
// 文件下载工具
|
||
export const downloadFile = (url, filename) => {
|
||
return api.get(url, { responseType: 'blob' })
|
||
.then(response => {
|
||
const blob = new Blob([response])
|
||
const downloadUrl = window.URL.createObjectURL(blob)
|
||
const link = document.createElement('a')
|
||
link.href = downloadUrl
|
||
link.download = filename
|
||
document.body.appendChild(link)
|
||
link.click()
|
||
document.body.removeChild(link)
|
||
window.URL.revokeObjectURL(downloadUrl)
|
||
})
|
||
}
|
||
//
|
||
export const historyAPI = {
|
||
// 获取检测会话历史
|
||
sessionsPage(params) {
|
||
return api.get('/api/history/sessions', { params })
|
||
},
|
||
// 删除检测数据记录
|
||
detectionDelById(id) {
|
||
return api.delete(`/api/detection/data/${id}`, {})
|
||
},
|
||
// 删除检测会话及其相关的检测数据
|
||
sessionsDelById(id) {
|
||
return api.delete(`api/detection/sessions/${id}`, {})
|
||
},
|
||
// 获取检测会话历史
|
||
sessionById(id) {
|
||
return api.get(`/api/history/sessions/${id}`)
|
||
},
|
||
|
||
//获取最新的检测数据
|
||
detectionLatestList(id) {
|
||
return api.get(`/api/detection/data/detail/${id}/latest`)
|
||
},
|
||
//根据主键ID查询检测数据详情
|
||
detectionById(id) {
|
||
return api.get(`/api/detection/data/detail/${id}`)
|
||
},
|
||
|
||
|
||
}
|
||
|
||
// 获取后端URL的函数
|
||
export const getBackendUrl = () => {
|
||
if (window.electronAPI) {
|
||
return window.electronAPI.getBackendUrl()
|
||
} else {
|
||
return 'http://localhost:5000'
|
||
}
|
||
}
|
||
|
||
export default api |