This commit is contained in:
魔方熊成祥
2026-05-07 22:54:21 +08:00
parent 1c8de9b5f4
commit 5a968a719f
16 changed files with 4549 additions and 283 deletions

BIN
dist.zip Normal file

Binary file not shown.

View File

@@ -0,0 +1,64 @@
import {
APP_API_PATHS,
normalizeAppAddressDefaultSetResponse,
normalizeAppAddressListResponse,
normalizeAppAddressSaveResponse,
normalizeMallAppPayload,
postMallApp,
} from './shared'
import type {
AppAddressDefaultSetRequest,
AppAddressDefaultSetResponse,
AppAddressDeleteRequest,
AppAddressDeleteResponse,
AppAddressListRequest,
AppAddressListResponse,
AppAddressSaveRequest,
AppAddressSaveResponse,
} from '@/types/mall'
export const apiAppAddressList = async (payload: AppAddressListRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppAddressListResponse, AppAddressListRequest>(
APP_API_PATHS.addressList,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppAddressListResponse(response.data),
}
}
export const apiAppAddressSave = async (payload: AppAddressSaveRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppAddressSaveResponse, AppAddressSaveRequest>(
APP_API_PATHS.addressSave,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppAddressSaveResponse(response.data),
}
}
export const apiAppAddressDelete = (payload: AppAddressDeleteRequest, signal?: AbortSignal) =>
postMallApp<AppAddressDeleteResponse, AppAddressDeleteRequest>(
APP_API_PATHS.addressDelete,
normalizeMallAppPayload(payload),
signal
)
export const apiAppAddressDefaultSet = async (payload: AppAddressDefaultSetRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppAddressDefaultSetResponse, AppAddressDefaultSetRequest>(
APP_API_PATHS.addressDefaultSet,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppAddressDefaultSetResponse(response.data),
}
}

View File

