吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10752|回复: 52
收起左侧

[Windows] A股主要指数实时监控工具2.1.0【支持添加指数、股票】

  [复制链接]
htlaoyang 发表于 2025-8-25 11:39
本帖最后由 htlaoyang 于 2025-9-10 11:12 编辑

1.png
2.png
3.png
实现功能:
1、可维护指数;
2、可维护股票;
2、优化界面;
通过网盘分享的文件:A股主要指数实时监控工具2.1.0.rar
链接: https://pan.baidu.com/s/1QCZF84LLcLIpYiLEa-zCKg?pwd=4cqi 提取码: 4cqi

----------------------------------------------A股主要指数实时监控工具1.0.0---------------------------------------------------------------------------------最近股市看着走势很强劲,想着电脑上监控一下,方便查看;
12355.png
实现功能:
1、多数据源获取指定A股指数,确保能获取到实时指数数据;
2、实时监控刷新;

通过网盘分享的文件:A股主要指数实时监控工具.exe
链接: https://pan.baidu.com/s/16QNwa8HBFvLYwxvkOcJgtA 提取码: bwsy


免费评分

参与人数 12吾爱币 +11 热心值 +10 收起 理由
TMVB + 1 用心讨论,共获提升!
navigat + 1 + 1 谢谢@Thanks!
mochiyouyu + 1 鼓励转贴优秀软件安全工具和文档!
Yqn0501 + 1 + 1 谢谢@Thanks!
sliver99 + 1 + 1 谢谢@Thanks!
程先森 + 1 + 1 我很赞同!
nxsu + 1 + 1 我很赞同!
onlyonemoon + 1 + 1 谢谢@Thanks!
woxobo + 1 + 1 谢谢@Thanks!
AndyKuen + 1 + 1 谢谢@Thanks!
Zed丶小灰狼 + 1 热心回复!
kissdust + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| htlaoyang 发表于 2025-8-26 09:22
源码 有需要的自取
[Python] 纯文本查看 复制代码
import requests
import json
import time
from datetime import datetime
import threading
import tkinter as tk
from tkinter import ttk, messagebox
import re

