pet_data/core/api-service.js

263 lines
5.9 KiB
JavaScript

// API 服務層 - 支援 mock 和真實 API 切換
export class ApiService {
constructor(config = {}) {
this.baseUrl = config.baseUrl || 'http://localhost:3000/api'
this.useMock = config.useMock !== false // 預設使用 mock
this.mockDelay = config.mockDelay || 100 // mock 延遲模擬網路請求
}
// 通用請求方法
async request(endpoint, options = {}) {
if (this.useMock) {
return this.mockRequest(endpoint, options)
}
return this.realRequest(endpoint, options)
}
// Mock 請求(使用本地資料)
async mockRequest(endpoint, options) {
await this.delay(this.mockDelay)
const [resource, action] = endpoint.split('/').filter(Boolean)
switch (`${resource}/${action}`) {
case 'pet/state':
return this.getMockPetState()
case 'pet/update':
return this.updateMockPetState(options.body)
case 'events/list':
return this.getMockEvents()
case 'events/trigger':
return this.triggerMockEvent(options.body)
case 'buffs/apply':
return this.applyMockBuff(options.body)
case 'deities/list':
return this.getMockDeities()
case 'deities/pray':
return this.mockPrayToDeity(options.body)
case 'fortune/draw':
return this.mockDrawFortune()
case 'items/list':
return this.getMockItems()
case 'items/use':
return this.mockUseItem(options.body)
case 'pet/save':
return this.saveMockPetState(options.body)
case 'pet/delete':
return this.deleteMockPetState()
default:
throw new Error(`Unknown endpoint: ${endpoint}`)
}
}
// 真實 API 請求
async realRequest(endpoint, options = {}) {
const url = `${this.baseUrl}/${endpoint}`
const config = {
method: options.method || 'GET',
headers: {
'Content-Type': 'application/json',
...options.headers
}
}
if (options.body) {
config.body = JSON.stringify(options.body)
}
const response = await fetch(url, config)
if (!response.ok) {
throw new Error(`API Error: ${response.status} ${response.statusText}`)
}
return response.json()
}
// 延遲模擬
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// ========== API 端點方法 ==========
// 寵物狀態相關
async getPetState() {
return this.request('pet/state')
}
async updatePetState(updates) {
return this.request('pet/update', {
method: 'POST',
body: updates
})
}
async savePetState(state) {
return this.request('pet/save', {
method: 'POST',
body: state
})
}
async deletePetState() {
return this.request('pet/delete', {
method: 'DELETE'
})
}
// 事件相關
async getEvents() {
return this.request('events/list')
}
async triggerEvent(eventId, petState) {
return this.request('events/trigger', {
method: 'POST',
body: { eventId, petState }
})
}
// Buff 相關
async applyBuff(buffData) {
return this.request('buffs/apply', {
method: 'POST',
body: buffData
})
}
// 神明相關
async getDeities() {
return this.request('deities/list')
}
async prayToDeity(deityId, petState) {
return this.request('deities/pray', {
method: 'POST',
body: { deityId, petState }
})
}
// 籤詩相關
async drawFortune() {
return this.request('fortune/draw', {
method: 'POST'
})
}
// 道具相關
async getItems() {
return this.request('items/list')
}
async useItem(itemId, count = 1) {
return this.request('items/use', {
method: 'POST',
body: { itemId, count }
})
}
// ========== Mock 資料方法 ==========
getMockPetState() {
// 從 localStorage 或預設值讀取
const stored = localStorage.getItem('petState')
if (stored) {
return JSON.parse(stored)
}
return null
}
updateMockPetState(updates) {
const current = this.getMockPetState()
const updated = { ...current, ...updates }
localStorage.setItem('petState', JSON.stringify(updated))
return { success: true, data: updated }
}
saveMockPetState(state) {
localStorage.setItem('petState', JSON.stringify(state))
return { success: true, message: '狀態已儲存' }
}
getMockEvents() {
// 動態載入事件配置
return import('../data/events.js').then(m => m.EVENT_CONFIG)
}
triggerMockEvent({ eventId, petState }) {
// 模擬事件觸發邏輯
return { success: true, eventId, effects: [] }
}
applyMockBuff(buffData) {
return { success: true, buff: buffData }
}
async getMockDeities() {
const { DEITIES } = await import('../data/deities.js')
return DEITIES
}
mockPrayToDeity({ deityId, petState }) {
return {
success: true,
favorIncrease: 5,
message: '祈福成功'
}
}
mockDrawFortune() {
// 模擬抽籤邏輯
const grades = ['上上', '上', '中', '下', '下下']
const weights = [0.05, 0.15, 0.40, 0.30, 0.10]
const random = Math.random()
let sum = 0
let selectedGrade = '中'
for (let i = 0; i < weights.length; i++) {
sum += weights[i]
if (random <= sum) {
selectedGrade = grades[i]
break
}
}
return {
success: true,
lot: {
id: Math.floor(Math.random() * 100) + 1,
grade: selectedGrade,
poem1: '示例籤詩',
meaning: '示例解釋'
}
}
}
async getMockItems() {
const { ITEMS } = await import('../data/items.js')
return Object.values(ITEMS)
}
mockUseItem({ itemId, count }) {
return {
success: true,
itemId,
count,
effects: {}
}
}
deleteMockPetState() {
localStorage.removeItem('petState')
return { success: true, message: '寵物已刪除' }
}
}
// 預設實例
export const apiService = new ApiService({
useMock: true, // 開發時使用 mock
mockDelay: 100
})