@@ -1,15 +1,26 @@
import { APP_API_PATHS, normalizeMallAppPayload, postMallApp } from './shared'
import {
APP_API_PATHS,
normalizeAppAfterSaleApplyResponse,
normalizeMallAppPayload,
postMallApp,
} from './shared'
import type {
AppAfterSaleApplyRequest,
AppAfterSaleApplyResponse,
} from '@/types/mall'
export const apiAppAfterSaleApply = (
export const apiAppAfterSaleApply = async (
payload: AppAfterSaleApplyRequest,
signal?: AbortSignal
) =>
postMallApp<AppAfterSaleApplyResponse, AppAfterSaleApplyRequest>(
) => {
const response = await postMallApp<AppAfterSaleApplyResponse, AppAfterSaleApplyRequest>(
APP_API_PATHS.afterSaleApply,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppAfterSaleApplyResponse(response.data),
}
}

View File

@@ -1,4 +1,10 @@
import { APP_API_PATHS, normalizeAppCartListResponse, normalizeMallAppPayload, postMallApp } from './shared'
import {
APP_API_PATHS,
normalizeAppCartListResponse,
normalizeAppCartSaveResponse,
normalizeMallAppPayload,
postMallApp,
} from './shared'
import type {
AppCartListRequest,
AppCartListResponse,
@@ -21,13 +27,19 @@ export const apiAppCartList = async (payload: AppCartListRequest, signal?: Abort
}
}
export const apiAppCartSave = (payload: AppCartSaveRequest, signal?: AbortSignal) =>
postMallApp<AppCartSaveResponse, AppCartSaveRequest>(
export const apiAppCartSave = async (payload: AppCartSaveRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppCartSaveResponse, AppCartSaveRequest>(
APP_API_PATHS.cartSave,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppCartSaveResponse(response.data),
}
}
export const apiAppCartRemove = (payload: AppCartRemoveRequest, signal?: AbortSignal) =>
postMallApp<AppCartRemoveResponse, AppCartRemoveRequest>(
APP_API_PATHS.cartRemove,

View File

@@ -2,6 +2,7 @@ export * from './shared'
export * from './home'
export * from './goods'
export * from './cart'
export * from './address'
export * from './trade'
export * from './order'
export * from './afterSale'

View File

@@ -1,31 +1,43 @@
import type {
AppAddressDefaultSetResponse,
AppAddressListResponse,
AppAddressSaveResponse,
AppAfterSaleApplyResponse,
AppCartListResponse,
AppCartSaveResponse,
AppGoodsDetailResponse,
AppGoodsPageResponse,
AppHomeMerchantGoodsResponse,
AppHomeResponse,
AppRecentNewGoodsResponse,
AppOrderDetailResponse,
AppOrderConfirmResponse,
AppOrderPageResponse,
AppTradeCreateResponse,
CartItemInfo,
CartGoodsGroupInfo,
CartMerchantGroupInfo,
GoodsDetailInfo,
GoodsSkuInfo,
GoodsSummary,
AppTradePreviewResponse,
HomeMerchantGoodsBlock,
MerchantDeliveryOptionInfo,
MerchantId,
MerchantInfo,
MerchantPackageOptionInfo,
OrderDetailInfo,
OrderSummary,
RecommendMerchantInfo,
RecentNewGoodsItem,
TradePreviewInfo,
TradePreviewItemInfo,
TradePreviewStoreInfo,
} from '@/types/mall'
type MaybeMallUidPayload = {
type MaybeMallIdentityPayload = {
uid?: number
memberId?: number
memberId?: MerchantId | number
}
type MaybeMallMerchantPayload = {
@@ -33,6 +45,22 @@ type MaybeMallMerchantPayload = {
storeId?: number | string
}
type MaybeMallIdPayload = {
id?: string | number
skuId?: string | number
skuIds?: Array<string | number>
addressId?: string | number
orderId?: string | number
orderItemId?: string | number
categoryId?: string | number
buyItems?: Array<{ skuId?: string | number; buyNum?: number }>
merchantOptions?: Array<{
merchantId?: MerchantId | number
deliveryOptionId?: string | number
packageOptionId?: string | number
}>
}
type RawRecommendMerchantPayload = Partial<RecommendMerchantInfo> & {
id?: RecommendMerchantInfo['id']
merchantId?: MerchantId | number | string
@@ -56,6 +84,8 @@ type RawMerchantEntityPayload = Partial<MerchantInfo> & {
}
type RawGoodsSummaryPayload = Partial<GoodsSummary> & {
id?: GoodsSummary['id'] | number
spuId?: GoodsSummary['id'] | number
merchantId?: MerchantId | number | string
createdAt?: GoodsSummary['createdAt'] | string | null
updatedAt?: GoodsSummary['updatedAt'] | string | null
@@ -69,14 +99,29 @@ type RawGoodsSummaryPayload = Partial<GoodsSummary> & {
update_time?: number | string | null
}
const toMerchantId = (value: MerchantId | number | string | null | undefined): MerchantId =>
value == null ? '' : String(value)
const toId = (value: string | number | null | undefined): string => (value == null ? '' : String(value))
const toMerchantId = (value: MerchantId | number | string | null | undefined): MerchantId => toId(value)
const toNumber = (value: number | string | null | undefined): number => {
const parsed = Number(value)
return Number.isFinite(parsed) ? parsed : 0
}
const toBoolean = (value: boolean | number | string | null | undefined): boolean => {
if (typeof value === 'boolean') {
return value
}
if (typeof value === 'number') {
return value !== 0
}
if (typeof value === 'string') {
return ['1', 'true', 'yes'].includes(value.trim().toLowerCase())
}
return false
}
const pickText = (...values: Array<string | null | undefined>): string => {
for (const value of values) {
if (typeof value === 'string' && value.trim()) {
@@ -111,12 +156,52 @@ const toUnixTime = (value: number | string | null | undefined): number => {
}
export const normalizeMallAppPayload = <TPayload extends object>(payload: TPayload): TPayload => {
const normalized = { ...payload } as TPayload & MaybeMallUidPayload & MaybeMallMerchantPayload
const normalized = { ...payload } as TPayload &
MaybeMallIdentityPayload &
MaybeMallMerchantPayload &
MaybeMallIdPayload
if (normalized.uid == null && normalized.memberId != null) {
normalized.uid = normalized.memberId
delete normalized.uid
if (normalized.memberId != null) {
normalized.memberId = toMerchantId(normalized.memberId)
}
if (normalized.id != null) {
normalized.id = toId(normalized.id)
}
if (normalized.skuId != null) {
normalized.skuId = toId(normalized.skuId)
}
if (normalized.skuIds != null) {
normalized.skuIds = normalized.skuIds.map(toId)
}
if (normalized.addressId != null) {
normalized.addressId = toId(normalized.addressId)
}
if (normalized.orderId != null) {
normalized.orderId = toId(normalized.orderId)
}
if (normalized.orderItemId != null) {
normalized.orderItemId = toId(normalized.orderItemId)
}
if (normalized.categoryId != null) {
normalized.categoryId = toId(normalized.categoryId)
}
if (normalized.buyItems != null) {
normalized.buyItems = normalized.buyItems.map(item => ({
...item,
skuId: item.skuId == null ? item.skuId : toId(item.skuId),
}))
}
if (normalized.merchantOptions != null) {
normalized.merchantOptions = normalized.merchantOptions.map(option => ({
...option,
merchantId: option.merchantId == null ? option.merchantId : toMerchantId(option.merchantId),
deliveryOptionId:
option.deliveryOptionId == null ? option.deliveryOptionId : toId(option.deliveryOptionId),
packageOptionId: option.packageOptionId == null ? option.packageOptionId : toId(option.packageOptionId),
}))
}
delete normalized.memberId
if (normalized.merchantId != null) {
normalized.merchantId = toMerchantId(normalized.merchantId)
@@ -131,7 +216,10 @@ export const normalizeMallAppPayload = <TPayload extends object>(payload: TPaylo
const normalizeGoodsSku = (sku: GoodsSkuInfo): GoodsSkuInfo => ({
...sku,
id: toId(sku.id),
spuId: String(sku.spuId),
merchantId: toMerchantId(sku.merchantId),
storeId: toId(sku.storeId),
})
const normalizeGoodsSummary = (goods: RawGoodsSummaryPayload): GoodsSummary => {
@@ -139,9 +227,12 @@ const normalizeGoodsSummary = (goods: RawGoodsSummaryPayload): GoodsSummary => {
return {
...normalized,
id: String(goods.spuId ?? goods.id ?? ''),
merchantId: toMerchantId(goods.merchantId),
merchantName: pickText(goods.merchantName),
merchantLogo: pickText(goods.merchantLogo),
storeId: toId(goods.storeId),
categoryId: toId(goods.categoryId),
createdAt: toUnixTime(goods.createdAt ?? goods.createAt ?? goods.created_at ?? goods.createTime ?? goods.create_time),
updatedAt: toUnixTime(goods.updatedAt ?? goods.updateAt ?? goods.updated_at ?? goods.updateTime ?? goods.update_time),
}
@@ -159,7 +250,10 @@ const normalizeRecentNewGoodsItem = (goods: RecentNewGoodsItem): RecentNewGoodsI
const normalizeGoodsDetailInfo = (detail: GoodsDetailInfo): GoodsDetailInfo => ({
...detail,
id: toId(detail.id),
merchantId: toMerchantId(detail.merchantId),
storeId: toId(detail.storeId),
categoryId: toId(detail.categoryId),
createdAt: toUnixTime(detail.createdAt),
updatedAt: toUnixTime(detail.updatedAt),
skus: (detail.skus ?? []).map(normalizeGoodsSku),
@@ -167,22 +261,104 @@ const normalizeGoodsDetailInfo = (detail: GoodsDetailInfo): GoodsDetailInfo => (
const normalizeCartItem = (item: CartItemInfo): CartItemInfo => ({
...item,
id: toId(item.id),
memberId: item.memberId == null ? undefined : toMerchantId(item.memberId),
merchantId: toMerchantId(item.merchantId),
merchantName: pickText(item.merchantName),
merchantLogo: pickText(item.merchantLogo),
storeId: toId(item.storeId),
spuId: String(item.spuId),
skuId: toId(item.skuId),
itemAmount:
item.itemAmount ??
(Number.isFinite(Number(item.salePrice)) && Number.isFinite(Number(item.buyNum))
? (Number(item.salePrice) * Number(item.buyNum)).toFixed(2)
: '0'),
})
const normalizeCartGoodsGroup = (goods: CartGoodsGroupInfo): CartGoodsGroupInfo => ({
...goods,
spuId: String(goods.spuId),
spuName: pickText(goods.spuName),
coverUrl: pickText(goods.coverUrl),
checked: Boolean(goods.checked),
goodsAmount: goods.goodsAmount ?? '0',
checkedAmount: goods.checkedAmount ?? '0',
items: (goods.items ?? []).map(normalizeCartItem),
})
const normalizeCartMerchantGroup = (group: CartMerchantGroupInfo): CartMerchantGroupInfo => ({
...group,
merchantId: toMerchantId(group.merchantId),
merchantName: pickText(group.merchantName) || '未命名商家',
merchantLogo: pickText(group.merchantLogo),
checked: Boolean(group.checked),
itemCount: toNumber(group.itemCount),
goodsCount: toNumber(group.goodsCount),
goodsAmount: group.goodsAmount ?? '0',
checkedAmount: group.checkedAmount ?? '0',
goods: (group.goods ?? []).map(normalizeCartGoodsGroup),
})
const normalizeTradePreviewItem = (item: TradePreviewItemInfo): TradePreviewItemInfo => ({
...item,
spuId: String(item.spuId),
skuId: toId(item.skuId),
})
const normalizeDeliveryOption = (option: MerchantDeliveryOptionInfo): MerchantDeliveryOptionInfo => ({
...option,
id: toId(option.id),
merchantId: toMerchantId(option.merchantId),
})
const normalizePackageOption = (option: MerchantPackageOptionInfo): MerchantPackageOptionInfo => ({
...option,
id: toId(option.id),
merchantId: toMerchantId(option.merchantId),
})
const normalizeTradePreviewGroup = (group: TradePreviewStoreInfo): TradePreviewStoreInfo => ({
...group,
merchantId: toMerchantId(group.merchantId),
storeId: group.storeId == null ? undefined : toId(group.storeId),
deliveryOptions: (group.deliveryOptions ?? []).map(normalizeDeliveryOption),
packageOptions: (group.packageOptions ?? []).map(normalizePackageOption),
selectedDeliveryOption: group.selectedDeliveryOption
? normalizeDeliveryOption(group.selectedDeliveryOption)
: undefined,
selectedPackageOption: group.selectedPackageOption ? normalizePackageOption(group.selectedPackageOption) : undefined,
items: (group.items ?? []).map(normalizeTradePreviewItem),
})
const normalizeOrderSummary = (order: OrderSummary): OrderSummary => ({
...order,
id: toId(order.id),
tradeId: toId(order.tradeId),
memberId: order.memberId == null ? undefined : toMerchantId(order.memberId),
merchantId: toMerchantId(order.merchantId),
storeId: toId(order.storeId),
})
const normalizeOrderDetailInfo = (order: OrderDetailInfo): OrderDetailInfo => ({
...order,
id: toId(order.id),
tradeId: toId(order.tradeId),
memberId: order.memberId == null ? undefined : toMerchantId(order.memberId),
merchantId: toMerchantId(order.merchantId),
storeId: toId(order.storeId),
selectedDeliveryOption: order.selectedDeliveryOption
? normalizeDeliveryOption(order.selectedDeliveryOption)
: undefined,
selectedPackageOption: order.selectedPackageOption ? normalizePackageOption(order.selectedPackageOption) : undefined,
items: (order.items ?? []).map(item => ({
...item,
id: toId(item.id),
orderId: toId(item.orderId),
tradeId: toId(item.tradeId),
spuId: String(item.spuId),
skuId: toId(item.skuId),
})),
})
const normalizeRecommendMerchant = (
@@ -194,6 +370,7 @@ const normalizeRecommendMerchant = (
return {
...(merchant as RecommendMerchantInfo),
id: toId(merchant.id ?? merchant.merchantId),
merchantId: toMerchantId(merchant.merchantId ?? merchant.id),
storeName: pickText(merchant.storeName, merchant.merchantName),
storeLogo: pickText(merchant.storeLogo, merchant.logo),
@@ -215,6 +392,7 @@ const normalizeMerchantEntity = (
return {
...(merchant as MerchantInfo),
id: toId(merchant.id ?? merchant.merchantId),
merchantId: toMerchantId(merchant.merchantId ?? merchant.id),
storeName: pickText(merchant.storeName, merchant.merchantName),
storeLogo: pickText(merchant.storeLogo, merchant.logo),
@@ -223,6 +401,26 @@ const normalizeMerchantEntity = (
}
}
const normalizeAddressInfo = (address: AppAddressListResponse['list'][number]) => ({
...address,
id: toId(address.id),
})
const normalizeBanner = (banner: AppHomeResponse['banners'][number]) => ({
...banner,
id: toId(banner.id),
})
const normalizeCategoryNav = (category: AppHomeResponse['categoryNavs'][number]) => ({
...category,
categoryId: toId(category.categoryId),
})
const normalizeChannel = (channel: AppHomeResponse['channels'][number]) => ({
...channel,
id: toId(channel.id),
})
const normalizeHomeMerchantGoodsBlock = (
block: HomeMerchantGoodsBlock | undefined
): HomeMerchantGoodsBlock | undefined => {
@@ -262,7 +460,40 @@ export const normalizeAppCartListResponse = (
payload: AppCartListResponse
): AppCartListResponse => ({
...payload,
list: payload.list.map(normalizeCartItem),
merchantGroups: (payload.merchantGroups ?? []).map(normalizeCartMerchantGroup),
itemCount: toNumber(payload.itemCount),
goodsCount: toNumber(payload.goodsCount),
goodsAmount: payload.goodsAmount ?? '0',
checkedCount: toNumber(payload.checkedCount),
checkedAmount: payload.checkedAmount ?? '0',
})
export const normalizeAppCartSaveResponse = (
payload: AppCartSaveResponse
): AppCartSaveResponse => ({
...payload,
cartId: toId(payload.cartId),
})
export const normalizeAppAddressListResponse = (
payload: AppAddressListResponse
): AppAddressListResponse => ({
...payload,
list: (payload.list ?? []).map(normalizeAddressInfo),
})
export const normalizeAppAddressSaveResponse = (
payload: AppAddressSaveResponse
): AppAddressSaveResponse => ({
...payload,
addressId: toId(payload.addressId),
})
export const normalizeAppAddressDefaultSetResponse = (
payload: AppAddressDefaultSetResponse
): AppAddressDefaultSetResponse => ({
...payload,
addressId: toId(payload.addressId),
})
export const normalizeAppOrderPageResponse = (
@@ -279,6 +510,20 @@ export const normalizeAppOrderDetailResponse = (
data: normalizeOrderDetailInfo(payload.data),
})
export const normalizeAppOrderConfirmResponse = (
payload: AppOrderConfirmResponse
): AppOrderConfirmResponse => ({
...payload,
orderId: toId(payload.orderId),
})
export const normalizeAppAfterSaleApplyResponse = (
payload: AppAfterSaleApplyResponse
): AppAfterSaleApplyResponse => ({
...payload,
afterSaleId: toId(payload.afterSaleId),
})
export const normalizeAppHomeResponse = (payload: AppHomeResponse): AppHomeResponse => {
const recommendMerchants = (payload.recommendMerchants ?? payload.recommendStores ?? [])
.map(normalizeRecommendMerchant)
@@ -289,6 +534,9 @@ export const normalizeAppHomeResponse = (payload: AppHomeResponse): AppHomeRespo
return {
...payload,
banners: (payload.banners ?? []).map(normalizeBanner),
categoryNavs: (payload.categoryNavs ?? []).map(normalizeCategoryNav),
channels: (payload.channels ?? []).map(normalizeChannel),
recommendGoods: payload.recommendGoods.map(normalizeGoodsSummary),
recommendMerchants,
featuredMerchants,
@@ -305,7 +553,7 @@ export const normalizeAppHomeMerchantGoodsResponse = (
normalizeHomeMerchantGoodsBlock(payload.data) ??
({
merchant: {
id: 0,
id: '0',
merchantId: '0',
storeName: '',
storeLogo: '',
@@ -319,7 +567,7 @@ export const normalizeAppHomeMerchantGoodsResponse = (
orderCount: 0,
},
store: {
id: 0,
id: '0',
merchantId: '0',
storeName: '',
storeLogo: '',
@@ -354,7 +602,7 @@ export const normalizeAppTradePreviewResponse = (
): AppTradePreviewResponse => {
const data = payload.data as TradePreviewInfo & {
uid?: number
memberId?: number
memberId?: MerchantId | number
merchantGroups?: TradePreviewInfo['merchantGroups']
storeGroups?: TradePreviewInfo['merchantGroups']
}
@@ -364,10 +612,24 @@ export const normalizeAppTradePreviewResponse = (
...payload,
data: {
...data,
uid: data.uid ?? data.memberId ?? 0,
memberId: data.memberId ?? data.uid,
addressId: toId(data.addressId),
uid: data.uid ?? 0,
memberId: data.memberId == null ? undefined : toMerchantId(data.memberId),
merchantGroups: merchantGroups.map(normalizeTradePreviewGroup),
storeGroups: merchantGroups.map(normalizeTradePreviewGroup),
},
}
}
export const normalizeAppTradeCreateResponse = (
payload: AppTradeCreateResponse
): AppTradeCreateResponse => ({
...payload,
tradeId: toId(payload.tradeId),
payUrl: pickText(payload.payUrl),
payExternal: toBoolean(payload.payExternal),
payExpiredAt: toUnixTime(payload.payExpiredAt),
payChannel: pickText(payload.payChannel),
paySubject: pickText(payload.paySubject),
orderIds: (payload.orderIds ?? []).map(toId),
})

View File

@@ -1,6 +1,7 @@
import {
APP_API_PATHS,
normalizeAppOrderDetailResponse,
normalizeAppOrderConfirmResponse,
normalizeAppOrderPageResponse,
normalizeMallAppPayload,
postMallApp,
@@ -40,9 +41,15 @@ export const apiAppOrderDetail = async (payload: AppOrderDetailRequest, signal?:
}
}
export const apiAppOrderConfirm = (payload: AppOrderConfirmRequest, signal?: AbortSignal) =>
postMallApp<AppOrderConfirmResponse, AppOrderConfirmRequest>(
export const apiAppOrderConfirm = async (payload: AppOrderConfirmRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppOrderConfirmResponse, AppOrderConfirmRequest>(
APP_API_PATHS.orderConfirm,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppOrderConfirmResponse(response.data),
}
}

View File

@@ -11,6 +11,10 @@ export const APP_API_PATHS = {
cartList: '/api/v1/mall/app/cart_list',
cartSave: '/api/v1/mall/app/cart_save',
cartRemove: '/api/v1/mall/app/cart_remove',
addressList: '/api/v1/mall/app/address_list',
addressSave: '/api/v1/mall/app/address_save',
addressDelete: '/api/v1/mall/app/address_delete',
addressDefaultSet: '/api/v1/mall/app/address_default_set',
tradePreview: '/api/v1/mall/app/trade_preview',
tradeCreate: '/api/v1/mall/app/trade_create',
orderPage: '/api/v1/mall/app/order_page',

View File

@@ -1,5 +1,6 @@
import {
APP_API_PATHS,
normalizeAppTradeCreateResponse,
normalizeAppTradePreviewResponse,
normalizeMallAppPayload,
postMallApp,
@@ -24,9 +25,15 @@ export const apiAppTradePreview = async (payload: AppTradePreviewRequest, signal
}
}
export const apiAppTradeCreate = (payload: AppTradeCreateRequest, signal?: AbortSignal) =>
postMallApp<AppTradeCreateResponse, AppTradeCreateRequest>(
export const apiAppTradeCreate = async (payload: AppTradeCreateRequest, signal?: AbortSignal) => {
const response = await postMallApp<AppTradeCreateResponse, AppTradeCreateRequest>(
APP_API_PATHS.tradeCreate,
normalizeMallAppPayload(payload),
signal
)
return {
...response,
data: normalizeAppTradeCreateResponse(response.data),
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -152,10 +152,10 @@ const buildGoods = (seed: string[], index: number): GoodsSummary => {
const price = 29 + index * 7
return {
id: 10001 + index,
id: String(10001 + index),
merchantId: String(5001 + (index % 4)),
storeId: 6001 + (index % 5),
categoryId: index + 1,
storeId: String(6001 + (index % 5)),
categoryId: String(index + 1),
categoryName: category.label,
spuNo: `YTSPU${String(index + 1).padStart(4, '0')}`,
spuName: seed[0],
@@ -181,7 +181,7 @@ const buildStore = (seed: string[], index: number): RecommendMerchantInfo => {
const category = MARKET_CATEGORIES[(index % (MARKET_CATEGORIES.length - 1)) + 1]
return {
id: 9001 + index,
id: String(9001 + index),
merchantId: String(5001 + index),
storeName: seed[0],
storeLogo: createArtwork(seed[0], seed[1], category.accent, category.accentSoft),
@@ -206,14 +206,14 @@ export const FALLBACK_GOODS_PAGE: AppGoodsPageResponse = {
export const FALLBACK_HOME: AppHomeResponse = {
categoryNavs: MARKET_CATEGORIES.map((item, index) => ({
categoryId: index + 1,
categoryId: String(index + 1),
categoryName: item.label,
goodsCount: Math.max(0, goodsList.length - index),
sort: index,
})),
banners: [
{
id: 1,
id: '1',
title: '精准搜款 · 一件代发',
subTitle: '多平台供给与商家资源聚合',
description: '首页主视觉广告栏',
@@ -228,7 +228,7 @@ export const FALLBACK_HOME: AppHomeResponse = {
endTime: 1730000000,
},
{
id: 2,
id: '2',
title: '热卖数码专场',
subTitle: '快充、支架、耳机同步起量',
description: '首页活动广告栏',
@@ -245,7 +245,7 @@ export const FALLBACK_HOME: AppHomeResponse = {
],
searchKeywords: HOT_KEYWORDS,
channels: PLATFORM_CHANNELS.map((item, index) => ({
id: index + 1,
id: String(index + 1),
title: item.label,
subTitle: item.subtitle,
iconUrl: '',

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { apiAppGoodsDetail } from '@/apis'
import { toast } from 'sonner'
import { apiAppCartSave, apiAppGoodsDetail } from '@/apis'
import MarketPageHeader from '@/components/MarketPageHeader'
import { useUserStore } from '@/store/user'
import type {
@@ -58,12 +59,12 @@ const WHITE_IMAGE_KEYWORDS = ['white', 'wash', 'clean', 'plain', 'background', '
const getSpecValue = (sku: ResolvedGoodsSkuInfo, patterns: string[]) => {
const matched = sku.specs.find(spec => {
const name = typeof spec.name === 'string' ? spec.name : ''
const name = typeof spec.attributeName === 'string' ? spec.attributeName : ''
return patterns.some(pattern => name.toLowerCase().includes(pattern.toLowerCase()))
})
return typeof matched?.value === 'string' ? matched.value.trim() : ''
return typeof matched?.attributeValue === 'string' ? matched.attributeValue.trim() : ''
}
const splitSkuName = (skuName: string) =>
@@ -175,14 +176,18 @@ const getProductParams = (detail: ResolvedGoodsDetailInfo): ParamItem[] => {
].filter(item => item.value)
}
const getSelectedCartItems = (skus: ResolvedGoodsSkuInfo[], quantities: Record<string, number>) =>
skus
.map(sku => ({
sku,
buyNum: Math.min(Math.max(0, quantities[sku.id] ?? 0), sku.stock),
}))
.filter(item => item.buyNum > 0)
function GoodsDetailPage() {
const { spuId = '' } = useParams()
const navigate = useNavigate()
const token = useUserStore(state => state.token)
const userInfo = useUserStore(state => state.userInfo)
const storedMemberId = useUserStore(state => state.memberId)
const currentUid = userInfo?.uid ?? storedMemberId ?? token?.memberId ?? token?.uid ?? 0
const [payload, setPayload] = useState<AppGoodsDetailResponse | null>(null)
const [loading, setLoading] = useState(true)
@@ -191,7 +196,8 @@ function GoodsDetailPage() {
const [keyword, setKeyword] = useState('')
const [selectedColor, setSelectedColor] = useState('')
const [activeDetailTab, setActiveDetailTab] = useState<DetailTabKey>('detail')
const [quantities, setQuantities] = useState<Record<number, number>>({})
const [quantities, setQuantities] = useState<Record<string, number>>({})
const [cartSaving, setCartSaving] = useState(false)
useEffect(() => {
if (!spuId) {
@@ -204,7 +210,7 @@ function GoodsDetailPage() {
setLoading(true)
setError(null)
apiAppGoodsDetail({ uid: currentUid, spuId }, controller.signal)
apiAppGoodsDetail({ spuId }, controller.signal)
.then(response => {
setPayload(response.data)
})
@@ -220,7 +226,7 @@ function GoodsDetailPage() {
})
return () => controller.abort()
}, [currentUid, spuId])
}, [spuId])
const detail = useMemo(() => (payload?.data ? resolveGoodsDetailInfo(payload.data) : null), [payload])
const merchant = payload?.merchant ?? payload?.store ?? null
@@ -273,6 +279,14 @@ function GoodsDetailPage() {
return galleryImages
}, [detailImages, galleryImages])
const whiteImages = useMemo(() => (detail ? getWhiteImageList(detail) : []), [detail])
const selectedCartItems = useMemo(
() => getSelectedCartItems(detail?.skus ?? [], quantities),
[detail, quantities]
)
const selectedCartTotal = useMemo(
() => selectedCartItems.reduce((total, item) => total + item.buyNum, 0),
[selectedCartItems]
)
useEffect(() => {
setActiveImage(galleryImages[0] ?? '')
@@ -282,9 +296,9 @@ function GoodsDetailPage() {
setSelectedColor(colorOptions[0]?.color ?? '')
}, [colorOptions])
const updateQuantity = (skuId: number, delta: number) => {
const updateQuantity = (skuId: string, delta: number, stock: number) => {
setQuantities(current => {
const nextValue = Math.max(0, (current[skuId] ?? 0) + delta)
const nextValue = Math.min(stock, Math.max(0, (current[skuId] ?? 0) + delta))
return {
...current,
[skuId]: nextValue,
@@ -292,6 +306,36 @@ function GoodsDetailPage() {
})
}
const handleAddCart = async () => {
if (!token?.accessToken) {
navigate('/login')
return
}
if (selectedCartItems.length === 0) {
toast.warning('请先选择要加入购物车的商品数量')
return
}
try {
setCartSaving(true)
await Promise.all(
selectedCartItems.map(item =>
apiAppCartSave({
skuId: item.sku.id,
buyNum: item.buyNum,
checked: true,
})
)
)
toast.success(`已加入购物车 ${selectedCartTotal} 件商品`)
} catch (nextError) {
toast.error(nextError instanceof Error ? nextError.message : '加入购物车失败')
} finally {
setCartSaving(false)
}
}
const handleHeaderSearch = (nextKeyword: string) => {
const trimmedKeyword = nextKeyword.trim()
navigate(trimmedKeyword ? `/list/new?key=${encodeURIComponent(trimmedKeyword)}` : '/list/new')
@@ -425,11 +469,15 @@ function GoodsDetailPage() {
<strong>{formatMoney(option.sku.salePrice || detail.minPrice)}</strong>
<small> {option.sku.stock}</small>
<div>
<button type="button" onClick={() => updateQuantity(option.sku.id, -1)}>
<button type="button" onClick={() => updateQuantity(option.sku.id, -1, option.sku.stock)}>
-
</button>
<b>{quantities[option.sku.id] ?? 0}</b>
<button type="button" onClick={() => updateQuantity(option.sku.id, 1)}>
<button
type="button"
disabled={option.sku.stock <= 0 || (quantities[option.sku.id] ?? 0) >= option.sku.stock}
onClick={() => updateQuantity(option.sku.id, 1, option.sku.stock)}
>
+
</button>
</div>
@@ -440,6 +488,27 @@ function GoodsDetailPage() {
) : (
<div className="market-empty-state"> SKU </div>
)}
{detail.skus.length > 0 ? (
<div className="market-detail-cart-actions">
<button
className="market-detail-cart-actions__primary"
type="button"
disabled={cartSaving}
onClick={() => void handleAddCart()}
>
{cartSaving ? '加入中...' : '加入购物车'}
</button>
<button
className="market-detail-cart-actions__ghost"
type="button"
onClick={() => navigate('/member?tab=cart')}
>
</button>
{selectedCartTotal > 0 ? <span> {selectedCartTotal} </span> : null}
</div>
) : null}
</section>
<aside

View File

@@ -4,7 +4,6 @@ import { toast } from 'sonner'
import { apiAppGoodsPage, apiAppHome, apiAppRecentNewGoods } from '@/apis'
import MarketPageHeader from '@/components/MarketPageHeader'
import type { MarketNavKey } from '@/components/MarketNav'
import { useUserStore } from '@/store/user'
import type {
AppGoodsPageResponse,
AppHomeResponse,
@@ -150,11 +149,7 @@ function HomePage() {
const navigate = useNavigate()
const location = useLocation()
const [searchParams] = useSearchParams()
const token = useUserStore(state => state.token)
const userInfo = useUserStore(state => state.userInfo)
const storedMemberId = useUserStore(state => state.memberId)
const currentUid = userInfo?.uid ?? storedMemberId ?? token?.memberId ?? token?.uid ?? 0
const initialSearchKeyword = searchParams.get('key')?.trim() ?? ''
const isInitialSearchPage = location.pathname === '/list/new' || Boolean(initialSearchKeyword)
@@ -193,7 +188,7 @@ function HomePage() {
setHomeLoading(true)
try {
const response = await apiAppHome({ uid: currentUid })
const response = await apiAppHome()
if (canceled) {
return
@@ -221,7 +216,7 @@ function HomePage() {
return () => {
canceled = true
}
}, [currentUid])
}, [])
useEffect(() => {
let canceled = false
@@ -231,7 +226,6 @@ function HomePage() {
try {
const response = await apiAppRecentNewGoods({
uid: currentUid,
page: 1,
size: RECENT_GOODS_PAGE_SIZE,
})
@@ -262,7 +256,7 @@ function HomePage() {
return () => {
canceled = true
}
}, [currentUid, recentNewGoodsRefreshKey])
}, [recentNewGoodsRefreshKey])
useEffect(() => {
let canceled = false
@@ -272,7 +266,6 @@ function HomePage() {
try {
const response = await apiAppGoodsPage({
uid: currentUid,
keyword: submittedKeyword || undefined,
sortType,
page: 1,
@@ -305,7 +298,7 @@ function HomePage() {
return () => {
canceled = true
}
}, [currentUid, sortType, submittedKeyword])
}, [sortType, submittedKeyword])
const banners = useMemo(() => resolveHomeTopBanners(homePayload), [homePayload])
const recommendStores = useMemo(() => resolveHomeRankStores(homePayload), [homePayload])

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@ import { useEffect, useMemo, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { apiAppGoodsPage, apiAppHomeMerchantGoods } from '@/apis'
import MarketPageHeader from '@/components/MarketPageHeader'
import { useUserStore } from '@/store/user'
import type { AppGoodsPageResponse, HomeMerchantGoodsBlock, GoodsSortType, GoodsSummary } from '@/types/mall'
const GOODS_SORT_OPTIONS: Array<{ key: GoodsSortType; label: string }> = [
@@ -36,11 +35,6 @@ const formatPrice = (item: GoodsSummary) => {
function ShopPage() {
const { merchantId = '' } = useParams()
const navigate = useNavigate()
const token = useUserStore(state => state.token)
const userInfo = useUserStore(state => state.userInfo)
const storedMemberId = useUserStore(state => state.memberId)
const currentUid = userInfo?.uid ?? storedMemberId ?? token?.memberId ?? token?.uid ?? 0
const [headerKeyword, setHeaderKeyword] = useState('')
const [keyword, setKeyword] = useState('')
@@ -61,14 +55,14 @@ function ShopPage() {
const controller = new AbortController()
setError(null)
apiAppHomeMerchantGoods({ uid: currentUid, merchantId, limit: 12 }, controller.signal)
apiAppHomeMerchantGoods({ merchantId, limit: 12 }, controller.signal)
.then(response => {
setMerchantBlock(response.data.data)
})
.catch(() => undefined)
return () => controller.abort()
}, [currentUid, merchantId])
}, [merchantId])
useEffect(() => {
if (!merchantId) {
@@ -81,7 +75,6 @@ function ShopPage() {
apiAppGoodsPage(
{
uid: currentUid,
merchantId,
keyword: searchKeyword || undefined,
sortType,
@@ -105,7 +98,7 @@ function ShopPage() {
})
return () => controller.abort()
}, [currentUid, merchantId, searchKeyword, sortType])
}, [merchantId, searchKeyword, sortType])
const goodsList = useMemo(() => goodsPayload?.list ?? merchantBlock?.goods ?? [], [goodsPayload, merchantBlock])
const merchant = merchantBlock?.merchant ?? merchantBlock?.store ?? null

View File

@@ -48,8 +48,8 @@ export interface DetailJson {
}
export interface SpecItem {
name: string
value: string
attributeName: string
attributeValue: string
}
export interface ParamItem {
@@ -74,7 +74,7 @@ export interface ExtraInfoJson {
}
export interface StoreInfo {
id: number
id: string
merchantId: MerchantId
merchantName?: string
logo?: string
@@ -102,10 +102,10 @@ export interface StoreInfo {
export type MerchantInfo = StoreInfo
export interface GoodsSkuInfo {
id: number
spuId: number
id: string
spuId: string
merchantId: MerchantId
storeId: number
storeId: string
skuNo: string
skuName: string
barcode: string
@@ -124,12 +124,12 @@ export interface GoodsSkuInfo {
}
export interface GoodsSummary {
id: number
id: string
merchantId: MerchantId
merchantName?: string
merchantLogo?: string
storeId: number
categoryId: number
storeId: string
categoryId: string
categoryName: string
spuNo: string
spuName: string
@@ -151,10 +151,10 @@ export interface GoodsSummary {
}
export interface GoodsDetailInfo {
id: number
id: string
merchantId: MerchantId
storeId: number
categoryId: number
storeId: string
categoryId: string
categoryName?: string
spuNo: string
spuName: string
@@ -182,13 +182,15 @@ export interface GoodsDetailInfo {
}
export interface CartItemInfo {
id: number
id: string
uid: number
memberId?: number
memberId?: MerchantId
merchantId: MerchantId
storeId: number
spuId: number
skuId: number
merchantName?: string
merchantLogo?: string
storeId: string
spuId: string
skuId: string
spuName: string
skuName: string
coverUrl: string
@@ -196,19 +198,91 @@ export interface CartItemInfo {
buyNum: number
checked: boolean
salePrice: string
itemAmount: string
status: CartItemStatus
createdAt: number
updatedAt: number
}
export interface CartGoodsGroupInfo {
spuId: string
spuName: string
coverUrl: string
checked: boolean
goodsAmount?: string
checkedAmount?: string
items: CartItemInfo[]
}
export interface CartMerchantGroupInfo {
merchantId: MerchantId
merchantName: string
merchantLogo: string
checked: boolean
itemCount?: number
goodsCount?: number
goodsAmount?: string
checkedAmount?: string
goods: CartGoodsGroupInfo[]
}
export interface UserAddressInfo {
id: string
uid: number
receiverName: string
receiverMobile: string
countryCode: string
province: string
city: string
district: string
addressDetail: string
zipCode: string
tag: string
isDefault: boolean
createdAt: number
updatedAt: number
}
export interface TradeBuyItem {
skuId: number
skuId: string
buyNum: number
}
export interface TradeMerchantOptionInput {
merchantId: MerchantId
deliveryOptionId?: string
packageOptionId?: string
}
export interface MerchantDeliveryOptionInfo {
id: string
merchantId: MerchantId
optionName: string
deliveryCode: string
feeAmount: string
description: string
sort: number
status: EnabledStatus
createdAt: number
updatedAt: number
}
export interface MerchantPackageOptionInfo {
id: string
merchantId: MerchantId
optionName: string
packageCode: string
feeAmount: string
description: string
sort: number
status: EnabledStatus
createdAt: number
updatedAt: number
}
export interface TradePreviewItemInfo {
spuId: number
skuId: number
spuId: string
skuId: string
spuName: string
skuName: string
coverUrl: string
@@ -220,19 +294,25 @@ export interface TradePreviewItemInfo {
export interface TradePreviewStoreInfo {
merchantId: MerchantId
storeId: number
storeName: string
merchantName: string
storeId?: string
storeName?: string
goodsAmount: string
freightAmount: string
packageAmount: string
discountAmount: string
payAmount: string
deliveryOptions: MerchantDeliveryOptionInfo[]
packageOptions: MerchantPackageOptionInfo[]
selectedDeliveryOption?: MerchantDeliveryOptionInfo
selectedPackageOption?: MerchantPackageOptionInfo
items: TradePreviewItemInfo[]
}
export interface TradePreviewInfo {
uid: number
memberId?: number
addressId: number
memberId?: MerchantId
addressId: string
receiverName: string
receiverMobile: string
receiverCountryCode: string
@@ -245,6 +325,7 @@ export interface TradePreviewInfo {
currency: string
goodsAmount: string
freightAmount: string
packageAmount: string
discountAmount: string
payAmount: string
orderCount: number
@@ -253,12 +334,12 @@ export interface TradePreviewInfo {
}
export interface OrderItemInfo {
id: number
orderId: number
tradeId: number
id: string
orderId: string
tradeId: string
orderNo: string
spuId: number
skuId: number
spuId: string
skuId: string
spuName: string
skuName: string
coverUrl: string
@@ -273,20 +354,21 @@ export interface OrderItemInfo {
}
export interface OrderSummary {
id: number
tradeId: number
id: string
tradeId: string
tradeNo: string
orderNo: string
uid: number
memberId?: number
memberId?: MerchantId
merchantId: MerchantId
storeId: number
storeId: string
storeName: string
orderStatus: OrderStatus
afterSaleStatus: AfterSaleStatus
currency: string
goodsAmount: string
freightAmount: string
packageAmount: string
discountAmount: string
payAmount: string
payTime: number
@@ -298,20 +380,21 @@ export interface OrderSummary {
}
export interface OrderDetailInfo {
id: number
tradeId: number
id: string
tradeId: string
tradeNo: string
orderNo: string
uid: number
memberId?: number
memberId?: MerchantId
merchantId: MerchantId
storeId: number
storeId: string
storeName: string
orderStatus: OrderStatus
afterSaleStatus: AfterSaleStatus
currency: string
goodsAmount: string
freightAmount: string
packageAmount: string
discountAmount: string
payAmount: string
buyerRemark: string
@@ -327,6 +410,8 @@ export interface OrderDetailInfo {
deliveryCompany: string
deliveryNo: string
payChannel: string
selectedDeliveryOption?: MerchantDeliveryOptionInfo
selectedPackageOption?: MerchantPackageOptionInfo
extraInfoJson: string
payTime: number
shipTime: number
@@ -339,7 +424,7 @@ export interface OrderDetailInfo {
}
export interface BannerInfo {
id: number
id: string
title: string
subTitle: string
description: string
@@ -355,14 +440,14 @@ export interface BannerInfo {
}
export interface HomeCategoryNav {
categoryId: number
categoryId: string
categoryName: string
goodsCount: number
sort: number
}
export interface HomeChannelCard {
id: number
id: string
title: string
subTitle: string
iconUrl: string
@@ -373,7 +458,7 @@ export interface HomeChannelCard {
}
export interface RecommendStoreInfo {
id: string | number
id: string
merchantId: MerchantId
storeName: string
storeLogo: string
@@ -439,9 +524,7 @@ export interface ResolvedOrderDetailInfo extends OrderDetailInfo {
}
export interface AppHomeRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
}
export interface AppHomeResponse {
@@ -470,9 +553,7 @@ export interface RecentNewGoodsItem {
}
export interface AppRecentNewGoodsRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
page?: number
size?: number
}
@@ -483,12 +564,10 @@ export interface AppRecentNewGoodsResponse {
}
export interface AppHomeMerchantGoodsRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
merchantId?: MerchantId
/** @deprecated use merchantId */
storeId?: number
storeId?: string
limit?: number
}
@@ -497,13 +576,11 @@ export interface AppHomeMerchantGoodsResponse {
}
export interface AppGoodsPageRequest extends IPageParams {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
merchantId?: MerchantId
/** @deprecated use merchantId */
storeId?: number
categoryId?: number
storeId?: string
categoryId?: string
keyword?: string
sortType?: GoodsSortType
}
@@ -514,10 +591,8 @@ export interface AppGoodsPageResponse {
}
export interface AppGoodsDetailRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
spuId: number | string
memberId?: MerchantId
spuId: string
}
export interface AppGoodsDetailResponse {
@@ -528,50 +603,86 @@ export interface AppGoodsDetailResponse {
}
export interface AppCartListRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
}
export interface AppCartListResponse {
list: CartItemInfo[]
merchantGroups: CartMerchantGroupInfo[]
itemCount: number
goodsCount: number
goodsAmount: string
checkedCount: number
checkedAmount: string
}
export interface AppCartSaveRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
skuId: number
memberId?: MerchantId
skuId: string
buyNum: number
checked: boolean
}
export interface AppCartSaveResponse {
cartId: number
cartId: string
buyNum: number
checked: boolean
}
export interface AppCartRemoveRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
skuIds: number[]
memberId?: MerchantId
skuIds: string[]
}
export interface AppCartRemoveResponse {
removedCount: number
}
export type AppAddressListRequest = Record<string, never>
export interface AppAddressListResponse {
list: UserAddressInfo[]
}
export interface AppAddressSaveRequest {
id?: string
receiverName: string
receiverMobile: string
countryCode?: string
province?: string
city?: string
district?: string
addressDetail: string
zipCode?: string
tag?: string
isDefault?: boolean
}
export interface AppAddressSaveResponse {
addressId: string
}
export interface AppAddressDeleteRequest {
addressId: string
}
export interface AppAddressDeleteResponse {
removedCount: number
}
export interface AppAddressDefaultSetRequest {
addressId: string
}
export interface AppAddressDefaultSetResponse {
addressId: string
}
export interface AppTradePreviewRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
buyItems?: TradeBuyItem[]
addressId: number
addressId: string
buyerRemark?: string
merchantOptions?: TradeMerchantOptionInput[]
}
export interface AppTradePreviewResponse {
@@ -579,30 +690,32 @@ export interface AppTradePreviewResponse {
}
export interface AppTradeCreateRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
buyItems?: TradeBuyItem[]
addressId: number
addressId: string
buyerRemark?: string
payChannel: string
merchantOptions?: TradeMerchantOptionInput[]
}
export interface AppTradeCreateResponse {
tradeId: number
tradeId: string
tradeNo: string
payStatus: PayStatus
tradeStatus: TradeStatus
payAmount: string
expiredAt: number
orderIds: number[]
payUrl?: string
payExternal?: boolean
payExpiredAt?: number
payChannel?: string
paySubject?: string
orderIds: string[]
orderNos: string[]
}
export interface AppOrderPageRequest extends IPageParams {
uid?: number
/** @deprecated use uid */
memberId?: number
memberId?: MerchantId
orderStatus?: OrderStatus
afterSaleStatus?: AfterSaleStatus
}
@@ -613,10 +726,8 @@ export interface AppOrderPageResponse {
}
export interface AppOrderDetailRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
orderId: number
memberId?: MerchantId
orderId: string
}
export interface AppOrderDetailResponse {
@@ -624,24 +735,20 @@ export interface AppOrderDetailResponse {
}
export interface AppOrderConfirmRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
orderId: number
memberId?: MerchantId
orderId: string
}
export interface AppOrderConfirmResponse {
orderId: number
orderId: string
orderStatus: OrderStatus
finishTime: number
}
export interface AppAfterSaleApplyRequest {
uid?: number
/** @deprecated use uid */
memberId?: number
orderId: number
orderItemId: number
memberId?: MerchantId
orderId: string
orderItemId: string
afterSaleType: AfterSaleType
reason: string
description?: string
@@ -650,7 +757,7 @@ export interface AppAfterSaleApplyRequest {
}
export interface AppAfterSaleApplyResponse {
afterSaleId: number
afterSaleId: string
afterSaleNo: string
afterSaleStatus: Exclude<AfterSaleStatus, 'none'>
}