javascript:(function () {
  const CLOSE_COL_NAME = '收盘价';
  const NEW_HDR_TEXT = '收盘价 止盈价';
  const RATE_INPUT_ID = 'stop_value';
  const TARGET_WIDTH = 240;
  const TAB_BUTTON = '盘后选债';
  const MAX_ROWS = 50;
  const LS_KEY = 'lude_stop_rate';
  const PANEL_ID = 'lude-stop-panel';
  const DEFAULT_RATE = 6;

  function getSavedRate() {
    const v = localStorage.getItem(LS_KEY);
    return v !== null ? parseFloat(v) : DEFAULT_RATE;
  }

  function saveRate(pct) {
    localStorage.setItem(LS_KEY, String(pct));
  }

  function getRate() {
    const panelEl = document.getElementById('lude-stop-input');
    if (panelEl) {
      const panelValue = parseFloat(panelEl.value);
      if (!isNaN(panelValue) && panelValue > 0) return panelValue / 100;
    }

    const el = document.getElementById(RATE_INPUT_ID);
    if (el) {
      const v = parseFloat(el.value || el.innerText);
      if (!isNaN(v) && v > 0) return v / 100;
    }
    return getSavedRate() / 100;
  }

  function notify(text) {
    const el = document.createElement('div');
    el.innerText = text;
    Object.assign(el.style, {
      position: 'fixed',
      top: '50%',
      left: '50%',
      transform: 'translate(-50%,-50%)',
      background: 'rgba(0,0,0,0.85)',
      color: '#fff',
      padding: '16px 32px',
      borderRadius: '10px',
      zIndex: '999999',
      fontSize: '16px',
      fontWeight: 'bold',
      boxShadow: '0 4px 15px rgba(0,0,0,0.4)',
      transition: 'opacity 0.5s'
    });
    document.body.appendChild(el);
    setTimeout(() => {
      el.style.opacity = '0';
      setTimeout(() => el.remove(), 500);
    }, 2000);
  }

  function createPanel() {
    if (document.getElementById(PANEL_ID)) return;

    const rate = getSavedRate();
    const panel = document.createElement('div');
    panel.id = PANEL_ID;
    Object.assign(panel.style, {
      position: 'fixed',
      top: '60px',
      right: '20px',
      background: '#1a1a2e',
      color: '#eee',
      padding: '12px 16px',
      borderRadius: '8px',
      zIndex: '999998',
      fontSize: '13px',
      boxShadow: '0 2px 12px rgba(0,0,0,0.5)',
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      fontFamily: 'system-ui, sans-serif',
      cursor: 'move',
      userSelect: 'none'
    });

    panel.innerHTML = `
      <span style="white-space:nowrap;">止盈比例</span>
      <input id="lude-stop-input" type="number" step="0.5" min="0.1" max="100"
        value="${rate}"
        style="width:60px;padding:4px 6px;border:1px solid #444;border-radius:4px;
               background:#0f0f23;color:#fff;font-size:13px;text-align:center;" />
      <span>%</span>
      <button id="lude-stop-apply"
        style="padding:4px 12px;border:none;border-radius:4px;
               background:#1677ff;color:#fff;font-size:13px;cursor:pointer;
               font-weight:bold;">
        重新计算
      </button>
      <button id="lude-stop-close"
        style="padding:4px 8px;border:none;border-radius:4px;
               background:#333;color:#aaa;font-size:12px;cursor:pointer;
               margin-left:4px;">
        ✕
      </button>
    `;
    document.body.appendChild(panel);

    const pageInput = document.getElementById(RATE_INPUT_ID);
    if (pageInput) pageInput.value = rate;

    let dragging = false;
    let ox;
    let oy;

    panel.addEventListener('mousedown', (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
      dragging = true;
      ox = e.clientX - panel.offsetLeft;
      oy = e.clientY - panel.offsetTop;
    });

    document.addEventListener('mousemove', (e) => {
      if (!dragging) return;
      panel.style.left = e.clientX - ox + 'px';
      panel.style.top = e.clientY - oy + 'px';
      panel.style.right = 'auto';
    });

    document.addEventListener('mouseup', () => {
      dragging = false;
    });

    document.getElementById('lude-stop-apply').addEventListener('click', () => {
      const inp = document.getElementById('lude-stop-input');
      const v = parseFloat(inp.value);
      if (isNaN(v) || v <= 0) {
        notify('请输入有效的止盈比例');
        return;
      }

      saveRate(v);
      const pageInput = document.getElementById(RATE_INPUT_ID);
      if (pageInput) pageInput.value = v;
      document.querySelectorAll('.ag-cell[data-ov]').forEach((c) => c.removeAttribute('data-ov'));
      update();
      notify('已更新止盈比例为 ' + v + '%');
    });

    document.getElementById('lude-stop-close').addEventListener('click', () => {
      panel.remove();
    });
  }

  function update() {
    const r = getRate();
    const headers = Array.from(document.querySelectorAll('.ag-header-cell'));
    const target = headers.find(
      (e) =>
        e.innerText.includes(CLOSE_COL_NAME) ||
        e.querySelector('.ag-header-cell-text')?.innerText === NEW_HDR_TEXT
    );
    if (!target) return;

    const colId = target.getAttribute('col-id');
    const origW = parseInt(target.getAttribute('data-ow') || target.offsetWidth);

    if (!target.getAttribute('data-ow') && origW > 0 && origW < TARGET_WIDTH) {
      target.setAttribute('data-ow', origW);
    }
    const widthDelta = TARGET_WIDTH - (parseInt(target.getAttribute('data-ow')) || origW);

    let origLeft = parseInt(target.getAttribute('data-ol'));
    if (isNaN(origLeft)) {
      origLeft = parseInt(target.style.left) || 0;
      target.setAttribute('data-ol', origLeft);
    }

    const hdrText = target.querySelector('.ag-header-cell-text');
    if (hdrText && hdrText.innerText !== NEW_HDR_TEXT) {
      hdrText.innerText = NEW_HDR_TEXT;
    }

    headers.forEach((h) => {
      let hl = parseInt(h.getAttribute('data-ol'));
      if (isNaN(hl)) {
        hl = parseInt(h.style.left) || 0;
        h.setAttribute('data-ol', hl);
      }
      if (hl > origLeft) h.style.left = hl + widthDelta + 'px';
      if (h.getAttribute('col-id') === colId) h.style.width = TARGET_WIDTH + 'px';
    });

    document.querySelectorAll('.ag-row').forEach((row) => {
      const idx = parseInt(row.getAttribute('row-index'));
      row.querySelectorAll('.ag-cell').forEach((cell) => {
        let cl = parseInt(cell.getAttribute('data-ol'));
        if (isNaN(cl)) {
          cl = parseInt(cell.style.left) || 0;
          cell.setAttribute('data-ol', cl);
        }
        if (cl > origLeft) cell.style.left = cl + widthDelta + 'px';

        if (cell.getAttribute('col-id') === colId) {
          cell.style.width = TARGET_WIDTH + 'px';

          let ov = cell.getAttribute('data-ov');
          if (!ov) {
            ov = cell.innerText.trim().split(' ')[0];
            cell.setAttribute('data-ov', ov);
          }

          if (!isNaN(idx) && idx < MAX_ROWS) {
            const val = parseFloat(ov.replace(/,/g, '')) || 0;
            const stopPrice = (Math.floor(val * (1 + r) * 1000) / 1000).toFixed(3);
            cell.innerHTML =
              ov +
              ' <span style="color:#ff4d4f;font-weight:bold;margin-left:12px;">' +
              stopPrice +
              '</span>';
          } else {
            cell.innerText = ov;
          }
        }
      });
    });
  }

  function bindTab() {
    const btn = Array.from(document.querySelectorAll('button,a,span')).find((e) =>
      e.innerText.includes(TAB_BUTTON)
    );
    if (btn && !btn.getAttribute('data-la')) {
      btn.setAttribute('data-la', '1');
      btn.addEventListener('click', () => {
        setTimeout(update, 1000);
        setTimeout(update, 2500);
      });
    }
  }

  try {
    createPanel();
    update();
    bindTab();
    notify('止盈价格插件已加载（前' + MAX_ROWS + '行）');

    const grid = document.querySelector('.ag-root-wrapper');
    if (grid) {
      new MutationObserver(() => {
        if (window._lude_stop_timer) clearTimeout(window._lude_stop_timer);
        window._lude_stop_timer = setTimeout(() => {
          update();
          bindTab();
        }, 200);
      }).observe(grid, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['style']
      });
    } else {
      setInterval(() => {
        update();
        bindTab();
      }, 1500);
    }
  } catch (e) {
    console.error('[止盈插件]', e);
  }
})();

