Files
vf_react/src/services/predictionMarketService.api.js
2025-11-24 08:05:19 +08:00

326 lines
7.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 预测市场服务 - API 版本
* 调用真实的后端 API数据存储到 MySQL 数据库
*/
import axios from 'axios';
import { getApiBase } from '@utils/apiConfig';
const api = axios.create({
baseURL: getApiBase(),
timeout: 10000,
withCredentials: true, // 携带 Cookiesession
});
// ==================== 积分系统 API ====================
/**
* 获取用户积分账户
*/
export const getUserAccount = async () => {
try {
const response = await api.get('/api/prediction/credit/account');
return response.data;
} catch (error) {
console.error('获取积分账户失败:', error);
throw error;
}
};
/**
* 领取每日奖励100积分
*/
export const claimDailyBonus = async () => {
try {
const response = await api.post('/api/prediction/credit/daily-bonus');
return response.data;
} catch (error) {
console.error('领取每日奖励失败:', error);
throw error;
}
};
// ==================== 预测话题 API ====================
/**
* 创建预测话题
* @param {Object} topicData - { title, description, category, deadline }
*/
export const createTopic = async (topicData) => {
try {
const response = await api.post('/api/prediction/topics', topicData);
return response.data;
} catch (error) {
console.error('创建预测话题失败:', error);
throw error;
}
};
/**
* 获取预测话题列表
* @param {Object} params - { status, category, sort_by, page, per_page }
*/
export const getTopics = async (params = {}) => {
try {
const response = await api.get('/api/prediction/topics', { params });
return response.data;
} catch (error) {
console.error('获取话题列表失败:', error);
throw error;
}
};
/**
* 获取预测话题详情
* @param {number} topicId
*/
export const getTopicDetail = async (topicId) => {
try {
const response = await api.get(`/api/prediction/topics/${topicId}`);
return response.data;
} catch (error) {
console.error('获取话题详情失败:', error);
throw error;
}
};
/**
* 结算预测话题(仅创建者可操作)
* @param {number} topicId
* @param {string} result - 'yes' | 'no' | 'draw'
*/
export const settleTopic = async (topicId, result) => {
try {
const response = await api.post(`/api/prediction/topics/${topicId}/settle`, { result });
return response.data;
} catch (error) {
console.error('结算话题失败:', error);
throw error;
}
};
// ==================== 交易 API ====================
/**
* 买入预测份额
* @param {Object} tradeData - { topic_id, direction, shares }
*/
export const buyShares = async (tradeData) => {
try {
const response = await api.post('/api/prediction/trade/buy', tradeData);
return response.data;
} catch (error) {
console.error('买入份额失败:', error);
throw error;
}
};
/**
* 获取用户持仓列表
*/
export const getUserPositions = async () => {
try {
const response = await api.get('/api/prediction/positions');
return response.data;
} catch (error) {
console.error('获取持仓列表失败:', error);
throw error;
}
};
// ==================== 评论 API ====================
/**
* 发表话题评论
* @param {number} topicId
* @param {Object} commentData - { content, parent_id }
*/
export const createComment = async (topicId, commentData) => {
try {
const response = await api.post(`/api/prediction/topics/${topicId}/comments`, commentData);
return response.data;
} catch (error) {
console.error('发表评论失败:', error);
throw error;
}
};
/**
* 获取话题评论列表
* @param {number} topicId
* @param {Object} params - { page, per_page }
*/
export const getComments = async (topicId, params = {}) => {
try {
const response = await api.get(`/api/prediction/topics/${topicId}/comments`, { params });
return response.data;
} catch (error) {
console.error('获取评论列表失败:', error);
throw error;
}
};
/**
* 点赞/取消点赞评论
* @param {number} commentId
*/
export const likeComment = async (commentId) => {
try {
const response = await api.post(`/api/prediction/comments/${commentId}/like`);
return response.data;
} catch (error) {
console.error('点赞评论失败:', error);
throw error;
}
};
// ==================== 观点IPO API ====================
/**
* 投资评论观点IPO
* @param {number} commentId - 评论ID
* @param {number} shares - 投资份额
*/
export const investComment = async (commentId, shares) => {
try {
const response = await api.post(`/api/prediction/comments/${commentId}/invest`, { shares });
return response.data;
} catch (error) {
console.error('投资评论失败:', error);
throw error;
}
};
/**
* 获取评论的投资列表
* @param {number} commentId - 评论ID
*/
export const getCommentInvestments = async (commentId) => {
try {
const response = await api.get(`/api/prediction/comments/${commentId}/investments`);
return response.data;
} catch (error) {
console.error('获取投资列表失败:', error);
throw error;
}
};
/**
* 验证评论结果(仅创建者可操作)
* @param {number} commentId - 评论ID
* @param {string} result - 'correct' | 'incorrect'
*/
export const verifyComment = async (commentId, result) => {
try {
const response = await api.post(`/api/prediction/comments/${commentId}/verify`, { result });
return response.data;
} catch (error) {
console.error('验证评论失败:', error);
throw error;
}
};
// ==================== 工具函数(价格计算保留在前端,用于实时预览)====================
export const MARKET_CONFIG = {
MAX_SEATS_PER_SIDE: 5,
TAX_RATE: 0.02,
MIN_PRICE: 50,
MAX_PRICE: 950,
BASE_PRICE: 500,
};
/**
* 计算当前价格简化版AMM
* @param {number} yesShares - Yes方总份额
* @param {number} noShares - No方总份额
* @returns {Object} {yes: price, no: price}
*/
export const calculatePrice = (yesShares, noShares) => {
const totalShares = yesShares + noShares;
if (totalShares === 0) {
return {
yes: MARKET_CONFIG.BASE_PRICE,
no: MARKET_CONFIG.BASE_PRICE,
};
}
const yesProb = yesShares / totalShares;
const noProb = noShares / totalShares;
let yesPrice = yesProb * 1000;
let noPrice = noProb * 1000;
yesPrice = Math.max(MARKET_CONFIG.MIN_PRICE, Math.min(MARKET_CONFIG.MAX_PRICE, yesPrice));
noPrice = Math.max(MARKET_CONFIG.MIN_PRICE, Math.min(MARKET_CONFIG.MAX_PRICE, noPrice));
return { yes: Math.round(yesPrice), no: Math.round(noPrice) };
};
/**
* 计算交易税
* @param {number} amount - 交易金额
* @returns {number} 税费
*/
export const calculateTax = (amount) => {
return Math.floor(amount * MARKET_CONFIG.TAX_RATE);
};
/**
* 计算买入成本(用于前端预览)
* @param {number} currentShares - 当前方总份额
* @param {number} otherShares - 对手方总份额
* @param {number} buyAmount - 买入数量
* @returns {Object} { amount, tax, total }
*/
export const calculateBuyCost = (currentShares, otherShares, buyAmount) => {
const currentPrice = calculatePrice(currentShares, otherShares);
const afterShares = currentShares + buyAmount;
const afterPrice = calculatePrice(afterShares, otherShares);
const avgPrice = (currentPrice.yes + afterPrice.yes) / 2;
const amount = avgPrice * buyAmount;
const tax = calculateTax(amount);
const total = amount + tax;
return {
amount: Math.round(amount),
tax: Math.round(tax),
total: Math.round(total),
avgPrice: Math.round(avgPrice),
};
};
export default {
// 积分系统
getUserAccount,
claimDailyBonus,
// 话题管理
createTopic,
getTopics,
getTopicDetail,
settleTopic,
// 交易
buyShares,
getUserPositions,
// 评论
createComment,
getComments,
likeComment,
// 观点IPO
investComment,
getCommentInvestments,
verifyComment,
// 工具函数
calculatePrice,
calculateTax,
calculateBuyCost,
MARKET_CONFIG,
};