JD Relay URL Modifier

Append __wsmode__=9 to relay*.jd.com/file/design?xxx URLs

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         JD Relay URL Modifier
// @namespace    http://tampermonkey.net/
// @version      0.3.7
// @description  Append __wsmode__=9 to relay*.jd.com/file/design?xxx URLs
// @author       Your Name
// @match        https://relay.jd.com/file/*
// @match        *://relay-test.jd.com/file/*
// @match        *://relay0.jd.com/file/*
// @match        *://ling.jd.com/file/*
// @match        *://ling-design.jd.com/file/*
// @match        *://ling-test.jd.com/file/*
// @match        *://ling-pre.jd.com/file/*
// @grant        none
// @license      MIT
// ==/UserScript==

; (function () {
  "use strict"
  const inFile = /\/file\/(design|chat)/.test(window.location.pathname)
  // 从 localStorage 获取状态
  let isEnabled = localStorage.getItem("wsmodeEnabled") === "true"

  // 创建按钮容器
  let container = document.createElement("div")
  container.id = "wsmode-container"
  container.style.position = "fixed"
  container.style.bottom = localStorage.getItem("buttonBottom") || "60px"
  container.style.right = localStorage.getItem("buttonRight") || "10px"
  container.style.zIndex = "1000"
  container.style.display = "flex"
  container.style.gap = "10px"
  document.body.appendChild(container)

  // 创建隐身按钮
  let button = document.createElement("button")
  button.id = "wsmode-button"

  // 幽灵图标
  const ghostIconEnabled = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0-1A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM6 3.5a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5zm4 0a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5zM8 7a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z"/></svg>'
  const ghostIconDisabled = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0-1A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM6 3.5a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5zm4 0a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5zM8 7a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z" opacity="0.5"/></svg>'
  const debugIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0-1A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM4 8a.5.5 0 0 1 .5-.5h3v-3a.5.5 0 0 1 1 0v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1z"/></svg>'

  button.innerHTML = isEnabled ? `${ghostIconEnabled}` : `${ghostIconDisabled}`
  button.style.padding = "10px 15px"
  button.style.border = "none"
  button.style.borderRadius = "5px"
  button.style.color = "white"
  button.style.cursor = "pointer"
  button.style.display = "flex"
  button.style.alignItems = "center"
  button.style.gap = "6px"
  button.style.fontSize = "14px"
  button.style.fontWeight = "500"
  button.style.transition = "background-color 0.2s ease, transform 0.1s ease"
  container.appendChild(button)

  // 创建调试按钮
  let debugButton = document.createElement("button")
  debugButton.id = "debug-button"
  debugButton.innerHTML = debugIcon
  debugButton.style.padding = "10px 15px"
  debugButton.style.border = "none"
  debugButton.style.borderRadius = "5px"
  debugButton.style.color = "white"
  debugButton.style.cursor = "pointer"
  debugButton.style.display = "flex"
  debugButton.style.alignItems = "center"
  debugButton.style.gap = "6px"
  debugButton.style.fontSize = "14px"
  debugButton.style.fontWeight = "500"
  debugButton.style.transition = "background-color 0.2s ease, transform 0.1s ease"
  debugButton.style.backgroundColor = "#2196F3"
  container.appendChild(debugButton)

  // 调试按钮点击事件
  debugButton.addEventListener("click", () => {
    if (typeof window.__DEBUG === "function") {
      window.__DEBUG()
    } else {
      console.warn("window.__DEBUG is not defined")
    }
  })

  // 设置按钮初始状态
  button.style.backgroundColor = isEnabled ? "#4CAF50" : "#9E9E9E"

  // 确保按钮在窗口视野内
  function ensureButtonInView() {
    const rect = container.getBoundingClientRect()
    const maxX = window.innerWidth - rect.width
    const maxY = window.innerHeight - rect.height

    let currentRight = parseFloat(container.style.right) || 0
    let currentBottom = parseFloat(container.style.bottom) || 0

    // 如果按钮超出右边界,吸附到右边
    if (currentRight < 0) {
      container.style.right = "10px"
    }
    // 如果按钮超出底边界,吸附到底边
    if (currentBottom < 0) {
      container.style.bottom = "60px"
    }

    // 保存调整后的位置
    localStorage.setItem("buttonRight", container.style.right)
    localStorage.setItem("buttonBottom", container.style.bottom)
  }

  // 窗口缩放时确保按钮在视野内
  window.addEventListener("resize", ensureButtonInView)

  // 页面加载时也检查一次
  setTimeout(ensureButtonInView, 100)

  // 按钮拖拽功能
  let isDragging = false
  let offsetX, offsetY
  let dragStartTime = 0
  let hasMoved = false

  container.addEventListener("mousedown", (e) => {
    isDragging = true
    hasMoved = false
    dragStartTime = Date.now()
    offsetX = e.clientX - container.getBoundingClientRect().left
    offsetY = e.clientY - container.getBoundingClientRect().top
    container.style.transition = "none" // 禁用动画
    container.style.opacity = "0.8" // 拖动时透明度变化
  })

  document.addEventListener("mousemove", (e) => {
    if (isDragging) {
      hasMoved = true
      const newRight = window.innerWidth - e.clientX - (container.offsetWidth - offsetX)
      const newBottom = window.innerHeight - e.clientY - (container.offsetHeight - offsetY)
      container.style.right = `${Math.max(0, newRight)}px`
      container.style.bottom = `${Math.max(0, newBottom)}px`
    }
  })

  document.addEventListener("mouseup", (e) => {
    if (isDragging) {
      const dragEndTime = Date.now()
      const dragDuration = dragEndTime - dragStartTime

      container.style.opacity = "1" // 恢复透明度
      container.style.transition = "background-color 0.2s ease" // 恢复动画

      // 保存位置到 localStorage
      localStorage.setItem("buttonRight", container.style.right)
      localStorage.setItem("buttonBottom", container.style.bottom)

      // 只有在非拖拽情况下才触发点击事件(短时间内没有移动鼠标)
      if (!hasMoved && dragDuration < 200 && e.target === button) {
        toggleMode()
      }

      isDragging = false
    }
  })

  // 抽取切换模式的逻辑为单独的函数
  function toggleMode() {
    const previousState = isEnabled
    isEnabled = !isEnabled
    localStorage.setItem("wsmodeEnabled", isEnabled)
    button.style.backgroundColor = isEnabled ? "#4CAF50" : "#9E9E9E"
    button.innerHTML = isEnabled ? `${ghostIconEnabled}` : `${ghostIconDisabled}`
    // 通知其他页面
    localStorage.setItem("wsmodeChanged", Date.now())

    // 如果在 inFile 页面并且 wsmode 状态有变化,刷新页面
    if (inFile && previousState !== isEnabled) {
      if (isEnabled && !url.searchParams.has("__wsmode__")) {
        url.searchParams.append("__wsmode__", "9")
      } else if (!isEnabled && url.searchParams.has("__wsmode__")) {
        url.searchParams.delete("__wsmode__")
      }
      window.location.replace(url.toString())
    }
  }

  // 获取当前 URL
  let url = new URL(window.location.href)

  // 检查是否已经有 __wsmode__ 参数并且功能开启
  if (inFile) {
    if (isEnabled && !url.searchParams.has("__wsmode__")) {
      // 添加 __wsmode__ 参数
      url.searchParams.append("__wsmode__", "9")
      // 重定向到新的 URL
      window.location.replace(url.toString())
    }
  }

  // 监听新打开的 /file/design 页面
  window.addEventListener("message", (event) => {
    console.log("Received message from relay.jd.com:", event)
    if (
      event.origin === location.origin &&
      event.data === "checkWsmode"
    ) {
      event.source.postMessage({ wsmodeEnabled: isEnabled }, event.origin)
    }
  })

  // 在 /file/design 页面中检查 __wsmode__ 参数
  if (inFile) {
    window.addEventListener("message", (event) => {
      if (
        event.origin === location.origin &&
        typeof event.data.wsmodeEnabled !== "undefined"
      ) {
        if (event.data.wsmodeEnabled) {
          if (!url.searchParams.has("__wsmode__")) {
            url.searchParams.append("__wsmode__", "9")
            window.location.replace(url.toString())
          }
        } else {
          if (url.searchParams.has("__wsmode__")) {
            url.searchParams.delete("__wsmode__")
            window.location.replace(url.toString())
          }
        }
      }
    })
  }

  // 监听 localStorage 变化
  window.addEventListener("storage", (event) => {
    if (event.key === "wsmodeChanged") {
      isEnabled = localStorage.getItem("wsmodeEnabled") === "true"
      button.style.backgroundColor = isEnabled ? "#4CAF50" : "#9E9E9E"
      button.innerHTML = isEnabled ? `${ghostIconEnabled}` : `${ghostIconDisabled}`
      if (inFile) {
        if (isEnabled && !url.searchParams.has("__wsmode__")) {
          url.searchParams.append("__wsmode__", "9")
          window.location.replace(url.toString())
        } else if (!isEnabled && url.searchParams.has("__wsmode__")) {
          url.searchParams.delete("__wsmode__")
          window.location.replace(url.toString())
        }
      }
    }
  })
})()