392 lines
8.8 KiB
JavaScript
392 lines
8.8 KiB
JavaScript
|
|
// API接口封装
|
|||
|
|
const API_BASE = 'https://pactgo.cn/api/v1'
|
|||
|
|
|
|||
|
|
class API {
|
|||
|
|
// 用户登录
|
|||
|
|
static async login(code) {
|
|||
|
|
return this.request('/wechat/login', 'POST', { code })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取用户信息
|
|||
|
|
static async getUserInfo() {
|
|||
|
|
return this.request('/wechat/userinfo', 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提交任务
|
|||
|
|
static async submitTask(taskData) {
|
|||
|
|
return this.request('/task/submit', 'POST', taskData)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取任务列表
|
|||
|
|
static async getTaskList(page = 1, limit = 20) {
|
|||
|
|
return this.request(`/task/list?page=${page}&limit=${limit}`, 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取任务详情
|
|||
|
|
static async getTaskDetail(taskId) {
|
|||
|
|
return this.request(`/task/${taskId}`, 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取任务状态
|
|||
|
|
static async getTaskStatus(taskId) {
|
|||
|
|
return this.request(`/task/${taskId}/status`, 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 发送聊天消息
|
|||
|
|
static async sendMessage(content, type = 'text') {
|
|||
|
|
return this.request('/chat/message', 'POST', { content, type })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取聊天记录
|
|||
|
|
static async getChatHistory(page = 1, limit = 50) {
|
|||
|
|
return this.request(`/chat/history?page=${page}&limit=${limit}`, 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取设备信息
|
|||
|
|
static async getDeviceInfo() {
|
|||
|
|
return this.request('/device/info', 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新设备状态
|
|||
|
|
static async updateDeviceStatus(status) {
|
|||
|
|
return this.request('/device/status', 'POST', { status })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取系统状态
|
|||
|
|
static async getSystemStatus() {
|
|||
|
|
return this.request('/system/status', 'GET')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 通用请求方法
|
|||
|
|
static async request(url, method = 'GET', data = null) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const token = wx.getStorageSync('token') || ''
|
|||
|
|
|
|||
|
|
wx.request({
|
|||
|
|
url: API_BASE + url,
|
|||
|
|
method,
|
|||
|
|
data,
|
|||
|
|
header: {
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
'Authorization': token ? `Bearer ${token}` : ''
|
|||
|
|
},
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.statusCode === 200) {
|
|||
|
|
if (res.data.success !== false) {
|
|||
|
|
resolve(res.data)
|
|||
|
|
} else {
|
|||
|
|
reject(new Error(res.data.message || '请求失败'))
|
|||
|
|
}
|
|||
|
|
} else if (res.statusCode === 401) {
|
|||
|
|
// Token过期,重新登录
|
|||
|
|
wx.removeStorageSync('token')
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '登录已过期,请重新登录',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(new Error('登录已过期'))
|
|||
|
|
} else {
|
|||
|
|
reject(new Error(`请求失败: ${res.statusCode}`))
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('API请求失败:', err)
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '网络连接失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
reject(err)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 上传文件
|
|||
|
|
static async uploadFile(filePath, formData = {}) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const token = wx.getStorageSync('token') || ''
|
|||
|
|
|
|||
|
|
wx.uploadFile({
|
|||
|
|
url: API_BASE + '/upload',
|
|||
|
|
filePath: filePath,
|
|||
|
|
name: 'file',
|
|||
|
|
formData: formData,
|
|||
|
|
header: {
|
|||
|
|
'Authorization': token ? `Bearer ${token}` : ''
|
|||
|
|
},
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.statusCode === 200) {
|
|||
|
|
try {
|
|||
|
|
const data = JSON.parse(res.data)
|
|||
|
|
resolve(data)
|
|||
|
|
} catch (e) {
|
|||
|
|
reject(new Error('解析响应失败'))
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
reject(new Error(`上传失败: ${res.statusCode}`))
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('文件上传失败:', err)
|
|||
|
|
reject(err)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// WebSocket管理器
|
|||
|
|
class WebSocketManager {
|
|||
|
|
constructor() {
|
|||
|
|
this.socket = null
|
|||
|
|
this.isConnected = false
|
|||
|
|
this.reconnectTimer = null
|
|||
|
|
this.messageHandlers = new Map()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
connect(url) {
|
|||
|
|
if (this.socket) {
|
|||
|
|
this.disconnect()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.socket = wx.connectSocket({
|
|||
|
|
url: url,
|
|||
|
|
header: {
|
|||
|
|
'content-type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
this.socket.onOpen(() => {
|
|||
|
|
console.log('WebSocket连接已打开')
|
|||
|
|
this.isConnected = true
|
|||
|
|
this.clearReconnectTimer()
|
|||
|
|
|
|||
|
|
// 发送认证信息
|
|||
|
|
this.send({
|
|||
|
|
type: 'auth',
|
|||
|
|
userId: wx.getStorageSync('userId') || 'anonymous',
|
|||
|
|
deviceId: wx.getSystemInfoSync().model,
|
|||
|
|
timestamp: Date.now()
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
this.socket.onMessage((res) => {
|
|||
|
|
console.log('收到WebSocket消息:', res.data)
|
|||
|
|
try {
|
|||
|
|
const data = JSON.parse(res.data)
|
|||
|
|
this.handleMessage(data)
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('解析WebSocket消息失败:', e)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
this.socket.onClose(() => {
|
|||
|
|
console.log('WebSocket连接已关闭')
|
|||
|
|
this.isConnected = false
|
|||
|
|
this.socket = null
|
|||
|
|
this.scheduleReconnect(url)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
this.socket.onError((err) => {
|
|||
|
|
console.error('WebSocket连接错误:', err)
|
|||
|
|
this.isConnected = false
|
|||
|
|
this.scheduleReconnect(url)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
disconnect() {
|
|||
|
|
this.clearReconnectTimer()
|
|||
|
|
if (this.socket) {
|
|||
|
|
this.socket.close()
|
|||
|
|
this.socket = null
|
|||
|
|
}
|
|||
|
|
this.isConnected = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
send(data) {
|
|||
|
|
if (this.isConnected && this.socket) {
|
|||
|
|
this.socket.send({
|
|||
|
|
data: JSON.stringify(data)
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
console.warn('WebSocket未连接,无法发送消息')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onMessage(type, handler) {
|
|||
|
|
if (!this.messageHandlers.has(type)) {
|
|||
|
|
this.messageHandlers.set(type, [])
|
|||
|
|
}
|
|||
|
|
this.messageHandlers.get(type).push(handler)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
offMessage(type, handler) {
|
|||
|
|
if (this.messageHandlers.has(type)) {
|
|||
|
|
const handlers = this.messageHandlers.get(type)
|
|||
|
|
const index = handlers.indexOf(handler)
|
|||
|
|
if (index > -1) {
|
|||
|
|
handlers.splice(index, 1)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
handleMessage(data) {
|
|||
|
|
if (data.type && this.messageHandlers.has(data.type)) {
|
|||
|
|
const handlers = this.messageHandlers.get(data.type)
|
|||
|
|
handlers.forEach(handler => {
|
|||
|
|
try {
|
|||
|
|
handler(data)
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('消息处理错误:', e)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scheduleReconnect(url) {
|
|||
|
|
this.clearReconnectTimer()
|
|||
|
|
this.reconnectTimer = setTimeout(() => {
|
|||
|
|
console.log('尝试重新连接WebSocket...')
|
|||
|
|
this.connect(url)
|
|||
|
|
}, 3000)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
clearReconnectTimer() {
|
|||
|
|
if (this.reconnectTimer) {
|
|||
|
|
clearTimeout(this.reconnectTimer)
|
|||
|
|
this.reconnectTimer = null
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 工具函数
|
|||
|
|
const util = {
|
|||
|
|
// 格式化时间
|
|||
|
|
formatTime(date) {
|
|||
|
|
const year = date.getFullYear()
|
|||
|
|
const month = date.getMonth() + 1
|
|||
|
|
const day = date.getDate()
|
|||
|
|
const hour = date.getHours()
|
|||
|
|
const minute = date.getMinutes()
|
|||
|
|
const second = date.getSeconds()
|
|||
|
|
|
|||
|
|
return [year, month, day].map(this.formatNumber).join('/') + ' ' +
|
|||
|
|
[hour, minute, second].map(this.formatNumber).join(':')
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatNumber(n) {
|
|||
|
|
n = n.toString()
|
|||
|
|
return n[1] ? n : '0' + n
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 显示加载提示
|
|||
|
|
showLoading(title = '加载中...') {
|
|||
|
|
wx.showLoading({
|
|||
|
|
title: title,
|
|||
|
|
mask: true
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 隐藏加载提示
|
|||
|
|
hideLoading() {
|
|||
|
|
wx.hideLoading()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 显示成功提示
|
|||
|
|
showSuccess(title = '操作成功') {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: title,
|
|||
|
|
icon: 'success',
|
|||
|
|
duration: 2000
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 显示错误提示
|
|||
|
|
showError(title = '操作失败') {
|
|||
|
|
wx.showToast({
|
|||
|
|
title: title,
|
|||
|
|
icon: 'error',
|
|||
|
|
duration: 2000
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 显示模态框
|
|||
|
|
showModal(title, content) {
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
wx.showModal({
|
|||
|
|
title: title,
|
|||
|
|
content: content,
|
|||
|
|
success: (res) => {
|
|||
|
|
resolve(res.confirm)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 防抖函数
|
|||
|
|
debounce(func, wait) {
|
|||
|
|
let timeout
|
|||
|
|
return function executedFunction(...args) {
|
|||
|
|
const later = () => {
|
|||
|
|
clearTimeout(timeout)
|
|||
|
|
func(...args)
|
|||
|
|
}
|
|||
|
|
clearTimeout(timeout)
|
|||
|
|
timeout = setTimeout(later, wait)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 节流函数
|
|||
|
|
throttle(func, limit) {
|
|||
|
|
let inThrottle
|
|||
|
|
return function() {
|
|||
|
|
const args = arguments
|
|||
|
|
const context = this
|
|||
|
|
if (!inThrottle) {
|
|||
|
|
func.apply(context, args)
|
|||
|
|
inThrottle = true
|
|||
|
|
setTimeout(() => inThrottle = false, limit)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 常量定义
|
|||
|
|
const constants = {
|
|||
|
|
// API基础地址
|
|||
|
|
API_BASE: 'https://pactgo.cn/api/v1',
|
|||
|
|
|
|||
|
|
// WebSocket地址
|
|||
|
|
WEBSOCKET_URL: 'wss://pactgo.cn/ws/task',
|
|||
|
|
|
|||
|
|
// 任务状态
|
|||
|
|
TASK_STATUS: {
|
|||
|
|
PENDING: 'pending',
|
|||
|
|
PROCESSING: 'processing',
|
|||
|
|
COMPLETED: 'completed',
|
|||
|
|
FAILED: 'failed'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 消息类型
|
|||
|
|
MESSAGE_TYPE: {
|
|||
|
|
TEXT: 'text',
|
|||
|
|
IMAGE: 'image',
|
|||
|
|
FILE: 'file',
|
|||
|
|
SYSTEM: 'system'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 本地存储键名
|
|||
|
|
STORAGE_KEYS: {
|
|||
|
|
TOKEN: 'token',
|
|||
|
|
USER_INFO: 'userInfo',
|
|||
|
|
DEVICE_ID: 'deviceId',
|
|||
|
|
TASK_HISTORY: 'taskHistory'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
API,
|
|||
|
|
WebSocketManager,
|
|||
|
|
util,
|
|||
|
|
constants
|
|||
|
|
}
|