490 lines
14 KiB
PHP
490 lines
14 KiB
PHP
<?php
|
||
|
||
/**
|
||
* 投票API接口
|
||
* 支持POST和GET请求方式
|
||
* 提供投票列表、投票详情、提交投票、获取结果等功能
|
||
*/
|
||
|
||
// 引入必要文件
|
||
require_once 'inc/pubs.php';
|
||
require_once 'inc/sqls.php';
|
||
|
||
// 设置响应头
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
header('Access-Control-Allow-Origin: *');
|
||
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
||
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
||
|
||
// 处理OPTIONS预检请求
|
||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||
http_response_code(200);
|
||
exit;
|
||
}
|
||
|
||
// 获取请求参数(支持GET和POST)
|
||
function getRequestParams() {
|
||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||
return $_GET;
|
||
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
if (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
|
||
$json = file_get_contents('php://input');
|
||
return json_decode($json, true) ?: [];
|
||
}
|
||
return $_POST;
|
||
}
|
||
return [];
|
||
}
|
||
|
||
// 获取请求参数
|
||
$params = getRequestParams();
|
||
|
||
// 获取操作类型
|
||
$action = isset($params['act']) ? $params['act'] : '';
|
||
|
||
// 实例化数据库操作类
|
||
$db = new DB();
|
||
|
||
// 根据操作类型执行相应操作
|
||
switch ($action) {
|
||
// 获取投票列表
|
||
case 'getVoteList':
|
||
handleGetVoteList($params, $db);
|
||
break;
|
||
|
||
// 获取投票详情
|
||
case 'getVoteDetail':
|
||
handleGetVoteDetail($params, $db);
|
||
break;
|
||
|
||
// 提交投票
|
||
case 'submitVote':
|
||
handleSubmitVote($params, $db);
|
||
break;
|
||
|
||
// 获取投票结果
|
||
case 'getVoteResult':
|
||
handleGetVoteResult($params, $db);
|
||
break;
|
||
|
||
// 获取用户的投票记录
|
||
case 'getUserVotes':
|
||
handleGetUserVotes($params, $db);
|
||
break;
|
||
|
||
// 未知操作
|
||
default:
|
||
apiResponse(1, '未知操作');
|
||
break;
|
||
}
|
||
|
||
/**
|
||
* 处理获取投票列表
|
||
* @param array $params 请求参数
|
||
* @param DB $db 数据库操作对象
|
||
*/
|
||
function handleGetVoteList($params, $db) {
|
||
// 获取分页参数
|
||
$page = isset($params['page']) ? intval($params['page']) : 1;
|
||
$pageSize = isset($params['pageSize']) ? intval($params['pageSize']) : 10;
|
||
|
||
// 获取筛选参数
|
||
$status = isset($params['status']) ? intval($params['status']) : -1;
|
||
$type = isset($params['type']) ? intval($params['type']) : -1;
|
||
|
||
// 构建查询条件
|
||
$whereConditions = [];
|
||
if ($status >= 0) {
|
||
$whereConditions[] = "status = $status";
|
||
}
|
||
if ($type >= 0) {
|
||
$whereConditions[] = "itype = $type";
|
||
}
|
||
|
||
$whereStr = !empty($whereConditions) ? implode(' AND ', $whereConditions) : '';
|
||
|
||
// 获取总记录数
|
||
$total = $db->count('vote', $whereStr);
|
||
|
||
// 计算分页信息
|
||
$pagination = getPagination($total, $page, $pageSize);
|
||
|
||
// 获取投票列表
|
||
$orderBy = "addtime DESC";
|
||
$limit = "{$pagination['offset']}, {$pagination['pageSize']}";
|
||
$voteList = $db->getAll('vote', $whereStr, '*', $orderBy, $limit);
|
||
|
||
// 当前时间,用于判断投票状态
|
||
$now = date('Y-m-d H:i:s');
|
||
|
||
// 处理投票状态
|
||
foreach ($voteList as &$vote) {
|
||
$vote['status_text'] = '';
|
||
$vote['status_class'] = '';
|
||
|
||
if ($vote['status'] == 0) {
|
||
$vote['status_text'] = '已禁用';
|
||
$vote['status_class'] = 'vote-status-disabled';
|
||
} else {
|
||
if ($vote['statime'] > $now) {
|
||
$vote['status_text'] = '未开始';
|
||
$vote['status_class'] = 'vote-status-pending';
|
||
} elseif ($vote['endtime'] < $now) {
|
||
$vote['status_text'] = '已结束';
|
||
$vote['status_class'] = 'vote-status-ended';
|
||
} else {
|
||
$vote['status_text'] = '进行中';
|
||
$vote['status_class'] = 'vote-status-active';
|
||
}
|
||
}
|
||
}
|
||
|
||
apiResponse(0, '获取成功', [
|
||
'list' => $voteList,
|
||
'pagination' => $pagination
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 处理获取投票详情
|
||
* @param array $params 请求参数
|
||
* @param DB $db 数据库操作对象
|
||
*/
|
||
function handleGetVoteDetail($params, $db) {
|
||
// 获取投票ID
|
||
$voteId = isset($params['id']) ? intval($params['id']) : 0;
|
||
|
||
if (!$voteId) {
|
||
apiResponse(1, '参数错误');
|
||
}
|
||
|
||
// 获取投票信息
|
||
$vote = $db->getOne('vote', "id = $voteId");
|
||
if (!$vote) {
|
||
apiResponse(1, '投票不存在');
|
||
}
|
||
|
||
// 更新浏览次数
|
||
$db->update('vote', ['iview' => $vote['iview'] + 1], "id = $voteId");
|
||
|
||
// 获取投票选项
|
||
$options = $db->getAll('xuan', "topic_id = $voteId", '*', 'sort ASC, id ASC');
|
||
|
||
// 当前时间,用于判断投票状态
|
||
$now = date('Y-m-d H:i:s');
|
||
|
||
// 处理投票状态
|
||
$vote['status_text'] = '';
|
||
$vote['status_class'] = '';
|
||
|
||
if ($vote['status'] == 0) {
|
||
$vote['status_text'] = '已禁用';
|
||
$vote['status_class'] = 'vote-status-disabled';
|
||
} else {
|
||
if ($vote['statime'] > $now) {
|
||
$vote['status_text'] = '未开始';
|
||
$vote['status_class'] = 'vote-status-pending';
|
||
} elseif ($vote['endtime'] < $now) {
|
||
$vote['status_text'] = '已结束';
|
||
$vote['status_class'] = 'vote-status-ended';
|
||
} else {
|
||
$vote['status_text'] = '进行中';
|
||
$vote['status_class'] = 'vote-status-active';
|
||
}
|
||
}
|
||
|
||
// 检查用户是否已投票
|
||
$hasVoted = false;
|
||
$userVotes = [];
|
||
$user = checkLogin();
|
||
|
||
if ($user) {
|
||
$userVoteRecords = $db->getAll('recs', "topic_id = $voteId AND user_id = {$user['id']}");
|
||
|
||
if (!empty($userVoteRecords)) {
|
||
$hasVoted = true;
|
||
foreach ($userVoteRecords as $record) {
|
||
$userVotes[] = $record['option_id'];
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算是否可以投票
|
||
$canVote = $vote['status'] == 1 && $vote['statime'] <= $now && $vote['endtime'] >= $now && !$hasVoted && $user;
|
||
|
||
apiResponse(0, '获取成功', [
|
||
'vote' => $vote,
|
||
'options' => $options,
|
||
'hasVoted' => $hasVoted,
|
||
'userVotes' => $userVotes,
|
||
'canVote' => $canVote
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 处理提交投票
|
||
* @param array $params 请求参数
|
||
* @param DB $db 数据库操作对象
|
||
*/
|
||
function handleSubmitVote($params, $db) {
|
||
// 验证权限
|
||
$user = checkLogin();
|
||
if (!$user) {
|
||
apiResponse(1, '请先登录');
|
||
}
|
||
|
||
// 获取参数
|
||
$topicId = isset($params['topic_id']) ? intval($params['topic_id']) : 0;
|
||
$options = isset($params['options']) ? $params['options'] : [];
|
||
|
||
// 参数验证
|
||
if (empty($topicId) || empty($options)) {
|
||
apiResponse(1, '参数错误');
|
||
}
|
||
|
||
// 确保options是数组
|
||
if (!is_array($options)) {
|
||
$options = explode(',', $options);
|
||
}
|
||
|
||
if (empty($options)) {
|
||
apiResponse(1, '请至少选择一个选项');
|
||
}
|
||
|
||
// 获取投票信息
|
||
$vote = $db->getOne('vote', "id = $topicId");
|
||
if (!$vote) {
|
||
apiResponse(1, '投票不存在');
|
||
}
|
||
|
||
// 验证投票状态
|
||
$now = date('Y-m-d H:i:s');
|
||
if ($vote['status'] != 1) {
|
||
apiResponse(1, '该投票已被禁用');
|
||
}
|
||
|
||
if ($vote['statime'] > $now) {
|
||
apiResponse(1, '该投票尚未开始');
|
||
}
|
||
|
||
if ($vote['endtime'] < $now) {
|
||
apiResponse(1, '该投票已经结束');
|
||
}
|
||
|
||
// 检查用户是否已投票
|
||
$hasVoted = $db->count('recs', "topic_id = $topicId AND user_id = {$user['id']}");
|
||
if ($hasVoted > 0) {
|
||
apiResponse(1, '您已经参与过该投票');
|
||
}
|
||
|
||
// 验证选项数量
|
||
if ($vote['itype'] == 1 && count($options) > $vote['maxtime']) {
|
||
apiResponse(1, "最多只能选择 {$vote['maxtime']} 项");
|
||
}
|
||
|
||
// 验证选项是否存在
|
||
foreach ($options as $optionId) {
|
||
$option = $db->getOne('xuan', "id = $optionId AND topic_id = $topicId");
|
||
if (!$option) {
|
||
apiResponse(1, '选项不存在');
|
||
}
|
||
}
|
||
|
||
// 开始事务
|
||
$db->startTransaction();
|
||
|
||
try {
|
||
// 添加投票记录
|
||
$ip = $_SERVER['REMOTE_ADDR'];
|
||
$time = date('Y-m-d H:i:s');
|
||
|
||
foreach ($options as $optionId) {
|
||
$result = $db->insert('recs', [
|
||
'topic_id' => $topicId,
|
||
'user_id' => $user['id'],
|
||
'option_id' => $optionId,
|
||
'vote_time' => $time,
|
||
'ip' => $ip
|
||
]);
|
||
|
||
if (!$result) {
|
||
throw new Exception('提交投票失败');
|
||
}
|
||
}
|
||
|
||
// 记录日志
|
||
writeLog($user['id'], 'vote', "参与投票:{$vote['title']}");
|
||
|
||
// 提交事务
|
||
$db->commit();
|
||
|
||
apiResponse(0, '投票成功');
|
||
} catch (Exception $e) {
|
||
// 回滚事务
|
||
$db->rollback();
|
||
apiResponse(1, $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理获取投票结果
|
||
* @param array $params 请求参数
|
||
* @param DB $db 数据库操作对象
|
||
*/
|
||
function handleGetVoteResult($params, $db) {
|
||
// 获取投票ID
|
||
$voteId = isset($params['id']) ? intval($params['id']) : 0;
|
||
|
||
if (!$voteId) {
|
||
apiResponse(1, '参数错误');
|
||
}
|
||
|
||
// 获取投票信息
|
||
$vote = $db->getOne('vote', "id = $voteId");
|
||
if (!$vote) {
|
||
apiResponse(1, '投票不存在');
|
||
}
|
||
|
||
// 获取选项列表
|
||
$options = $db->getAll('xuan', "topic_id = $voteId", '*', 'sort ASC, id ASC');
|
||
if (empty($options)) {
|
||
apiResponse(1, '暂无投票选项');
|
||
}
|
||
|
||
// 获取投票结果
|
||
$sql = "SELECT option_id, COUNT(*) as vote_count FROM " . $db->table('recs') . " WHERE topic_id = $voteId GROUP BY option_id";
|
||
$result = $db->query($sql);
|
||
|
||
$voteResults = [];
|
||
$totalVotes = 0;
|
||
|
||
if ($result) {
|
||
while ($row = $result->fetch_assoc()) {
|
||
$voteResults[$row['option_id']] = $row['vote_count'];
|
||
$totalVotes += $row['vote_count'];
|
||
}
|
||
}
|
||
|
||
// 格式化结果
|
||
$formattedResults = [];
|
||
foreach ($options as $option) {
|
||
$voteCount = isset($voteResults[$option['id']]) ? $voteResults[$option['id']] : 0;
|
||
$percentage = $totalVotes > 0 ? round(($voteCount / $totalVotes) * 100, 1) : 0;
|
||
|
||
$formattedResults[] = [
|
||
'id' => $option['id'],
|
||
'name' => $option['name'],
|
||
'idesc' => $option['idesc'],
|
||
'imgs' => $option['imgs'],
|
||
'count' => $voteCount,
|
||
'percentage' => $percentage
|
||
];
|
||
}
|
||
|
||
// 用户是否已投票
|
||
$hasVoted = false;
|
||
$userVotes = [];
|
||
$user = checkLogin();
|
||
|
||
if ($user) {
|
||
$userVoteRecords = $db->getAll('recs', "topic_id = $voteId AND user_id = {$user['id']}");
|
||
|
||
if (!empty($userVoteRecords)) {
|
||
$hasVoted = true;
|
||
foreach ($userVoteRecords as $record) {
|
||
$userVotes[] = $record['option_id'];
|
||
}
|
||
}
|
||
}
|
||
|
||
apiResponse(0, '获取成功', [
|
||
'vote' => $vote,
|
||
'options' => $formattedResults,
|
||
'totalVotes' => $totalVotes,
|
||
'hasVoted' => $hasVoted,
|
||
'userVotes' => $userVotes
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 处理获取用户的投票记录
|
||
* @param array $params 请求参数
|
||
* @param DB $db 数据库操作对象
|
||
*/
|
||
function handleGetUserVotes($params, $db) {
|
||
// 验证权限
|
||
$user = checkLogin();
|
||
if (!$user) {
|
||
apiResponse(1, '请先登录');
|
||
}
|
||
|
||
// 获取分页参数
|
||
$page = isset($params['page']) ? intval($params['page']) : 1;
|
||
$pageSize = isset($params['pageSize']) ? intval($params['pageSize']) : 10;
|
||
|
||
// 查询该用户参与的投票
|
||
$sql = "SELECT DISTINCT v.* FROM " . $db->table('vote') . " v
|
||
INNER JOIN " . $db->table('recs') . " r ON v.id = r.topic_id
|
||
WHERE r.user_id = " . $user['id'] . "
|
||
ORDER BY r.vote_time DESC";
|
||
|
||
$result = $db->query($sql);
|
||
$myVotes = [];
|
||
if ($result) {
|
||
while ($row = $result->fetch_assoc()) {
|
||
$myVotes[] = $row;
|
||
}
|
||
}
|
||
|
||
// 计算分页信息
|
||
$total = count($myVotes);
|
||
$pagination = getPagination($total, $page, $pageSize);
|
||
|
||
// 按分页截取数据
|
||
$myVotesList = array_slice($myVotes, $pagination['offset'], $pagination['pageSize']);
|
||
|
||
// 当前时间,用于判断投票状态
|
||
$now = date('Y-m-d H:i:s');
|
||
|
||
// 处理投票状态
|
||
foreach ($myVotesList as &$vote) {
|
||
$vote['status_text'] = '';
|
||
$vote['status_class'] = '';
|
||
|
||
if ($vote['status'] == 0) {
|
||
$vote['status_text'] = '已禁用';
|
||
$vote['status_class'] = 'vote-status-disabled';
|
||
} else {
|
||
if ($vote['statime'] > $now) {
|
||
$vote['status_text'] = '未开始';
|
||
$vote['status_class'] = 'vote-status-pending';
|
||
} elseif ($vote['endtime'] < $now) {
|
||
$vote['status_text'] = '已结束';
|
||
$vote['status_class'] = 'vote-status-ended';
|
||
} else {
|
||
$vote['status_text'] = '进行中';
|
||
$vote['status_class'] = 'vote-status-active';
|
||
}
|
||
}
|
||
}
|
||
|
||
apiResponse(0, '获取成功', [
|
||
'list' => $myVotesList,
|
||
'pagination' => $pagination
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 统一API响应格式
|
||
* @param int $code 状态码,0表示成功,非0表示失败
|
||
* @param string $msg 提示信息
|
||
* @param array $data 返回数据
|
||
*/
|
||
function apiResponse($code = 0, $msg = '', $data = []) {
|
||
echo json_encode([
|
||
'code' => $code,
|
||
'msg' => $msg,
|
||
'data' => $data
|
||
], JSON_UNESCAPED_UNICODE);
|
||
exit;
|
||
} |