4 changed files with 478 additions and 9 deletions
@ -0,0 +1,36 @@
@@ -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 @@
@@ -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 @@
@@ -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