1062 lines
36 KiB
PHP
1062 lines
36 KiB
PHP
<?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, charset');
|
||
|
||
// 引入工具类
|
||
require_once 'utils/FileManager.php';
|
||
require_once 'utils/ApiBase.php';
|
||
|
||
class FundAdminAPI extends ApiBase {
|
||
private $configFile = 'data/fund_config.json';
|
||
private $operationFile = 'data/operation_log.json';
|
||
private $fundNamesFile = 'data/fund_names.json';
|
||
private $recommendedFundsFile = 'data/recommended_funds.json';
|
||
|
||
public function __construct() {
|
||
// 确保数据目录存在
|
||
FileManager::ensureDirExists('data');
|
||
|
||
// 初始化配置文件(如果不存在)
|
||
if (!FileManager::fileExists($this->configFile)) {
|
||
$this->initConfig();
|
||
}
|
||
|
||
// 初始化操作日志文件(如果不存在)
|
||
if (!FileManager::fileExists($this->operationFile)) {
|
||
$this->initOperationLog();
|
||
}
|
||
|
||
// 初始化基金名称文件(如果不存在)
|
||
if (!FileManager::fileExists($this->fundNamesFile)) {
|
||
$this->initFundNames();
|
||
}
|
||
|
||
// 初始化推荐基金文件(如果不存在)
|
||
if (!FileManager::fileExists($this->recommendedFundsFile)) {
|
||
$this->initRecommendedFunds();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 初始化配置文件
|
||
*/
|
||
private function initConfig() {
|
||
$defaultConfig = [
|
||
[
|
||
"channel" => "0",
|
||
"fund_code" => "003766",
|
||
"investment" => 1000,
|
||
"name" => "汇添富医疗服务混合"
|
||
],
|
||
[
|
||
"channel" => "0",
|
||
"fund_code" => "004206",
|
||
"investment" => 1000,
|
||
"name" => "基金004206"
|
||
],
|
||
[
|
||
"channel" => "0",
|
||
"fund_code" => "019432",
|
||
"investment" => 1000,
|
||
"name" => "基金019432"
|
||
],
|
||
[
|
||
"channel" => "1",
|
||
"fund_code" => "003766",
|
||
"investment" => 1000,
|
||
"name" => "汇添富医疗服务混合"
|
||
],
|
||
[
|
||
"channel" => "1",
|
||
"fund_code" => "008327",
|
||
"investment" => 1000,
|
||
"name" => "基金008327"
|
||
],
|
||
[
|
||
"channel" => "2",
|
||
"fund_code" => "017811",
|
||
"investment" => 1000,
|
||
"name" => "基金017811"
|
||
]
|
||
];
|
||
|
||
FileManager::saveJsonFile($this->configFile, $defaultConfig);
|
||
}
|
||
|
||
/**
|
||
* 初始化操作日志
|
||
*/
|
||
private function initOperationLog() {
|
||
$initialLog = [
|
||
'operations' => []
|
||
];
|
||
|
||
FileManager::saveJsonFile($this->operationFile, $initialLog);
|
||
}
|
||
|
||
/**
|
||
* 初始化推荐基金文件
|
||
*/
|
||
private function initRecommendedFunds() {
|
||
$initialData = [];
|
||
FileManager::saveJsonFile($this->recommendedFundsFile, $initialData);
|
||
}
|
||
|
||
/**
|
||
* 初始化基金名称文件
|
||
*/
|
||
private function initFundNames() {
|
||
// 从配置中提取已有的基金名称作为初始数据
|
||
$defaultFundNames = [];
|
||
$config = $this->loadConfig();
|
||
|
||
foreach ($config as $fund) {
|
||
if (isset($fund['fund_code']) && isset($fund['name']) && $fund['name'] !== "基金{$fund['fund_code']}") {
|
||
$defaultFundNames[$fund['fund_code']] = $fund['name'];
|
||
}
|
||
}
|
||
|
||
// 添加一些常用基金名称
|
||
$commonFunds = [
|
||
'003766' => '汇添富医疗服务混合',
|
||
'110022' => '易方达消费行业股票',
|
||
'001714' => '工银文体产业股票',
|
||
'000241' => '中欧时代先锋股票',
|
||
'001475' => '易方达国防军工混合',
|
||
'161725' => '招商中证白酒指数',
|
||
'000689' => '前海开源新经济混合',
|
||
'001102' => '前海开源国家比较优势混合',
|
||
'001593' => '天弘创业板ETF联接',
|
||
'000971' => '高升沪深300指数增强'
|
||
];
|
||
|
||
// 合并默认基金名称
|
||
$fundNames = array_merge($defaultFundNames, $commonFunds);
|
||
|
||
FileManager::saveJsonFile($this->fundNamesFile, $fundNames);
|
||
}
|
||
|
||
/**
|
||
* 加载基金名称映射
|
||
*/
|
||
private function loadFundNames() {
|
||
if (!FileManager::fileExists($this->fundNamesFile)) {
|
||
$this->initFundNames();
|
||
}
|
||
|
||
return FileManager::loadJsonFile($this->fundNamesFile, []);
|
||
}
|
||
|
||
/**
|
||
* 保存基金名称映射
|
||
*/
|
||
private function saveFundNames($fundNames) {
|
||
$result = FileManager::saveJsonFile($this->fundNamesFile, $fundNames);
|
||
|
||
if ($result === false) {
|
||
error_log('无法写入基金名称文件,请检查目录权限');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 记录操作日志
|
||
*/
|
||
private function logOperation($type, $fundCode, $channel = null, $investment = null, $details = '') {
|
||
$log = $this->loadOperationLog();
|
||
|
||
$operation = [
|
||
'id' => uniqid(),
|
||
'type' => $type, // 'add', 'update', 'delete'
|
||
'fund_code' => $fundCode,
|
||
'channel' => $channel,
|
||
'investment' => $investment,
|
||
'details' => $details,
|
||
'timestamp' => time(),
|
||
'date' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$log['operations'][] = $operation;
|
||
|
||
// 只保留最近100条操作记录
|
||
if (count($log['operations']) > 100) {
|
||
$log['operations'] = array_slice($log['operations'], -100);
|
||
}
|
||
// 记录操作日志
|
||
FileManager::saveJsonFile($this->operationFile, $log);
|
||
|
||
return $operation;
|
||
}
|
||
|
||
/**
|
||
* 加载操作日志
|
||
*/
|
||
private function loadOperationLog() {
|
||
return FileManager::loadJsonFile($this->operationFile, ['operations' => []], [$this, 'initOperationLog']);
|
||
}
|
||
|
||
/**
|
||
* 获取基金名称(优先从文件读取,不存在时从API获取并保存)
|
||
*/
|
||
public function getFundName($fundCode) {
|
||
try {
|
||
// 优先从文件中查找
|
||
$fundNames = $this->loadFundNames();
|
||
if (isset($fundNames[$fundCode])) {
|
||
return [
|
||
'success' => true,
|
||
'name' => $fundNames[$fundCode]
|
||
];
|
||
} else {
|
||
// 文件中没有,尝试从API获取
|
||
$fundName = $this->fetchFundNameFromAPI($fundCode);
|
||
if ($fundName) {
|
||
// 将新获取的基金名称保存到文件中
|
||
$fundNames[$fundCode] = $fundName;
|
||
$this->saveFundNames($fundNames);
|
||
|
||
return [
|
||
'success' => true,
|
||
'name' => $fundName
|
||
];
|
||
} else {
|
||
// 如果API也获取失败,尝试从本地数据查找
|
||
$config = $this->loadConfig();
|
||
$fund = array_filter($config, function($item) use ($fundCode) {
|
||
return $item['fund_code'] == $fundCode;
|
||
});
|
||
|
||
$fund = reset($fund);
|
||
if ($fund && isset($fund['name'])) {
|
||
// 保存到文件中供以后使用
|
||
$fundNames[$fundCode] = $fund['name'];
|
||
$this->saveFundNames($fundNames);
|
||
|
||
return [
|
||
'success' => true,
|
||
'name' => $fund['name']
|
||
];
|
||
} else {
|
||
// 如果都没有,返回默认名称
|
||
return [
|
||
'success' => true,
|
||
'name' => "基金$fundCode"
|
||
];
|
||
}
|
||
}
|
||
}
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '获取基金名称失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取操作日志
|
||
*/
|
||
public function getOperationLog($limit = 20) {
|
||
try {
|
||
$log = $this->loadOperationLog();
|
||
$operations = $log['operations'];
|
||
|
||
// 按时间倒序排列
|
||
usort($operations, function($a, $b) {
|
||
return $b['timestamp'] - $a['timestamp'];
|
||
});
|
||
|
||
// 限制返回数量
|
||
$operations = array_slice($operations, 0, $limit);
|
||
|
||
return [
|
||
'success' => true,
|
||
'data' => $operations
|
||
];
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '获取操作日志失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载基金配置
|
||
*/
|
||
private function loadConfig() {
|
||
return FileManager::loadJsonFile($this->configFile, [], [$this, 'initConfig']);
|
||
}
|
||
|
||
/**
|
||
* 保存基金配置
|
||
*/
|
||
private function saveConfig($config) {
|
||
$result = FileManager::saveJsonFile($this->configFile, $config);
|
||
|
||
if ($result === false) {
|
||
throw new Exception('无法写入配置文件,请检查目录权限');
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 获取所有基金配置
|
||
*/
|
||
public function getFunds() {
|
||
try {
|
||
$config = $this->loadConfig();
|
||
|
||
return [
|
||
'success' => true,
|
||
'data' => $config
|
||
];
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '获取基金配置失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 添加基金
|
||
*/
|
||
public function addFund($fundData) {
|
||
try {
|
||
// 调试:记录接收到的数据
|
||
error_log("addFund received: " . print_r($fundData, true));
|
||
|
||
$config = $this->loadConfig();
|
||
|
||
// 验证数据
|
||
if (!isset($fundData['fund_code']) || trim($fundData['fund_code']) === '') {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金代码不能为空'
|
||
];
|
||
}
|
||
|
||
if (!isset($fundData['channel']) || trim($fundData['channel']) === '') {
|
||
return [
|
||
'success' => false,
|
||
'message' => '渠道不能为空'
|
||
];
|
||
}
|
||
|
||
$fundCode = trim($fundData['fund_code']);
|
||
$channel = trim($fundData['channel']);
|
||
|
||
// 验证基金代码格式
|
||
if (!preg_match('/^\d{6}$/', $fundCode)) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金代码必须是6位数字'
|
||
];
|
||
}
|
||
|
||
// 检查是否已存在
|
||
foreach ($config as $item) {
|
||
if ($item['fund_code'] === $fundCode && $item['channel'] === $channel) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '该渠道下已存在相同的基金代码'
|
||
];
|
||
}
|
||
}
|
||
|
||
// 添加新基金
|
||
// 获取基金名称
|
||
$fundName = "基金{$fundCode}";
|
||
$fundNames = [
|
||
'003766' => '汇添富医疗服务混合',
|
||
'110022' => '易方达消费行业股票'
|
||
];
|
||
if (isset($fundNames[$fundCode])) {
|
||
$fundName = $fundNames[$fundCode];
|
||
}
|
||
|
||
$newFund = [
|
||
'channel' => $channel,
|
||
'fund_code' => $fundCode,
|
||
'investment' => isset($fundData['investment']) ? floatval($fundData['investment']) : 1000,
|
||
'name' => $fundName
|
||
];
|
||
|
||
$config[] = $newFund;
|
||
|
||
if ($this->saveConfig($config)) {
|
||
// 记录操作日志
|
||
$this->logOperation('add', $fundCode, $channel, $newFund['investment'], '添加基金');
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => '基金添加成功'
|
||
];
|
||
} else {
|
||
return [
|
||
'success' => false,
|
||
'message' => '保存配置失败'
|
||
];
|
||
}
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '添加基金失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新基金
|
||
*/
|
||
public function updateFund($fundData) {
|
||
try {
|
||
// 调试:记录接收到的数据
|
||
error_log("updateFund received: " . print_r($fundData, true));
|
||
|
||
$config = $this->loadConfig();
|
||
$index = isset($fundData['index']) ? intval($fundData['index']) : -1;
|
||
|
||
// 验证索引
|
||
if ($index < 0 || !isset($config[$index])) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金不存在'
|
||
];
|
||
}
|
||
|
||
// 验证数据
|
||
if (!isset($fundData['fund_code']) || trim($fundData['fund_code']) === '') {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金代码不能为空'
|
||
];
|
||
}
|
||
|
||
if (!isset($fundData['channel']) || trim($fundData['channel']) === '') {
|
||
return [
|
||
'success' => false,
|
||
'message' => '渠道不能为空'
|
||
];
|
||
}
|
||
|
||
$fundCode = trim($fundData['fund_code']);
|
||
$channel = trim($fundData['channel']);
|
||
|
||
// 获取旧数据用于日志
|
||
$oldFund = $config[$index];
|
||
|
||
// 检查重复(排除自身)
|
||
foreach ($config as $i => $item) {
|
||
if ($i !== $index && $item['fund_code'] === $fundCode && $item['channel'] === $channel) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '该渠道下已存在相同的基金代码'
|
||
];
|
||
}
|
||
}
|
||
|
||
// 更新基金信息
|
||
$config[$index] = [
|
||
'channel' => $channel,
|
||
'fund_code' => $fundCode,
|
||
'investment' => isset($fundData['investment']) ? floatval($fundData['investment']) : 1000,
|
||
'name' => $oldFund['name'] ?? "基金{$fundCode}"
|
||
];
|
||
|
||
if ($this->saveConfig($config)) {
|
||
// 记录操作日志
|
||
$details = sprintf('更新基金: 投资金额 %s -> %s',
|
||
$oldFund['investment'],
|
||
$config[$index]['investment']
|
||
);
|
||
$this->logOperation('update', $fundCode, $channel, $config[$index]['investment'], $details);
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => '基金更新成功'
|
||
];
|
||
} else {
|
||
return [
|
||
'success' => false,
|
||
'message' => '保存配置失败'
|
||
];
|
||
}
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '更新基金失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除基金
|
||
*/
|
||
public function deleteFund($index) {
|
||
try {
|
||
$config = $this->loadConfig();
|
||
$index = intval($index);
|
||
|
||
// 验证索引
|
||
if (!isset($config[$index])) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金不存在'
|
||
];
|
||
}
|
||
|
||
// 获取要删除的基金信息用于日志
|
||
$deletedFund = $config[$index];
|
||
|
||
// 删除基金
|
||
array_splice($config, $index, 1);
|
||
|
||
if ($this->saveConfig($config)) {
|
||
// 记录操作日志
|
||
$this->logOperation('delete', $deletedFund['fund_code'], $deletedFund['channel'], $deletedFund['investment'], '删除基金');
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => '基金删除成功'
|
||
];
|
||
} else {
|
||
return [
|
||
'success' => false,
|
||
'message' => '保存配置失败'
|
||
];
|
||
}
|
||
} catch (Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '删除基金失败: ' . $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取基金名称列表(优先从文件读取,不存在时从API获取并保存)
|
||
*/
|
||
public function getFundNames() {
|
||
$fundCodes = $_GET['fund_codes'] ?? '';
|
||
|
||
if (empty($fundCodes)) {
|
||
return [
|
||
'success' => false,
|
||
'message' => '基金代码不能为空'
|
||
];
|
||
}
|
||
|
||
$codes = explode(',', $fundCodes);
|
||
$results = [];
|
||
$fundNames = $this->loadFundNames();
|
||
|
||
foreach ($codes as $code) {
|
||
$code = trim($code);
|
||
if (!empty($code)) {
|
||
// 先从文件中查找
|
||
if (isset($fundNames[$code])) {
|
||
$results[$code] = $fundNames[$code];
|
||
} else {
|
||
// 文件中没有,则从API获取
|
||
$fundName = $this->fetchFundNameFromAPI($code);
|
||
if ($fundName) {
|
||
$results[$code] = $fundName;
|
||
// 将新获取的基金名称保存到文件中
|
||
$fundNames[$code] = $fundName;
|
||
$this->saveFundNames($fundNames);
|
||
} else {
|
||
// 如果API也获取失败,使用默认名称
|
||
$results[$code] = "基金$code";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return [
|
||
'success' => true,
|
||
'data' => $results,
|
||
'message' => '获取基金名称成功'
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 获取推荐基金列表
|
||
*/
|
||
private function getRecommendedFunds() {
|
||
try {
|
||
$recommendedFunds = FileManager::loadJsonFile($this->recommendedFundsFile, []);
|
||
|
||
// 按时间倒序排序
|
||
usort($recommendedFunds, function($a, $b) {
|
||
return strtotime($b['timestamp']) - strtotime($a['timestamp']);
|
||
});
|
||
|
||
echo json_encode(['success' => true, 'data' => $recommendedFunds], JSON_UNESCAPED_UNICODE);
|
||
} catch (Exception $e) {
|
||
echo json_encode(['success' => false, 'message' => '获取推荐基金失败: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批准推荐基金
|
||
*/
|
||
private function approveRecommendedFund() {
|
||
try {
|
||
$fundCode = isset($_GET['fund_code']) ? $_GET['fund_code'] : '';
|
||
|
||
if (empty($fundCode)) {
|
||
echo json_encode(['success' => false, 'message' => '基金代码不能为空'], JSON_UNESCAPED_UNICODE);
|
||
return;
|
||
}
|
||
|
||
// 加载推荐基金数据
|
||
$recommendedFunds = FileManager::loadJsonFile($this->recommendedFundsFile, []);
|
||
|
||
// 查找并更新基金状态
|
||
$found = false;
|
||
foreach ($recommendedFunds as &$fund) {
|
||
if ($fund['fund_code'] == $fundCode) {
|
||
$fund['status'] = 'approved';
|
||
$found = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$found) {
|
||
echo json_encode(['success' => false, 'message' => '未找到该推荐基金'], JSON_UNESCAPED_UNICODE);
|
||
return;
|
||
}
|
||
|
||
// 保存更新后的数据
|
||
FileManager::saveJsonFile($this->recommendedFundsFile, $recommendedFunds);
|
||
|
||
// 添加到基金配置中
|
||
$config = $this->loadConfig();
|
||
$fundExists = false;
|
||
foreach ($config as $existingFund) {
|
||
if ($existingFund['fund_code'] == $fundCode && $existingFund['channel'] == '0') {
|
||
$fundExists = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$fundExists) {
|
||
$newFund = [
|
||
'channel' => '2', // 2表示支付宝渠道
|
||
'fund_code' => $fundCode,
|
||
'investment' => 1000,
|
||
'name' => '基金' . $fundCode
|
||
];
|
||
$config[] = $newFund;
|
||
$this->saveConfig($config);
|
||
}
|
||
|
||
// 记录操作日志
|
||
$this->logOperation('approve_recommended_fund', ['fund_code' => $fundCode]);
|
||
|
||
echo json_encode(['success' => true, 'message' => '基金批准成功'], JSON_UNESCAPED_UNICODE);
|
||
} catch (Exception $e) {
|
||
echo json_encode(['success' => false, 'message' => '批准基金失败: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除推荐基金
|
||
*/
|
||
private function deleteRecommendedFund() {
|
||
try {
|
||
$fundCode = isset($_GET['fund_code']) ? $_GET['fund_code'] : '';
|
||
|
||
if (empty($fundCode)) {
|
||
echo json_encode(['success' => false, 'message' => '基金代码不能为空'], JSON_UNESCAPED_UNICODE);
|
||
return;
|
||
}
|
||
|
||
// 加载推荐基金数据
|
||
$recommendedFunds = FileManager::loadJsonFile($this->recommendedFundsFile, []);
|
||
|
||
// 过滤掉要删除的基金
|
||
$filteredFunds = array_filter($recommendedFunds, function($fund) use ($fundCode) {
|
||
return $fund['fund_code'] != $fundCode;
|
||
});
|
||
|
||
// 保存过滤后的数据
|
||
FileManager::saveJsonFile($this->recommendedFundsFile, array_values($filteredFunds));
|
||
|
||
// 记录操作日志
|
||
$this->logOperation('delete_recommended_fund', ['fund_code' => $fundCode]);
|
||
|
||
echo json_encode(['success' => true, 'message' => '基金删除成功'], JSON_UNESCAPED_UNICODE);
|
||
} catch (Exception $e) {
|
||
echo json_encode(['success' => false, 'message' => '删除基金失败: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 从API获取基金名称(只在文件中不存在时调用)
|
||
*/
|
||
private function fetchFundNameFromAPI($fundCode) {
|
||
// 尝试多个API源
|
||
$apiSources = [
|
||
"https://fundgz.1234567.com.cn/js/{$fundCode}.js?rt=" . time(),
|
||
"https://api.doctorxiong.club/v1/fund/detail?code={$fundCode}"
|
||
];
|
||
|
||
foreach ($apiSources as $apiUrl) {
|
||
try {
|
||
// 设置超时时间
|
||
$context = stream_context_create([
|
||
'http' => [
|
||
'timeout' => 5,
|
||
'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
||
]
|
||
]);
|
||
|
||
$response = FileManager::loadFile($apiUrl);
|
||
|
||
if ($response) {
|
||
// 处理不同API的响应格式
|
||
if (strpos($apiUrl, 'fundgz.1234567.com.cn') !== false) {
|
||
// 处理JSONP格式
|
||
if (preg_match('/jsonpgz\((.*)\)/', $response, $matches)) {
|
||
$data = json_decode($matches[1], true);
|
||
if (isset($data['name']) && !empty($data['name'])) {
|
||
return $data['name'];
|
||
}
|
||
}
|
||
} else if (strpos($apiUrl, 'doctorxiong.club') !== false) {
|
||
// 处理JSON格式
|
||
$data = json_decode($response, true);
|
||
if (isset($data['data']['name']) && !empty($data['data']['name'])) {
|
||
return $data['data']['name'];
|
||
}
|
||
}
|
||
}
|
||
} catch (Exception $e) {
|
||
// 记录错误但继续尝试下一个API源
|
||
error_log("获取基金{$fundCode}名称失败: " . $e->getMessage());
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 所有API都失败,返回false
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 处理API请求
|
||
*/
|
||
public function handleRequest() {
|
||
// 处理OPTIONS请求
|
||
$this->handleOptionsRequest();
|
||
|
||
// 解析请求参数
|
||
$request = $this->parseRequest();
|
||
$method = $request['method'];
|
||
$action = $request['action'];
|
||
$params = $request['params'];
|
||
|
||
if ($method === 'GET') {
|
||
switch ($action) {
|
||
case 'get_funds':
|
||
$result = $this->getFunds();
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
|
||
case 'get_operation_log':
|
||
$limit = isset($params['limit']) ? intval($params['limit']) : 20;
|
||
$result = $this->getOperationLog($limit);
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
|
||
case 'get_fund_name':
|
||
$fundCode = $params['fund_code'] ?? '';
|
||
if ($fundCode) {
|
||
$result = $this->getFundName($fundCode);
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
} else {
|
||
echo json_encode(['success' => false, 'message' => '基金代码不能为空']);
|
||
}
|
||
break;
|
||
|
||
case 'get_fund_names':
|
||
$result = $this->getFundNames();
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
case 'get_recommended_funds':
|
||
$this->getRecommendedFunds();
|
||
break;
|
||
case 'approve_recommended_fund':
|
||
$this->approveRecommendedFund();
|
||
break;
|
||
case 'delete_recommended_fund':
|
||
$this->deleteRecommendedFund();
|
||
break;
|
||
case 'get_email_config':
|
||
$this->getEmailConfig();
|
||
break;
|
||
|
||
default:
|
||
http_response_code(404);
|
||
echo json_encode(['success' => false, 'message' => 'Endpoint not found']);
|
||
}
|
||
} elseif ($method === 'POST') {
|
||
// 如果之前没有成功解析POST数据,则再次尝试
|
||
if (!isset($postData) || json_last_error() !== JSON_ERROR_NONE) {
|
||
// 获取POST数据
|
||
$input = file_get_contents('php://input');
|
||
$postData = json_decode($input, true);
|
||
|
||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||
http_response_code(400);
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '无效的JSON数据: ' . json_last_error_msg(),
|
||
'debug_input' => $input
|
||
]);
|
||
return;
|
||
}
|
||
}
|
||
|
||
switch ($action) {
|
||
case 'add_fund':
|
||
$result = $this->addFund($postData);
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
|
||
case 'update_fund':
|
||
$result = $this->updateFund($postData);
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
|
||
case 'delete_fund':
|
||
$result = $this->deleteFund($postData['index']);
|
||
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
||
break;
|
||
case 'update_email_config':
|
||
$this->updateEmailConfig($postData);
|
||
break;
|
||
case 'add_email_recipient':
|
||
$this->addEmailRecipient($postData);
|
||
break;
|
||
case 'delete_email_recipient':
|
||
$this->deleteEmailRecipient($postData);
|
||
break;
|
||
|
||
default:
|
||
http_response_code(404);
|
||
echo json_encode(['success' => false, 'message' => 'Endpoint not found']);
|
||
}
|
||
} else {
|
||
http_response_code(405);
|
||
echo json_encode(['success' => false, 'message' => 'Method not allowed']);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取邮箱配置
|
||
*/
|
||
private function getEmailConfig() {
|
||
$emailConfigFile = 'data/email_config.json';
|
||
|
||
$emailConfig = FileManager::loadJsonFile($emailConfigFile, null);
|
||
if ($emailConfig !== null) {
|
||
echo json_encode([
|
||
'success' => true,
|
||
'data' => $emailConfig
|
||
]);
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱配置文件不存在'
|
||
]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新邮箱配置
|
||
*/
|
||
private function updateEmailConfig($postData) {
|
||
$emailConfigFile = 'data/email_config.json';
|
||
|
||
// 验证必要参数
|
||
$requiredParams = ['smtp_server', 'smtp_port', 'smtp_secure', 'username', 'password', 'from_email', 'from_name'];
|
||
foreach ($requiredParams as $param) {
|
||
if (!isset($postData[$param]) || empty(trim($postData[$param]))) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => "参数 {$param} 不能为空"
|
||
]);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 构建新的配置
|
||
$newConfig = [
|
||
'smtp_server' => trim($postData['smtp_server']),
|
||
'smtp_port' => intval($postData['smtp_port']),
|
||
'smtp_secure' => trim($postData['smtp_secure']),
|
||
'username' => trim($postData['username']),
|
||
'password' => trim($postData['password']),
|
||
'from_email' => trim($postData['from_email']),
|
||
'from_name' => trim($postData['from_name']),
|
||
'to_emails' => isset($postData['to_emails']) && is_array($postData['to_emails']) ? $postData['to_emails'] : []
|
||
];
|
||
|
||
// 保存配置
|
||
if (FileManager::saveJsonFile($emailConfigFile, $newConfig)) {
|
||
// 记录操作日志
|
||
$this->logOperation('更新邮箱配置', ['smtp_server' => $newConfig['smtp_server'], 'username' => $newConfig['username']]);
|
||
|
||
echo json_encode([
|
||
'success' => true,
|
||
'message' => '邮箱配置更新成功'
|
||
]);
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱配置更新失败'
|
||
]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 添加邮箱收件人
|
||
*/
|
||
private function addEmailRecipient($postData) {
|
||
$emailConfigFile = 'data/email_config.json';
|
||
|
||
if (!isset($postData['email']) || empty(trim($postData['email']))) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱地址不能为空'
|
||
]);
|
||
return;
|
||
}
|
||
|
||
$newEmail = trim($postData['email']);
|
||
|
||
// 验证邮箱格式
|
||
if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱地址格式无效'
|
||
]);
|
||
return;
|
||
}
|
||
|
||
$emailConfig = FileManager::loadJsonFile($emailConfigFile, null);
|
||
if ($emailConfig !== null) {
|
||
// 检查邮箱是否已经存在
|
||
if (in_array($newEmail, $emailConfig['to_emails'])) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱地址已经存在'
|
||
]);
|
||
return;
|
||
}
|
||
|
||
// 添加新邮箱
|
||
$emailConfig['to_emails'][] = $newEmail;
|
||
|
||
// 保存配置
|
||
if (FileManager::saveJsonFile($emailConfigFile, $emailConfig)) {
|
||
// 记录操作日志
|
||
$this->logOperation('添加邮箱收件人', ['email' => $newEmail]);
|
||
|
||
echo json_encode([
|
||
'success' => true,
|
||
'message' => '邮箱收件人添加成功',
|
||
'data' => $emailConfig['to_emails']
|
||
]);
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱收件人添加失败'
|
||
]);
|
||
}
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱配置文件不存在'
|
||
]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除邮箱收件人
|
||
*/
|
||
private function deleteEmailRecipient($postData) {
|
||
$emailConfigFile = 'data/email_config.json';
|
||
|
||
if (!isset($postData['email']) || empty(trim($postData['email']))) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱地址不能为空'
|
||
]);
|
||
return;
|
||
}
|
||
|
||
$deleteEmail = trim($postData['email']);
|
||
|
||
$emailConfig = FileManager::loadJsonFile($emailConfigFile, null);
|
||
if ($emailConfig !== null) {
|
||
// 查找邮箱在数组中的位置
|
||
$index = array_search($deleteEmail, $emailConfig['to_emails']);
|
||
if ($index === false) {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '未找到该邮箱地址'
|
||
]);
|
||
return;
|
||
}
|
||
|
||
// 删除邮箱
|
||
unset($emailConfig['to_emails'][$index]);
|
||
// 重新索引数组
|
||
$emailConfig['to_emails'] = array_values($emailConfig['to_emails']);
|
||
|
||
// 保存配置
|
||
if (FileManager::saveJsonFile($emailConfigFile, $emailConfig)) {
|
||
// 记录操作日志
|
||
$this->logOperation('删除邮箱收件人', ['email' => $deleteEmail]);
|
||
|
||
echo json_encode([
|
||
'success' => true,
|
||
'message' => '邮箱收件人删除成功',
|
||
'data' => $emailConfig['to_emails']
|
||
]);
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱收件人删除失败'
|
||
]);
|
||
}
|
||
} else {
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '邮箱配置文件不存在'
|
||
]);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 错误处理
|
||
try {
|
||
$api = new FundAdminAPI();
|
||
$api->handleRequest();
|
||
} catch (Exception $e) {
|
||
http_response_code(500);
|
||
echo json_encode([
|
||
'success' => false,
|
||
'message' => '服务器内部错误: ' . $e->getMessage()
|
||
]);
|
||
}
|
||
?>
|