<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>配置说明 - WebCrawling</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 40px 20px;
        }

        .container {
            max-width: 900px;
            margin: 0 auto;
            background: #fff;
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 40px;
            text-align: center;
        }

        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            font-weight: 600;
        }

        .header p {
            opacity: 0.9;
            font-size: 1.1rem;
        }

        .content {
            padding: 40px;
        }

        .section {
            margin-bottom: 40px;
        }

        .section-title {
            color: #333;
            font-size: 1.5rem;
            font-weight: 600;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 3px solid #667eea;
            position: relative;
        }

        .section-title::after {
            content: '';
            position: absolute;
            bottom: -3px;
            left: 0;
            width: 60px;
            height: 3px;
            background: #764ba2;
        }

        .step-list {
            list-style: none;
            counter-reset: step-counter;
        }

        .step-list li {
            counter-increment: step-counter;
            position: relative;
            padding: 15px 20px 15px 50px;
            margin-bottom: 12px;
            background: #f8f9fa;
            border-radius: 10px;
            transition: all 0.3s ease;
        }

        .step-list li:hover {
            background: #e9ecef;
            transform: translateX(5px);
        }

        .step-list li::before {
            content: counter(step-counter);
            position: absolute;
            left: 15px;
            top: 50%;
            transform: translateY(-50%);
            width: 28px;
            height: 28px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 600;
            font-size: 0.9rem;
        }

        .code-section {
            background: #1e1e1e;
            border-radius: 12px;
            overflow: hidden;
            margin-top: 20px;
        }

        .code-header {
            background: #2d2d2d;
            padding: 12px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .code-header span {
            color: #858585;
            font-size: 0.9rem;
        }

        .code-header button {
            background: #667eea;
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 0.85rem;
            transition: background 0.3s ease;
        }

        .code-header button:hover {
            background: #5a6fd6;
        }

        .code-content {
            padding: 20px;
            overflow-x: auto;
        }

        .code-content pre {
            margin: 0;
            color: #d4d4d4;
            font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
            font-size: 0.9rem;
            line-height: 1.6;
        }

        .code-content code {
            display: block;
            white-space: pre;
        }

        .note {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
            padding: 15px 20px;
            border-radius: 0 8px 8px 0;
            margin-top: 15px;
            color: #856404;
        }

        .note strong {
            color: #856404;
        }

        .warning {
            background: #f8d7da;
            border-left: 4px solid #dc3545;
            padding: 15px 20px;
            border-radius: 0 8px 8px 0;
            margin-top: 15px;
            color: #721c24;
        }

        .warning strong {
            color: #721c24;
        }

        .mt4-badge, .mt5-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.8rem;
            font-weight: 600;
            margin-left: 10px;
        }

        .mt4-badge {
            background: #00d4ff;
            color: #0066cc;
        }

        .mt5-badge {
            background: #ffd700;
            color: #b8860b;
        }

        .footer {
            background: #f8f9fa;
            padding: 20px;
            text-align: center;
            color: #666;
            font-size: 0.9rem;
        }

        @media (max-width: 768px) {
            .header h1 {
                font-size: 1.8rem;
            }

            .content {
                padding: 25px 20px;
            }

            .section-title {
                font-size: 1.3rem;
            }

            .step-list li {
                padding: 12px 15px 12px 45px;
            }

            .step-list li::before {
                width: 24px;
                height: 24px;
                font-size: 0.8rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>配置说明</h1>
            <p>WebCrawling 价格数据采集工具 - MT4/MT5 配置指南</p>
        </div>

        <div class="content">
            <div class="section">
                <h2 class="section-title">
                    MT4 配置步骤
                    <span class="mt4-badge">MetaTrader 4</span>
                </h2>
                <ol class="step-list">
                    <li>完成MT4软件安装后，请按以下步骤依次操作</li>
                    <li>将源目录中的 <strong>MQL4.zip</strong> 解压，把其中三个文件夹复制至MT4的“安装目录”下的 <strong>MQL4</strong> 文件夹中。若遇重名文件，请选择复制并替换</li>
                    <li>打开“MT4”软件，依次点击上方选项卡 <strong>工具 → 选项</strong>，在弹出页面中选择 <strong>EA交易</strong></li>
                    <li>勾选 <strong>允许DLL导入（潜在的危险，只为受信任的应用程序启用）</strong>，勾选 <strong>允许WebRequest用于所列URL</strong></li>
                    <li>在下方URL输入框中添加如下链接：<strong>http://127.0.0.1</strong></li>
                    <li>点击 <strong>确定</strong> 按钮，配置完成</li>
                    <li>在MT4平台上添加拟抓取的交易品种</li>
                    <li>将交易品种拖动至右侧以生成独立的折线图，在左侧导航的“EA交易”中找到 <strong>TCPSocket</strong> 文件，拖动至折线图上，点击“确定”即可</li>
                </ol>
            </div>

            <div class="section">
                <h2 class="section-title">
                    MT5 配置步骤
                    <span class="mt5-badge">MetaTrader 5</span>
                </h2>
                <ol class="step-list">
                    <li>完成MT5软件安装后，请按以下步骤依次操作</li>
                    <li>打开“MT5”软件，依次点击上方选项卡 <strong>工具 → 选项</strong>，在弹出页面中选择 <strong>EA交易</strong></li>
                    <li>勾选 <strong>允许DLL导入（潜在的危险，只为受信任的应用程序启用）</strong>，勾选 <strong>允许WebRequest用于所列URL</strong></li>
                    <li>在下方URL输入框中添加如下链接：<strong>http://127.0.0.1</strong></li>
                    <li>打开软件左侧“导航栏”，找到“EA交易”，右键“EA交易”，点击“用MetaEditor创建”</li>
                    <li>选择EA交易（模板），点击“下一页”；名称后边输入 <strong>TCPSocket</strong>，然后一直点击“下一页”，直至“完成”即可</li>
                    <li>在弹出的MetaEditor编辑器中，删除默认生成的代码</li>
                    <li>从下方代码模块复制全部代码，粘贴进上一步弹出的弹窗</li>
                    <li>点击编写按钮，关闭当前窗口即可</li>
                    <li>在MT5平台上添加拟抓取的交易品种</li>
                </ol>

                <div class="warning">
                    <strong>重要提示：</strong>若出现错误4014，需要在MT5终端中添加允许访问的地址：
                    <ol style="margin-top: 10px; padding-left: 20px;">
                        <li>打开MT5终端</li>
                        <li>点击 工具 -> 选项 -> 专家顾问</li>
                        <li>在"允许WebRequest对下列URL的访问"中添加：<strong>http://127.0.0.1:8087</strong></li>
                        <li>点击确定保存设置</li>
                        <li>重新启动MT5终端</li>
                    </ol>
                </div>
            </div>

            <div class="section">
                <h2 class="section-title">MT5 EA 代码</h2>
                <div class="code-section">
                    <div class="code-header">
                        <span>WebRequest.mq5</span>
                        <button onclick="copyCode()">复制代码</button>
                    </div>
                    <div class="code-content">
                        <pre><code>//+------------------------------------------------------------------+
//|                                                   WebRequest.mq5 |
//|                                  版权所有 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "http://127.0.0.1:8087"
#property version   "1.00"
#property description "价格上传功能：将当前品种的价格信息实时推送到服务器。\n错误4014表示需要在MT5选项中添加允许访问的地址。"
#property script_show_inputs

//--- 输入参数
input string   Address="127.0.0.1";
input int      Port=8087;
bool           ExtTLS = false;
datetime       lastPriceUpdate = 0;
const int      priceUpdateInterval = 200;

//+------------------------------------------------------------------+
//| 向服务器发送命令                                                 |
//+------------------------------------------------------------------+
bool HTTPSend(int socket, string request)
{
    uchar req[];
    int len = StringToCharArray(request, req) - 1;
    if(len < 0)
    {
        Print("发送失败: 数据转换失败");
        return(false);
    }
    if(ExtTLS)
        return(SocketTlsSend(socket, req, len) == len);
    else
        return(SocketSend(socket, req, len) == len);
}

//+------------------------------------------------------------------+
//| 获取当前品种的价格信息                                           |
//+------------------------------------------------------------------+
string GetPriceInfo(string symbol)
{
    double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
    double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
    datetime time = TimeLocal();
    long accountLogin = AccountInfoInteger(ACCOUNT_LOGIN);
    string accountServer = AccountInfoString(ACCOUNT_SERVER);
    
    string result = StringFormat("PRICE_INFO|%s|%f|%f|%s|%d|%s",
                                symbol, bid, ask,
                                TimeToString(time, TIME_DATE|TIME_MINUTES|TIME_SECONDS),
                                accountLogin, accountServer);
    return result;
}

//+------------------------------------------------------------------+
//| 脚本程序开始函数                                                 |
//+------------------------------------------------------------------+
void OnStart()
{
    Print("WebRequest脚本开始执行（仅价格上传功能）");
    
    int socket = INVALID_HANDLE;
    bool connected = false;
    
    while(!IsStopped())
    {
        if(!connected || socket == INVALID_HANDLE)
        {
            Print("尝试连接服务器...");
            socket = SocketCreate();
            if(socket != INVALID_HANDLE)
            {
                if(SocketConnect(socket, Address, Port, 1000))
                {
                    Print("成功连接到 ", Address, ":", Port);
                    connected = true;
                    
                    string subject, issuer, serial, thumbprint;
                    datetime expiration;
                    if(SocketTlsCertificate(socket, subject, issuer, serial, thumbprint, expiration))
                    {
                        ExtTLS = true;
                    }
                    Print("初始化完成，开始推送价格信息...");
                }
                else
                {
                    Print("连接失败, 错误 ", GetLastError());
                    connected = false;
                }
            }
            else
            {
                Print("创建套接字失败, 错误 ", GetLastError());
                connected = false;
            }
            
            if(!connected)
            {
                Print("5秒后重新尝试连接...");
                Sleep(5000);
                continue;
            }
        }
        
        if(connected && socket != INVALID_HANDLE)
        {
            if(GetTickCount() - lastPriceUpdate > priceUpdateInterval)
            {
                string priceInfo = GetPriceInfo(Symbol());
                if(HTTPSend(socket, priceInfo + "\r\n"))
                {
                    Print("价格信息已发送: ", priceInfo);
                    lastPriceUpdate = GetTickCount();
                }
                else
                {
                    Print("发送价格信息失败，连接可能已断开");
                    connected = false;
                    SocketClose(socket);
                    socket = INVALID_HANDLE;
                }
            }
            else
            {
                Sleep(50);
            }
        }
    }
    
    if(socket != INVALID_HANDLE)
    {
        SocketClose(socket);
    }
    Print("WebRequest脚本执行结束");
}
//+------------------------------------------------------------------+</code></pre>
                    </div>
                </div>
            </div>
        </div>

        <div class="footer">
            <p>WebCrawling v1.0.0 | 价格数据采集工具</p>
        </div>
    </div>

    <script>
        function copyCode() {
            const code = document.querySelector('.code-content pre code').textContent;
            navigator.clipboard.writeText(code).then(() => {
                alert('代码已复制到剪贴板！');
            }).catch(err => {
                console.error('复制失败:', err);
            });
        }
    </script>
</body>
</html>