317 lines
9.9 KiB
TypeScript
317 lines
9.9 KiB
TypeScript
import dayjs from 'dayjs'
|
|
import type { PageResponse, TokenResponse } from '@/types/api'
|
|
import type {
|
|
CommodityOrder,
|
|
CommodityOrderSearch,
|
|
UserOrderDetail,
|
|
WriteOffPayload,
|
|
WriteOffResult
|
|
} from '@/types/order'
|
|
import type { CreateEventPayload, EventData, EventSearch } from '@/types/event'
|
|
import { addDays, formatDateTime, today } from '@/utils/date'
|
|
|
|
const wait = (ms = 260) => new Promise((resolve) => window.setTimeout(resolve, ms))
|
|
|
|
const coverImages = [
|
|
'https://images.unsplash.com/photo-1566073771259-6a8506099945?auto=format&fit=crop&w=900&q=80',
|
|
'https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?auto=format&fit=crop&w=900&q=80',
|
|
'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?auto=format&fit=crop&w=900&q=80'
|
|
]
|
|
|
|
let orders: CommodityOrder[] = [
|
|
{
|
|
id: '202606160001',
|
|
orderAmt: '699.00',
|
|
visitorName: '林清',
|
|
contactPhone: '13800000001',
|
|
checkInData: today(),
|
|
checkOutData: addDays(1),
|
|
orderStatus: '2',
|
|
payStatus: '1',
|
|
payAmt: '659.00',
|
|
discountAmt: '40.00',
|
|
payTime: formatDateTime(dayjs().subtract(2, 'hour').toDate()),
|
|
orderType: '0',
|
|
createTime: formatDateTime(dayjs().subtract(3, 'hour').toDate()),
|
|
roomId: '1208',
|
|
commodityName: '湖景大床房含双早',
|
|
commodityCoverPhoto: coverImages[0],
|
|
commodityAmount: 1,
|
|
reservationDate: today()
|
|
},
|
|
{
|
|
id: '202606150108',
|
|
orderAmt: '238.00',
|
|
visitorName: '王予安',
|
|
contactPhone: '13800000002',
|
|
orderStatus: '6',
|
|
payStatus: '1',
|
|
payAmt: '238.00',
|
|
orderType: '2',
|
|
createTime: formatDateTime(dayjs().subtract(1, 'day').toDate()),
|
|
commodityName: '云端餐厅双人套餐',
|
|
commodityCoverPhoto: coverImages[1],
|
|
commodityAmount: 1,
|
|
writeOffTime: formatDateTime(dayjs().subtract(4, 'hour').toDate())
|
|
},
|
|
{
|
|
id: '202606140072',
|
|
orderAmt: '158.00',
|
|
visitorName: '赵一鸣',
|
|
contactPhone: '13800000003',
|
|
orderStatus: '4',
|
|
payStatus: '1',
|
|
payAmt: '158.00',
|
|
orderType: '1',
|
|
createTime: formatDateTime(dayjs().subtract(2, 'day').toDate()),
|
|
commodityName: '温泉中心成人票',
|
|
commodityCoverPhoto: coverImages[2],
|
|
commodityAmount: 2
|
|
},
|
|
{
|
|
id: '202606130045',
|
|
orderAmt: '899.00',
|
|
visitorName: '许知夏',
|
|
contactPhone: '13800000004',
|
|
checkInData: addDays(2),
|
|
checkOutData: addDays(3),
|
|
orderStatus: '1',
|
|
payStatus: '1',
|
|
payAmt: '899.00',
|
|
orderType: '0',
|
|
createTime: formatDateTime(dayjs().subtract(3, 'day').toDate()),
|
|
commodityName: '亲子套房一晚',
|
|
commodityCoverPhoto: coverImages[0],
|
|
commodityAmount: 1,
|
|
reservationDate: addDays(2)
|
|
}
|
|
]
|
|
|
|
let events: EventData[] = [
|
|
{
|
|
id: 'EVT20260616001',
|
|
entityName: '前台',
|
|
eventDescription: '端午假期入住高峰,前台增开一组接待人员并优先处理已预付订单。',
|
|
eventStatus: 0,
|
|
effectiveStartTime: formatDateTime(dayjs().subtract(1, 'hour').toDate()),
|
|
effectiveEndTime: formatDateTime(dayjs().add(8, 'hour').toDate()),
|
|
createByName: '值班经理',
|
|
popUpReminder: 1,
|
|
publicTime: formatDateTime(dayjs().subtract(2, 'hour').toDate()),
|
|
imgUrl: coverImages[0],
|
|
showStatusDesc: '生效中'
|
|
},
|
|
{
|
|
id: 'EVT20260615002',
|
|
entityName: '餐饮部',
|
|
eventDescription: '晚餐第二时段预约已满,建议推荐客人选择 19:45 后到店。',
|
|
eventStatus: 0,
|
|
effectiveStartTime: formatDateTime(dayjs().add(1, 'hour').toDate()),
|
|
effectiveEndTime: formatDateTime(dayjs().add(10, 'hour').toDate()),
|
|
createByName: '餐饮主管',
|
|
popUpReminder: 0,
|
|
publicTime: formatDateTime(dayjs().subtract(1, 'day').toDate()),
|
|
imgUrl: coverImages[1],
|
|
showStatusDesc: '待生效'
|
|
}
|
|
]
|
|
|
|
const page = <T>(records: T[], pageNum: number, pageSize: number): PageResponse<T> => {
|
|
const start = (pageNum - 1) * pageSize
|
|
const current = records.slice(start, start + pageSize)
|
|
return {
|
|
records: current,
|
|
total: records.length,
|
|
size: pageSize,
|
|
current: pageNum,
|
|
pages: Math.ceil(records.length / pageSize)
|
|
}
|
|
}
|
|
|
|
export const mockApi = {
|
|
async sendMobileCode(payload: { phone: string; imageRandomStr?: string; imageCode?: string }) {
|
|
await wait()
|
|
if (!payload.phone) return { data: false, msg: '请输入手机号' }
|
|
if (!payload.imageRandomStr || !payload.imageCode) return { data: false, msg: '请输入图形验证码' }
|
|
return { data: true, msg: '5678nianxx' }
|
|
},
|
|
|
|
async loginByMobile(phone: string): Promise<TokenResponse> {
|
|
await wait()
|
|
return {
|
|
access_token: `mock-token-${Date.now()}`,
|
|
refresh_token: 'mock-refresh-token',
|
|
token_type: 'Bearer',
|
|
expires_in: 43200,
|
|
scope: 'server',
|
|
client_id: 'custom',
|
|
clientId: 'custom',
|
|
user_id: '10001',
|
|
username: phone,
|
|
tenant_id: 1
|
|
}
|
|
},
|
|
|
|
async checkBindPhone() {
|
|
await wait(120)
|
|
return true
|
|
},
|
|
|
|
async bindOrganization(phone: string) {
|
|
await wait(180)
|
|
if (!phone) {
|
|
throw new Error('未绑定组织,请联系管理员')
|
|
}
|
|
return {
|
|
memberId: 'MEMBER10001',
|
|
organizationId: 'ORG10001',
|
|
memberName: '当前员工',
|
|
userPhone: phone,
|
|
memberRoleId: 'ROLE_STAFF'
|
|
}
|
|
},
|
|
|
|
async getBindStaffInfo() {
|
|
await wait(180)
|
|
return {
|
|
userId: 'USER10001',
|
|
memberId: 'MEMBER10001',
|
|
organizationId: 'ORG10001',
|
|
memberName: '当前员工',
|
|
memberRoleId: 'ROLE_STAFF'
|
|
}
|
|
},
|
|
|
|
async orderList(query: CommodityOrderSearch) {
|
|
await wait()
|
|
const keyword = query.orderId || query.contactPhone || ''
|
|
const filtered = orders.filter((item) => {
|
|
const matchStatus = query.orderStatus ? item.orderStatus === query.orderStatus : true
|
|
const matchType = query.commodityTypeCode ? item.orderType === query.commodityTypeCode : true
|
|
const matchKeyword = keyword
|
|
? item.id.includes(keyword) || item.contactPhone.includes(keyword) || item.visitorName.includes(keyword)
|
|
: true
|
|
return matchStatus && matchType && matchKeyword
|
|
})
|
|
return page(filtered, query.pageNum, query.pageSize)
|
|
},
|
|
|
|
async orderDetail(orderId: string): Promise<UserOrderDetail> {
|
|
await wait()
|
|
const order = orders.find((item) => item.id === orderId) || orders[0]
|
|
const totalCount = Number(order.commodityAmount) || 1
|
|
const writeOffCount = order.writeOffTime ? totalCount : 0
|
|
return {
|
|
orderId: order.id,
|
|
orderAmt: order.orderAmt,
|
|
consumerInfoList: [
|
|
{
|
|
id: '1',
|
|
visitorName: order.visitorName,
|
|
contactPhone: order.contactPhone,
|
|
idCard: '430***********2218'
|
|
}
|
|
],
|
|
checkInData: order.checkInData,
|
|
checkOutData: order.checkOutData,
|
|
reservationDate: order.reservationDate,
|
|
orderStatus: order.orderStatus,
|
|
userId: order.userId,
|
|
organizationId: order.organizationId,
|
|
payStatus: order.payStatus,
|
|
payAmt: order.payAmt,
|
|
discountAmt: order.discountAmt,
|
|
payTime: order.payTime,
|
|
createTime: order.createTime,
|
|
commodityCoverPhoto: order.commodityCoverPhoto,
|
|
commodityName: order.commodityName,
|
|
commodityAddress: '星河湾酒店一层前台',
|
|
commodityServiceList: [{ serviceName: '到店核销' }, { serviceName: '不可拆分使用' }],
|
|
commodityTip: '请在预约日期到店使用,核销后不支持退款。',
|
|
payWay: '0',
|
|
paySerialNumber: `WX${order.id}`,
|
|
paySource: '2',
|
|
orderType: order.orderType,
|
|
commodityAmount: String(order.commodityAmount),
|
|
storeName: '星河湾酒店',
|
|
complaintHotline: '18285123187',
|
|
refundable: order.orderStatus !== '6',
|
|
commodityId: `COM${order.id.slice(-4)}`,
|
|
commodityTypeCode: order.orderType,
|
|
commodityFacilityList: ['含早餐', '免费停车', '可预约'],
|
|
commodityDescription: '面向到店客人的酒店权益商品,需由员工确认后核销。',
|
|
commodityPackageConfig: [
|
|
{
|
|
packageName: order.commodityName,
|
|
packageContent: `${order.commodityName} x ${order.commodityAmount}`,
|
|
name: order.commodityName,
|
|
count: totalCount,
|
|
unit: '份',
|
|
packageStatus: writeOffCount >= totalCount ? 1 : 0,
|
|
writeOffCount
|
|
}
|
|
],
|
|
reservationEnabled: order.reservationDate ? 1 : 0,
|
|
reservationRuleDesc: '预约订单请核对预约日期和联系人信息。',
|
|
writeOffRecordList: order.writeOffTime
|
|
? [
|
|
{
|
|
id: `WO${order.id}`,
|
|
orderId: order.id,
|
|
commodityName: order.commodityName,
|
|
packageName: order.commodityName,
|
|
userName: '当前员工',
|
|
createTime: order.writeOffTime
|
|
}
|
|
]
|
|
: []
|
|
}
|
|
},
|
|
|
|
async writeOff(payload: WriteOffPayload): Promise<WriteOffResult> {
|
|
await wait()
|
|
orders = orders.map((item) =>
|
|
item.id === payload.orderId
|
|
? { ...item, orderStatus: '6', writeOffTime: formatDateTime(new Date()) }
|
|
: item
|
|
)
|
|
return {
|
|
success: true,
|
|
orderId: payload.orderId,
|
|
packageName: payload.packageName,
|
|
message: '核销成功',
|
|
operatedAt: formatDateTime(new Date())
|
|
}
|
|
},
|
|
|
|
async eventList(query: EventSearch) {
|
|
await wait()
|
|
const filtered = events.filter((item) => {
|
|
const matchName = query.entityName ? item.entityName.includes(query.entityName) : true
|
|
const matchStatus = query.eventStatus === undefined ? true : item.eventStatus === query.eventStatus
|
|
return matchName && matchStatus
|
|
})
|
|
return page(filtered, query.pageNum, query.pageSize)
|
|
},
|
|
|
|
async createEvent(payload: CreateEventPayload) {
|
|
await wait()
|
|
events = [
|
|
{
|
|
id: `EVT${Date.now()}`,
|
|
...payload,
|
|
eventStatus: 0,
|
|
createByName: '当前员工',
|
|
showStatusDesc: '待生效'
|
|
},
|
|
...events
|
|
]
|
|
return true
|
|
},
|
|
|
|
async uploadFile(file: File) {
|
|
await wait()
|
|
return URL.createObjectURL(file)
|
|
}
|
|
}
|