class ChinaStockIndexGUI:
    """A股主要指数获取工具类(图形界面版)"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("A股指数监控工具")
        self.root.geometry("800x600")
        self.root.minsize(700, 500)
        
        # 设置中文字体
        self.style = ttk.Style()
        self.style.configure("Treeview.Heading", font=("SimHei", 10, "bold"))
        self.style.configure("Treeview", font=("SimHei", 10), rowheight=25)
        self.style.configure("TLabel", font=("SimHei", 10))
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("Header.TLabel", font=("SimHei", 12, "bold"))
        
        self.index_codes = {
            "上证指数": "000001",
            "深证成指": "399001",
            "创业板指": "399006",
            "沪深300": "000300",
            "上证50": "000016",
            "中证500": "000905",
            "科创50": "000688",
            "中小板指": "399005"
        }
        
        # 选中的指数
        self.selected_indices = list(self.index_codes.keys())
        self.index_vars = {name: tk.BooleanVar(value=True) for name in self.index_codes.keys()}
        
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        
        # 更新间隔(秒)
        self.update_interval = 300  # 默认5分钟
        
        # 控制线程运行的标志
        self.running = False
        self.update_thread = None
        
        # 创建界面
        self.create_widgets()
        
        # 绑定窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)
    
    def create_widgets(self):
        """创建界面组件"""
        # 顶部标题
        header_frame = ttk.Frame(self.root)
        header_frame.pack(fill=tk.X, padx=10, pady=10)
        
        ttk.Label(header_frame, text="A股指数实时监控", style="Header.TLabel").pack(side=tk.LEFT)
        self.update_time_label = ttk.Label(header_frame, text="", style="TLabel")
        self.update_time_label.pack(side=tk.RIGHT)
        
        # 指数选择区域
        selection_frame = ttk.LabelFrame(self.root, text="选择要监控的指数")
        selection_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 创建复选框网格
        row, col = 0, 0
        for index_name in self.index_codes.keys():
            ttk.Checkbutton(
                selection_frame, 
                text=index_name, 
                variable=self.index_vars[index_name]
            ).grid(row=row, column=col, padx=10, pady=5, sticky=tk.W)
            col += 1
            if col >= 4:
                col = 0
                row += 1
        
        # 控制按钮区域
        control_frame = ttk.Frame(self.root)
        control_frame.pack(fill=tk.X, padx=10, pady=5)
        
        self.start_stop_btn = ttk.Button(
            control_frame, 
            text="开始监控", 
            command=self.toggle_monitoring
        )
        self.start_stop_btn.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(control_frame, text="更新间隔(分钟):").pack(side=tk.LEFT, padx=5)
        self.interval_var = tk.StringVar(value=str(self.update_interval // 60))
        interval_entry = ttk.Entry(control_frame, textvariable=self.interval_var, width=5)
        interval_entry.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(control_frame, text="应用间隔", command=self.apply_interval).pack(side=tk.LEFT, padx=5)
        
        # 指数数据表格
        table_frame = ttk.Frame(self.root)
        table_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建滚动条
        scrollbar = ttk.Scrollbar(table_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建表格
        columns = ("index_name", "current_value", "change_amount", "change_percent", 
                  "open", "high", "low", "prev_close", "update_time", "data_source")
        self.tree = ttk.Treeview(
            table_frame, 
            columns=columns, 
            show="headings", 
            yscrollcommand=scrollbar.set
        )
        
        # 设置列标题
        self.tree.heading("index_name", text="指数名称")
        self.tree.heading("current_value", text="当前值")
        self.tree.heading("change_amount", text="涨跌额")
        self.tree.heading("change_percent", text="涨跌幅")
        self.tree.heading("open", text="开盘价")
        self.tree.heading("high", text="最高价")
        self.tree.heading("low", text="最低价")
        self.tree.heading("prev_close", text="昨收价")
        self.tree.heading("update_time", text="更新时间")
        self.tree.heading("data_source", text="数据源")
        
        # 设置列宽
        self.tree.column("index_name", width=100)
        self.tree.column("current_value", width=80)
        self.tree.column("change_amount", width=80)
        self.tree.column("change_percent", width=80)
        self.tree.column("open", width=80)
        self.tree.column("high", width=80)
        self.tree.column("low", width=80)
        self.tree.column("prev_close", width=80)
        self.tree.column("update_time", width=130)
        self.tree.column("data_source", width=100)
        
        self.tree.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
        scrollbar.config(command=self.tree.yview)
        
        # 状态标签
        self.status_var = tk.StringVar(value="就绪,点击开始监控按钮启动")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    
    def toggle_monitoring(self):
        """切换监控状态(开始/停止)"""
        if not self.running:
            # 开始监控
            self.update_selected_indices()
            self.running = True
            self.start_stop_btn.config(text="停止监控")
            self.status_var.set(f"正在监控 {', '.join(self.selected_indices)},每{self.update_interval//60}分钟更新一次")
            
            # 启动更新线程
            self.update_thread = threading.Thread(target=self.scheduled_update)
            self.update_thread.daemon = True
            self.update_thread.start()
            
            # 立即获取一次数据
            self.root.after(100, self.fetch_and_display_data)
        else:
            # 停止监控
            self.running = False
            self.start_stop_btn.config(text="开始监控")
            self.status_var.set("监控已停止,点击开始监控按钮重新启动")
    
    def apply_interval(self):
        """应用更新间隔设置"""
        try:
            minutes = int(self.interval_var.get())
            if minutes < 1:
                messagebox.showerror("错误", "更新间隔不能小于1分钟")
                return
            self.update_interval = minutes * 60
            self.status_var.set(f"更新间隔已设置为 {minutes} 分钟")
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")
    
    def update_selected_indices(self):
        """更新选中的指数列表"""
        self.selected_indices = [name for name, var in self.index_vars.items() if var.get()]
        if not self.selected_indices:
            # 如果没有选择任何指数,默认选择上证指数
            self.selected_indices = ["上证指数"]
            self.index_vars["上证指数"].set(True)
    
    def get_index_via_sina(self, index_code):
        """从新浪财经获取指数数据"""
        try:
            url = f"https://hq.sinajs.cn/list=s_{index_code}"
            headers = {
                'Referer': 'https://finance.sina.com.cn',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            }
            
            response = requests.get(url, headers=headers, timeout=10)
            response.encoding = 'gbk'
            
            data_str = response.text
            data_str = data_str[data_str.find('="')+2:data_str.rfind('"')]
            fields = data_str.split(',')
            
            if len(fields) >= 3:
                index_name = fields[0]
                current_value = fields[1]
                change_amount = fields[2]
                change_percent = fields[3]
                
                if change_percent == '' and current_value and change_amount:
                    try:
                        prev_close = float(current_value) - float(change_amount)
                        if prev_close != 0:
                            change_percent = f"{round(float(change_amount) / prev_close * 100, 2)}%"
                    except:
                        pass
                
                return {
                    '指数名称': index_name,
                    '当前值': current_value,
                    '涨跌额': change_amount,
                    '涨跌幅': change_percent,
                    '更新时间': fields[-2] + ' ' + fields[-1],
                    '数据源': '新浪财经'
                }
            else:
                return {'错误': '新浪API返回数据格式异常'}
                
        except Exception as e:
            return {'错误': f'新浪API请求异常: {str(e)}'}
    
    def get_index_via_163(self, index_code):
        """从网易财经获取指数数据"""
        try:
            if index_code.startswith('000'):
                code_163 = '0' + index_code
            else:
                code_163 = '1' + index_code
                
            url = f"http://api.money.126.net/data/feed/{code_163}"
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = 'utf-8'
            
            data_str = response.text
            data_str = data_str[data_str.find('(')+1:data_str.rfind(')')]
            data = json.loads(data_str)
            
            index_data = data[code_163]
            
            return {
                '指数名称': index_data['name'],
                '当前值': str(index_data['price']),
                '涨跌额': str(round(index_data['updown'], 2)),
                '涨跌幅': f"{round(index_data['percent'] * 100, 2)}%",
                '开盘价': str(index_data['open']),
                '最高价': str(index_data['high']),
                '最低价': str(index_data['low']),
                '昨收价': str(index_data['yestclose']),
                '更新时间': datetime.fromtimestamp(index_data['time']/1000).strftime('%Y-%m-%d %H:%M:%S'),
                '数据源': '网易财经'
            }
                
        except Exception as e:
            return {'错误': f'网易API请求异常: {str(e)}'}
    
    def get_index_via_eastmoney(self, index_code):
        """从东方财富API获取指数数据"""
        try:
            if index_code.startswith('000'):
                secid = f"1.{index_code}"
            else:
                secid = f"0.{index_code}"
                
            url = "https://push2.eastmoney.com/api/qt/stock/get"
            params = {
                "secid": secid,
                "fields": "f43,f44,f45,f46,f60,f169,f170,f47,f48,f49,f50,f51,f52,f57,f58,f59,f152,f161,f162,f163,f164,f165,f166,f167,f168,f169,f170",
                "ut": "fa5fd1943c7b386f172d6893dbfba10b",
                "invt": "2"
            }
            
            response = requests.get(url, params=params, headers=self.headers, timeout=10)
            data = response.json()
            
            if data['data']:
                item = data['data']
                current_value = item.get('f43', 0) / 100
                change_amount = item.get('f170', 0) / 100
                change_percent = item.get('f170', 0) / 10000
                open_price = item.get('f46', 0) / 100
                high_price = item.get('f44', 0) / 100
                low_price = item.get('f45', 0) / 100
                prev_close = item.get('f60', 0) / 100
                
                return {
                    '指数名称': self.get_index_name(index_code),
                    '当前值': f"{current_value:.2f}",
                    '涨跌额': f"{change_amount:+.2f}",
                    '涨跌幅': f"{change_percent:+.2f}%",
                    '开盘价': f"{open_price:.2f}",
                    '最高价': f"{high_price:.2f}",
                    '最低价': f"{low_price:.2f}",
                    '昨收价': f"{prev_close:.2f}",
                    '更新时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    '数据源': '东方财富API'
                }
            else:
                return {'错误': '东方财富API返回数据为空'}
                
        except Exception as e:
            return {'错误': f'东方财富API请求异常: {str(e)}'}
    
    def get_index_name(self, index_code):
        """根据指数代码获取指数名称"""
        for name, code in self.index_codes.items():
            if code == index_code:
                return name
        return f"指数{index_code}"
    
    def fetch_indices_data(self):
        """获取选中指数的数据"""
        results = {}
        
        for index_name in self.selected_indices:
            index_code = self.index_codes[index_name]
            
            # 尝试多个数据源
            data = self.get_index_via_sina(index_code)
            if '错误' in data:
                data = self.get_index_via_163(index_code)
            if '错误' in data:
                data = self.get_index_via_eastmoney(index_code)
            
            results[index_name] = data
            time.sleep(0.5)  # 避免请求过于频繁
        
        return results
    
    def fetch_and_display_data(self):
        """获取并显示指数数据"""
        if not self.running:
            return
            
        try:
            results = self.fetch_indices_data()
            
            # 清空表格
            for item in self.tree.get_children():
                self.tree.delete(item)
            
            # 更新表格数据
            for index_name, data in results.items():
                if '错误' in data:
                    # 显示错误信息
                    self.tree.insert("", tk.END, values=(
                        index_name, data['错误'], "", "", "", "", "", "", "", ""
                    ))
                else:
                    # 插入数据行
                    values = (
                        data.get('指数名称', index_name),
                        data.get('当前值', ''),
                        data.get('涨跌额', ''),
                        data.get('涨跌幅', ''),
                        data.get('开盘价', ''),
                        data.get('最高价', ''),
                        data.get('最低价', ''),
                        data.get('昨收价', ''),
                        data.get('更新时间', ''),
                        data.get('数据源', '')
                    )
                    item = self.tree.insert("", tk.END, values=values)
                    
                    # 根据涨跌额设置颜色
                    change_amount = data.get('涨跌额', '')
                    try:
                        # 提取数字部分
                        num = float(re.sub(r'[^\d.-]', '', change_amount))
                        if num > 0:
                            # 上涨,设置为红色
                            self.tree.tag_configure("up", foreground="red")
                            self.tree.item(item, tags=("up",))
                        elif num < 0:
                            # 下跌,设置为绿色
                            self.tree.tag_configure("down", foreground="green")
                            self.tree.item(item, tags=("down",))
                    except:
                        pass
            
            # 更新时间标签
            current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            self.update_time_label.config(text=f"最后更新: {current_time}")
            self.status_var.set(f"已更新数据 - {current_time},将在{self.update_interval//60}分钟后再次更新")
            
        except Exception as e:
            self.status_var.set(f"获取数据时出错: {str(e)}")
            messagebox.showerror("错误", f"获取数据时出错: {str(e)}")
    
    def scheduled_update(self):
        """定时更新数据"""
        while self.running:
            # 等待指定的时间间隔
            for _ in range(self.update_interval):
                if not self.running:
                    return
                time.sleep(1)
            
            # 触发数据更新(在主线程中执行)
            if self.running:
                self.root.after(0, self.fetch_and_display_data)
    
    def on_close(self):
        """关闭窗口时的处理"""
        self.running = False
        if self.update_thread:
            self.update_thread.join(timeout=1.0)
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = ChinaStockIndexGUI(root)
    root.mainloop()
    
 楼主| htlaoyang 发表于 2025-8-28 12:09
本帖最后由 htlaoyang 于 2025-8-28 12:11 编辑
ga3m666 发表于 2025-8-28 11:22
个股有么?

个股,3个数据来源 应该也是支持的。没细研究。
个股与指数 入参,3个来源应该 有些差异。以下是东方财富个股代码可参考一下。

    def get_stock_via_eastmoney(self, stock_code):
        """从东方财富API获取个股数据"""
        try:
            # 沪市股票代码以6开头,深市以0或3开头
            if stock_code.startswith('6'):
                secid = f"1.{stock_code}"
            else:
                secid = f"0.{stock_code}"

            url = "https://push2.eastmoney.com/api/qt/stock/get"
            params = {
                "secid": secid,
                "fields": "f43,f44,f45,f46,f60,f169,f170,f47,f48,f49,f50,f51,f52,f57,f58,f59,f152",
                "ut": "fa5fd1943c7b386f172d6893dbfba10b",
                "invt": "2"
            }

            response = requests.get(url, params=params, headers=self.headers, timeout=10)
            data = response.json()

            if data['data']:
                item = data['data']
                current_value = item.get('f43', 0) / 100
                change_amount = item.get('f170', 0) / 100
                change_percent = item.get('f170', 0) / 10000
                open_price = item.get('f46', 0) / 100
                high_price = item.get('f44', 0) / 100
                low_price = item.get('f45', 0) / 100
                prev_close = item.get('f60', 0) / 100

                # 获取股票名称
                stock_name = item.get('f58', f"股票{stock_code}")

                return {
                    '名称': stock_name,
                    '代码': stock_code,
                    '当前值': f"{current_value:.2f}",
                    '涨跌额': f"{change_amount:+.2f}",
                    '涨跌幅': f"{change_percent:+.2f}%",
                    '开盘价': f"{open_price:.2f}",
                    '最高价': f"{high_price:.2f}",
                    '最低价': f"{low_price:.2f}",
                    '昨收价': f"{prev_close:.2f}",
                    '更新时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    '数据源': '东方财富API'
                }
            else:
                return {'错误': '东方财富API返回数据为空'}

        except Exception as e:
            return {'错误': f'东方财富API请求异常: {str(e)}'}
ck1994 发表于 2025-8-28 00:33
[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>A股主要指数实时监控工具</title>
  <!-- 引入Tailwind CSS -->
  <script src="https://cdn.tailwindcss.com"></script>
  <!-- 引入Font Awesome -->
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <!-- 引入Chart.js -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
  
  <!-- 配置Tailwind -->
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#165DFF',
            secondary: '#4080FF',
            rise: '#00B42A',      // 上涨颜色-绿色
            fall: '#F53F3F',      // 下跌颜色-红色
            neutral: '#86909C',   // 中性色
            dark: '#1D2129',      // 深色文本
            light: '#F2F3F5'      // 浅色背景
          },
          fontFamily: {
            inter: ['Inter', 'system-ui', 'sans-serif'],
          },
        },
      }
    }
  </script>
  
  <!-- 自定义工具类 -->
  <style type="text/tailwindcss">
    [url=home.php?mod=space&uid=1688376]@layer[/url] utilities {
      .content-auto {
        content-visibility: auto;
      }
      .card-shadow {
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
      }
      .index-card-hover {
        transition: all 0.3s ease;
      }
      .index-card-hover:hover {
        transform: translateY(-5px);
        box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
      }
      .page-transition {
        animation: fadeIn 0.3s ease-in-out;
      }
      @keyframes fadeIn {
        from { opacity: 0; transform: translateY(10px); }
        to { opacity: 1; transform: translateY(0); }
      }
    }
  </style>
</head>

<body class="font-inter bg-gray-50 text-dark">
  <!-- 顶部导航栏 -->
  <header class="bg-white shadow-md fixed top-0 left-0 right-0 z-50 transition-all duration-300">
    <div class="container mx-auto px-4 py-3 flex items-center justify-between">
      <div class="flex items-center space-x-2">
        <i class="fa fa-line-chart text-primary text-2xl"></i>
        <h1 class="text-xl font-bold text-primary">A股指数监控</h1>
      </div>
      
      <nav class="hidden md:flex items-center space-x-6">
        <a href="#market" class="nav-link text-primary font-medium border-b-2 border-primary py-1" data-page="market">实时行情</a>
        <a href="#history" class="nav-link text-gray-600 hover:text-primary transition-colors py-1" data-page="history">历史数据</a>
        <a href="#news" class="nav-link text-gray-600 hover:text-primary transition-colors py-1" data-page="news">市场资讯</a>
        <a href="#settings" class="nav-link text-gray-600 hover:text-primary transition-colors py-1" data-page="settings">设置</a>
      </nav>
      
      <div class="flex items-center space-x-3">
        <button id="refreshBtn" class="flex items-center space-x-1 text-gray-600 hover:text-primary transition-colors">
          <i class="fa fa-refresh"></i>
          <span class="hidden sm:inline">刷新</span>
        </button>
        <button class="md:hidden text-gray-600" id="mobileMenuBtn">
          <i class="fa fa-bars text-xl"></i>
        </button>
      </div>
    </div>
    
    <!-- 移动端菜单 -->
    <div id="mobileMenu" class="hidden md:hidden bg-white border-t">
      <div class="container mx-auto px-4 py-2 flex flex-col space-y-3">
        <a href="#market" class="mobile-nav-link text-primary font-medium py-2" data-page="market">实时行情</a>
        <a href="#history" class="mobile-nav-link text-gray-600 hover:text-primary transition-colors py-2" data-page="history">历史数据</a>
        <a href="#news" class="mobile-nav-link text-gray-600 hover:text-primary transition-colors py-2" data-page="news">市场资讯</a>
        <a href="#settings" class="mobile-nav-link text-gray-600 hover:text-primary transition-colors py-2" data-page="settings">设置</a>
      </div>
    </div>
  </header>

  <!-- 主内容区 -->
  <main class="container mx-auto px-4 pt-20 pb-10">
    <!-- 页面容器 - 所有页面都在这里切换显示 -->
    <div id="pageContainer">
      <!-- 1. 实时行情页面 -->
      <section id="marketPage" class="page-content page-transition">
        <!-- 市场状态和时间信息 -->
        <div class="bg-white rounded-lg p-4 mb-6 shadow-sm">
          <div class="flex flex-col md:flex-row md:items-center justify-between">
            <div class="flex items-center space-x-4 mb-3 md:mb-0">
              <div class="flex items-center">
                <span class="inline-block w-3 h-3 rounded-full bg-rise mr-2 animate-pulse" id="marketStatusIndicator"></span>
                <span id="marketStatus" class="font-medium">加载中...</span>
              </div>
              <span id="currentTime" class="text-neutral">--:--:--</span>
              <span id="lastUpdateTime" class="text-xs bg-gray-100 px-2 py-0.5 rounded text-neutral">最后更新: 未更新</span>
            </div>
            
            <div class="flex flex-wrap gap-3">
              <div class="flex items-center text-sm">
                <span class="text-neutral mr-2">刷新频率:</span>
                <select id="refreshInterval" class="border border-gray-200 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-primary">
                  <option value="5">5秒</option>
                  <option value="10" selected>10秒</option>
                  <option value="30">30秒</option>
                  <option value="60">1分钟</option>
                  <option value="0">不自动刷新</option>
                </select>
              </div>
              
              <div class="flex items-center text-sm">
                <span class="text-neutral mr-2">图表周期:</span>
                <div class="flex border border-gray-200 rounded overflow-hidden">
                  <button class="chart-period-btn px-3 py-1 bg-primary text-white" data-period="day">日K</button>
                  <button class="chart-period-btn px-3 py-1 bg-white text-gray-600 hover:bg-gray-100" data-period="min">分时</button>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 主要指数卡片 -->
        <section class="mb-8">
          <h2 class="text-lg font-bold mb-4 flex items-center">
            <i class="fa fa-star text-primary mr-2"></i>主要指数
          </h2>
          
          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
            <!-- 上证指数 -->
            <div class="bg-white rounded-lg p-5 card-shadow index-card-hover cursor-pointer" data-detail="sse">
              <div class="flex justify-between items-start mb-3">
                <div>
                  <h3 class="font-bold text-lg">上证指数</h3>
                  <p class="text-neutral text-sm">000001.SH</p>
                </div>
                <span class="bg-primary/10 text-primary text-xs px-2 py-1 rounded-full">宽基</span>
              </div>
              
              <div class="mb-3">
                <div class="text-2xl font-bold" id="sseIndex">--</div>
                <div class="flex items-center mt-1">
                  <span class="font-medium" id="sseChange">--</span>
                  <span class="ml-2 text-sm" id="ssePercent">--</span>
                </div>
              </div>
              
              <div class="flex justify-between text-sm text-neutral pt-2 border-t border-gray-100">
                <div>
                  <p>今开: <span id="sseOpen">--</span></p>
                  <p>最高: <span id="sseHigh">--</span></p>
                </div>
                <div>
                  <p>昨收: <span id="sseClose">--</span></p>
                  <p>最低: <span id="sseLow">--</span></p>
                </div>
                <div>
                  <p>成交量: <span id="sseVolume">--</span></p>
                  <p>成交额: <span id="sseAmount">--</span></p>
                </div>
              </div>
            </div>
            
            <!-- 深证成指 -->
            <div class="bg-white rounded-lg p-5 card-shadow index-card-hover cursor-pointer" data-detail="szse">
              <div class="flex justify-between items-start mb-3">
                <div>
                  <h3 class="font-bold text-lg">深证成指</h3>
                  <p class="text-neutral text-sm">399001.SZ</p>
                </div>
                <span class="bg-primary/10 text-primary text-xs px-2 py-1 rounded-full">宽基</span>
              </div>
              
              <div class="mb-3">
                <div class="text-2xl font-bold" id="szseIndex">--</div>
                <div class="flex items-center mt-1">
                  <span class="font-medium" id="szseChange">--</span>
                  <span class="ml-2 text-sm" id="szsePercent">--</span>
                </div>
              </div>
              
              <div class="flex justify-between text-sm text-neutral pt-2 border-t border-gray-100">
                <div>
                  <p>今开: <span id="szseOpen">--</span></p>
                  <p>最高: <span id="szseHigh">--</span></p>
                </div>
                <div>
                  <p>昨收: <span id="szseClose">--</span></p>
                  <p>最低: <span id="szseLow">--</span></p>
                </div>
                <div>
                  <p>成交量: <span id="szseVolume">--</span></p>
                  <p>成交额: <span id="szseAmount">--</span></p>
                </div>
              </div>
            </div>
            
            <!-- 创业板指 -->
            <div class="bg-white rounded-lg p-5 card-shadow index-card-hover cursor-pointer" data-detail="gem">
              <div class="flex justify-between items-start mb-3">
                <div>
                  <h3 class="font-bold text-lg">创业板指</h3>
                  <p class="text-neutral text-sm">399006.SZ</p>
                </div>
                <span class="bg-primary/10 text-primary text-xs px-2 py-1 rounded-full">宽基</span>
              </div>
              
              <div class="mb-3">
                <div class="text-2xl font-bold" id="gemIndex">--</div>
                <div class="flex items-center mt-1">
                  <span class="font-medium" id="gemChange">--</span>
                  <span class="ml-2 text-sm" id="gemPercent">--</span>
                </div>
              </div>
              
              <div class="flex justify-between text-sm text-neutral pt-2 border-t border-gray-100">
                <div>
                  <p>今开: <span id="gemOpen">--</span></p>
                  <p>最高: <span id="gemHigh">--</span></p>
                </div>
                <div>
                  <p>昨收: <span id="gemClose">--</span></p>
                  <p>最低: <span id="gemLow">--</span></p>
                </div>
                <div>
                  <p>成交量: <span id="gemVolume">--</span></p>
                  <p>成交额: <span id="gemAmount">--</span></p>
                </div>
              </div>
            </div>
            
            <!-- 科创50 -->
            <div class="bg-white rounded-lg p-5 card-shadow index-card-hover cursor-pointer" data-detail="star">
              <div class="flex justify-between items-start mb-3">
                <div>
                  <h3 class="font-bold text-lg">科创50</h3>
                  <p class="text-neutral text-sm">000688.SH</p>
                </div>
                <span class="bg-primary/10 text-primary text-xs px-2 py-1 rounded-full">宽基</span>
              </div>
              
              <div class="mb-3">
                <div class="text-2xl font-bold" id="starIndex">--</div>
                <div class="flex items-center mt-1">
                  <span class="font-medium" id="starChange">--</span>
                  <span class="ml-2 text-sm" id="starPercent">--</span>
                </div>
              </div>
              
              <div class="flex justify-between text-sm text-neutral pt-2 border-t border-gray-100">
                <div>
                  <p>今开: <span id="starOpen">--</span></p>
                  <p>最高: <span id="starHigh">--</span></p>
                </div>
                <div>
                  <p>昨收: <span id="starClose">--</span></p>
                  <p>最低: <span id="starLow">--</span></p>
                </div>
                <div>
                  <p>成交量: <span id="starVolume">--</span></p>
                  <p>成交额: <span id="starAmount">--</span></p>
                </div>
              </div>
            </div>
          </div>
        </section>
        
        <!-- 指数走势图 -->
        <section class="mb-8">
          <div class="flex justify-between items-center mb-4">
            <h2 class="text-lg font-bold flex items-center">
              <i class="fa fa-area-chart text-primary mr-2"></i>指数走势
            </h2>
            
            <div class="flex space-x-2">
              <button class="index-chart-btn px-3 py-1 bg-primary text-white rounded text-sm" data-index="sse">上证指数</button>
              <button class="index-chart-btn px-3 py-1 bg-white text-gray-600 hover:bg-gray-100 rounded text-sm" data-index="szse">深证成指</button>
              <button class="index-chart-btn px-3 py-1 bg-white text-gray-600 hover:bg-gray-100 rounded text-sm" data-index="gem">创业板指</button>
              <button class="index-chart-btn px-3 py-1 bg-white text-gray-600 hover:bg-gray-100 rounded text-sm" data-index="star">科创50</button>
            </div>
          </div>
          
          <div class="bg-white rounded-lg p-4 md:p-6 shadow-sm">
            <div class="h-[400px] relative">
              <canvas id="indexChart"></canvas>
              <div id="chartLoading" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex flex-col items-center">
                <i class="fa fa-circle-o-notch fa-spin text-primary text-3xl mb-2"></i>
                <p class="text-neutral">加载图表数据中...</p>
              </div>
            </div>
          </div>
        </section>
        
        <!-- 行业板块指数 -->
        <section>
          <h2 class="text-lg font-bold mb-4 flex items-center">
            <i class="fa fa-th-large text-primary mr-2"></i>行业板块指数
          </h2>
          
          <div class="bg-white rounded-lg shadow-sm overflow-hidden">
            <div class="overflow-x-auto">
              <table class="min-w-full divide-y divide-gray-200">
                <thead class="bg-gray-50">
                  <tr>
                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-neutral uppercase tracking-wider">板块名称</th>
                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-neutral uppercase tracking-wider">指数代码</th>
                    <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">最新价</th>
                    <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">涨跌幅</th>
                    <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">涨跌额</th>
                    <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">成交量(万手)</th>
                    <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">成交额(亿元)</th>
                  </tr>
                </thead>
                <tbody class="bg-white divide-y divide-gray-200" id="sectorTable">
                  <tr>
                    <td colspan="7" class="px-6 py-10 text-center text-neutral">
                      <div class="flex flex-col items-center">
                        <i class="fa fa-circle-o-notch fa-spin text-primary text-2xl mb-2"></i>
                        <p>加载板块数据中...</p>
                      </div>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </section>
      </section>
      
      <!-- 2. 历史数据页面 -->
      <section id="historyPage" class="page-content hidden">
        <div class="bg-white rounded-lg p-6 shadow-sm mb-6">
          <h2 class="text-xl font-bold mb-6 flex items-center">
            <i class="fa fa-history text-primary mr-2"></i>历史数据查询
          </h2>
          
          <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
            <div>
              <label class="block text-sm font-medium text-neutral mb-1">指数选择</label>
              <select id="historyIndexSelect" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                <option value="sse">上证指数 (000001.SH)</option>
                <option value="szse">深证成指 (399001.SZ)</option>
                <option value="gem">创业板指 (399006.SZ)</option>
                <option value="star">科创50 (000688.SH)</option>
              </select>
            </div>
            
            <div>
              <label class="block text-sm font-medium text-neutral mb-1">时间周期</label>
              <select id="historyPeriodSelect" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                <option value="day">日线</option>
                <option value="week">周线</option>
                <option value="month">月线</option>
                <option value="year">年线</option>
              </select>
            </div>
            
            <div>
              <label class="block text-sm font-medium text-neutral mb-1">日期范围</label>
              <div class="flex space-x-2">
                <input type="date" id="historyStartDate" class="flex-1 border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                <input type="date" id="historyEndDate" class="flex-1 border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
              </div>
            </div>
          </div>
          
          <div class="flex justify-end mb-6">
            <button id="queryHistoryBtn" class="bg-primary text-white px-4 py-2 rounded hover:bg-primary/90 transition-colors flex items-center">
              <i class="fa fa-search mr-2"></i>查询数据
            </button>
          </div>
          
          <div class="h-[400px] relative">
            <canvas id="historyChart"></canvas>
            <div id="historyChartLoading" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex flex-col items-center hidden">
              <i class="fa fa-circle-o-notch fa-spin text-primary text-3xl mb-2"></i>
              <p class="text-neutral">加载历史数据中...</p>
            </div>
            <div id="historyChartEmpty" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex flex-col items-center">
              <i class="fa fa-bar-chart text-neutral text-3xl mb-2"></i>
              <p class="text-neutral">请选择指数和日期范围查询历史数据</p>
            </div>
          </div>
        </div>
        
        <div class="bg-white rounded-lg shadow-sm overflow-hidden">
          <div class="p-6 border-b border-gray-100">
            <h3 class="font-bold text-lg">历史数据列表</h3>
          </div>
          <div class="overflow-x-auto">
            <table class="min-w-full divide-y divide-gray-200">
              <thead class="bg-gray-50">
                <tr>
                  <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-neutral uppercase tracking-wider">日期</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">开盘价</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">最高价</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">最低价</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">收盘价</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">涨跌幅</th>
                  <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-neutral uppercase tracking-wider">成交量(万手)</th>
                </tr>
              </thead>
              <tbody class="bg-white divide-y divide-gray-200" id="historyTable">
                <tr>
                  <td colspan="7" class="px-6 py-10 text-center text-neutral">
                    <p>请先查询历史数据</p>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
          
          <div class="p-4 flex justify-between items-center border-t border-gray-100">
            <div class="text-sm text-neutral">显示 0 条记录</div>
            <div class="flex space-x-2">
              <button class="px-3 py-1 border border-gray-200 rounded text-sm text-neutral hover:bg-gray-50 disabled:opacity-50" disabled>上一页</button>
              <button class="px-3 py-1 border border-gray-200 rounded text-sm text-neutral hover:bg-gray-50 disabled:opacity-50" disabled>下一页</button>
            </div>
          </div>
        </div>
      </section>
      
      <!-- 3. 市场资讯页面 -->
      <section id="newsPage" class="page-content hidden">
        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
          <div class="lg:col-span-2">
            <div class="bg-white rounded-lg shadow-sm overflow-hidden mb-6">
              <div class="p-6 border-b border-gray-100">
                <h2 class="text-xl font-bold flex items-center">
                  <i class="fa fa-newspaper-o text-primary mr-2"></i>最新资讯
                </h2>
              </div>
              
              <div id="newsList" class="divide-y divide-gray-100">
                <!-- 新闻条目将通过JavaScript动态生成 -->
              </div>
              
              <div class="p-4 flex justify-center border-t border-gray-100">
                <button id="loadMoreNews" class="px-4 py-2 border border-primary text-primary rounded hover:bg-primary/5 transition-colors flex items-center">
                  <i class="fa fa-refresh mr-2"></i>加载更多
                </button>
              </div>
            </div>
          </div>
          
          <div>
            <div class="bg-white rounded-lg shadow-sm overflow-hidden mb-6">
              <div class="p-4 border-b border-gray-100">
                <h3 class="font-bold">热门板块</h3>
              </div>
              <div id="hotSectors" class="p-4">
                <!-- 热门板块将通过JavaScript动态生成 -->
              </div>
            </div>
            
            <div class="bg-white rounded-lg shadow-sm overflow-hidden">
              <div class="p-4 border-b border-gray-100">
                <h3 class="font-bold">市场日历</h3>
              </div>
              <div class="p-4">
                <div class="text-sm text-neutral mb-4">今日暂无重大事件</div>
                <div class="space-y-3">
                  <div class="p-3 bg-light rounded border border-gray-100">
                    <div class="font-medium text-sm">明日</div>
                    <div class="text-xs text-neutral mt-1">&#8226; 中国7月CPI数据公布</div>
                    <div class="text-xs text-neutral">&#8226; 3家公司IPO申购</div>
                  </div>
                  <div class="p-3 bg-light rounded border border-gray-100">
                    <div class="font-medium text-sm">本周六</div>
                    <div class="text-xs text-neutral mt-1">&#8226; 美联储公布7月货币政策会议纪要</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
      
      <!-- 4. 设置页面 -->
      <section id="settingsPage" class="page-content hidden">
        <div class="bg-white rounded-lg shadow-sm p-6 mb-6">
          <h2 class="text-xl font-bold mb-6 flex items-center">
            <i class="fa fa-cog text-primary mr-2"></i>系统设置
          </h2>
          
          <div class="space-y-6">
            <div>
              <h3 class="font-bold mb-4">刷新设置</h3>
              <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                  <label class="block text-sm font-medium text-neutral mb-1">默认刷新频率</label>
                  <select id="defaultRefreshInterval" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                    <option value="5">5秒</option>
                    <option value="10" selected>10秒</option>
                    <option value="30">30秒</option>
                    <option value="60">1分钟</option>
                    <option value="0">不自动刷新</option>
                  </select>
                </div>
                <div>
                  <label class="block text-sm font-medium text-neutral mb-1">休市时自动刷新</label>
                  <div class="flex items-center space-x-4">
                    <label class="inline-flex items-center">
                      <input type="radio" name="refreshWhenClosed" value="yes" class="text-primary focus:ring-primary">
                      <span class="ml-2">启用</span>
                    </label>
                    <label class="inline-flex items-center">
                      <input type="radio" name="refreshWhenClosed" value="no" checked class="text-primary focus:ring-primary">
                      <span class="ml-2">禁用</span>
                    </label>
                  </div>
                </div>
              </div>
            </div>
            
            <div class="pt-4 border-t border-gray-100">
              <h3 class="font-bold mb-4">显示设置</h3>
              <div class="space-y-4">
                <div class="flex items-center justify-between">
                  <div>
                    <div class="font-medium">深色模式</div>
                    <div class="text-sm text-neutral">切换深色/浅色显示主题</div>
                  </div>
                  <label class="relative inline-flex items-center cursor-pointer">
                    <input type="checkbox" id="darkModeToggle" class="sr-only peer">
                    <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-primary rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
                  </label>
                </div>
                
                <div class="flex items-center justify-between">
                  <div>
                    <div class="font-medium">显示涨跌动画</div>
                    <div class="text-sm text-neutral">指数涨跌时显示数值变化动画</div>
                  </div>
                  <label class="relative inline-flex items-center cursor-pointer">
                    <input type="checkbox" id="animateChangesToggle" checked class="sr-only peer">
                    <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-primary rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
                  </label>
                </div>
                
                <div class="flex items-center justify-between">
                  <div>
                    <div class="font-medium">显示成交量</div>
                    <div class="text-sm text-neutral">在指数卡片中显示成交量数据</div>
                  </div>
                  <label class="relative inline-flex items-center cursor-pointer">
                    <input type="checkbox" id="showVolumeToggle" checked class="sr-only peer">
                    <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-primary rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
                  </label>
                </div>
              </div>
            </div>
            
            <div class="pt-4 border-t border-gray-100">
              <h3 class="font-bold mb-4">通知设置</h3>
              <div class="space-y-4">
                <div class="flex items-center justify-between">
                  <div>
                    <div class="font-medium">指数预警</div>
                    <div class="text-sm text-neutral">当指数涨跌超过设定阈值时通知</div>
                  </div>
                  <label class="relative inline-flex items-center cursor-pointer">
                    <input type="checkbox" id="alertToggle" class="sr-only peer">
                    <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-1 peer-focus:ring-primary rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
                  </label>
                </div>
                
                <div id="alertThresholdContainer" class="hidden grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
                  <div>
                    <label class="block text-sm font-medium text-neutral mb-1">上涨预警阈值 (%)</label>
                    <input type="number" id="riseThreshold" step="0.1" min="0.1" max="10" value="1.0" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                  </div>
                  <div>
                    <label class="block text-sm font-medium text-neutral mb-1">下跌预警阈值 (%)</label>
                    <input type="number" id="fallThreshold" step="0.1" min="0.1" max="10" value="1.0" class="w-full border border-gray-200 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-primary">
                  </div>
                </div>
              </div>
            </div>
            
            <div class="pt-4 border-t border-gray-100 flex justify-end">
              <button id="saveSettingsBtn" class="bg-primary text-white px-6 py-2 rounded hover:bg-primary/90 transition-colors flex items-center">
                <i class="fa fa-save mr-2"></i>保存设置
              </button>
            </div>
          </div>
        </div>
      </section>
      
      <!-- 指数详情模态框 -->
      <div id="indexDetailModal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden flex items-center justify-center p-4">
        <div class="bg-white rounded-lg shadow-lg w-full max-w-3xl max-h-[90vh] overflow-hidden flex flex-col">
          <div class="p-4 border-b border-gray-100 flex justify-between items-center">
            <h3 class="text-lg font-bold" id="modalTitle">指数详情</h3>
            <button id="closeModalBtn" class="text-gray-500 hover:text-gray-700">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          
          <div class="p-6 overflow-y-auto flex-1" id="modalContent">
            <!-- 模态框内容将通过JavaScript动态生成 -->
          </div>
          
          <div class="p-4 border-t border-gray-100 flex justify-end">
            <button id="closeModalBtn2" class="bg-gray-100 text-gray-700 px-4 py-2 rounded hover:bg-gray-200 transition-colors">
              关闭
            </button>
          </div>
        </div>
      </div>
    </div>
  </main>
  
  <!-- 页脚 -->
  <footer class="bg-white border-t border-gray-200 py-6">
    <div class="container mx-auto px-4">
      <div class="flex flex-col md:flex-row justify-between items-center">
        <div class="mb-4 md:mb-0">
          <p class="text-neutral text-sm">&#169; 2023 A股指数监控工具. 数据仅供参考,不构成投资建议.</p>
        </div>
        <div class="flex space-x-6">
          <a href="#" class="text-neutral hover:text-primary transition-colors text-sm">关于我们</a>
          <a href="#" class="text-neutral hover:text-primary transition-colors text-sm">使用帮助</a>
          <a href="#" class="text-neutral hover:text-primary transition-colors text-sm">数据来源</a>
          <a href="#" class="text-neutral hover:text-primary transition-colors text-sm">联系我们</a>
        </div>
      </div>
    </div>
  </footer>
  
  <!-- 数据更新提示 -->
  <div id="updateToast" class="fixed bottom-4 right-4 bg-primary text-white px-4 py-2 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center">
    <i class="fa fa-refresh mr-2"></i>
    <span>数据已更新</span>
  </div>

  <!-- 错误提示 -->
  <div id="errorToast" class="fixed bottom-4 right-4 bg-fall text-white px-4 py-2 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center">
    <i class="fa fa-exclamation-circle mr-2"></i>
    <span id="errorMessage">数据加载失败</span>
  </div>

  <!-- 成功提示 -->
  <div id="successToast" class="fixed bottom-4 right-4 bg-rise text-white px-4 py-2 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center">
    <i class="fa fa-check-circle mr-2"></i>
    <span id="successMessage">操作成功</span>
  </div>

  <script>
    // 全局状态管理
    const appState = {
      currentPage: 'market',
      currentIndex: 'sse',
      currentPeriod: 'day',
      refreshIntervalId: null,
      indexData: {},
      sectorData: [],
      newsData: [],
      settings: {
        refreshInterval: 10,
        refreshWhenClosed: false,
        darkMode: false,
        animateChanges: true,
        showVolume: true,
        alertEnabled: false,
        riseThreshold: 1.0,
        fallThreshold: 1.0
      }
    };
    
    // 指数代码映射
    const indexCodes = {
      sse: { code: '000001', name: '上证指数', market: 'sh' },
      szse: { code: '399001', name: '深证成指', market: 'sz' },
      gem: { code: '399006', name: '创业板指', market: 'sz' },
      star: { code: '000688', name: '科创50', market: 'sh' }
    };
    
    // 行业板块代码
    const sectorCodes = [
      { name: '半导体', code: '881121' },
      { name: '新能源', code: '881151' },
      { name: '医疗健康', code: '881130' },
      { name: '证券', code: '881157' },
      { name: '银行', code: '881155' },
      { name: '房地产', code: '881153' },
      { name: '国防军工', code: '881124' },
      { name: '计算机', code: '881126' }
    ];
    
    // 模拟新闻数据
    const mockNewsData = [
      {
        id: 1,
        title: '上证指数震荡上行,科技板块领涨',
        source: '证券时报',
        time: '2023-06-15 09:35',
        content: '今日开盘后,上证指数小幅低开后迅速回升,科技板块表现活跃,半导体、人工智能等板块涨幅居前。市场交投情绪回暖,成交量较昨日有所放大。分析人士认为,随着政策面持续向好,市场信心逐步恢复,短期指数有望延续震荡上行趋势。'
      },
      {
        id: 2,
        title: '央行开展1000亿元逆回购操作,维持流动性合理充裕',
        source: '中国证券报',
        time: '2023-06-14 16:20',
        content: '央行今日开展1000亿元逆回购操作,中标利率为2.10%,与此前持平。因今日有500亿元逆回购到期,当日实现净投放500亿元。分析指出,央行此举旨在维护半年末流动性平稳,预计后续仍将有结构性货币政策工具推出。'
      },
      {
        id: 3,
        title: '新能源板块持续调整,机构称长期投资价值显现',
        source: '上海证券报',
        time: '2023-06-14 11:05',
        content: '近期新能源板块持续调整,光伏、锂电池等细分领域跌幅较大。对此,多家机构表示,板块调整主要受短期情绪影响,长期来看,新能源行业成长逻辑未变,随着产业链供需格局改善和技术进步,优质企业投资价值逐步显现。'
      },
      {
        id: 4,
        title: '证监会:进一步规范上市公司信息披露行为',
        source: '新华网',
        time: '2023-06-13 18:45',
        content: '证监会今日发布《关于进一步规范上市公司信息披露的指导意见》,要求上市公司切实提高信息披露质量,确保信息披露的真实、准确、完整、及时、公平。意见明确了对信息披露违规行为的惩戒措施,旨在保护投资者合法权益,维护资本市场秩序。'
      },
      {
        id: 5,
        title: '外资持续加仓A股,消费板块获青睐',
        source: '第一财经',
        time: '2023-06-13 10:20',
        content: '近期北向资金持续净流入A股市场,其中消费板块成为外资加仓重点。数据显示,过去一周北向资金累计净买入超过100亿元,食品饮料、家用电器等消费细分领域获显著增持。分析认为,随着国内消费市场逐步复苏,消费板块估值有望得到修复。'
      }
    ];
    
    // 图表实例
    let indexChart = null;
    let historyChart = null;
    
    // 工具函数 - 格式化数字
    function formatNumber(num, decimalPlaces = 2) {
      if (num === null || num === undefined || isNaN(num)) return '--';
      return num.toLocaleString('zh-CN', {
        minimumFractionDigits: decimalPlaces,
        maximumFractionDigits: decimalPlaces
      });
    }
    
    // 工具函数 - 格式化大数字(成交量、成交额)
    function formatLargeNumber(num) {
      if (num === null || num === undefined || isNaN(num)) return '--';
      
      // 成交量单位处理(手 -> 万手)
      if (num > 10000) {
        return (num / 10000).toFixed(2) + '万';
      }
      return num.toFixed(2);
    }
    
    // 工具函数 - 格式化成交额(元 -> 亿元)
    function formatAmount(num) {
      if (num === null || num === undefined || isNaN(num)) return '--';
      return (num / 100000000).toFixed(2);
    }
    
    // 工具函数 - 显示提示信息
    function showToast(elementId, message = '') {
      if (message) {
        const messageEl = document.getElementById(`${elementId}Message`);
        if (messageEl) messageEl.textContent = message;
      }
      
      const toast = document.getElementById(elementId);
      toast.classList.remove('translate-y-20', 'opacity-0');
      
      setTimeout(() => {
        toast.classList.add('translate-y-20', 'opacity-0');
      }, 3000);
    }
    
    // 页面导航功能
    function navigateToPage(pageId) {
      // 更新当前页面状态
      appState.currentPage = pageId;
      
      // 隐藏所有页面
      document.querySelectorAll('.page-content').forEach(page => {
        page.classList.add('hidden');
        page.classList.remove('page-transition');
      });
      
      // 显示目标页面
      const targetPage = document.getElementById(`${pageId}Page`);
      targetPage.classList.remove('hidden');
      // 触发重排后添加动画类
      setTimeout(() => {
        targetPage.classList.add('page-transition');
      }, 10);
      
      // 更新导航栏样式
      document.querySelectorAll('.nav-link, .mobile-nav-link').forEach(link => {
        if (link.dataset.page === pageId) {
          link.classList.add('text-primary', 'font-medium', 'border-b-2', 'border-primary');
          link.classList.remove('text-gray-600');
        } else {
          link.classList.remove('text-primary', 'font-medium', 'border-b-2', 'border-primary');
          link.classList.add('text-gray-600');
        }
      });
      
      // 关闭移动端菜单
      document.getElementById('mobileMenu').classList.add('hidden');
      
      // 如果导航到历史数据页面且未初始化图表,初始化图表
      if (pageId === 'history' && !historyChart) {
        initHistoryChart();
      }
      
      // 如果导航到资讯页面且未加载资讯,加载资讯
      if (pageId === 'news' && appState.newsData.length === 0) {
        loadNewsData();
        loadHotSectors();
      }
      
      // 如果导航到设置页面,加载设置
      if (pageId === 'settings') {
        loadSettings();
      }
    }
    
    // 更新当前时间
    function updateCurrentTime() {
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, '0');
      const day = String(now.getDate()).padStart(2, '0');
      const hours = String(now.getHours()).padStart(2, '0');
      const minutes = String(now.getMinutes()).padStart(2, '0');
      const seconds = String(now.getSeconds()).padStart(2, '0');
      
      const timeString = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
      document.getElementById('currentTime').textContent = timeString;
      
      // 设置历史数据默认日期范围(最近30天)
      if (!document.getElementById('historyStartDate').value) {
        const startDate = new Date();
        startDate.setDate(now.getDate() - 30);
        document.getElementById('historyStartDate').value = startDate.toISOString().split('T')[0];
        document.getElementById('historyEndDate').value = now.toISOString().split('T')[0];
      }
    }
    
    // 更新最后更新时间
    function updateLastUpdateTime() {
      const now = new Date();
      const hours = String(now.getHours()).padStart(2, '0');
      const minutes = String(now.getMinutes()).padStart(2, '0');
      const seconds = String(now.getSeconds()).padStart(2, '0');
      
      document.getElementById('lastUpdateTime').textContent = `最后更新: ${hours}:${minutes}:${seconds}`;
    }
    
    // 检查市场状态
    function checkMarketStatus() {
      const now = new Date();
      const day = now.getDay();
      const hours = now.getHours();
      const minutes = now.getMinutes();
      
      const statusEl = document.getElementById('marketStatus');
      const indicatorEl = document.getElementById('marketStatusIndicator');
      
      // 周末休市
      if (day === 0 || day === 6) {
        statusEl.textContent = '休市中';
        indicatorEl.className = 'inline-block w-3 h-3 rounded-full bg-neutral mr-2';
        indicatorEl.classList.remove('animate-pulse');
        return false;
      }
      
      // 交易日时间: 9:30-11:30, 13:00-15:00
      const isMorningSession = (hours === 9 && minutes >= 30) || (hours > 9 && hours < 11) || (hours === 11 && minutes <= 30);
      const isAfternoonSession = (hours === 13 && minutes >= 0) || (hours > 13 && hours < 15) || (hours === 15 && minutes === 0);
      
      if (isMorningSession || isAfternoonSession) {
        statusEl.textContent = '交易中';
        indicatorEl.className = 'inline-block w-3 h-3 rounded-full bg-rise mr-2 animate-pulse';
        return true;
      } else {
        statusEl.textContent = '休市中';
        indicatorEl.className = 'inline-block w-3 h-3 rounded-full bg-neutral mr-2';
        indicatorEl.classList.remove('animate-pulse');
        return false;
      }
    }
    
    // 从公开数据源获取指数数据
    async function fetchIndexData(indexType) {
      try {
        const indexInfo = indexCodes[indexType];
        // 使用公开的财经数据接口获取数据
        const url = `https://hq.sinajs.cn/list=${indexInfo.market}${indexInfo.code}`;
        
        const response = await fetch(url);
        const data = await response.text();
        
        // 解析数据
        // 新浪财经接口返回格式: var hq_str_sh000001="上证指数,3286.45,23.12,0.71,3265.78,3291.23,3262.15,3263.33,283000000,325600000000";
        const match = data.match(/"(.*?)"/);
        if (!match) throw new Error('数据格式错误');
        
        const parts = match[1].split(',');
        if (parts.length < 9) throw new Error('数据不完整');
        
        const result = {
          name: parts[0],
          price: parseFloat(parts[1]),
          change: parseFloat(parts[2]),
          percent: parseFloat(parts[3]),
          open: parseFloat(parts[4]),
          high: parseFloat(parts[5]),
          low: parseFloat(parts[6]),
          prevClose: parseFloat(parts[7]),
          volume: parseFloat(parts[8]),
          amount: parseFloat(parts[9])
        };
        
        // 保存到全局状态
        appState.indexData[indexType] = result;
        
        return result;
      } catch (error) {
        console.error(`获取${indexType}数据失败:`, error);
        showToast('errorToast', `获取${indexCodes[indexType].name}数据失败`);
        return null;
      }
    }
    
    // 更新指数卡片数据
    async function updateIndexCard(indexType) {
      const data = await fetchIndexData(indexType);
      if (!data) return false;
      
      // 更新指数值
      const indexEl = document.getElementById(`${indexType}Index`);
      if (appState.settings.animateChanges && indexEl.textContent !== '--') {
        animateValueChange(indexEl, parseFloat(indexEl.textContent.replace(/,/g, '')), data.price);
      } else {
        indexEl.textContent = formatNumber(data.price);
      }
      
      // 更新涨跌额和涨跌幅
      const changeEl = document.getElementById(`${indexType}Change`);
      const percentEl = document.getElementById(`${indexType}Percent`);
      
      // 设置涨跌颜色和内容
      if (data.change >= 0) {
        changeEl.className = 'rise font-medium';
        percentEl.className = 'rise ml-2 text-sm';
        changeEl.textContent = `+${formatNumber(data.change)}`;
        percentEl.textContent = `+${formatNumber(data.percent, 2)}%`;
      } else {
        changeEl.className = 'fall font-medium';
        percentEl.className = 'fall ml-2 text-sm';
        changeEl.textContent = formatNumber(data.change);
        percentEl.textContent = `${formatNumber(data.percent, 2)}%`;
      }
      
      // 更新其他数据
      document.getElementById(`${indexType}Open`).textContent = formatNumber(data.open);
      document.getElementById(`${indexType}High`).textContent = formatNumber(data.high);
      document.getElementById(`${indexType}Low`).textContent = formatNumber(data.low);
      document.getElementById(`${indexType}Close`).textContent = formatNumber(data.prevClose);
      
      // 根据设置决定是否显示成交量
      const volumeEl = document.getElementById(`${indexType}Volume`);
      const amountEl = document.getElementById(`${indexType}Amount`);
      
      if (appState.settings.showVolume) {
        volumeEl.textContent = formatLargeNumber(data.volume);
        amountEl.textContent = formatAmount(data.amount) + '亿';
      } else {
        volumeEl.textContent = '隐藏';
        amountEl.textContent = '隐藏';
      }
      
      // 检查是否触发预警
      if (appState.settings.alertEnabled) {
        checkIndexAlert(indexType, data);
      }
      
      return true;
    }
    
    // 检查指数是否触发预警
    function checkIndexAlert(indexType, data) {
      if (Math.abs(data.percent) >= appState.settings.riseThreshold && data.percent > 0) {
        showToast('errorToast', `${indexCodes[indexType].name}上涨超过${appState.settings.riseThreshold}%`);
      } else if (Math.abs(data.percent) >= appState.settings.fallThreshold && data.percent < 0) {
        showToast('errorToast', `${indexCodes[indexType].name}下跌超过${appState.settings.fallThreshold}%`);
      }
    }
    
    // 批量更新所有指数卡片
    async function updateAllIndexCards() {
      const indexTypes = Object.keys(indexCodes);
      let allSuccess = true;
      
      for (const type of indexTypes) {
        const success = await updateIndexCard(type);
        if (!success) allSuccess = false;
      }
      
      if (allSuccess) {
        updateLastUpdateTime();
        showToast('updateToast', '数据已更新');
      }
      
      return allSuccess;
    }
    
    // 从数据源获取板块数据
    async function fetchSectorData(sector) {
      try {
        const url = `https://hq.sinajs.cn/list=zs${sector.code}`;
        const response = await fetch(url);
        const data = await response.text();
        
        // 解析板块数据
        const match = data.match(/"(.*?)"/);
        if (!match) throw new Error('板块数据格式错误');
        
        const parts = match[1].split(',');
        if (parts.length < 9) throw new Error('板块数据不完整');
        
        return {
          name: sector.name,
          code: sector.code,
          price: parseFloat(parts[1]),
          change: parseFloat(parts[2]),
          percent: parseFloat(parts[3]),
          volume: parseFloat(parts[8]),
          amount: parseFloat(parts[9])
        };
      } catch (error) {
        console.error(`获取${sector.name}数据失败:`, error);
        return {
          name: sector.name,
          code: sector.code,
          price: null,
          change: null,
          percent: null,
          volume: null,
          amount: null
        };
      }
    }
    
    // 更新行业板块表格
    async function updateSectorTable() {
      const tableBody = document.getElementById('sectorTable');
      tableBody.innerHTML = '';
      
      // 并行获取所有板块数据
      const sectorPromises = sectorCodes.map(sector => fetchSectorData(sector));
      const sectorsData = await Promise.all(sectorPromises);
      
      // 保存到全局状态
      appState.sectorData = sectorsData;
      
      sectorsData.forEach(sector => {
        const row = document.createElement('tr');
        row.className = 'hover:bg-gray-50 transition-colors cursor-pointer';
        row.addEventListener('click', () => {
          showSectorDetail(sector);
        });
        
        // 涨跌颜色判断
        const changeClass = sector.change !== null && sector.change >= 0 ? 'text-rise' : 'text-fall';
        
        row.innerHTML = `
          <td class="px-6 py-4 whitespace-nowrap">
            <div class="font-medium">${sector.name}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-neutral">
            <div>${sector.code}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right">
            <div>${formatNumber(sector.price)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right ${changeClass}">
            <div>${sector.percent !== null ? `${sector.percent >= 0 ? '+' : ''}${formatNumber(sector.percent, 2)}%` : '--'}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right ${changeClass}">
            <div>${sector.change !== null ? `${sector.change >= 0 ? '+' : ''}${formatNumber(sector.change)}` : '--'}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right text-neutral">
            <div>${formatLargeNumber(sector.volume)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right text-neutral">
            <div>${sector.amount !== null ? formatAmount(sector.amount) : '--'}</div>
          </td>
        `;
        
        tableBody.appendChild(row);
      });
    }
    
    // 显示板块详情
    function showSectorDetail(sector) {
      const modalTitle = document.getElementById('modalTitle');
      const modalContent = document.getElementById('modalContent');
      
      modalTitle.textContent = `${sector.name}(${sector.code}) 详情`;
      
      // 涨跌颜色判断
      const changeClass = sector.change !== null && sector.change >= 0 ? 'text-rise' : 'text-fall';
      
      modalContent.innerHTML = `
        <div class="text-center mb-6">
          <div class="text-3xl font-bold mb-2">${formatNumber(sector.price)}</div>
          <div class="flex items-center justify-center">
            <span class="${changeClass} text-xl font-medium">${sector.change !== null ? (sector.change >= 0 ? '+' : '') + formatNumber(sector.change) : '--'}</span>
            <span class="${changeClass} ml-3 text-xl">${sector.percent !== null ? (sector.percent >= 0 ? '+' : '') + formatNumber(sector.percent, 2) + '%' : '--'}</span>
          </div>
        </div>
        
        <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">今开</div>
            <div class="font-medium">${formatNumber(sector.open)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">最高</div>
            <div class="font-medium">${formatNumber(sector.high)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">最低</div>
            <div class="font-medium">${formatNumber(sector.low)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">昨收</div>
            <div class="font-medium">${formatNumber(sector.prevClose)}</div>
          </div>
        </div>
        
        <div class="mb-6">
          <h4 class="font-medium mb-3">板块简介</h4>
          <p class="text-sm text-neutral">${sector.name}板块包含该行业内的主要上市公司,反映了该行业的整体表现。板块成分股涵盖了行业内规模较大、流动性较好的公司,是投资者了解行业景气度的重要参考指标。</p>
        </div>
        
        <div>
          <h4 class="font-medium mb-3">近期表现</h4>
          <div class="h-[200px]">
            <canvas id="sectorDetailChart"></canvas>
          </div>
        </div>
      `;
      
      // 显示模态框
      document.getElementById('indexDetailModal').classList.remove('hidden');
      
      // 生成板块详情图表
      generateSectorDetailChart(sector);
    }
    
    // 生成板块详情图表
    function generateSectorDetailChart(sector) {
      const ctx = document.getElementById('sectorDetailChart').getContext('2d');
      
      // 生成模拟的板块历史数据
      const generateMockData = () => {
        const data = [];
        let value = sector.price || 5000;
        
        for (let i = 14; i >= 0; i--) {
          const date = new Date();
          date.setDate(date.getDate() - i);
          
          // 跳过周末
          const day = date.getDay();
          if (day === 0 || day === 6) continue;
          
          // 随机波动
          const change = (Math.random() - 0.5) * 2 * 50;
          value += change;
          
          data.push({
            date: `${date.getMonth() + 1}/${date.getDate()}`,
            value: Number(value.toFixed(2))
          });
        }
        
        return data;
      };
      
      const mockData = generateMockData();
      const labels = mockData.map(item => item.date);
      const values = mockData.map(item => item.value);
      
      new Chart(ctx, {
        type: 'line',
        data: {
          labels: labels,
          datasets: [{
            label: sector.name,
            data: values,
            borderColor: '#165DFF',
            backgroundColor: 'rgba(22, 93, 255, 0.1)',
            borderWidth: 2,
            pointRadius: 3,
            pointBackgroundColor: '#165DFF',
            fill: true,
            tension: 0.2
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              display: false
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              }
            },
            y: {
              grid: {
                color: 'rgba(0, 0, 0, 0.05)'
              }
            }
          }
        }
      });
    }
    
    // 从数据源获取K线数据
    async function fetchKlineData(indexType, period = 'day') {
      try {
        const indexInfo = indexCodes[indexType];
        
        // 这里使用模拟数据,实际应用中需要替换为真实的K线数据接口
        if (period === 'day') {
          // 日K线数据 - 模拟最近30天
          return generateMockKlineData(30, indexType);
        } else {
          // 分时数据 - 模拟当天交易时段
          return generateMockMinuteData(indexType);
        }
      } catch (error) {
        console.error(`获取${indexType}K线数据失败:`, error);
        showToast('errorToast', `获取${indexCodes[indexType].name}图表数据失败`);
        return null;
      }
    }
    
    // 生成模拟K线数据
    function generateMockKlineData(days, indexType) {
      // 基础值
      const baseValues = {
        sse: 3260,
        szse: 11500,
        gem: 2360,
        star: 1080
      };
      
      // 波动率
      const volatility = {
        sse: 15,
        szse: 80,
        gem: 30,
        star: 10
      };
      
      const data = [];
      let value = baseValues[indexType];
      const today = new Date();
      
      for (let i = days; i >= 0; i--) {
        const date = new Date();
        date.setDate(today.getDate() - i);
        
        // 跳过周末
        const day = date.getDay();
        if (day === 0 || day === 6) continue;
        
        // 随机波动
        const change = (Math.random() - 0.5) * 2 * volatility[indexType];
        value += change;
        
        const open = value;
        const high = value + Math.random() * volatility[indexType] * 0.5;
        const low = value - Math.random() * volatility[indexType] * 0.5;
        const close = value;
        
        data.push({
          date: `${date.getMonth() + 1}/${date.getDate()}`,
          open: Number(open.toFixed(2)),
          high: Number(high.toFixed(2)),
          low: Number(low.toFixed(2)),
          close: Number(close.toFixed(2)),
          volume: Math.floor(Math.random() * 100000000) + 100000000
        });
      }
      
      return data;
    }
    
    // 生成模拟分时数据
    function generateMockMinuteData(indexType) {
      // 基础值
      const baseValues = {
        sse: 3263.33,
        szse: 11498.56,
        gem: 2364.23,
        star: 1081.65
      };
      
      // 波动率
      const volatility = {
        sse: 2,
        szse: 8,
        gem: 4,
        star: 1.5
      };
      
      // 生成时间标签(9:30-15:00的交易时间)
      const generateTimeLabels = () => {
        const labels = [];
        let hour = 9;
        let minute = 30;
        
        while (hour < 15 || (hour === 15 && minute === 0)) {
          labels.push(`${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`);
          
          minute += 5; // 每5分钟一个数据点
          if (minute >= 60) {
            minute = 0;
            hour++;
            
            // 跳过午休时间(11:30-13:00)
            if (hour === 11 && minute === 30) {
              hour = 13;
              minute = 0;
            }
          }
        }
        
        return labels;
      };
      
      const timeLabels = generateTimeLabels();
      const data = [];
      let value = baseValues[indexType];
      
      timeLabels.forEach(time => {
        // 随机波动
        const change = (Math.random() - 0.5) * 2 * volatility[indexType];
        value += change;
        
        data.push({
          time: time,
          price: Number(value.toFixed(2)),
          volume: Math.floor(Math.random() * 1000000) + 500000
        });
      });
      
      return data;
    }
    
    // 初始化主图表
    function initChart() {
      const ctx = document.getElementById('indexChart').getContext('2d');
      
      // 创建空图表
      indexChart = new Chart(ctx, {
        type: 'line',
        data: {
          labels: [],
          datasets: [{
            label: indexCodes[appState.currentIndex].name,
            data: [],
            borderColor: '#165DFF',
            backgroundColor: 'rgba(22, 93, 255, 0.1)',
            borderWidth: 2,
            pointRadius: 0,
            pointHoverRadius: 4,
            pointBackgroundColor: '#165DFF',
            fill: true,
            tension: 0.2,
            spanGaps: false
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          interaction: {
            mode: 'index',
            intersect: false,
          },
          plugins: {
            legend: {
              display: false
            },
            tooltip: {
              backgroundColor: 'rgba(0, 0, 0, 0.7)',
              padding: 10,
              titleFont: {
                size: 14
              },
              bodyFont: {
                size: 13
              },
              callbacks: {
                label: function(context) {
                  return `指数: ${context.raw}`;
                }
              }
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              },
              ticks: {
                maxTicksLimit: 8
              }
            },
            y: {
              position: 'right',
              grid: {
                color: 'rgba(0, 0, 0, 0.05)'
              },
              ticks: {
                callback: function(value) {
                  return value.toLocaleString();
                }
              }
            }
          },
          animation: {
            duration: 1000,
            easing: 'easeOutQuart'
          }
        }
      });
      
      // 加载实际数据
      updateChartData(appState.currentIndex, appState.currentPeriod);
    }
    
    // 初始化历史数据图表
    function initHistoryChart() {
      const ctx = document.getElementById('historyChart').getContext('2d');
      
      // 创建空图表
      historyChart = new Chart(ctx, {
        type: 'line',
        data: {
          labels: [],
          datasets: [{
            label: indexCodes[appState.currentIndex].name,
            data: [],
            borderColor: '#165DFF',
            backgroundColor: 'rgba(22, 93, 255, 0.1)',
            borderWidth: 2,
            pointRadius: 3,
            pointBackgroundColor: '#165DFF',
            fill: true,
            tension: 0.2
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          interaction: {
            mode: 'index',
            intersect: false,
          },
          plugins: {
            legend: {
              display: true,
              position: 'top'
            },
            tooltip: {
              backgroundColor: 'rgba(0, 0, 0, 0.7)',
              padding: 10,
              callbacks: {
                label: function(context) {
                  return `指数: ${context.raw}`;
                }
              }
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              }
            },
            y: {
              position: 'right',
              grid: {
                color: 'rgba(0, 0, 0, 0.05)'
              },
              ticks: {
                callback: function(value) {
                  return value.toLocaleString();
                }
              }
            }
          }
        }
      });
    }
    
    // 更新图表数据
    async function updateChartData(indexType, period = 'day') {
      // 显示加载指示器
      document.getElementById('chartLoading').style.display = 'flex';
      
      try {
        const data = await fetchKlineData(indexType, period);
        if (!data || data.length === 0) {
          throw new Error('未获取到图表数据');
        }
        
        // 更新全局状态
        appState.currentIndex = indexType;
        appState.currentPeriod = period;
        
        // 准备图表数据
        const labels = [];
        const priceData = [];
        
        if (period === 'day') {
          // 日K线数据
          data.forEach(item => {
            labels.push(item.date);
            priceData.push(item.close);
          });
        } else {
          // 分时数据
          data.forEach(item => {
            labels.push(item.time);
            priceData.push(item.price);
          });
        }
        
        // 设置图表颜色
        const colors = {
          sse: '#165DFF',
          szse: '#722ED1',
          gem: '#EB0AA4',
          star: '#F5319D'
        };
        
        // 更新图表
        indexChart.data.labels = labels;
        indexChart.data.datasets[0].data = priceData;
        indexChart.data.datasets[0].label = indexCodes[indexType].name;
        indexChart.data.datasets[0].borderColor = colors[indexType] || '#165DFF';
        indexChart.data.datasets[0].backgroundColor = `${colors[indexType] || '#165DFF'}33`; // 添加透明度
        indexChart.data.datasets[0].pointBackgroundColor = colors[indexType] || '#165DFF';
        indexChart.update();
      } catch (error) {
        console.error('更新图表失败:', error);
        showToast('errorToast', '图表数据更新失败');
      } finally {
        // 隐藏加载指示器
        document.getElementById('chartLoading').style.display = 'none';
      }
    }
    
    // 查询历史数据
    async function queryHistoryData() {
      const indexType = document.getElementById('historyIndexSelect').value;
      const period = document.getElementById('historyPeriodSelect').value;
      const startDate = document.getElementById('historyStartDate').value;
      const endDate = document.getElementById('historyEndDate').value;
      
      if (!startDate || !endDate) {
        showToast('errorToast', '请选择日期范围');
        return;
      }
      
      // 显示加载状态
      document.getElementById('historyChartEmpty').style.display = 'none';
      document.getElementById('historyChartLoading').style.display = 'flex';
      document.getElementById('historyTable').innerHTML = `
        <tr>
          <td colspan="7" class="px-6 py-10 text-center text-neutral">
            <div class="flex flex-col items-center">
              <i class="fa fa-circle-o-notch fa-spin text-primary text-xl mb-2"></i>
              <p>加载历史数据中...</p>
            </div>
          </td>
        </tr>
      `;
      
      try {
        // 生成模拟的历史数据
        const days = Math.ceil((new Date(endDate) - new Date(startDate)) / (1000 * 60 * 60 * 24));
        const data = generateMockKlineData(days, indexType);
        
        // 准备图表数据
        const labels = data.map(item => item.date);
        const priceData = data.map(item => item.close);
        
        // 设置图表颜色
        const colors = {
          sse: '#165DFF',
          szse: '#722ED1',
          gem: '#EB0AA4',
          star: '#F5319D'
        };
        
        // 更新历史图表
        historyChart.data.labels = labels;
        historyChart.data.datasets[0].data = priceData;
        historyChart.data.datasets[0].label = indexCodes[indexType].name;
        historyChart.data.datasets[0].borderColor = colors[indexType] || '#165DFF';
        historyChart.data.datasets[0].backgroundColor = `${colors[indexType] || '#165DFF'}33`;
        historyChart.data.datasets[0].pointBackgroundColor = colors[indexType] || '#165DFF';
        historyChart.update();
        
        // 更新历史表格
        updateHistoryTable(data);
      } catch (error) {
        console.error('查询历史数据失败:', error);
        showToast('errorToast', '查询历史数据失败');
        document.getElementById('historyTable').innerHTML = `
          <tr>
            <td colspan="7" class="px-6 py-10 text-center text-neutral">
              <p>加载历史数据失败,请重试</p>
            </td>
          </tr>
        `;
      } finally {
        // 隐藏加载状态
        document.getElementById('historyChartLoading').style.display = 'none';
      }
    }
    
    // 更新历史数据表格
    function updateHistoryTable(data) {
      const tableBody = document.getElementById('historyTable');
      tableBody.innerHTML = '';
      
      // 只显示最近30条记录
      const displayData = data.slice(-30).reverse();
      
      displayData.forEach(item => {
        // 计算涨跌幅
        const prevItem = data[data.indexOf(item) - 1];
        const change = prevItem ? item.close - prevItem.close : 0;
        const percent = prevItem ? (change / prevItem.close) * 100 : 0;
        
        // 涨跌颜色判断
        const changeClass = change >= 0 ? 'text-rise' : 'text-fall';
        
        const row = document.createElement('tr');
        row.className = 'hover:bg-gray-50 transition-colors';
        
        row.innerHTML = `
          <td class="px-6 py-4 whitespace-nowrap">
            <div>${item.date}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right">
            <div>${formatNumber(item.open)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right">
            <div>${formatNumber(item.high)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right">
            <div>${formatNumber(item.low)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right">
            <div>${formatNumber(item.close)}</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right ${changeClass}">
            <div>${percent >= 0 ? '+' : ''}${formatNumber(percent, 2)}%</div>
          </td>
          <td class="px-6 py-4 whitespace-nowrap text-right text-neutral">
            <div>${formatLargeNumber(item.volume)}</div>
          </td>
        `;
        
        tableBody.appendChild(row);
      });
      
      // 更新分页信息
      const paginationEl = tableBody.nextElementSibling;
      paginationEl.querySelector('.text-sm').textContent = `显示 ${displayData.length} 条记录,共 ${data.length} 条`;
    }
    
    // 加载新闻数据
    function loadNewsData() {
      // 使用模拟新闻数据
      appState.newsData = mockNewsData;
      
      const newsListEl = document.getElementById('newsList');
      newsListEl.innerHTML = '';
      
      appState.newsData.forEach(news => {
        const newsItem = document.createElement('div');
        newsItem.className = 'p-6 hover:bg-gray-50 transition-colors cursor-pointer';
        newsItem.addEventListener('click', () => showNewsDetail(news));
        
        newsItem.innerHTML = `
          <h3 class="font-bold text-lg mb-2 line-clamp-2">${news.title}</h3>
          <p class="text-neutral text-sm mb-3 line-clamp-2">${news.content}</p>
          <div class="flex justify-between text-xs text-neutral">
            <span>${news.source}</span>
            <span>${news.time}</span>
          </div>
        `;
        
        newsListEl.appendChild(newsItem);
      });
    }
    
    // 显示新闻详情
    function showNewsDetail(news) {
      const modalTitle = document.getElementById('modalTitle');
      const modalContent = document.getElementById('modalContent');
      
      modalTitle.textContent = news.title;
      
      modalContent.innerHTML = `
        <div class="text-sm text-neutral mb-4 flex justify-between">
          <span>${news.source}</span>
          <span>${news.time}</span>
        </div>
        
        <div class="prose max-w-none">
          <p>${news.content}</p>
          <p class="mt-4">市场分析人士表示,当前A股市场处于震荡整理阶段,投资者应保持理性,关注政策面和基本面变化,把握结构性机会。中长期来看,随着经济复苏向好和企业盈利改善,A股市场有望逐步走强。</p>
          <p class="mt-4">风险提示:市场有风险,投资需谨慎。本文观点仅供参考,不构成投资建议。</p>
        </div>
      `;
      
      // 显示模态框
      document.getElementById('indexDetailModal').classList.remove('hidden');
    }
    
    // 加载更多新闻
    function loadMoreNews() {
      // 复制现有新闻并修改ID和时间,模拟加载更多
      const newNews = appState.newsData.map(news => {
        const newDate = new Date(news.time);
        newDate.setDate(newDate.getDate() - 1);
        
        return {
          ...news,
          id: news.id + 100,
          time: `${newDate.getFullYear()}-${String(newDate.getMonth() + 1).padStart(2, '0')}-${String(newDate.getDate()).padStart(2, '0')} ${String(newDate.getHours()).padStart(2, '0')}:${String(newDate.getMinutes()).padStart(2, '0')}`
        };
      });
      
      appState.newsData = [...appState.newsData, ...newNews];
      
      // 更新新闻列表
      loadNewsData();
      
      showToast('successToast', '已加载更多资讯');
    }
    
    // 加载热门板块
    function loadHotSectors() {
      const hotSectorsEl = document.getElementById('hotSectors');
      hotSectorsEl.innerHTML = '';
      
      // 从板块数据中筛选涨幅前5的板块
      const sortedSectors = [...appState.sectorData]
        .sort((a, b) => (b.percent || 0) - (a.percent || 0))
        .slice(0, 5);
      
      sortedSectors.forEach((sector, index) => {
        const sectorItem = document.createElement('div');
        sectorItem.className = 'flex items-center justify-between py-2 border-b border-gray-100 last:border-0';
        
        // 涨跌颜色判断
        const changeClass = sector.change !== null && sector.change >= 0 ? 'text-rise' : 'text-fall';
        // 前三名添加特殊标识
        const rankClass = index < 3 ? 'bg-primary/10 text-primary' : 'bg-gray-100 text-neutral';
        
        sectorItem.innerHTML = `
          <div class="flex items-center">
            <span class="w-5 h-5 flex items-center justify-center rounded-full ${rankClass} text-xs mr-3">${index + 1}</span>
            <span>${sector.name}</span>
          </div>
          <span class="${changeClass}">${sector.percent !== null ? `${sector.percent >= 0 ? '+' : ''}${formatNumber(sector.percent, 2)}%` : '--'}</span>
        `;
        
        sectorItem.addEventListener('click', () => showSectorDetail(sector));
        hotSectorsEl.appendChild(sectorItem);
      });
    }
    
    // 加载设置
    function loadSettings() {
      // 从全局状态加载设置到表单
      document.getElementById('defaultRefreshInterval').value = appState.settings.refreshInterval;
      document.getElementById('refreshWhenClosed').value = appState.settings.refreshWhenClosed ? 'yes' : 'no';
      document.getElementById('darkModeToggle').checked = appState.settings.darkMode;
      document.getElementById('animateChangesToggle').checked = appState.settings.animateChanges;
      document.getElementById('showVolumeToggle').checked = appState.settings.showVolume;
      document.getElementById('alertToggle').checked = appState.settings.alertEnabled;
      document.getElementById('riseThreshold').value = appState.settings.riseThreshold;
      document.getElementById('fallThreshold').value = appState.settings.fallThreshold;
      
      // 显示/隐藏预警阈值设置
      document.getElementById('alertThresholdContainer').classList.toggle('hidden', !appState.settings.alertEnabled);
      
      // 应用深色模式
      applyDarkMode(appState.settings.darkMode);
    }
    
    // 保存设置
    function saveSettings() {
      // 从表单获取设置并保存到全局状态
      appState.settings.refreshInterval = parseInt(document.getElementById('defaultRefreshInterval').value);
      appState.settings.refreshWhenClosed = document.getElementById('refreshWhenClosed').value === 'yes';
      appState.settings.darkMode = document.getElementById('darkModeToggle').checked;
      appState.settings.animateChanges = document.getElementById('animateChangesToggle').checked;
      appState.settings.showVolume = document.getElementById('showVolumeToggle').checked;
      appState.settings.alertEnabled = document.getElementById('alertToggle').checked;
      appState.settings.riseThreshold = parseFloat(document.getElementById('riseThreshold').value);
      appState.settings.fallThreshold = parseFloat(document.getElementById('fallThreshold').value);
      
      // 应用设置
      applySettings();
      
      // 显示成功提示
      showToast('successToast', '设置已保存');
      
      // 如果在设置页面,切换到市场页面
      navigateToPage('market');
    }
    
    // 应用设置
    function applySettings() {
      // 应用刷新频率设置
      document.getElementById('refreshInterval').value = appState.settings.refreshInterval;
      setupAutoRefresh();
      
      // 应用深色模式
      applyDarkMode(appState.settings.darkMode);
      
      // 重新加载指数卡片以应用成交量显示设置
      updateAllIndexCards();
      
      // 显示/隐藏预警阈值设置
      document.getElementById('alertThresholdContainer').classList.toggle('hidden', !appState.settings.alertEnabled);
    }
    
    // 应用深色模式
    function applyDarkMode(enable) {
      if (enable) {
        document.body.classList.add('bg-gray-900', 'text-white');
        document.body.classList.remove('bg-gray-50', 'text-dark');
      } else {
        document.body.classList.add('bg-gray-50', 'text-dark');
        document.body.classList.remove('bg-gray-900', 'text-white');
      }
    }
    
    // 显示指数详情
    function showIndexDetail(indexType) {
      const indexInfo = indexCodes[indexType];
      const indexData = appState.indexData[indexType];
      
      if (!indexData) {
        showToast('errorToast', '暂无该指数数据');
        return;
      }
      
      const modalTitle = document.getElementById('modalTitle');
      const modalContent = document.getElementById('modalContent');
      
      modalTitle.textContent = `${indexInfo.name}(${indexInfo.code}.${indexInfo.market.toUpperCase()}) 详情`;
      
      // 涨跌颜色判断
      const changeClass = indexData.change >= 0 ? 'text-rise' : 'text-fall';
      
      modalContent.innerHTML = `
        <div class="text-center mb-6">
          <div class="text-3xl font-bold mb-2">${formatNumber(indexData.price)}</div>
          <div class="flex items-center justify-center">
            <span class="${changeClass} text-xl font-medium">${indexData.change >= 0 ? '+' : ''}${formatNumber(indexData.change)}</span>
            <span class="${changeClass} ml-3 text-xl">${indexData.change >= 0 ? '+' : ''}${formatNumber(indexData.percent, 2)}%</span>
          </div>
        </div>
        
        <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">今开</div>
            <div class="font-medium">${formatNumber(indexData.open)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">最高</div>
            <div class="font-medium">${formatNumber(indexData.high)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">最低</div>
            <div class="font-medium">${formatNumber(indexData.low)}</div>
          </div>
          <div class="bg-light p-3 rounded">
            <div class="text-sm text-neutral">昨收</div>
            <div class="font-medium">${formatNumber(indexData.prevClose)}</div>
          </div>
        </div>
        
        <div class="mb-6">
          <h4 class="font-medium mb-3">指数简介</h4>
          <p class="text-sm text-neutral">${getIndexDescription(indexType)}</p>
        </div>
        
        <div>
          <h4 class="font-medium mb-3">近期表现</h4>
          <div class="h-[200px]">
            <canvas id="indexDetailChart"></canvas>
          </div>
        </div>
      `;
      
      // 显示模态框
      document.getElementById('indexDetailModal').classList.remove('hidden');
      
      // 生成指数详情图表
      generateIndexDetailChart(indexType);
    }
    
    // 获取指数描述
    function getIndexDescription(indexType) {
      const descriptions = {
        sse: '上证指数(000001.SH)是上海证券交易所编制的,以上海证券交易所挂牌上市的全部股票为计算范围,以发行量为权数的加权综合股价指数。上证指数反映了上海证券交易市场的总体走势。',
        szse: '深证成指(399001.SZ)是深圳证券交易所的主要股指。它是按一定标准选出500家有代表性的上市公司作为样本股,用样本股的自由流通股数作为权数,采用派氏加权法编制而成的股价指标。',
        gem: '创业板指(399006.SZ)是反映创业板市场整体走势的核心指数,由创业板中市值大、流动性好的100家上市公司组成,具有较高的市场代表性。',
        star: '科创50(000688.SH)由上海证券交易所科创板中市值大、流动性好的50只证券组成,反映最具市场代表性的一批科创企业的整体表现。'
      };
      
      return descriptions[indexType] || '';
    }
    
    // 生成指数详情图表
    function generateIndexDetailChart(indexType) {
      const ctx = document.getElementById('indexDetailChart').getContext('2d');
      
      // 获取该指数的K线数据
      fetchKlineData(indexType, 'day').then(data => {
        if (!data) return;
        
        const labels = data.map(item => item.date);
        const values = data.map(item => item.close);
        
        new Chart(ctx, {
          type: 'line',
          data: {
            labels: labels,
            datasets: [{
              label: indexCodes[indexType].name,
              data: values,
              borderColor: '#165DFF',
              backgroundColor: 'rgba(22, 93, 255, 0.1)',
              borderWidth: 2,
              pointRadius: 3,
              pointBackgroundColor: '#165DFF',
              fill: true,
              tension: 0.2
            }]
          },
          options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
              legend: {
                display: false
              }
            },
            scales: {
              x: {
                grid: {
                  display: false
                }
              },
              y: {
                grid: {
                  color: 'rgba(0, 0, 0, 0.05)'
                }
              }
            }
          }
        });
      });
    }
    
    // 数值变化动画
    function animateValueChange(element, start, end, duration = 1000) {
      let startTimestamp = null;
      const step = (timestamp) => {
        if (!startTimestamp) startTimestamp = timestamp;
        const progress = Math.min((timestamp - startTimestamp) / duration, 1);
        const value = start + progress * (end - start);
        element.textContent = formatNumber(value);
        if (progress < 1) {
          window.requestAnimationFrame(step);
        }
      };
      window.requestAnimationFrame(step);
    }
    
    // 自动刷新功能
    function setupAutoRefresh() {
      // 清除现有定时器
      if (appState.refreshIntervalId) {
        clearInterval(appState.refreshIntervalId);
      }
      
      const interval = parseInt(document.getElementById('refreshInterval').value) * 1000;
      
      // 如果选择不自动刷新,直接返回
      if (interval === 0) return;
      
      // 设置新的定时器
      appState.refreshIntervalId = setInterval(async () => {
        // 检查是否在交易时间或设置了休市时刷新
        const isTrading = checkMarketStatus();
        if (isTrading || appState.settings.refreshWhenClosed) {
          const success = await updateAllIndexCards();
          if (success) {
            // 每3次数据刷新,更新一次图表
            const now = new Date();
            if (now.getMinutes() % 3 === 0) {
              updateChartData(appState.currentIndex, appState.currentPeriod);
              updateSectorTable();
            }
          }
        }
      }, interval);
    }
    
    // 关闭模态框
    function closeModal() {
      document.getElementById('indexDetailModal').classList.add('hidden');
    }
    
    // 页面加载完成后初始化
    document.addEventListener('DOMContentLoaded', () => {
      // 设置相对定位,使图表加载指示器正确显示
      document.querySelector('.h-\\[400px\\]').style.position = 'relative';
      
      // 初始化时间更新
      updateCurrentTime();
      setInterval(updateCurrentTime, 1000);
      
      // 检查市场状态
      checkMarketStatus();
      setInterval(checkMarketStatus, 60000); // 每分钟检查一次
      
      // 初始化图表
      initChart();
      
      // 加载指数数据
      updateAllIndexCards();
      
      // 加载行业板块数据
      updateSectorTable();
      
      // 设置自动刷新
      setupAutoRefresh();
      
      // 导航链接事件绑定
      document.querySelectorAll('.nav-link, .mobile-nav-link').forEach(link => {
        link.addEventListener('click', (e) => {
          e.preventDefault();
          navigateToPage(link.dataset.page);
        });
      });
      
      // 移动端菜单切换
      document.getElementById('mobileMenuBtn').addEventListener('click', () => {
        const mobileMenu = document.getElementById('mobileMenu');
        mobileMenu.classList.toggle('hidden');
      });
      
      // 手动刷新按钮
      document.getElementById('refreshBtn').addEventListener('click', async () => {
        // 显示加载状态
        document.getElementById('refreshBtn').querySelector('i').classList.add('fa-spin');
        
        try {
          await updateAllIndexCards();
          await updateSectorTable();
          updateChartData(appState.currentIndex, appState.currentPeriod);
        } finally {
          // 隐藏加载状态
          document.getElementById('refreshBtn').querySelector('i').classList.remove('fa-spin');
        }
      });
      
      // 图表周期切换
      document.querySelectorAll('.chart-period-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          // 更新按钮样式
          document.querySelectorAll('.chart-period-btn').forEach(b => {
            b.classList.remove('bg-primary', 'text-white');
            b.classList.add('bg-white', 'text-gray-600', 'hover:bg-gray-100');
          });
          
          btn.classList.remove('bg-white', 'text-gray-600', 'hover:bg-gray-100');
          btn.classList.add('bg-primary', 'text-white');
          
          // 更新图表数据
          updateChartData(appState.currentIndex, btn.dataset.period);
        });
      });
      
      // 指数图表切换
      document.querySelectorAll('.index-chart-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          // 更新按钮样式
          document.querySelectorAll('.index-chart-btn').forEach(b => {
            b.classList.remove('bg-primary', 'text-white');
            b.classList.add('bg-white', 'text-gray-600', 'hover:bg-gray-100');
          });
          
          btn.classList.remove('bg-white', 'text-gray-600', 'hover:bg-gray-100');
          btn.classList.add('bg-primary', 'text-white');
          
          // 更新图表数据
          updateChartData(btn.dataset.index, appState.currentPeriod);
        });
      });
      
      // 指数卡片点击事件(显示详情)
      document.querySelectorAll('[data-detail]').forEach(card => {
        card.addEventListener('click', () => {
          showIndexDetail(card.dataset.detail);
        });
      });
      
      // 关闭模态框按钮
      document.getElementById('closeModalBtn').addEventListener('click', closeModal);
      document.getElementById('closeModalBtn2').addEventListener('click', closeModal);
      
      // 点击模态框外部关闭
      document.getElementById('indexDetailModal').addEventListener('click', (e) => {
        if (e.target === document.getElementById('indexDetailModal')) {
          closeModal();
        }
      });
      
      // 历史数据查询按钮
      document.getElementById('queryHistoryBtn').addEventListener('click', queryHistoryData);
      
      // 加载更多新闻按钮
      document.getElementById('loadMoreNews').addEventListener('click', loadMoreNews);
      
      // 保存设置按钮
      document.getElementById('saveSettingsBtn').addEventListener('click', saveSettings);
      
      // 预警开关切换
      document.getElementById('alertToggle').addEventListener('change', (e) => {
        document.getElementById('alertThresholdContainer').classList.toggle('hidden', !e.target.checked);
      });
      
      // 刷新频率变更
      document.getElementById('refreshInterval').addEventListener('change', setupAutoRefresh);
      
      // 滚动时导航栏效果
      window.addEventListener('scroll', () => {
        const header = document.querySelector('header');
        if (window.scrollY > 10) {
          header.classList.add('py-2', 'shadow');
          header.classList.remove('py-3', 'shadow-md');
        } else {
          header.classList.add('py-3', 'shadow-md');
          header.classList.remove('py-2', 'shadow');
        }
      });
    });
  </script>
</body>
</html>
woaipojie23456 发表于 2025-8-26 08:04
炒股小能手啊
winwoo 发表于 2025-8-26 09:33
股票都不会,我应该用不到这个软件
yunzheyueer 发表于 2025-8-27 09:04
感谢分享,坐等回本
gpslon 发表于 2025-8-27 09:37
最近大势更重于鏊
huaxiaoxu 发表于 2025-8-27 09:42
这个不错,正需要
junyue99828 发表于 2025-8-27 10:29
谢谢大佬
linn12000 发表于 2025-8-27 16:12
这个很不错,感谢分享。
hexiwo 发表于 2025-8-27 16:15
本帖最后由 hexiwo 于 2025-8-27 16:16 编辑

大哥此代码很具参考意义,可以改成自己想要关注的股票。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-5 10:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表