| {% extends "layout.html" %}
|
|
|
| {% block title %}资金流向 - 智能分析系统{% endblock %}
|
|
|
| {% block content %}
|
| <div class="container-fluid py-3">
|
| <div id="alerts-container"></div>
|
|
|
| <div class="row mb-3">
|
| <div class="col-12">
|
| <div class="card">
|
| <div class="card-header py-2">
|
| <h5 class="mb-0">资金流向分析</h5>
|
| </div>
|
| <div class="card-body py-2">
|
| <form id="capital-flow-form" class="row g-2">
|
| <div class="col-md-3">
|
| <div class="input-group input-group-sm">
|
| <span class="input-group-text">数据类型</span>
|
| <select class="form-select" id="data-type">
|
| <option value="concept" selected>概念资金流</option>
|
| <option value="individual" >个股资金流</option>
|
| </select>
|
| </div>
|
| </div>
|
| <div class="col-md-3">
|
| <div class="input-group input-group-sm">
|
| <span class="input-group-text">周期</span>
|
| <select class="form-select" id="period-select">
|
| <option value="10日排行" selected>10日排行</option>
|
| <option value="5日排行">5日排行</option>
|
| <option value="3日排行">3日排行</option>
|
| </select>
|
| </div>
|
| </div>
|
| <div class="col-md-4 stock-input" style="display: none;">
|
| <div class="input-group input-group-sm">
|
| <span class="input-group-text">股票代码</span>
|
| <input type="text" class="form-control" id="stock-code" placeholder="例如: 600519">
|
| </div>
|
| </div>
|
| <div class="col-md-2">
|
| <button type="submit" class="btn btn-primary btn-sm w-100">
|
| <i class="fas fa-search"></i> 查询
|
| </button>
|
| </div>
|
| </form>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="loading-panel" class="text-center py-5" style="display: none;">
|
| <div class="spinner-border text-primary" role="status">
|
| <span class="visually-hidden">Loading...</span>
|
| </div>
|
| <p class="mt-3 mb-0">正在获取资金流向数据...</p>
|
| </div>
|
|
|
|
|
| <div id="concept-flow-panel" class="row g-3 mb-3" style="display: none;">
|
| <div class="col-12">
|
| <div class="card">
|
| <div class="card-header py-2 d-flex justify-content-between align-items-center">
|
| <h5 class="mb-0">概念资金流向</h5>
|
| <span id="concept-period-badge" class="badge bg-primary">10日排行</span>
|
| </div>
|
| <div class="card-body">
|
| <div class="table-responsive">
|
| <table class="table table-sm table-striped table-hover">
|
| <thead>
|
| <tr>
|
| <th>序号</th>
|
| <th>概念/行业</th>
|
| <th>行业指数</th>
|
| <th>涨跌幅</th>
|
| <th>流入资金(亿)</th>
|
| <th>流出资金(亿)</th>
|
| <th>净额(亿)</th>
|
| <th>公司家数</th>
|
| <th>操作</th>
|
| </tr>
|
| </thead>
|
| <tbody id="concept-flow-table">
|
|
|
| </tbody>
|
| </table>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="concept-stocks-panel" class="row g-3 mb-3" style="display: none;">
|
| <div class="col-12">
|
| <div class="card">
|
| <div class="card-header py-2">
|
| <h5 id="concept-stocks-title" class="mb-0">概念成分股</h5>
|
| </div>
|
| <div class="card-body">
|
| <div class="table-responsive">
|
| <table class="table table-sm table-striped table-hover">
|
| <thead>
|
| <tr>
|
| <th>代码</th>
|
| <th>名称</th>
|
| <th>最新价</th>
|
| <th>涨跌幅</th>
|
| <th>主力净流入</th>
|
| <th>主力净流入占比</th>
|
| <th>操作</th>
|
| </tr>
|
| </thead>
|
| <tbody id="concept-stocks-table">
|
|
|
| </tbody>
|
| </table>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="individual-flow-panel" class="row g-3 mb-3" style="display: none;">
|
| <div class="col-12">
|
| <div class="card">
|
| <div class="card-header py-2 d-flex justify-content-between align-items-center">
|
| <h5 id="individual-flow-title" class="mb-0">个股资金流向</h5>
|
| <span id="individual-period-badge" class="badge bg-primary">10日排行</span>
|
| </div>
|
| <div class="card-body">
|
| <div class="row">
|
| <div class="col-md-6">
|
| <h6>资金流向概览</h6>
|
| <table class="table table-sm">
|
| <tbody id="individual-flow-summary">
|
|
|
| </tbody>
|
| </table>
|
| </div>
|
| <div class="col-md-6">
|
| <h6>资金流入占比</h6>
|
| <div id="fund-flow-pie-chart" style="height: 200px;"></div>
|
| </div>
|
| </div>
|
| <div class="row mt-3">
|
| <div class="col-12">
|
| <h6>资金流向历史</h6>
|
| <div id="fund-flow-history-chart" style="height: 300px;"></div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="individual-rank-panel" class="row g-3 mb-3" style="display: none;">
|
| <div class="col-12">
|
| <div class="card">
|
| <div class="card-header py-2 d-flex justify-content-between align-items-center">
|
| <h5 class="mb-0">个股资金流向排名</h5>
|
| <span id="individual-rank-period-badge" class="badge bg-primary">10日排行</span>
|
| </div>
|
| <div class="card-body">
|
| <div class="table-responsive">
|
| <table class="table table-sm table-striped table-hover">
|
| <thead>
|
| <tr>
|
| <th>序号</th>
|
| <th>代码</th>
|
| <th>名称</th>
|
| <th>最新价</th>
|
| <th>涨跌幅</th>
|
| <th>主力净流入</th>
|
| <th>主力净流入占比</th>
|
| <th>超大单净流入</th>
|
| <th>大单净流入</th>
|
| <th>中单净流入</th>
|
| <th>小单净流入</th>
|
| <th>操作</th>
|
| </tr>
|
| </thead>
|
| <tbody id="individual-rank-table">
|
|
|
| </tbody>
|
| </table>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| {% endblock %}
|
|
|
| {% block scripts %}
|
| <script>
|
| $(document).ready(function() {
|
|
|
| loadConceptFundFlow('90日排行');
|
|
|
|
|
| $('#capital-flow-form').submit(function(e) {
|
| e.preventDefault();
|
| const dataType = $('#data-type').val();
|
| const period = $('#period-select').val();
|
| const stockCode = $('#stock-code').val().trim();
|
|
|
| if (dataType === 'concept') {
|
| loadConceptFundFlow(period);
|
| } else if (dataType === 'individual') {
|
| if (stockCode) {
|
| loadIndividualFundFlow(stockCode);
|
| } else {
|
| loadIndividualFundFlowRank(period);
|
| }
|
| }
|
| });
|
|
|
|
|
| $('#data-type').change(function() {
|
| const dataType = $(this).val();
|
| if (dataType === 'individual') {
|
| $('.stock-input').show();
|
| } else {
|
| $('.stock-input').hide();
|
| }
|
| });
|
| });
|
|
|
|
|
| function loadConceptFundFlow(period) {
|
| $('#loading-panel').show();
|
| $('#concept-flow-panel, #concept-stocks-panel, #individual-flow-panel, #individual-rank-panel').hide();
|
|
|
| $.ajax({
|
| url: `/api/concept_fund_flow?period=${period}`,
|
| type: 'GET',
|
| success: function(response) {
|
| renderConceptFundFlow(response, period);
|
| $('#loading-panel').hide();
|
| $('#concept-flow-panel').show();
|
| },
|
| error: function(xhr, status, error) {
|
| $('#loading-panel').hide();
|
| showError('获取概念资金流向数据失败: ' + error);
|
| }
|
| });
|
| }
|
|
|
|
|
| function loadConceptStocks(sector) {
|
| $('#loading-panel').show();
|
| $('#concept-stocks-panel').hide();
|
|
|
| $.ajax({
|
| url: `/api/sector_stocks?sector=${encodeURIComponent(sector)}`,
|
| type: 'GET',
|
| success: function(response) {
|
| renderConceptStocks(response, sector);
|
| $('#loading-panel').hide();
|
| $('#concept-stocks-panel').show();
|
| },
|
| error: function(xhr, status, error) {
|
| $('#loading-panel').hide();
|
| showError('获取概念成分股数据失败: ' + error);
|
| }
|
| });
|
| }
|
|
|
|
|
| function loadIndividualFundFlow(stockCode) {
|
| $('#loading-panel').show();
|
| $('#concept-flow-panel, #concept-stocks-panel, #individual-flow-panel, #individual-rank-panel').hide();
|
|
|
| $.ajax({
|
| url: `/api/individual_fund_flow?stock_code=${stockCode}`,
|
| type: 'GET',
|
| success: function(response) {
|
| renderIndividualFundFlow(response);
|
| $('#loading-panel').hide();
|
| $('#individual-flow-panel').show();
|
| },
|
| error: function(xhr, status, error) {
|
| $('#loading-panel').hide();
|
| showError('获取个股资金流向数据失败: ' + error);
|
| }
|
| });
|
| }
|
|
|
|
|
| function loadIndividualFundFlowRank(period) {
|
| $('#loading-panel').show();
|
| $('#concept-flow-panel, #concept-stocks-panel, #individual-flow-panel, #individual-rank-panel').hide();
|
|
|
| $.ajax({
|
| url: `/api/individual_fund_flow_rank?period=${period}`,
|
| type: 'GET',
|
| success: function(response) {
|
| renderIndividualFundFlowRank(response, period);
|
| $('#loading-panel').hide();
|
| $('#individual-rank-panel').show();
|
| },
|
| error: function(xhr, status, error) {
|
| $('#loading-panel').hide();
|
| showError('获取个股资金流向排名数据失败: ' + error);
|
| }
|
| });
|
| }
|
|
|
|
|
| function renderConceptFundFlow(data, period) {
|
| $('#concept-period-badge').text(period);
|
|
|
| let html = '';
|
| if (!data || data.length === 0) {
|
| html = '<tr><td colspan="9" class="text-center">暂无数据</td></tr>';
|
| } else {
|
| data.forEach((item, index) => {
|
| const changeClass = parseFloat(item.change_percent) >= 0 ? 'trend-up' : 'trend-down';
|
| const changeIcon = parseFloat(item.change_percent) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| const netFlowClass = parseFloat(item.net_flow) >= 0 ? 'trend-up' : 'trend-down';
|
| const netFlowIcon = parseFloat(item.net_flow) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| html += `
|
| <tr>
|
| <td>${item.rank}</td>
|
| <td><a href="javascript:void(0)" onclick="loadConceptStocks('${item.sector}')">${item.sector}</a></td>
|
| <td>${formatNumber(item.sector_index, 2)}</td>
|
| <td class="${changeClass}">${changeIcon} ${formatPercent(item.change_percent)}</td>
|
| <td>${formatNumber(item.inflow, 2)}</td>
|
| <td>${formatNumber(item.outflow, 2)}</td>
|
| <td class="${netFlowClass}">${netFlowIcon} ${formatNumber(item.net_flow, 2)}</td>
|
| <td>${item.company_count}</td>
|
| <td>
|
| <button class="btn btn-sm btn-outline-primary" onclick="loadConceptStocks('${item.sector}')">
|
| <i class="fas fa-search"></i>
|
| </button>
|
| </td>
|
| </tr>
|
| `;
|
| });
|
| }
|
|
|
| $('#concept-flow-table').html(html);
|
| }
|
|
|
|
|
| function renderConceptStocks(data, sector) {
|
| $('#concept-stocks-title').text(`${sector} 成分股`);
|
|
|
| let html = '';
|
| if (!data || data.length === 0) {
|
| html = '<tr><td colspan="7" class="text-center">暂无数据</td></tr>';
|
| } else {
|
| data.forEach((item) => {
|
| const changeClass = parseFloat(item.change_percent) >= 0 ? 'trend-up' : 'trend-down';
|
| const changeIcon = parseFloat(item.change_percent) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| const netFlowClass = parseFloat(item.main_net_inflow) >= 0 ? 'trend-up' : 'trend-down';
|
| const netFlowIcon = parseFloat(item.main_net_inflow) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| html += `
|
| <tr>
|
| <td>${item.code}</td>
|
| <td>${item.name}</td>
|
| <td>${formatNumber(item.price, 2)}</td>
|
| <td class="${changeClass}">${changeIcon} ${formatPercent(item.change_percent)}</td>
|
| <td class="${netFlowClass}">${netFlowIcon} ${formatMoney(item.main_net_inflow)}</td>
|
| <td class="${netFlowClass}">${formatPercent(item.main_net_inflow_percent)}</td>
|
| <td>
|
| <a href="/stock_detail/${item.code}" class="btn btn-sm btn-outline-primary">
|
| <i class="fas fa-chart-line"></i>
|
| </a>
|
| <button class="btn btn-sm btn-outline-info" onclick="loadIndividualFundFlow('${item.code}')">
|
| <i class="fas fa-money-bill-wave"></i>
|
| </button>
|
| </td>
|
| </tr>
|
| `;
|
| });
|
| }
|
|
|
| $('#concept-stocks-table').html(html);
|
| }
|
|
|
|
|
| function renderIndividualFundFlow(data) {
|
| if (!data || !data.data || data.data.length === 0) {
|
| showError('未获取到有效的个股资金流向数据');
|
| return;
|
| }
|
|
|
|
|
| data.data.sort((a, b) => {
|
|
|
| let dateA = new Date(a.date);
|
| let dateB = new Date(b.date);
|
| return dateB - dateA;
|
| });
|
|
|
|
|
| recalculateSummary(data, 90);
|
|
|
|
|
| $('#individual-flow-title').text(`${data.stock_code} 资金流向`);
|
|
|
|
|
| renderIndividualFlowSummary(data);
|
|
|
|
|
| renderFundFlowPieChart(data);
|
|
|
|
|
| renderFundFlowHistoryChart(data);
|
| }
|
|
|
| function recalculateSummary(data, days) {
|
|
|
| const recent_data = data.data.slice(0, Math.min(days, data.data.length));
|
|
|
|
|
| const total_main_net_inflow = recent_data.reduce((sum, item) => sum + item.main_net_inflow, 0);
|
| const avg_main_net_inflow_percent = recent_data.reduce((sum, item) => sum + item.main_net_inflow_percent, 0) / recent_data.length;
|
| const positive_days = recent_data.filter(item => item.main_net_inflow > 0).length;
|
| const negative_days = recent_data.length - positive_days;
|
|
|
|
|
| data.summary = {
|
| recent_days: recent_data.length,
|
| total_main_net_inflow: total_main_net_inflow,
|
| avg_main_net_inflow_percent: avg_main_net_inflow_percent,
|
| positive_days: positive_days,
|
| negative_days: negative_days
|
| };
|
| }
|
|
|
|
|
| function renderIndividualFlowSummary(data) {
|
| if (!data.summary) return;
|
|
|
| const summary = data.summary;
|
|
|
| const recent = data.data[0];
|
|
|
| let html = `
|
| <tr>
|
| <td>最新日期:</td>
|
| <td>${recent.date}</td>
|
| <td>最新价:</td>
|
| <td>${formatNumber(recent.price, 2)}</td>
|
| </tr>
|
| <tr>
|
| <td>涨跌幅:</td>
|
| <td class="${recent.change_percent >= 0 ? 'trend-up' : 'trend-down'}">
|
| ${recent.change_percent >= 0 ? '↑' : '↓'} ${formatPercent(recent.change_percent)}
|
| </td>
|
| <td>分析周期:</td>
|
| <td>${summary.recent_days}天</td>
|
| </tr>
|
| <tr>
|
| <td>主力净流入:</td>
|
| <td class="${summary.total_main_net_inflow >= 0 ? 'trend-up' : 'trend-down'}">
|
| ${summary.total_main_net_inflow >= 0 ? '↑' : '↓'} ${formatMoney(summary.total_main_net_inflow)}
|
| </td>
|
| <td>净流入占比:</td>
|
| <td class="${summary.avg_main_net_inflow_percent >= 0 ? 'trend-up' : 'trend-down'}">
|
| ${summary.avg_main_net_inflow_percent >= 0 ? '↑' : '↓'} ${formatPercent(summary.avg_main_net_inflow_percent)}
|
| </td>
|
| </tr>
|
| <tr>
|
| <td>资金流入天数:</td>
|
| <td>${summary.positive_days}天</td>
|
| <td>资金流出天数:</td>
|
| <td>${summary.negative_days}天</td>
|
| </tr>
|
| `;
|
|
|
| $('#individual-flow-summary').html(html);
|
| }
|
|
|
|
|
| function renderFundFlowPieChart(data) {
|
| if (!data.data || data.data.length === 0) return;
|
|
|
|
|
| const recent = data.data[0];
|
|
|
|
|
| const totalInflow = Math.abs(recent.super_large_net_inflow) +
|
| Math.abs(recent.large_net_inflow) +
|
| Math.abs(recent.medium_net_inflow) +
|
| Math.abs(recent.small_net_inflow);
|
|
|
|
|
| const superLargePct = Math.abs(recent.super_large_net_inflow) / totalInflow * 100;
|
| const largePct = Math.abs(recent.large_net_inflow) / totalInflow * 100;
|
| const mediumPct = Math.abs(recent.medium_net_inflow) / totalInflow * 100;
|
| const smallPct = Math.abs(recent.small_net_inflow) / totalInflow * 100;
|
|
|
| const options = {
|
| series: [superLargePct, largePct, mediumPct, smallPct],
|
| chart: {
|
| type: 'pie',
|
| height: 200
|
| },
|
| labels: ['超大单', '大单', '中单', '小单'],
|
| colors: ['#0d6efd', '#198754', '#ffc107', '#dc3545'],
|
| legend: {
|
| position: 'bottom'
|
| },
|
| tooltip: {
|
| y: {
|
| formatter: function(value) {
|
| return value.toFixed(2) + '%';
|
| }
|
| }
|
| }
|
| };
|
|
|
|
|
| $('#fund-flow-pie-chart').empty();
|
|
|
| const chart = new ApexCharts(document.querySelector("#fund-flow-pie-chart"), options);
|
| chart.render();
|
| }
|
|
|
|
|
| function renderFundFlowHistoryChart(data) {
|
| if (!data.data || data.data.length === 0) return;
|
|
|
|
|
|
|
| const historyData = data.data.slice(0, 90).reverse();
|
|
|
| const dates = historyData.map(item => item.date);
|
| const mainNetInflow = historyData.map(item => item.main_net_inflow);
|
| const superLargeInflow = historyData.map(item => item.super_large_net_inflow);
|
| const largeInflow = historyData.map(item => item.large_net_inflow);
|
| const mediumInflow = historyData.map(item => item.medium_net_inflow);
|
| const smallInflow = historyData.map(item => item.small_net_inflow);
|
| const priceChanges = historyData.map(item => item.change_percent);
|
|
|
| const options = {
|
| series: [
|
| {
|
| name: '主力净流入',
|
| type: 'column',
|
| data: mainNetInflow
|
| },
|
| {
|
| name: '超大单',
|
| type: 'line',
|
| data: superLargeInflow
|
| },
|
| {
|
| name: '大单',
|
| type: 'line',
|
| data: largeInflow
|
| },
|
| {
|
| name: '价格涨跌幅',
|
| type: 'line',
|
| data: priceChanges
|
| }
|
| ],
|
| chart: {
|
| height: 300,
|
| type: 'line',
|
| toolbar: {
|
| show: false
|
| }
|
| },
|
| stroke: {
|
| width: [0, 2, 2, 2],
|
| curve: 'smooth'
|
| },
|
| plotOptions: {
|
| bar: {
|
| columnWidth: '50%'
|
| }
|
| },
|
| colors: ['#0d6efd', '#198754', '#ffc107', '#dc3545'],
|
| dataLabels: {
|
| enabled: false
|
| },
|
| labels: dates,
|
| xaxis: {
|
| type: 'category'
|
| },
|
| yaxis: [
|
| {
|
| title: {
|
| text: '资金流入(亿)',
|
| style: {
|
| fontSize: '12px'
|
| }
|
| },
|
| labels: {
|
| formatter: function(val) {
|
|
|
| return (val / 100000000).toFixed(2);
|
| }
|
| }
|
| },
|
| {
|
| opposite: true,
|
| title: {
|
| text: '价格涨跌幅(%)',
|
| style: {
|
| fontSize: '12px'
|
| }
|
| },
|
| labels: {
|
| formatter: function(val) {
|
| return val.toFixed(2);
|
| }
|
| },
|
| min: -10,
|
| max: 10,
|
| tickAmount: 5
|
| }
|
| ],
|
| tooltip: {
|
| shared: true,
|
| intersect: false,
|
| y: {
|
| formatter: function(y, { seriesIndex }) {
|
| if (seriesIndex === 3) {
|
| return y.toFixed(2) + '%';
|
| }
|
|
|
| return (y / 100000000).toFixed(2) + ' 亿';
|
| }
|
| }
|
| },
|
| legend: {
|
| position: 'top'
|
| }
|
| };
|
|
|
|
|
| $('#fund-flow-history-chart').empty();
|
|
|
| const chart = new ApexCharts(document.querySelector("#fund-flow-history-chart"), options);
|
| chart.render();
|
| }
|
|
|
|
|
| function renderIndividualFundFlowRank(data, period) {
|
| $('#individual-rank-period-badge').text(period);
|
|
|
| let html = '';
|
| if (!data || data.length === 0) {
|
| html = '<tr><td colspan="12" class="text-center">暂无数据</td></tr>';
|
| } else {
|
| data.forEach((item) => {
|
| const changeClass = parseFloat(item.change_percent) >= 0 ? 'trend-up' : 'trend-down';
|
| const changeIcon = parseFloat(item.change_percent) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| const mainNetClass = parseFloat(item.main_net_inflow) >= 0 ? 'trend-up' : 'trend-down';
|
| const mainNetIcon = parseFloat(item.main_net_inflow) >= 0 ? '<i class="fas fa-caret-up"></i>' : '<i class="fas fa-caret-down"></i>';
|
|
|
| html += `
|
| <tr>
|
| <td>${item.rank}</td>
|
| <td>${item.code}</td>
|
| <td>${item.name}</td>
|
| <td>${formatNumber(item.price, 2)}</td>
|
| <td class="${changeClass}">${changeIcon} ${formatPercent(item.change_percent)}</td>
|
| <td class="${mainNetClass}">${mainNetIcon} ${formatMoney(item.main_net_inflow)}</td>
|
| <td class="${mainNetClass}">${formatPercent(item.main_net_inflow_percent)}</td>
|
| <td>${formatMoney(item.super_large_net_inflow)}</td>
|
| <td>${formatMoney(item.large_net_inflow)}</td>
|
| <td>${formatMoney(item.medium_net_inflow)}</td>
|
| <td>${formatMoney(item.small_net_inflow)}</td>
|
| <td>
|
| <a href="/stock_detail/${item.code}" class="btn btn-sm btn-outline-primary">
|
| <i class="fas fa-chart-line"></i>
|
| </a>
|
| <button class="btn btn-sm btn-outline-info" onclick="loadIndividualFundFlow('${item.code}')">
|
| <i class="fas fa-money-bill-wave"></i>
|
| </button>
|
| </td>
|
| </tr>
|
| `;
|
| });
|
| }
|
|
|
| $('#individual-rank-table').html(html);
|
| }
|
|
|
|
|
| function formatCompactNumber(num) {
|
| if (Math.abs(num) >= 1.0e9) {
|
| return (num / 1.0e9).toFixed(2) + "B";
|
| } else if (Math.abs(num) >= 1.0e6) {
|
| return (num / 1.0e6).toFixed(2) + "M";
|
| } else if (Math.abs(num) >= 1.0e3) {
|
| return (num / 1.0e3).toFixed(2) + "K";
|
| } else {
|
| return num.toFixed(2);
|
| }
|
| }
|
|
|
|
|
| function formatMoney(value) {
|
| if (value === null || value === undefined) {
|
| return '--';
|
| }
|
|
|
| value = parseFloat(value);
|
| if (isNaN(value)) {
|
| return '--';
|
| }
|
|
|
| if (Math.abs(value) >= 1e8) {
|
| return (value / 1e8).toFixed(2) + ' 亿';
|
| } else if (Math.abs(value) >= 1e4) {
|
| return (value / 1e4).toFixed(2) + ' 万';
|
| } else {
|
| return value.toFixed(2) + ' 元';
|
| }
|
| }
|
|
|
|
|
| function formatPercent(value) {
|
| if (value === null || value === undefined) {
|
| return '--';
|
| }
|
|
|
| value = parseFloat(value);
|
| if (isNaN(value)) {
|
| return '--';
|
| }
|
|
|
| return value.toFixed(2) + '%';
|
| }
|
|
|
| document.addEventListener('DOMContentLoaded', function() {
|
| const dataType = document.getElementById('data-type');
|
| const periodSelect = document.getElementById('period-select');
|
| const stockInput = document.querySelector('.stock-input');
|
|
|
|
|
| toggleOptions();
|
|
|
| dataType.addEventListener('change', toggleOptions);
|
|
|
| function toggleOptions() {
|
| if (dataType.value === 'individual') {
|
|
|
| periodSelect.innerHTML = `
|
| <option value="3日">3日</option>
|
| <option value="5日">5日</option>
|
| <option value="10日">10日</option>
|
| `;
|
| stockInput.style.display = 'block';
|
| } else {
|
|
|
| periodSelect.innerHTML = `
|
| <option value="10日排行" selected>10日排行</option>
|
| <option value="5日排行">5日排行</option>
|
| <option value="3日排行">3日排行</option>
|
| `;
|
| stockInput.style.display = 'none';
|
| }
|
| }
|
| });
|
| </script>
|
| {% endblock %} |