topfans/frontend/composables/useLaserMint.js
2026-06-03 22:19:22 +08:00

123 lines
3.2 KiB
JavaScript

import { ref } from 'vue'
import { estimateMintCostApi } from '@/utils/api.js'
import { submitCraftMintFromPath } from '@/utils/craftMintSubmit.js'
function updateLocalBalance(newBalance) {
try {
const userStr = uni.getStorageSync('user')
if (!userStr) return
const user = typeof userStr === 'string' ? JSON.parse(userStr) : { ...userStr }
user.crystal_balance = Number(newBalance) || 0
uni.setStorageSync('user', JSON.stringify(user))
uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
} catch (e) {
console.warn('[useLaserMint] updateLocalBalance failed:', e)
}
}
/**
* laser-result 选卡确认后的铸造(估价 → ConfirmModal → craftMintSubmit 多素材上传)
*/
export function useLaserMint({ getSelectedImagePath, getSelectedOssKey, getSelectedPresetIndex, formDataRef, getInstanceNo }) {
const showConfirmModal = ref(false)
const confirmCostInfo = ref({
costCrystal: 0,
currentBalance: 0,
mintCount: 0,
nextTierCost: 0,
})
const selectAsset = async () => {
const imagePath = getSelectedImagePath()
if (!imagePath) {
uni.showToast({ title: '缺少作品图', icon: 'none' })
return
}
try {
uni.showLoading({ title: '加载中…', mask: true })
const costRes = await estimateMintCostApi()
uni.hideLoading()
if (costRes.code === 200 && costRes.data) {
confirmCostInfo.value = {
costCrystal: costRes.data.cost_crystal || 0,
currentBalance: costRes.data.current_balance || 0,
mintCount: costRes.data.mint_count || 0,
nextTierCost: costRes.data.next_tier_cost || 0,
}
} else {
confirmCostInfo.value = {
costCrystal: 100,
currentBalance: 0,
mintCount: 0,
nextTierCost: 0,
}
}
} catch (e) {
uni.hideLoading()
console.error('[useLaserMint] estimateMintCostApi failed:', e)
confirmCostInfo.value = {
costCrystal: 100,
currentBalance: 0,
mintCount: 0,
nextTierCost: 0,
}
}
showConfirmModal.value = true
}
const handleConfirmMint = async () => {
showConfirmModal.value = false
const imagePath = getSelectedImagePath()
if (!imagePath) {
uni.showToast({ title: '缺少作品图', icon: 'none' })
return
}
if (confirmCostInfo.value.currentBalance < confirmCostInfo.value.costCrystal) {
uni.showToast({ title: '水晶余额不足,无法铸造', icon: 'none' })
return
}
uni.showLoading({ title: '铸造中…', mask: true })
try {
await submitCraftMintFromPath({
imagePath,
ossKey: getSelectedOssKey ? getSelectedOssKey() : '',
instanceNo: getInstanceNo ? getInstanceNo() : '',
formData: formDataRef.value,
laserPresetIndex: getSelectedPresetIndex(),
})
const balanceAfter = Math.max(
0,
Number(confirmCostInfo.value.currentBalance) - Number(confirmCostInfo.value.costCrystal)
)
updateLocalBalance(balanceAfter)
uni.navigateTo({ url: '/pages/castlove/success' })
} catch (e) {
console.error('[useLaserMint] mint failed:', e)
uni.showToast({ title: e?.message || '铸造失败', icon: 'none' })
} finally {
uni.hideLoading()
}
}
const handleCancelMint = () => {
showConfirmModal.value = false
}
return {
showConfirmModal,
confirmCostInfo,
selectAsset,
handleConfirmMint,
handleCancelMint,
}
}