Claw 项目完整结构提交
This commit is contained in:
392
Claw/client/wechat_app/utils/api.js
Normal file
392
Claw/client/wechat_app/utils/api.js
Normal file
@@ -0,0 +1,392 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user