4 changed files with 478 additions and 9 deletions
@ -0,0 +1,36 @@ |
|||||||
|
/** |
||||||
|
* 应用配置文件 |
||||||
|
* 可根据环境变量配置不同的 API 地址 |
||||||
|
*/ |
||||||
|
|
||||||
|
// API 基础地址配置
|
||||||
|
// 直接配置,如需修改请更改此处
|
||||||
|
const API_BASE_URL = 'https://39.101.75.71:8889' |
||||||
|
|
||||||
|
// API 版本
|
||||||
|
const API_VERSION = 'v2' |
||||||
|
|
||||||
|
// 完整的 API 前缀
|
||||||
|
const API_PREFIX = `${API_BASE_URL}/api/${API_VERSION}` |
||||||
|
|
||||||
|
// 是否开启调试模式(可根据需要手动切换)
|
||||||
|
const DEBUG_MODE = true |
||||||
|
|
||||||
|
export const config = { |
||||||
|
// API 基础地址
|
||||||
|
apiBaseUrl: API_BASE_URL, |
||||||
|
|
||||||
|
// API 版本
|
||||||
|
apiVersion: API_VERSION, |
||||||
|
|
||||||
|
// 完整 API 前缀
|
||||||
|
apiPrefix: API_PREFIX, |
||||||
|
|
||||||
|
// 请求超时时间(毫秒)
|
||||||
|
timeout: 30000, |
||||||
|
|
||||||
|
// 是否开启调试模式
|
||||||
|
debug: DEBUG_MODE, |
||||||
|
} |
||||||
|
|
||||||
|
export default config |
||||||
@ -0,0 +1,183 @@ |
|||||||
|
/** |
||||||
|
* 请求封装 |
||||||
|
* 基于 Taro.request 封装的 HTTP 请求工具 |
||||||
|
*/ |
||||||
|
import Taro from '@tarojs/taro' |
||||||
|
import config from '../config' |
||||||
|
|
||||||
|
// 请求配置接口
|
||||||
|
interface RequestConfig { |
||||||
|
url: string |
||||||
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'TRACE' | 'CONNECT' |
||||||
|
data?: any |
||||||
|
header?: Record<string, string> |
||||||
|
timeout?: number |
||||||
|
showLoading?: boolean |
||||||
|
loadingText?: string |
||||||
|
showError?: boolean |
||||||
|
} |
||||||
|
|
||||||
|
// 响应结果接口
|
||||||
|
interface ResponseResult<T = any> { |
||||||
|
message: string |
||||||
|
code: number |
||||||
|
success: boolean |
||||||
|
data: T |
||||||
|
} |
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
const requestInterceptor = (options: RequestConfig) => { |
||||||
|
// 处理完整 URL
|
||||||
|
let url = options.url |
||||||
|
if (!url.startsWith('http')) { |
||||||
|
url = `${config.apiPrefix}${url}` |
||||||
|
} |
||||||
|
|
||||||
|
// 默认请求头
|
||||||
|
const header: Record<string, string> = { |
||||||
|
'Content-Type': 'application/json', |
||||||
|
...options.header, |
||||||
|
} |
||||||
|
|
||||||
|
// 获取 token(如果有)
|
||||||
|
const token = Taro.getStorageSync('token') |
||||||
|
if (token) { |
||||||
|
header['Authorization'] = `Bearer ${token}` |
||||||
|
} |
||||||
|
|
||||||
|
// 获取 openId(如果有)
|
||||||
|
const openId = Taro.getStorageSync('openId') |
||||||
|
if (openId) { |
||||||
|
header['X-OpenId'] = openId |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
...options, |
||||||
|
url, |
||||||
|
header, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
const responseInterceptor = <T>(response: Taro.request.SuccessCallbackResult<ResponseResult<T>>): ResponseResult<T> => { |
||||||
|
const { statusCode, data } = response |
||||||
|
|
||||||
|
if (statusCode >= 200 && statusCode < 300) { |
||||||
|
// 请求成功
|
||||||
|
if (data.success) { |
||||||
|
return data |
||||||
|
} else { |
||||||
|
// 业务错误
|
||||||
|
throw { |
||||||
|
code: data.code, |
||||||
|
message: data.message || '请求失败', |
||||||
|
data: data.data, |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (statusCode === 401) { |
||||||
|
// 未授权,清除登录信息
|
||||||
|
Taro.removeStorageSync('token') |
||||||
|
Taro.removeStorageSync('openId') |
||||||
|
throw { |
||||||
|
code: 401, |
||||||
|
message: '登录已过期,请重新登录', |
||||||
|
} |
||||||
|
} else if (statusCode === 400) { |
||||||
|
// 参数错误
|
||||||
|
throw { |
||||||
|
code: data.code || 400, |
||||||
|
message: data.message || '请求参数错误', |
||||||
|
data: data.data, |
||||||
|
} |
||||||
|
} else if (statusCode === 500) { |
||||||
|
// 服务器错误
|
||||||
|
throw { |
||||||
|
code: data.code || 500, |
||||||
|
message: data.message || '服务器内部错误', |
||||||
|
data: data.data, |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw { |
||||||
|
code: statusCode, |
||||||
|
message: `请求失败: ${statusCode}`, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 封装请求方法
|
||||||
|
const request = async <T = any>(options: RequestConfig): Promise<ResponseResult<T>> => { |
||||||
|
const { |
||||||
|
showLoading = false, |
||||||
|
loadingText = '加载中...', |
||||||
|
showError = true, |
||||||
|
timeout = config.timeout, |
||||||
|
...restOptions |
||||||
|
} = options |
||||||
|
|
||||||
|
// 显示加载提示
|
||||||
|
if (showLoading) { |
||||||
|
Taro.showLoading({ title: loadingText, mask: true }) |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
// 请求拦截
|
||||||
|
const finalOptions = requestInterceptor(restOptions) |
||||||
|
|
||||||
|
if (config.debug) { |
||||||
|
console.log('[Request]', finalOptions.method || 'GET', finalOptions.url, finalOptions.data) |
||||||
|
} |
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
const response = await Taro.request<ResponseResult<T>>({ |
||||||
|
...finalOptions, |
||||||
|
timeout, |
||||||
|
}) |
||||||
|
|
||||||
|
if (config.debug) { |
||||||
|
console.log('[Response]', response.statusCode, response.data) |
||||||
|
} |
||||||
|
|
||||||
|
// 响应拦截
|
||||||
|
return responseInterceptor<T>(response) |
||||||
|
} catch (error: any) { |
||||||
|
if (config.debug) { |
||||||
|
console.error('[Request Error]', error) |
||||||
|
} |
||||||
|
|
||||||
|
// 显示错误提示
|
||||||
|
if (showError) { |
||||||
|
const errorMessage = error.message || error.errMsg || '网络请求失败' |
||||||
|
Taro.showToast({ |
||||||
|
title: errorMessage, |
||||||
|
icon: 'none', |
||||||
|
duration: 2000, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
throw error |
||||||
|
} finally { |
||||||
|
// 隐藏加载提示
|
||||||
|
if (showLoading) { |
||||||
|
Taro.hideLoading() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 快捷方法
|
||||||
|
export const get = <T = any>(url: string, data?: any, options?: Partial<RequestConfig>) => { |
||||||
|
return request<T>({ url, method: 'GET', data, ...options }) |
||||||
|
} |
||||||
|
|
||||||
|
export const post = <T = any>(url: string, data?: any, options?: Partial<RequestConfig>) => { |
||||||
|
return request<T>({ url, method: 'POST', data, ...options }) |
||||||
|
} |
||||||
|
|
||||||
|
export const put = <T = any>(url: string, data?: any, options?: Partial<RequestConfig>) => { |
||||||
|
return request<T>({ url, method: 'PUT', data, ...options }) |
||||||
|
} |
||||||
|
|
||||||
|
export const del = <T = any>(url: string, data?: any, options?: Partial<RequestConfig>) => { |
||||||
|
return request<T>({ url, method: 'DELETE', data, ...options }) |
||||||
|
} |
||||||
|
|
||||||
|
export default request |
||||||
@ -0,0 +1,150 @@ |
|||||||
|
/** |
||||||
|
* 球台相关 API |
||||||
|
* 包含开台、关台、续费等接口 |
||||||
|
*/ |
||||||
|
import { post } from './request' |
||||||
|
|
||||||
|
/** |
||||||
|
* 开台操作类型 |
||||||
|
*/ |
||||||
|
export enum TableOperationType { |
||||||
|
/** 押金开台 */ |
||||||
|
SelfServiceDeposit = 1, |
||||||
|
/** 余额开台 */ |
||||||
|
SelfServiceBalance = 2, |
||||||
|
/** 定时开台 */ |
||||||
|
Timed = 3, |
||||||
|
/** 信用开台 */ |
||||||
|
Credit = 4, |
||||||
|
/** 团购券开台 */ |
||||||
|
GroupBuy = 5, |
||||||
|
/** 立即关台 */ |
||||||
|
ImmediateClose = 6, |
||||||
|
/** 续费 */ |
||||||
|
Renew = 7, |
||||||
|
/** 关灯重开 */ |
||||||
|
ReopenAfterClose = 8, |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 支付渠道 |
||||||
|
*/ |
||||||
|
export enum PaymentChannel { |
||||||
|
/** 微信支付 */ |
||||||
|
WechatPay = 1, |
||||||
|
/** 支付宝 */ |
||||||
|
Alipay = 2, |
||||||
|
/** 银联支付 */ |
||||||
|
UnionPay = 3, |
||||||
|
/** 余额支付 */ |
||||||
|
Balance = 4, |
||||||
|
/** 银行卡支付 */ |
||||||
|
BankCard = 5, |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 开台请求参数 |
||||||
|
*/ |
||||||
|
export interface StartTableRequest { |
||||||
|
/** 设备编码 */ |
||||||
|
grpSn: string |
||||||
|
/** 用户 OpenId */ |
||||||
|
openId: string |
||||||
|
/** 开台操作类型 */ |
||||||
|
ctrlType: TableOperationType |
||||||
|
/** 消费金额 */ |
||||||
|
amount?: number |
||||||
|
/** 支付渠道 */ |
||||||
|
payType?: PaymentChannel |
||||||
|
/** 开台时长(小时),定时开台使用 */ |
||||||
|
durationHours?: number |
||||||
|
/** 团购券码,团购券开台使用 */ |
||||||
|
couponCode?: string |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 开台响应数据 |
||||||
|
*/ |
||||||
|
export interface StartTableResponse { |
||||||
|
/** 机构编码 */ |
||||||
|
instSn: string |
||||||
|
/** 店铺编码 */ |
||||||
|
bpSn: string |
||||||
|
/** 球台编码 */ |
||||||
|
grpSn: string |
||||||
|
/** 开台设备id */ |
||||||
|
operationId: number |
||||||
|
/** 开始时间 */ |
||||||
|
startTime: string |
||||||
|
/** 结束时间 */ |
||||||
|
expectedEndTime: string |
||||||
|
/** 开台操作详情id */ |
||||||
|
detailIds: number[] |
||||||
|
/** 控制id */ |
||||||
|
controlMessageId: number |
||||||
|
/** 商户订单号 */ |
||||||
|
outTradeNo: string |
||||||
|
/** 支付参数(用于调起微信支付) */ |
||||||
|
payParameters: WechatPayParameters | null |
||||||
|
/** 支付URL(用于扫码支付) */ |
||||||
|
payUrl: string |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 微信支付参数 |
||||||
|
*/ |
||||||
|
export interface WechatPayParameters { |
||||||
|
/** 时间戳 */ |
||||||
|
timeStamp: string |
||||||
|
/** 随机字符串 */ |
||||||
|
nonceStr: string |
||||||
|
/** 统一下单接口返回的 prepay_id */ |
||||||
|
package: string |
||||||
|
/** 签名方式 */ |
||||||
|
signType: string |
||||||
|
/** 签名 */ |
||||||
|
paySign: string |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 开台 API |
||||||
|
* @param data 开台请求参数 |
||||||
|
* @returns 开台响应 |
||||||
|
*/ |
||||||
|
export const startTable = (data: StartTableRequest) => { |
||||||
|
return post<StartTableResponse>('/Tables/start', data, { |
||||||
|
showLoading: true, |
||||||
|
loadingText: '开台中...', |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 调起微信支付 |
||||||
|
* @param payParams 支付参数 |
||||||
|
* @returns Promise |
||||||
|
*/ |
||||||
|
export const invokeWechatPay = (payParams: WechatPayParameters): Promise<void> => { |
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
// 使用 wx.requestPayment 调起微信支付
|
||||||
|
wx.requestPayment({ |
||||||
|
timeStamp: payParams.timeStamp, |
||||||
|
nonceStr: payParams.nonceStr, |
||||||
|
package: payParams.package, |
||||||
|
signType: payParams.signType as 'MD5' | 'HMAC-SHA256' | 'RSA', |
||||||
|
paySign: payParams.paySign, |
||||||
|
success: () => { |
||||||
|
resolve() |
||||||
|
}, |
||||||
|
fail: (err) => { |
||||||
|
reject(err) |
||||||
|
}, |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export default { |
||||||
|
startTable, |
||||||
|
invokeWechatPay, |
||||||
|
TableOperationType, |
||||||
|
PaymentChannel, |
||||||
|
} |
||||||
Loading…
Reference in new issue