Files
JoyD/Claw/client/wechat_app/utils/api.js
2026-03-16 15:47:55 +08:00

392 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}