某花顺隐藏了重仓涨幅,通过chrome插件计算基金的重仓涨幅

效果图:

代码图:

content.js

javascript 复制代码
// 从Chrome存储中获取需要匹配的网址字符
chrome.storage.sync.get(['matchText'], function (result) {
  const matchText = result.matchText || ''; // 默认空字符(匹配所有网址)
  const currentUrl = window.location.href;

  // 判断当前网址是否包含指定字符(忽略大小写)
  if (matchText && !currentUrl.toLowerCase().includes(matchText.toLowerCase())) {
    return; // 不匹配则不执行统计
  }

  // 计算重仓加权涨跌幅的核心函数
  async function calculateWeightedReturn() {
    try {
      // 找到目标表格(ui-table-hover)
      const targetTable = document.querySelector('table.ui-table-hover');
      if (!targetTable) {
        console.log('未找到持仓表格');
        return;
      }

      // 获取表格行(排除表头tr)
      const tableRows = targetTable.querySelectorAll('tbody tr:not(:first-child)');
      if (tableRows.length === 0) {
        console.log('表格无持仓数据');
        return;
      }

      let totalWeightedReturn = 0; // 加权涨跌幅总和
      let totalPositionRatio = 0; // 总持仓占比(用于校验)
      const stockDataList = []; // 存储单只股票数据(用于展示)

      // 遍历每行提取数据
      for (const row of tableRows) {
        // 1. 提取股票名称
        const stockName = row.querySelector('td.alignLeft a')?.title || '未知股票';
        
        // 2. 提取持仓占比(去掉%转小数)
        const positionRatioText = row.querySelector('td.alignRight.bold')?.textContent.trim() || '0%';
        const positionRatio = parseFloat(positionRatioText.replace('%', '')) || 0;
        
        // 3. 提取涨跌幅(去掉%转小数,处理正负号)
        const returnRateText = row.querySelector('td.alignRight.bold span')?.textContent.trim() || '0%';
        const returnRate = parseFloat(returnRateText.replace('%', '')) || 0;

        // 4. 计算单只股票加权涨幅,累加至总和
        const weightedReturn = positionRatio * returnRate / 100; // 持仓占比% * 涨跌幅% = ‰,转%需/100
        totalWeightedReturn += weightedReturn;
        totalPositionRatio += positionRatio;

        // 存储单只股票数据
        stockDataList.push({
          name: stockName,
          positionRatio: positionRatioText,
          returnRate: returnRateText,
          weightedReturn: weightedReturn.toFixed(4) + '%' // 格式化单只加权值
        });
      }

      // 格式化最终加权涨幅(保留2位小数)
      const formattedTotalReturn = totalWeightedReturn.toFixed(4) + '%';
      // 格式化总持仓占比
      const formattedTotalPosition = totalPositionRatio.toFixed(2) + '%';

      // 创建统计结果显示面板
      const statsPanel = document.createElement('div');
      statsPanel.style.cssText = `
        position: fixed;
        top: 10px;
        right: 10px;
        background: #fff;
        border: 1px solid #ccc;
        padding: 10px 15px;
        border-radius: 8px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        z-index: 99999999;
        font-family: Arial, sans-serif;
        font-size: 14px;
        color: #333;
        max-height: 400px;
        overflow-y: auto;
        min-width: 300px;
      `;

      // 拼接面板HTML(总览+单只股票明细)
      let panelHtml = `
        <strong style="font-size:16px;">重仓加权涨幅统计</strong><br>
        <hr style="margin:8px 0; border:0; border-top:1px solid #eee;">
        总持仓占比:${formattedTotalPosition}<br>
        加权总涨幅:<span style="color: ${totalWeightedReturn >= 0 ? '#e63946' : '#16a34a'}">${formattedTotalReturn}</span><br>
        <hr style="margin:8px 0; border:0; border-top:1px solid #eee;">
        <strong>单只股票明细</strong><br>
      `;

      // 拼接每只股票的明细
      stockDataList.forEach(stock => {
        panelHtml += `
          <div style="margin:4px 0; padding:4px; background:#f8f9fa; border-radius:4px;">
            ${stock.name}<br>
            持仓占比:${stock.positionRatio} | 涨跌幅:${stock.returnRate} | 加权贡献:${stock.weightedReturn}
          </div>
        `;
      });

      statsPanel.innerHTML = panelHtml;

      // 先移除旧面板(避免重复),再插入新面板
      const oldPanel = document.querySelector('div[style*="z-index: 99999999"]');
      if (oldPanel) oldPanel.remove();
      document.body.appendChild(statsPanel);

    } catch (error) {
      console.error('重仓涨幅计算失败:', error);
    }
  }

  // 执行计算(DOM加载完成后执行,确保表格已渲染)
  if (document.readyState === 'complete') {
    calculateWeightedReturn();
  } else {
    window.addEventListener('load', calculateWeightedReturn);
  }
});

