- 升级 ECharts 到 5.4.2,重构 lib/ 目录结构 - 新增 DataTables 2.x 和 FixedColumns 插件 - 新增 quant/ 宏观研究报告模块 - 重构图表页面:stock_trend、hkholdbycode 等采用 JS fetch API.doorcome.cn 模式 - 新增 CLAUDE.md 补充页面文档和新数据流说明 - 更新 inc/config.php TuShare API 配置 - 更新新闻联播分析模块 news/ 和相关研究报告 research/ - 新增 api_document/ 参考文档 - 清理 .gitignore,排除 uploads/xls/.mcp.json/ source maps 等非代码文件 - 所有 PHP 文件通过 php -l 语法检查 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
178 lines
5.3 KiB
PHP
178 lines
5.3 KiB
PHP
<?php
|
|
include_once __DIR__ . "/config.php";
|
|
/**
|
|
* 宁波各区县List
|
|
*/
|
|
function districtList(){
|
|
?>
|
|
<select name='district' id='district'>
|
|
<option value='北仑区'>北仑区</option>
|
|
<option value='余姚市'>余姚市</option>
|
|
<option value='海曙区'>海曙区</option>
|
|
<option value='江北区'>江北区</option>
|
|
<option value='镇海区'>镇海区</option>
|
|
<option value='鄞州区'>鄞州区</option>
|
|
<option value='奉化区'>奉化区</option>
|
|
<option value='慈溪市'>慈溪市</option>
|
|
<option value='宁海县'>宁海县</option>
|
|
<option value='象山县'>象山县</option>
|
|
<option value='合计'>合计</option>
|
|
</select>
|
|
<?php
|
|
}
|
|
|
|
function indexList($id='code'): void{
|
|
?>
|
|
<select name='<?=$id?>' id='<?=$id?>'>
|
|
<option value='000001.SH'>上证指数</option>
|
|
<option value='399001.SZ'>深圳成指</option>
|
|
<option value='399005.SZ'>中小板指</option>
|
|
<option value='399006.SZ'>创业板指</option>
|
|
<option value='000016.SH'>上证50</option>
|
|
<option value='399300.SZ'>沪深300</option>
|
|
<option value='399905.SZ'>中证500</option>
|
|
<option value='899050.BJ'>北证50</option>
|
|
</select>
|
|
<?php
|
|
}
|
|
|
|
/* 证券交易所list */
|
|
function seList($id='se'): void{
|
|
?>
|
|
<select name='<?=$id?>' id='<?=$id?>'>
|
|
<option value='SSE'>上交所</option>
|
|
<option value='SZSE'>深交所</option>
|
|
<option value='BSE'>北交所</option>
|
|
</select>
|
|
<?php
|
|
}
|
|
|
|
/* select list by Day month */
|
|
function byDM($id,$oid,$nid){
|
|
$str=<<<EOF
|
|
<select name='{$id}' id='{$id}' onchange="dmChange('{$id}','{$oid}','{$nid}');">
|
|
<option value='Daily'>Daily</option>
|
|
<option value='Monthly'>Monthly</option>
|
|
</select>
|
|
EOF;
|
|
echo $str;
|
|
}
|
|
|
|
|
|
// 辅助函数:调用TuShare API
|
|
function callTushareApi($method, $params){
|
|
$token = TUSHARE_API_TOKEN;
|
|
// 将参数编码为JSON格式
|
|
$postData = json_encode([
|
|
"api_name" => $method,
|
|
"token" => $token,
|
|
"params" => $params,
|
|
"fields" => "" // 其他字段需要根据具体API调整
|
|
]);
|
|
// 初始化cURL会话
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, 'http://api.tushare.pro');
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
'Content-Type: application/json',
|
|
'Content-Length: ' . strlen($postData)
|
|
]);
|
|
|
|
// 执行cURL请求
|
|
$response = curl_exec($ch);
|
|
$err = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
// 调试输出:打印请求和响应信息
|
|
if (debug_enabled()) { // 假设这是一个函数,用于检查是否启用了调试模式
|
|
error_log("TuShare API Request: " . $postData);
|
|
error_log("TuShare API Response: " . $response);
|
|
}
|
|
|
|
// 错误处理
|
|
if ($err) {
|
|
error_log("cURL error: " . $err);
|
|
return "cURL error: " . $err;
|
|
}
|
|
|
|
|
|
|
|
$responseData = json_decode($response, true);
|
|
// 检查API调用是否成功
|
|
if (isset($responseData['code']) && $responseData['code'] != 200) {
|
|
error_log("TuShare API Error: " . $responseData['msg']);
|
|
return "TuShare API Error: " . $responseData['msg'];
|
|
}
|
|
|
|
if (isset($responseData['data']) && isset($responseData['data']['items'])) {
|
|
return $responseData['data']['items'];
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// 假设的调试模式开关函数
|
|
function debug_enabled()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 记录页面访问日志
|
|
*/
|
|
function log_pv(){
|
|
$mysqli = get_mysqli_connection();
|
|
$vpage = $_SERVER['PHP_SELF'];
|
|
$ua = $_SERVER['HTTP_USER_AGENT'];
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
$qs = $_SERVER['QUERY_STRING'];
|
|
$vtime = date("Y-m-d H:i:s");
|
|
$sql = "insert into pv_log(vpage,querystring,remoteip,ua,vtime) values (?,?,?,?,?)";
|
|
db_query($mysqli, $sql, [$vpage, $qs, $ip, $ua, $vtime]);
|
|
$mysqli->close();
|
|
}
|
|
|
|
/**
|
|
* 页面访问计数器,输出命中数
|
|
*/
|
|
function pv_counter($user=''){
|
|
$mysqli = get_mysqli_connection();
|
|
$page = $_SERVER['PHP_SELF'];
|
|
$lmtime = date("Y-m-d H:i:s");
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
|
|
$result = db_query($mysqli, "select hits from pv_counter where page_name = ?", [$page]);
|
|
$rt = $result->fetch_all(MYSQLI_ASSOC);
|
|
$n = count($rt);
|
|
|
|
if($n < 1){
|
|
db_query($mysqli,
|
|
"insert into pv_counter(page_id,Page_name,hits,lm_date,lm_ip,lm_user) values (null,?,1,?,?,?)",
|
|
[$page, $lmtime, $ip, $user]);
|
|
$hits = 1;
|
|
} elseif($n == 1){
|
|
$hits = $rt[0]['hits'] + 1;
|
|
db_query($mysqli,
|
|
"update pv_counter set hits = ?, lm_date = ?, lm_ip = ?, lm_user = ? where page_name = ?",
|
|
[$hits, $lmtime, $ip, $user, $page]);
|
|
} else {
|
|
$mysqli->close();
|
|
return "<p align='center'>There is error on pv_counter</p>";
|
|
}
|
|
|
|
$result = db_query($mysqli, "select sum(hits) hits_all from pv_counter");
|
|
$hits_all = $result->fetch_all(MYSQLI_ASSOC);
|
|
$mysqli->close();
|
|
echo "Page hits: " . $hits . " Total: " . $hits_all[0]['hits_all'];
|
|
}
|
|
|
|
/**
|
|
* 页面访问统计(日志+计数器)
|
|
*/
|
|
function page_counter(){
|
|
log_pv();
|
|
pv_counter();
|
|
}
|
|
?>
|