Compare commits
No commits in common. 'v2.0' and 'master' have entirely different histories.
45 changed files with 1278 additions and 2425 deletions
@ -1,66 +0,0 @@ |
|||||||
/** |
|
||||||
* magdev 统一操作接口 |
|
||||||
* peroperate:/api/v2/magdev/peroperate — 去开台(预检) |
|
||||||
* operate: /api/v2/magdev/operate — 开台/关台/续费/关灯重开/分享等 |
|
||||||
* getopstatus:/api/v2/magdev/getopstatus — 查询开台结果(付款后查一次) |
|
||||||
*/ |
|
||||||
import { get, post } from '../services/request' |
|
||||||
import { |
|
||||||
normalizePreOperateResponse, |
|
||||||
normalizeOperateResponse, |
|
||||||
normalizeGetOpStatusResponse, |
|
||||||
} from '../utils/operateNormalize' |
|
||||||
import { OperateRequestDto } from '../types/magdev' |
|
||||||
import { CtrlType, PayType } from '../types/startDevice' |
|
||||||
|
|
||||||
/** 小程序 JSAPI 支付固定交易类型 */ |
|
||||||
const MINI_PROGRAM_TRADE_TYPE = 1 |
|
||||||
|
|
||||||
/** |
|
||||||
* 去开台(预开台) |
|
||||||
* @param type 开台类型(1-押金 2-定时 3-信用 4-团购券) |
|
||||||
* @param grpSn 设备编码 |
|
||||||
* @param openId 用户 openId |
|
||||||
*/ |
|
||||||
export const preOperate = async (type: number, grpSn: string, openId: string) => { |
|
||||||
const res = await post<Record<string, unknown>>( |
|
||||||
'/magdev/peroperate', |
|
||||||
{ type, grpsn: grpSn, openid: openId }, |
|
||||||
{ showLoading: true, loadingText: '处理中...' } |
|
||||||
) |
|
||||||
return { ...res, data: normalizePreOperateResponse(res.data as Record<string, unknown>) } |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 统一操作接口(开台/关台/续费/关灯重开/分享等) |
|
||||||
* @param dto 操作请求参数 |
|
||||||
*/ |
|
||||||
export const operate = async (dto: OperateRequestDto) => { |
|
||||||
const res = await post<Record<string, unknown>>( |
|
||||||
'/magdev/operate', |
|
||||||
{ |
|
||||||
grpsn: dto.grpSn, |
|
||||||
openid: dto.openId, |
|
||||||
ctrltype: dto.ctrlType, |
|
||||||
amount: dto.amount, |
|
||||||
paytype: dto.payType, |
|
||||||
tradetype: dto.tradeType ?? MINI_PROGRAM_TRADE_TYPE, |
|
||||||
couponcode: dto.couponCode ?? '', |
|
||||||
remark: dto.remark ?? '', |
|
||||||
attach: dto.attach ?? '', |
|
||||||
}, |
|
||||||
{ showLoading: true, loadingText: '处理中...' } |
|
||||||
) |
|
||||||
return { ...res, data: normalizeOperateResponse(res.data as Record<string, unknown>) } |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 查询开台状态(微信支付成功后调用一次,不轮询) |
|
||||||
* @param sn 设备编码(grpSn) |
|
||||||
*/ |
|
||||||
export const getOpStatus = async (sn: string) => { |
|
||||||
const res = await get<Record<string, unknown>>('/magdev/getopstatus', { sn }) |
|
||||||
return { ...res, data: normalizeGetOpStatusResponse(res.data as Record<string, unknown>) } |
|
||||||
} |
|
||||||
|
|
||||||
export { CtrlType, PayType } |
|
||||||
@ -1,60 +0,0 @@ |
|||||||
/** |
|
||||||
* 支付渠道相关 API |
|
||||||
*/ |
|
||||||
import { get } from '../services/request' |
|
||||||
import { pickField, toNumber } from '../utils/apiNormalize' |
|
||||||
|
|
||||||
export interface PaymentChannelItem { |
|
||||||
/** 渠道编码:1-微信 */ |
|
||||||
code: number |
|
||||||
name: string |
|
||||||
enabled: boolean |
|
||||||
} |
|
||||||
|
|
||||||
/** 微信支付渠道码 */ |
|
||||||
export const PAY_CHANNEL_WECHAT = 1 |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取机构支持的支付方式 |
|
||||||
* 文档暂无响应体定义,按常见结构归一化;仅微信时使用 code=1 |
|
||||||
*/ |
|
||||||
export const getPaymentChannels = async (instSn: string) => { |
|
||||||
const res = await get<unknown>('/payment/channels', { instsn: instSn }, { showError: false }) |
|
||||||
|
|
||||||
let list: PaymentChannelItem[] = [] |
|
||||||
const raw = res.data |
|
||||||
|
|
||||||
if (Array.isArray(raw)) { |
|
||||||
list = raw.map((item) => normalizeChannelItem(item as Record<string, unknown>)) |
|
||||||
} else if (raw && typeof raw === 'object') { |
|
||||||
const channels = pickField<Record<string, unknown>[]>( |
|
||||||
raw as Record<string, unknown>, |
|
||||||
'channels', |
|
||||||
'data' |
|
||||||
) |
|
||||||
if (Array.isArray(channels)) { |
|
||||||
list = channels.map(normalizeChannelItem) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return { ...res, data: list } |
|
||||||
} |
|
||||||
|
|
||||||
const normalizeChannelItem = (raw: Record<string, unknown>): PaymentChannelItem => ({ |
|
||||||
code: toNumber(pickField(raw, 'code', 'paytype', 'channel')), |
|
||||||
name: String(pickField(raw, 'name', 'channelName', 'channelname') ?? ''), |
|
||||||
enabled: pickField(raw, 'enabled', 'available') !== false, |
|
||||||
}) |
|
||||||
|
|
||||||
/** |
|
||||||
* 是否支持微信支付(本期仅对接微信) |
|
||||||
*/ |
|
||||||
export const isWechatPaySupported = async (instSn: string): Promise<boolean> => { |
|
||||||
try { |
|
||||||
const res = await getPaymentChannels(instSn) |
|
||||||
if (!res.data.length) return true |
|
||||||
return res.data.some((item) => item.code === PAY_CHANNEL_WECHAT && item.enabled) |
|
||||||
} catch { |
|
||||||
return true |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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, |
||||||
|
} |
||||||
@ -1,91 +0,0 @@ |
|||||||
/** |
|
||||||
* magdev(开台/关台)接口相关类型定义 |
|
||||||
* 对应接口:/api/v2/magdev/peroperate、/api/v2/magdev/operate、/api/v2/magdev/getopstatus |
|
||||||
*/ |
|
||||||
import { PriceInfoDto, CtrlType, PayType, WechatPayParameters } from './startDevice' |
|
||||||
|
|
||||||
/** 去开台(预开台)请求参数 */ |
|
||||||
export interface PreOperateRequestDto { |
|
||||||
type: number |
|
||||||
grpSn: string |
|
||||||
openId: string |
|
||||||
} |
|
||||||
|
|
||||||
/** 支付方式DTO(peroperate 返回) */ |
|
||||||
export interface PaymentMethodDto { |
|
||||||
type: number |
|
||||||
name: string |
|
||||||
available: boolean |
|
||||||
balanceDisplay: string | null |
|
||||||
} |
|
||||||
|
|
||||||
/** 设备简要信息(peroperate 返回) */ |
|
||||||
export interface DevInfoDto { |
|
||||||
id: number |
|
||||||
sn: string |
|
||||||
name: string |
|
||||||
number: string |
|
||||||
wstatus: number |
|
||||||
status: number |
|
||||||
shared: number |
|
||||||
} |
|
||||||
|
|
||||||
/** 去开台响应数据(对应 data 字段) */ |
|
||||||
export interface PreOperateResponseData { |
|
||||||
/** 余额充足时直接开台返回订单号,为空表示需进子页支付 */ |
|
||||||
outTradeNo: string |
|
||||||
message: string |
|
||||||
isMember: boolean |
|
||||||
balance: number |
|
||||||
bpName: string |
|
||||||
bpSn: string |
|
||||||
instSn: string |
|
||||||
devType: number |
|
||||||
devInfo: DevInfoDto |
|
||||||
price: PriceInfoDto |
|
||||||
paymentMethods: PaymentMethodDto[] |
|
||||||
} |
|
||||||
|
|
||||||
/** operate 统一操作请求参数 */ |
|
||||||
export interface OperateRequestDto { |
|
||||||
grpSn: string |
|
||||||
openId: string |
|
||||||
ctrlType: CtrlType |
|
||||||
amount: number |
|
||||||
payType: PayType |
|
||||||
tradeType?: number |
|
||||||
couponCode?: string |
|
||||||
remark?: string |
|
||||||
attach?: string |
|
||||||
} |
|
||||||
|
|
||||||
/** operate 响应中的支付信息 */ |
|
||||||
export interface OperatePaymentResponseDto { |
|
||||||
outTradeNo: string |
|
||||||
channel: number |
|
||||||
payParameters: WechatPayParameters | null |
|
||||||
payUrl: string |
|
||||||
} |
|
||||||
|
|
||||||
/** operate 响应数据(对应 data 字段) */ |
|
||||||
export interface OperateResponseData { |
|
||||||
consumptionId: number |
|
||||||
errorMessage: string |
|
||||||
paymentResponseDto: OperatePaymentResponseDto | null |
|
||||||
} |
|
||||||
|
|
||||||
/** getopstatus 响应中的操作选项 */ |
|
||||||
export interface OpenOptionItem { |
|
||||||
title: string |
|
||||||
type: number |
|
||||||
desc: string |
|
||||||
available: boolean |
|
||||||
} |
|
||||||
|
|
||||||
/** getopstatus 响应数据(对应 data 字段) */ |
|
||||||
export interface GetOpStatusResponseData { |
|
||||||
isOpened: boolean |
|
||||||
openOptions: OpenOptionItem[] |
|
||||||
} |
|
||||||
|
|
||||||
export { CtrlType, PayType } |
|
||||||
@ -1,24 +0,0 @@ |
|||||||
/** |
|
||||||
* 新接口字段大小写兼容:Word/Swagger 多为全小写,现网前端用 camelCase |
|
||||||
*/ |
|
||||||
export const pickField = <T = unknown>( |
|
||||||
source: Record<string, any> | null | undefined, |
|
||||||
...keys: string[] |
|
||||||
): T | undefined => { |
|
||||||
if (!source) return undefined |
|
||||||
for (const key of keys) { |
|
||||||
if (source[key] !== undefined && source[key] !== null) { |
|
||||||
return source[key] as T |
|
||||||
} |
|
||||||
} |
|
||||||
return undefined |
|
||||||
} |
|
||||||
|
|
||||||
export const toNumber = (value: unknown, fallback = 0): number => { |
|
||||||
if (typeof value === 'number' && !Number.isNaN(value)) return value |
|
||||||
if (typeof value === 'string' && value.trim() !== '') { |
|
||||||
const n = Number(value) |
|
||||||
return Number.isNaN(n) ? fallback : n |
|
||||||
} |
|
||||||
return fallback |
|
||||||
} |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
/** |
|
||||||
* 拨打门店/店长电话(来自扫码 qrcode.phone) |
|
||||||
*/ |
|
||||||
import Taro from '@tarojs/taro' |
|
||||||
|
|
||||||
export const callShopPhone = (phone?: string | null): void => { |
|
||||||
const phoneNumber = (phone || '').trim() |
|
||||||
if (!phoneNumber) { |
|
||||||
Taro.showToast({ title: '暂无店长电话', icon: 'none', duration: 2000 }) |
|
||||||
return |
|
||||||
} |
|
||||||
Taro.makePhoneCall({ phoneNumber }).catch((err) => { |
|
||||||
console.error('拨打电话失败:', err) |
|
||||||
}) |
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
/** |
|
||||||
* 客户字段归一化(新接口全小写 / 旧 camelCase) |
|
||||||
*/ |
|
||||||
import { CustomerDto, CustomerBalanceListItem } from '../types/login' |
|
||||||
import { pickField, toNumber } from '../utils/apiNormalize' |
|
||||||
|
|
||||||
export const normalizeCustomer = (raw: Record<string, any> | null | undefined): CustomerDto => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
id: toNumber(pickField(src, 'id')), |
|
||||||
sn: String(pickField(src, 'sn') ?? ''), |
|
||||||
wxOpenId: String(pickField(src, 'wxOpenId', 'wxopenid') ?? ''), |
|
||||||
name: String(pickField(src, 'name') ?? ''), |
|
||||||
type: toNumber(pickField(src, 'type')), |
|
||||||
typeName: String(pickField(src, 'typeName', 'typename') ?? ''), |
|
||||||
amount: toNumber(pickField(src, 'amount')), |
|
||||||
wchart: String(pickField(src, 'wchart') ?? ''), |
|
||||||
phone: String(pickField(src, 'phone') ?? ''), |
|
||||||
bpSn: String(pickField(src, 'bpSn', 'bpsn') ?? ''), |
|
||||||
bpInfoName: String(pickField(src, 'bpInfoName', 'bpinfoname', 'bpname') ?? ''), |
|
||||||
instSn: String(pickField(src, 'instSn', 'instsn') ?? ''), |
|
||||||
ownerName: String(pickField(src, 'ownerName', 'ownername') ?? ''), |
|
||||||
createTime: String(pickField(src, 'createTime', 'createtime') ?? ''), |
|
||||||
lastLoginTime: String(pickField(src, 'lastLoginTime', 'lastlogintime') ?? ''), |
|
||||||
wxNickName: String(pickField(src, 'wxNickName', 'wxnickname', 'name') ?? ''), |
|
||||||
wxAvatarUrl: String(pickField(src, 'wxAvatarUrl', 'wxavatarurl') ?? ''), |
|
||||||
birthday: pickField<string>(src, 'birthday'), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 归一化单条门店余额(balancelist 数组项) */ |
|
||||||
export const normalizeBalanceListItem = (raw: Record<string, any>): CustomerBalanceListItem => ({ |
|
||||||
bpSn: String(pickField(raw, 'bpSn', 'bpsn') ?? ''), |
|
||||||
bpName: String(pickField(raw, 'bpName', 'bpname') ?? ''), |
|
||||||
amount: toNumber(pickField(raw, 'amount')), |
|
||||||
points: toNumber(pickField(raw, 'points')), |
|
||||||
lockerCount: toNumber(pickField(raw, 'lockerCount', 'lockercount')), |
|
||||||
vipEndTime: pickField<string | null>(raw, 'vipEndTime', 'vipendtime') ?? null, |
|
||||||
}) |
|
||||||
|
|
||||||
/** 归一化客户跨店余额列表 */ |
|
||||||
export const normalizeBalanceList = ( |
|
||||||
raw: Record<string, any>[] | null | undefined |
|
||||||
): CustomerBalanceListItem[] => { |
|
||||||
if (!Array.isArray(raw)) return [] |
|
||||||
return raw.map(normalizeBalanceListItem) |
|
||||||
} |
|
||||||
|
|
||||||
/** 登录 data:扁平(Word)或嵌套 customer(旧) */ |
|
||||||
export const normalizeLoginData = (data: Record<string, any> | null | undefined) => { |
|
||||||
const src = data || {} |
|
||||||
const nested = pickField<Record<string, any>>(src, 'customer') |
|
||||||
const customer = normalizeCustomer(nested || src) |
|
||||||
const isNewCustomer = Boolean( |
|
||||||
pickField(src, 'isNewCustomer', 'isnewcustomer') ?? false |
|
||||||
) |
|
||||||
return { customer, isNewCustomer, message: String(pickField(src, 'message') ?? '') } |
|
||||||
} |
|
||||||
@ -1,135 +0,0 @@ |
|||||||
/** |
|
||||||
* magdev operate / peroperate / getopstatus 响应字段归一化 |
|
||||||
*/ |
|
||||||
import { pickField, toNumber } from './apiNormalize' |
|
||||||
import { normalizeWechatPayParams } from './rechargeNormalize' |
|
||||||
import { PriceInfoDto, TimePriceDto } from '../types/startDevice' |
|
||||||
import { |
|
||||||
OperateResponseData, |
|
||||||
OperatePaymentResponseDto, |
|
||||||
PreOperateResponseData, |
|
||||||
PaymentMethodDto, |
|
||||||
DevInfoDto, |
|
||||||
GetOpStatusResponseData, |
|
||||||
OpenOptionItem, |
|
||||||
} from '../types/magdev' |
|
||||||
|
|
||||||
const normalizeTimePrice = (raw: Record<string, any>): TimePriceDto => ({ |
|
||||||
startTime: String(pickField(raw, 'startTime', 'starttime') ?? ''), |
|
||||||
endTime: String(pickField(raw, 'endTime', 'endtime') ?? ''), |
|
||||||
price: toNumber(pickField(raw, 'price')), |
|
||||||
description: String(pickField(raw, 'description') ?? ''), |
|
||||||
}) |
|
||||||
|
|
||||||
const normalizePrice = (raw: Record<string, any> | null | undefined): PriceInfoDto => { |
|
||||||
const src = raw || {} |
|
||||||
const timePrices = pickField<Record<string, any>[]>(src, 'timePrices', 'timeprices') || [] |
|
||||||
return { |
|
||||||
standard: toNumber(pickField(src, 'standard')), |
|
||||||
memberPrice: toNumber(pickField(src, 'memberPrice', 'memberprice')), |
|
||||||
unit: String(pickField(src, 'unit') ?? ''), |
|
||||||
deposit: toNumber(pickField(src, 'deposit')), |
|
||||||
pricePerMinute: toNumber(pickField(src, 'pricePerMinute', 'pricePerminute', 'priceperminute')), |
|
||||||
memberPricePerMinute: toNumber(pickField(src, 'memberPricePerMinute', 'memberpriceperminute')), |
|
||||||
currentPrice: toNumber(pickField(src, 'currentPrice', 'currentprice')), |
|
||||||
descript: String(pickField(src, 'descript') ?? ''), |
|
||||||
pricePeriod: String(pickField(src, 'pricePeriod', 'priceperiod') ?? ''), |
|
||||||
timePrices: Array.isArray(timePrices) ? timePrices.map(normalizeTimePrice) : [], |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const normalizeDevInfo = (raw: Record<string, any> | null | undefined): DevInfoDto => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
id: toNumber(pickField(src, 'id')), |
|
||||||
sn: String(pickField(src, 'sn') ?? ''), |
|
||||||
name: String(pickField(src, 'name') ?? ''), |
|
||||||
number: String(pickField(src, 'number') ?? ''), |
|
||||||
wstatus: toNumber(pickField(src, 'wstatus')), |
|
||||||
status: toNumber(pickField(src, 'status')), |
|
||||||
shared: toNumber(pickField(src, 'shared')), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const normalizePaymentMethods = (raw: any[]): PaymentMethodDto[] => { |
|
||||||
if (!Array.isArray(raw)) return [] |
|
||||||
return raw.map(item => ({ |
|
||||||
type: toNumber(pickField(item, 'type')), |
|
||||||
name: String(pickField(item, 'name') ?? ''), |
|
||||||
available: !!pickField(item, 'available'), |
|
||||||
balanceDisplay: pickField<string>(item, 'balanceDisplay', 'balancedisplay') ?? null, |
|
||||||
})) |
|
||||||
} |
|
||||||
|
|
||||||
const normalizeOperatePaymentResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): OperatePaymentResponseDto | null => { |
|
||||||
if (!raw) return null |
|
||||||
const payParams = normalizeWechatPayParams( |
|
||||||
pickField<Record<string, any>>(raw, 'payParameters', 'payparameters') |
|
||||||
) |
|
||||||
if (!payParams && !pickField(raw, 'outTradeNo', 'outtradeno')) return null |
|
||||||
return { |
|
||||||
outTradeNo: String(pickField(raw, 'outTradeNo', 'outtradeno') ?? ''), |
|
||||||
channel: toNumber(pickField(raw, 'channel')), |
|
||||||
payParameters: payParams, |
|
||||||
payUrl: String(pickField(raw, 'payUrl', 'payurl') ?? ''), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 归一化 operate(开台/关台/续费)响应 data */ |
|
||||||
export const normalizeOperateResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): OperateResponseData => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
consumptionId: toNumber(pickField(src, 'consumptionId', 'consumptionid')), |
|
||||||
errorMessage: String(pickField(src, 'errorMessage', 'errormessage') ?? ''), |
|
||||||
paymentResponseDto: normalizeOperatePaymentResponse( |
|
||||||
pickField<Record<string, any>>(src, 'paymentResponseDto', 'paymentresponsedto') |
|
||||||
), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 归一化 peroperate(去开台)响应 data */ |
|
||||||
export const normalizePreOperateResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): PreOperateResponseData => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
message: String(pickField(src, 'message') ?? ''), |
|
||||||
outTradeNo: String(pickField(src, 'outTradeNo', 'outtradeno') ?? ''), |
|
||||||
isMember: !!pickField(src, 'isMember', 'ismember'), |
|
||||||
balance: toNumber(pickField(src, 'balance')), |
|
||||||
bpName: String(pickField(src, 'bpName', 'bpname') ?? ''), |
|
||||||
bpSn: String(pickField(src, 'bpSn', 'bpsn') ?? ''), |
|
||||||
instSn: String(pickField(src, 'instSn', 'instsn') ?? ''), |
|
||||||
devType: toNumber(pickField(src, 'devType', 'devtype')), |
|
||||||
devInfo: normalizeDevInfo( |
|
||||||
pickField<Record<string, any>>(src, 'devInfo', 'devinfo') |
|
||||||
), |
|
||||||
price: normalizePrice(pickField<Record<string, any>>(src, 'price')), |
|
||||||
paymentMethods: normalizePaymentMethods( |
|
||||||
pickField<any[]>(src, 'paymentMethods', 'paymentmethods') ?? [] |
|
||||||
), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 归一化 getopstatus 响应 data */ |
|
||||||
export const normalizeGetOpStatusResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): GetOpStatusResponseData => { |
|
||||||
const src = raw || {} |
|
||||||
const opts = pickField<any[]>(src, 'openOptions', 'openoptions') ?? [] |
|
||||||
return { |
|
||||||
isOpened: !!pickField(src, 'isOpened', 'isopened'), |
|
||||||
openOptions: Array.isArray(opts) |
|
||||||
? opts.map((item): OpenOptionItem => ({ |
|
||||||
title: String(pickField(item, 'title') ?? ''), |
|
||||||
type: toNumber(pickField(item, 'type')), |
|
||||||
desc: String(pickField(item, 'desc', 'description') ?? ''), |
|
||||||
available: !!pickField(item, 'available'), |
|
||||||
})) |
|
||||||
: [], |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,70 +0,0 @@ |
|||||||
/** |
|
||||||
* 订单记录 / 订单详情 字段归一化 |
|
||||||
* 对应接口:/api/v2/order/records、/api/v2/order/detail/{id} |
|
||||||
*/ |
|
||||||
import { pickField, toNumber } from './apiNormalize' |
|
||||||
import { OrderRecordItem, OrderRecordPagedResult, OrderDetailDto } from '../types/order' |
|
||||||
|
|
||||||
/** 归一化单条订单记录(列表项) */ |
|
||||||
export const normalizeOrderRecordItem = (raw: Record<string, any>): OrderRecordItem => ({ |
|
||||||
id: toNumber(pickField(raw, 'id')), |
|
||||||
title: String(pickField(raw, 'title') ?? ''), |
|
||||||
statusText: String(pickField(raw, 'statusText', 'statustext') ?? ''), |
|
||||||
bpName: String(pickField(raw, 'bpName', 'bpname') ?? ''), |
|
||||||
startTime: String(pickField(raw, 'startTime', 'starttime') ?? ''), |
|
||||||
durationText: String(pickField(raw, 'durationText', 'durationtext') ?? ''), |
|
||||||
actualAmount: toNumber(pickField(raw, 'actualAmount', 'actualamount')), |
|
||||||
}) |
|
||||||
|
|
||||||
/** 归一化订单记录分页响应 */ |
|
||||||
export const normalizeOrderRecordPagedResult = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): OrderRecordPagedResult => { |
|
||||||
const src = raw || {} |
|
||||||
const list = pickField<Record<string, any>[]>(src, 'data') || [] |
|
||||||
return { |
|
||||||
data: Array.isArray(list) ? list.map(normalizeOrderRecordItem) : [], |
|
||||||
totalCount: toNumber(pickField(src, 'totalCount', 'totalcount')), |
|
||||||
pageIndex: toNumber(pickField(src, 'pageIndex', 'pageindex'), 1), |
|
||||||
pageSize: toNumber(pickField(src, 'pageSize', 'pagesize'), 10), |
|
||||||
totalPages: toNumber(pickField(src, 'totalPages', 'totalpages')), |
|
||||||
hasPrevious: Boolean(pickField(src, 'hasPrevious', 'hasprevious') ?? false), |
|
||||||
hasNext: Boolean(pickField(src, 'hasNext', 'hasnext') ?? false), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 归一化订单详情 */ |
|
||||||
export const normalizeOrderDetail = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): OrderDetailDto => { |
|
||||||
const src = raw || {} |
|
||||||
const memberPrice = pickField<number | null>(src, 'memberPrice', 'memberprice') |
|
||||||
const couponDeduction = pickField<number | null>(src, 'couponDeduction', 'coupondeduction') |
|
||||||
const couponDescription = pickField<string | null>(src, 'couponDescription', 'coupondescription') |
|
||||||
const actualAmount = pickField<number | null>(src, 'actualAmount', 'actualamount') |
|
||||||
return { |
|
||||||
id: toNumber(pickField(src, 'id')), |
|
||||||
projectName: String(pickField(src, 'projectName', 'projectname') ?? ''), |
|
||||||
statusText: String(pickField(src, 'statusText', 'statustext') ?? ''), |
|
||||||
storePhone: String(pickField(src, 'storePhone', 'storephone') ?? ''), |
|
||||||
durationText: String(pickField(src, 'durationText', 'durationtext') ?? ''), |
|
||||||
actualAmount: actualAmount === null || actualAmount === undefined ? null : toNumber(actualAmount), |
|
||||||
pricePerHour: toNumber(pickField(src, 'pricePerHour', 'priceperhour')), |
|
||||||
discountPricePerHour: toNumber(pickField(src, 'discountPricePerHour', 'discountpriceperhour')), |
|
||||||
onlineTotalPayment: toNumber(pickField(src, 'onlineTotalPayment', 'onlinetotalpayment')), |
|
||||||
deposit: toNumber(pickField(src, 'deposit')), |
|
||||||
originalAmount: toNumber(pickField(src, 'originalAmount', 'originalamount')), |
|
||||||
memberPrice: memberPrice === null || memberPrice === undefined ? null : toNumber(memberPrice), |
|
||||||
couponDeduction: |
|
||||||
couponDeduction === null || couponDeduction === undefined ? null : toNumber(couponDeduction), |
|
||||||
couponDescription: couponDescription === null || couponDescription === undefined ? null : String(couponDescription), |
|
||||||
bpName: String(pickField(src, 'bpName', 'bpname') ?? ''), |
|
||||||
bpAddress: String(pickField(src, 'bpAddress', 'bpaddress') ?? ''), |
|
||||||
tableName: String(pickField(src, 'tableName', 'tablename') ?? ''), |
|
||||||
startTime: String(pickField(src, 'startTime', 'starttime') ?? ''), |
|
||||||
stopTime: String(pickField(src, 'stopTime', 'stoptime') ?? ''), |
|
||||||
outTradeNo: String(pickField(src, 'outTradeNo', 'outtradeno') ?? ''), |
|
||||||
chargingStandard: String(pickField(src, 'chargingStandard', 'chargingstandard') ?? ''), |
|
||||||
payTypeName: String(pickField(src, 'payTypeName', 'paytypename') ?? ''), |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,69 +0,0 @@ |
|||||||
/** |
|
||||||
* 充值相关字段归一化 |
|
||||||
*/ |
|
||||||
import { |
|
||||||
RechargePaymentResponseDto, |
|
||||||
RechargeWechatPayParameters, |
|
||||||
RechargeStatusResult, |
|
||||||
RechargeRuleItem, |
|
||||||
RechargeRuleQueryResult, |
|
||||||
} from '../types/recharge' |
|
||||||
import { pickField, toNumber } from './apiNormalize' |
|
||||||
|
|
||||||
export const normalizeWechatPayParams = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): RechargeWechatPayParameters | null => { |
|
||||||
if (!raw) return null |
|
||||||
const timeStamp = pickField<string>(raw, 'timeStamp', 'timestamp') |
|
||||||
if (!timeStamp) return null |
|
||||||
return { |
|
||||||
timeStamp: String(timeStamp), |
|
||||||
nonceStr: String(pickField(raw, 'nonceStr', 'noncestr') ?? ''), |
|
||||||
package: String(pickField(raw, 'package') ?? ''), |
|
||||||
signType: String(pickField(raw, 'signType', 'signtype') ?? 'RSA'), |
|
||||||
paySign: String(pickField(raw, 'paySign', 'paysign') ?? ''), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeRechargePaymentResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): RechargePaymentResponseDto => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
outTradeNo: String(pickField(src, 'outTradeNo', 'outtradeno') ?? ''), |
|
||||||
channel: toNumber(pickField(src, 'channel')), |
|
||||||
payParameters: normalizeWechatPayParams( |
|
||||||
pickField<Record<string, any>>(src, 'payParameters', 'payparameters') |
|
||||||
), |
|
||||||
payUrl: String(pickField(src, 'payUrl', 'payurl') ?? ''), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeRechargeStatus = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): RechargeStatusResult => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
amount: toNumber(pickField(src, 'amount')), |
|
||||||
giftAmount: toNumber(pickField(src, 'giftAmount', 'giftamount')), |
|
||||||
balance: toNumber(pickField(src, 'balance')), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeRechargeRuleItem = (raw: Record<string, any>): RechargeRuleItem => ({ |
|
||||||
recharge: toNumber(pickField(raw, 'recharge')), |
|
||||||
gift: toNumber(pickField(raw, 'gift')), |
|
||||||
desc: String(pickField(raw, 'desc', 'description') ?? ''), |
|
||||||
}) |
|
||||||
|
|
||||||
export const normalizeRechargeRules = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): RechargeRuleQueryResult => { |
|
||||||
const src = raw || {} |
|
||||||
const rules = pickField<Record<string, any>[]>(src, 'rules') || [] |
|
||||||
return { |
|
||||||
instName: String(pickField(src, 'instName', 'instname') ?? ''), |
|
||||||
bpName: String(pickField(src, 'bpName', 'bpname') ?? ''), |
|
||||||
rules: Array.isArray(rules) ? rules.map(normalizeRechargeRuleItem) : [], |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,111 +0,0 @@ |
|||||||
/** |
|
||||||
* 充值记录:月份区间、状态文案、列表展示映射 |
|
||||||
*/ |
|
||||||
import { getRechargeRecords } from '../api/recharge' |
|
||||||
import { RechargeRecordItem } from '../types/recharge' |
|
||||||
import { userStore } from '../store' |
|
||||||
|
|
||||||
/** 列表项(页面展示结构) */ |
|
||||||
export interface RechargeRecordViewItem { |
|
||||||
id: string |
|
||||||
storeName: string |
|
||||||
rechargeTime: string |
|
||||||
rechargeType: string |
|
||||||
amount: number |
|
||||||
status: string |
|
||||||
} |
|
||||||
|
|
||||||
/** 当前年月 YYYY-MM */ |
|
||||||
export const getCurrentYearMonth = (): string => { |
|
||||||
const now = new Date() |
|
||||||
const year = now.getFullYear() |
|
||||||
const month = String(now.getMonth() + 1).padStart(2, '0') |
|
||||||
return `${year}-${month}` |
|
||||||
} |
|
||||||
|
|
||||||
/** 某月起止时间(供 records 接口过滤) */ |
|
||||||
export const getMonthDateRange = (yearMonth: string): { startDate: string; endDate: string } => { |
|
||||||
const [yStr, mStr] = yearMonth.split('-') |
|
||||||
const year = Number(yStr) |
|
||||||
const month = Number(mStr) |
|
||||||
const lastDay = new Date(year, month, 0).getDate() |
|
||||||
const day = String(lastDay).padStart(2, '0') |
|
||||||
return { |
|
||||||
startDate: `${yearMonth}-01 00:00:00`, |
|
||||||
endDate: `${yearMonth}-${day} 23:59:59`, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 支付状态(后端枚举,适用于 recharge/records.status 等) |
|
||||||
* 来源:后端「支付状态定义」 |
|
||||||
*/ |
|
||||||
export enum RechargePaymentStatus { |
|
||||||
Invalid = 0, |
|
||||||
Pending = 1, |
|
||||||
Initialized = 2, |
|
||||||
Paying = 3, |
|
||||||
Success = 4, |
|
||||||
Failed = 5, |
|
||||||
Cancelled = 6, |
|
||||||
Refunding = 7, |
|
||||||
Refunded = 8, |
|
||||||
RefundFailed = 9, |
|
||||||
Closed = 10, |
|
||||||
} |
|
||||||
|
|
||||||
export const RECHARGE_PAYMENT_STATUS_LABEL: Record<number, string> = { |
|
||||||
[RechargePaymentStatus.Invalid]: '无效', |
|
||||||
[RechargePaymentStatus.Pending]: '待支付', |
|
||||||
[RechargePaymentStatus.Initialized]: '已初始化', |
|
||||||
[RechargePaymentStatus.Paying]: '支付中', |
|
||||||
[RechargePaymentStatus.Success]: '支付成功', |
|
||||||
[RechargePaymentStatus.Failed]: '支付失败', |
|
||||||
[RechargePaymentStatus.Cancelled]: '已取消', |
|
||||||
[RechargePaymentStatus.Refunding]: '退款中', |
|
||||||
[RechargePaymentStatus.Refunded]: '已退款', |
|
||||||
[RechargePaymentStatus.RefundFailed]: '退款失败', |
|
||||||
[RechargePaymentStatus.Closed]: '已关闭', |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 充值状态文案(后端支付状态定义) |
|
||||||
*/ |
|
||||||
export const formatRechargeStatus = (status: number): string => { |
|
||||||
if (RECHARGE_PAYMENT_STATUS_LABEL[status] !== undefined) { |
|
||||||
return RECHARGE_PAYMENT_STATUS_LABEL[status] |
|
||||||
} |
|
||||||
return '未知状态' |
|
||||||
} |
|
||||||
|
|
||||||
export const mapRechargeRecordToView = (item: RechargeRecordItem): RechargeRecordViewItem => ({ |
|
||||||
id: String(item.id || item.outTradeNo || item.logTime), |
|
||||||
storeName: item.bpName || '--', |
|
||||||
rechargeTime: item.logTime || '--', |
|
||||||
rechargeType: item.rcgTypeName || '账户充值', |
|
||||||
amount: item.amount, |
|
||||||
status: formatRechargeStatus(item.status), |
|
||||||
}) |
|
||||||
|
|
||||||
/** |
|
||||||
* 拉取指定月份充值记录(需已登录且有客户 sn) |
|
||||||
*/ |
|
||||||
export const fetchRechargeRecordsByMonth = async ( |
|
||||||
yearMonth: string |
|
||||||
): Promise<RechargeRecordViewItem[]> => { |
|
||||||
const customerSn = userStore.userInfo?.sn |
|
||||||
if (!customerSn) { |
|
||||||
throw new Error('NO_CUSTOMER_SN') |
|
||||||
} |
|
||||||
|
|
||||||
const { startDate, endDate } = getMonthDateRange(yearMonth) |
|
||||||
const res = await getRechargeRecords({ |
|
||||||
customerSn, |
|
||||||
startDate, |
|
||||||
endDate, |
|
||||||
pageIndex: 1, |
|
||||||
pageSize: 100, |
|
||||||
}) |
|
||||||
|
|
||||||
return (res.data?.data || []).map(mapRechargeRecordToView) |
|
||||||
} |
|
||||||
@ -1,119 +0,0 @@ |
|||||||
/** |
|
||||||
* 扫码(qrcode)响应字段归一化 |
|
||||||
*/ |
|
||||||
import { |
|
||||||
TableScanResponseDto, |
|
||||||
TableInfoDto, |
|
||||||
PriceInfoDto, |
|
||||||
TimePriceDto, |
|
||||||
OptionDto, |
|
||||||
OpInfoDto, |
|
||||||
} from '../types/startDevice' |
|
||||||
import { pickField, toNumber } from './apiNormalize' |
|
||||||
|
|
||||||
const normalizeTimePrice = (raw: Record<string, any>): TimePriceDto => ({ |
|
||||||
startTime: String(pickField(raw, 'startTime', 'starttime') ?? ''), |
|
||||||
endTime: String(pickField(raw, 'endTime', 'endtime') ?? ''), |
|
||||||
price: toNumber(pickField(raw, 'price')), |
|
||||||
description: String(pickField(raw, 'description') ?? ''), |
|
||||||
}) |
|
||||||
|
|
||||||
const normalizePrice = (raw: Record<string, any> | null | undefined): PriceInfoDto => { |
|
||||||
const src = raw || {} |
|
||||||
const timePrices = pickField<Record<string, any>[]>(src, 'timePrices', 'timeprices') || [] |
|
||||||
return { |
|
||||||
standard: toNumber(pickField(src, 'standard')), |
|
||||||
memberPrice: toNumber(pickField(src, 'memberPrice', 'memberprice')), |
|
||||||
unit: String(pickField(src, 'unit') ?? ''), |
|
||||||
deposit: toNumber(pickField(src, 'deposit')), |
|
||||||
pricePerMinute: toNumber(pickField(src, 'pricePerMinute', 'pricePerminute', 'priceperminute')), |
|
||||||
memberPricePerMinute: toNumber( |
|
||||||
pickField(src, 'memberPricePerMinute', 'memberpriceperminute') |
|
||||||
), |
|
||||||
currentPrice: toNumber(pickField(src, 'currentPrice', 'currentprice')), |
|
||||||
descript: String(pickField(src, 'descript') ?? ''), |
|
||||||
pricePeriod: String(pickField(src, 'pricePeriod', 'priceperiod') ?? ''), |
|
||||||
timePrices: Array.isArray(timePrices) ? timePrices.map(normalizeTimePrice) : [], |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const normalizeTableInfo = (raw: Record<string, any> | null | undefined): TableInfoDto => { |
|
||||||
const src = raw || {} |
|
||||||
return { |
|
||||||
id: toNumber(pickField(src, 'id')), |
|
||||||
sn: String(pickField(src, 'sn', 'grpsn') ?? ''), |
|
||||||
name: String(pickField(src, 'name', 'tablename') ?? ''), |
|
||||||
tableNumber: String(pickField(src, 'tableNumber', 'tablenumber', 'number') ?? ''), |
|
||||||
status: toNumber(pickField(src, 'status', 'wstatus')), |
|
||||||
statusDescription: String( |
|
||||||
pickField(src, 'statusDescription', 'statusdescription', 'statusdesc') ?? '' |
|
||||||
), |
|
||||||
isShared: Boolean(pickField(src, 'isShared', 'isshared', 'share')), |
|
||||||
currentSession: String(pickField(src, 'currentSession', 'currentsession') ?? ''), |
|
||||||
area: String(pickField(src, 'area', 'class') ?? ''), |
|
||||||
chanNum: toNumber(pickField(src, 'chanNum', 'channum')), |
|
||||||
startChan: toNumber(pickField(src, 'startChan', 'startchan')), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const normalizeOpenOption = (raw: Record<string, any>): OptionDto => ({ |
|
||||||
title: String(pickField(raw, 'title') ?? ''), |
|
||||||
type: toNumber(pickField(raw, 'type')), |
|
||||||
description: String(pickField(raw, 'description', 'desc') ?? ''), |
|
||||||
actionText: String(pickField(raw, 'actionText', 'actiontext') ?? ''), |
|
||||||
refundPolicy: String(pickField(raw, 'refundPolicy', 'refundpolicy') ?? ''), |
|
||||||
available: pickField(raw, 'available') !== false, |
|
||||||
optionCode: toNumber(pickField(raw, 'optionCode', 'optioncode', 'type')), |
|
||||||
icon: String(pickField(raw, 'icon') ?? ''), |
|
||||||
condition: String(pickField(raw, 'condition') ?? ''), |
|
||||||
actionUrl: String(pickField(raw, 'actionUrl', 'actionurl') ?? ''), |
|
||||||
}) |
|
||||||
|
|
||||||
const normalizeOpInfo = (raw: Record<string, any> | null | undefined): OpInfoDto | null => { |
|
||||||
if (!raw) return null |
|
||||||
return { |
|
||||||
opId: toNumber(pickField(raw, 'opId', 'opid')), |
|
||||||
orderNo: String(pickField(raw, 'orderNo', 'orderno') ?? ''), |
|
||||||
startTime: String(pickField(raw, 'startTime', 'starttime') ?? ''), |
|
||||||
usedTime: String(pickField(raw, 'usedTime', 'usedtime') ?? ''), |
|
||||||
usedMinutes: toNumber(pickField(raw, 'usedMinutes', 'usedminutes')), |
|
||||||
ctrlType: toNumber(pickField(raw, 'ctrlType', 'ctrltype')), |
|
||||||
ctrlTypeDescription: String( |
|
||||||
pickField(raw, 'ctrlTypeDescription', 'ctrltypedescription') ?? '' |
|
||||||
), |
|
||||||
payType: toNumber(pickField(raw, 'payType', 'paytype')), |
|
||||||
payTypeDescription: String( |
|
||||||
pickField(raw, 'payTypeDescription', 'paytypedescription') ?? '' |
|
||||||
), |
|
||||||
currentAmount: toNumber(pickField(raw, 'currentAmount', 'currentamount')), |
|
||||||
deposit: toNumber(pickField(raw, 'deposit')), |
|
||||||
depositStatus: String(pickField(raw, 'depositStatus', 'depositstatus') ?? ''), |
|
||||||
discountAmount: toNumber(pickField(raw, 'discountAmount', 'discountamount')), |
|
||||||
payableAmount: toNumber(pickField(raw, 'payableAmount', 'payableamount')), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeTableScanResponse = ( |
|
||||||
raw: Record<string, any> | null | undefined |
|
||||||
): TableScanResponseDto => { |
|
||||||
const src = raw || {} |
|
||||||
const openOptions = pickField<Record<string, any>[]>(src, 'openOptions', 'openoptions') || [] |
|
||||||
const devInfo = pickField<Record<string, any>>(src, 'tableInfo', 'devinfo', 'tableinfo') |
|
||||||
|
|
||||||
return { |
|
||||||
scanType: (pickField<string>(src, 'scanType', 'scantype') || 'open') as 'open' | 'close', |
|
||||||
// 后端默认 true(本人开台),只有明确返回 false 时才判定为"别人开的台"
|
|
||||||
isOwner: pickField(src, 'isOwner', 'isowner') !== false, |
|
||||||
shopName: String(pickField(src, 'shopName', 'bpname', 'shopname') ?? ''), |
|
||||||
shopCode: String(pickField(src, 'shopCode', 'bpsn', 'shopcode') ?? ''), |
|
||||||
instSn: String(pickField(src, 'instSn', 'instsn') ?? ''), |
|
||||||
phone: String(pickField(src, 'phone') ?? ''), |
|
||||||
tableInfo: normalizeTableInfo(devInfo), |
|
||||||
price: normalizePrice(pickField(src, 'price')), |
|
||||||
businessHours: String(pickField(src, 'businessHours', 'businesshours') ?? ''), |
|
||||||
openOptions: Array.isArray(openOptions) ? openOptions.map(normalizeOpenOption) : [], |
|
||||||
recommendedOption: String(pickField(src, 'recommendedOption', 'recommendedoption') ?? ''), |
|
||||||
scanTime: String(pickField(src, 'scanTime', 'scantime') ?? ''), |
|
||||||
opInfo: normalizeOpInfo(pickField(src, 'opInfo', 'opinfo')), |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
/** |
|
||||||
* 门店列表字段归一化(新接口 BpInfoSimpleDto → 现网 StoreInfoDto) |
|
||||||
*/ |
|
||||||
import { StoreInfoDto } from '../api/basicInfo' |
|
||||||
import { pickField, toNumber } from './apiNormalize' |
|
||||||
|
|
||||||
const hashSn = (sn: string): number => { |
|
||||||
let h = 0 |
|
||||||
for (let i = 0; i < sn.length; i++) { |
|
||||||
h = (Math.imul(31, h) + sn.charCodeAt(i)) | 0 |
|
||||||
} |
|
||||||
return Math.abs(h) |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeStoreItem = (raw: Record<string, any>): StoreInfoDto => { |
|
||||||
const inst = pickField<Record<string, any>>(raw, 'inst') || {} |
|
||||||
const sn = String(pickField(raw, 'sn') ?? '') |
|
||||||
return { |
|
||||||
id: hashSn(sn || String(pickField(raw, 'id') ?? '')), |
|
||||||
sn, |
|
||||||
name: String(pickField(raw, 'name') ?? ''), |
|
||||||
type: toNumber(pickField(raw, 'type')), |
|
||||||
typeName: String(pickField(raw, 'typeName', 'typename') ?? ''), |
|
||||||
isUnion: toNumber(pickField(raw, 'isUnion', 'isunion')), |
|
||||||
address: String(pickField(raw, 'address', 'add') ?? ''), |
|
||||||
manager: String(pickField(raw, 'manager') ?? ''), |
|
||||||
phone: String(pickField(raw, 'phone') ?? ''), |
|
||||||
inst_Sn: String(pickField(inst, 'sn', 'instsn') ?? pickField(raw, 'instSn', 'instsn') ?? ''), |
|
||||||
instName: String(pickField(inst, 'name', 'instname') ?? pickField(raw, 'instName', 'instname') ?? ''), |
|
||||||
rgn_Sn: String(pickField(raw, 'rgn_Sn', 'rgnsn') ?? ''), |
|
||||||
regionName: String(pickField(raw, 'regionName', 'regionname', 'city') ?? pickField(raw, 'city') ?? ''), |
|
||||||
longItude: toNumber(pickField(raw, 'longItude', 'longitude')), |
|
||||||
latItude: toNumber(pickField(raw, 'latItude', 'latitude')), |
|
||||||
createTime: String(pickField(raw, 'createTime', 'createtime') ?? ''), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const normalizeStoreList = (list: Record<string, any>[] | null | undefined): StoreInfoDto[] => { |
|
||||||
if (!Array.isArray(list)) return [] |
|
||||||
return list.map(normalizeStoreItem) |
|
||||||
} |
|
||||||
Loading…
Reference in new issue