manifest.json

javascript 复制代码
{
  "manifest_version": 3,
  "name": "网页图片统计插件",
  "version": "1.0",
  "description": "自动统计指定网址的图片数量和数据量",
  "permissions": ["storage"],
  "host_permissions": ["<all_urls>"], // 解决跨域请求问题
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'" // Manifest V3 必须用对象格式
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icon16.png",
      "48": "icon48.png",
      "128": "icon128.png"
    }
  },
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  }
}

popup.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>图片统计设置</title>
  <meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'self'"> <!-- 显式声明CSP(可选但推荐) -->
  <style>
    body { width: 200px; padding: 10px; }
    .form-group { margin-bottom: 10px; }
    label { display: block; margin-bottom: 5px; font-weight: bold; }
    input { width: 100%; padding: 5px; box-sizing: border-box; }
    button { width: 100%; padding: 6px; background: #4285f4; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
    button:hover { background: #3367d6; }
  </style>
</head>
<body>
  <div class="form-group">
    <label for="matchText">网址包含字符:</label>
    <input type="text" id="matchText" placeholder="如:baidu、taobao">
  </div>
  <button id="saveBtn">保存设置</button>

  <!-- 引入外部JS文件,替代内联脚本 -->
  <script src="popup.js"></script>
</body>
</html>

popup.js

javascript 复制代码
// 加载已保存的设置
chrome.storage.sync.get(['matchText'], function (result) {
  if (result.matchText) {
    document.getElementById('matchText').value = result.matchText;
  }
});

// 保存设置到Chrome存储
document.getElementById('saveBtn').addEventListener('click', function () {
  const matchText = document.getElementById('matchText').value.trim();
  chrome.storage.sync.set({ matchText: matchText }, function () {
    alert('设置保存成功!刷新网页生效');
  });
});

图片自己随便找个替换即可。

将上述文件放到一个文件夹,打开chrome浏览器或qq浏览器。加载已解压的扩展插件,

最后大概基金页面(比如天天基金网),右上角就能看到啦

代码都是ai生成,你也试试吧

相关推荐
Async Cipher2 小时前
TypeScript 的用法
前端·typescript
web打印社区2 小时前
vue页面打印:printjs实现与进阶方案推荐
前端·javascript·vue.js·electron·html
We་ct2 小时前
LeetCode 30. 串联所有单词的子串:从暴力到高效,滑动窗口优化详解
前端·算法·leetcode·typescript
木卫二号Coding2 小时前
Docker-构建自己的Web-Linux系统-Ubuntu:22.04
linux·前端·docker
CHU7290353 小时前
一番赏盲盒抽卡机小程序:解锁惊喜体验与社交乐趣的多元功能设计
前端·小程序·php
RFCEO3 小时前
前端编程 课程十二、:CSS 基础应用 Flex 布局
前端·css·flex 布局·css3原生自带的布局模块·flexible box·弹性盒布局·垂直居中困难
天若有情6733 小时前
XiangJsonCraft v1.2.0重大更新解读:本地配置优先+全量容错,JSON解耦开发体验再升级
前端·javascript·npm·json·xiangjsoncraft
2501_944525543 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 预算详情页面
android·开发语言·前端·javascript·flutter·ecmascript
打小就很皮...4 小时前
《在 React/Vue 项目中引入 Supademo 实现交互式新手指引》
前端·supademo·新手指引