Cookies切换

掌控你的cookie吧~~

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Cookies切换
// @namespace    https://tampermonkey.net/
// @version      1.0
// @description  掌控你的cookie吧~~
// @author       Cheney & Gemini
// @match        http://*/*
// @match        https://*/*
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAArlJREFUSEullktoE0EYx//ftEKxD2uVFitW8AH25AssKIiCvVQQsaAeeiiKBzWZRMylXmwvnipkZ6OUoniwh6BexMdBPYiIggcVRS1YwQdUbKWRIhLbuJ+d3abNdjfJNlmYw+73+H0z859vllDgYSlbAMQAVJNSxwv5FrORnwNHo/VgvgDmkzn2PlKqt1jCfHYPiKPRLbCsAQBtniDL2kuJxONSYC4Qh0IHIcRVAA2+yZiryDT/lgXiUKgZQjwBsN43EdFLMoztpUB0zNyMWMpLAE5lE70Zz+Dy6z8YaK9zPjGPkGluLAvEUnYAuJebpFaN2a89bdU411btmIgOk2HcLAVmz4ilvALAJV/PjLLZS4QRR6OrYFnvAdQvotIkgM+kVE/QGGIpTwNIBA3I8RsmpVqDxmmQlvOxoAE5fmkIsY7i8e9BYokjkadg3hXE2ccncLfQoHEwrywRpMM8MI7FGqm/35Ht7OMBfZ38Z5ta6ipc7NHfFtpvpbC2tgL3Oz26+QTmb7NHYA+EOEPxeHwhyLV0+vy0NlTiRZe7C32YyGDH0IRdwLvuFcUWYBjMnWSaWs0OnyORa2Duzn7YnZxAzRLhVzVejWXQtFSguUYUA2l7Gun0Ghoc/OmApNSt/3yQyCA+qbSF5VWuQvocUCi0CUK8BVAZJFEhn0O3f+Hhlyl7aRfs8dlsC7oOoKtc0IkHk3g2Oo2hjmXY2jhX9w9MT7c6oHB4P4julgvKE99LSvXNXxORSBLMRwrBFikGneoOKXXA3qPcxCwl5wMtUt46zSgptXpO3i5QOLwZRI9mmqynU0xOMfbdSGFbU+X8ZZivKqLnZBg7XQfWz7csyRPFyDAuLszr+7uVI5CjAPQoJv0MAL3HSTJN103tu3S+s3POmYZtmB3Z/4aPM0dixB6WlaREYriQkP4DhYT2pc+2+CQAAAAASUVORK5CYII=
// @grant       GM_cookie
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_setClipboard
// @license MIT
// ==/UserScript==

(function () {
  "use strict";
  const hostname = location.hostname;
  const domain = hostname;
  let cookiesConfig = GM_getValue("cookiesConfig", {});
  const mainClassName = `cookieSwitchWrapper_${randomStr()}`;

  const LIVE_COOKIES_OPTION_VALUE = "__LIVE_COOKIES__";
  const LIVE_COOKIES_OPTION_TEXT = "当前Cookie";

  function randomStr() {
    const letters = "abcdefghijklmnopqrstuvwxyz";
    let str = "";
    for (let i = 0; i < 6; i++) {
      str += letters[Math.floor(Math.random() * 26)];
    }
    return str;
  }

  function closePannel() {
    $(`.${mainClassName}`).css("transform", "translateX(110%)");
  }

  /**
   * Checks if the table width exceeds the panel width and applies word wrapping to the Name column if necessary.
   */
  function checkAndAdjustNameColumnWrap() {
    setTimeout(() => {
        const $mainDiv = $(`.${mainClassName}`);
        if (!$mainDiv.length) return;

        const $table = $mainDiv.find('.cookieTable');
        if (!$table.length || $table.find('tbody tr').length === 0) return;

        const $nameColumn = $table.find('th:first-child, td.cookie-name');

        // Temporarily remove the class to measure the table's natural width
        $nameColumn.removeClass('force-wrap-name');

        if ($table.outerWidth() > $mainDiv.width()) {
            $nameColumn.addClass('force-wrap-name');
        }
    }, 100); // Use a short delay to ensure DOM is updated before measuring
  }


  function createStyle() {
    const css = `
      .${mainClassName} {
        position: fixed; z-index: 999999; top: 0; right: 0;
        width: 1000px; height: 100%; padding: 10px;
        transition: transform 200ms; transform: translateX(110%);
        background-color: #fff !important; color: #000 !important;
        box-shadow: -10px 0 10px #ddd; overflow: auto;
      }
      .${mainClassName} .topWrapper {
        display: flex; justify-content: space-between; align-items: center; margin-bottom:10px;
      }
      .${mainClassName} .topWrapper span { color: #000 !important; }
      .${mainClassName} select, .${mainClassName} input, .${mainClassName} button {
        background-color: #fff !important;
        color: #000 !important;
        border: 1px solid #ccc !important;
        padding: 5px 8px !important;
        border-radius: 3px !important;
        margin-left: 5px !important;
      }
      .${mainClassName} select { min-width: 180px; }
      .${mainClassName} .titleInput { font-size: 14px; outline: none; flex-grow: 1; margin-left:10px !important; }
      .${mainClassName} .topWrapper button { margin-left: 10px !important; }
      .${mainClassName} .delete-setting-btn { background-color: #ffdddd !important; border-color: #ffaaaa !important;}

      .${mainClassName} .cookieTable { width: 100%; margin-top: 15px; border-collapse: collapse; }
      .${mainClassName} .cookieTable thead { background-color: #f0f0f0 !important; }
      .${mainClassName} .cookieTable th, .${mainClassName} .cookieTable td {
        font-size: 12px; padding: 6px; text-align: center;
        border: 1px solid #ddd !important;
        color: #000 !important;
      }
      .${mainClassName} .cookieTable th { font-size: 13px; white-space: nowrap; background-color: #e9e9e9 !important; }
      .${mainClassName} .cookieTable tbody tr:nth-child(odd) { background-color: #f9f9f9 !important; }
      .${mainClassName} .cookieTable tbody tr:hover { background-color: #f1f1f1 !important; }
      .${mainClassName} .cookieTable td.cookie-name { text-align: left; }
      .${mainClassName} .cookieTable td.cookie-value { text-align: left; word-break: break-all; }
      .${mainClassName} .cookieTable textarea {
        width: 100%;
        box-sizing: border-box;
        padding: 2px !important;
        border: 1px solid #eee !important;
        outline: none;
		color: #000 !important;
        background-color: #FFFFFF !important;
        font-family: inherit;
        font-size: inherit;
        line-height: inherit;
        resize: none;
        overflow-y: hidden;
        vertical-align: top;
      }
      .${mainClassName} .cookieTable button {
        word-break: keep-all; padding: 3px 6px !important; font-size:11px !important;
      }
      .${mainClassName} .btnWrapper {
        display: flex; justify-content: center; margin-top: 20px;
      }
      .${mainClassName} .btnWrapper button {
        margin-left: 15px !important; padding: 8px 20px !important; cursor: pointer;
        border: 1px solid #ddd;border-radius: 4px;background-color: #fff;&:hover {background-color: #f1f1f1;
      }
      #cookieBtn {
        background-color: #FF6E6E !important;
      }
      /* Style to force word wrapping on the name column when needed */
      .${mainClassName} .force-wrap-name {
        white-space: normal !important;
        word-break: break-all !important;
      }
    `;
    return $("<style lang='scss'></style>").text(css);
  }

  function createCookieBtn() {
    const cookieBtn = $(
      `<div id="cookieBtn"><svg t="1715656222971" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1852" width="26" height="26"><path d="M1023.72271 650.495659a541.231658 541.231658 0 0 1-881.127308 230.481105 544.362949 544.362949 0 0 1 221.599077-880.946655A161.773348 161.773348 0 0 0 414.897311 63.37854c9.183114 12.133754 19.901765 23.002948 31.915085 32.366713-12.766034 33.26997-49.468381 147.381451 27.097713 191.791593 16.077976 28.84401 48.655449 49.980227 108.782264 51.184569 0.602171 41.579935 9.785285 109.264001 59.283775 139.222029 27.850427 44.620901 84.635191 71.206769 198.716563 22.611536A167.102565 167.102565 0 0 0 903.288429 609.186701a98.816327 98.816327 0 0 0 120.434281 41.308958z" fill="#FF6E6E" p-id="1853"></path><path d="M195.737029 542.104807a45.162855 45.162855 0 1 1 0 90.32571 45.162855 45.162855 0 0 1 0-90.32571z m270.977132 270.977132a45.162855 45.162855 0 1 1 0 90.32571 45.162855 45.162855 0 0 1 0-90.32571z m0-301.085703a45.162855 45.162855 0 1 1 0 90.325711 45.162855 45.162855 0 0 1 0-90.325711z m-180.651422-301.085702a45.162855 45.162855 0 1 1 0 90.325711 45.162855 45.162855 0 0 1 0-90.325711z m511.845694 451.628553a45.162855 45.162855 0 1 1 0 90.325711 45.162855 45.162855 0 0 1 0-90.325711z" fill="#0C0058" p-id="1854"></path></svg></div>`
    )
      .css({
        width: "26px", height: "26px", position: "fixed",
        right: "10px", bottom: "40px", "z-index": 99999,
        cursor: "pointer", "user-select": "none",
        "box-shadow": "-4px 4px 8px #ddd", "border-radius": "50%",
        opacity: "0.9",
      })
      .click(() => {
        $(`.${mainClassName}`).css("transform", "translateX(0)");
        checkAndAdjustNameColumnWrap();
      });
    return cookieBtn;
  }

  function updateDeleteButtonVisibility() {
    const selectedValue = $(`.${mainClassName} .title-select`).val();
    const deleteBtn = $(`.${mainClassName} .delete-setting-btn`);
    if (selectedValue && selectedValue !== LIVE_COOKIES_OPTION_VALUE && cookiesConfig[domain] && cookiesConfig[domain].some(s => s.title === selectedValue)) {
      deleteBtn.show();
    } else {
      deleteBtn.hide();
    }
  }

  function refreshSettingsUI(selectThisValue = null) {
    const titleSelect = $(`.${mainClassName} .title-select`);
    const titleInput = $(`.${mainClassName} .titleInput`);
    titleSelect.empty();

    // Always add Live Cookies option first
    titleSelect.append($("<option>").val(LIVE_COOKIES_OPTION_VALUE).text(LIVE_COOKIES_OPTION_TEXT));

    // Add saved configurations
    if (cookiesConfig[domain] && cookiesConfig[domain].length > 0) {
      cookiesConfig[domain].forEach((item) => {
        titleSelect.append($("<option>").val(item.title).text(item.title));
      });
    }

    let finalSelectedValue = selectThisValue || LIVE_COOKIES_OPTION_VALUE; // Default to live if nothing specific

    // Ensure the value to select is actually in the dropdown
    if (finalSelectedValue !== LIVE_COOKIES_OPTION_VALUE && (!cookiesConfig[domain] || !cookiesConfig[domain].some(s => s.title === finalSelectedValue))) {
        finalSelectedValue = LIVE_COOKIES_OPTION_VALUE; // Fallback to live if requested saved config not found
    }

    titleSelect.val(finalSelectedValue);

    if (finalSelectedValue === LIVE_COOKIES_OPTION_VALUE) {
      titleInput.val(""); // Clear input, ready for new name if user wants to save live state
      GM_cookie.list({}, function (cookies, error) {
        if (!error) {
          fillTable(cookies);
        } else {
          $(`.${mainClassName} tbody`).html("<tr><td colspan='10'>无法加载当前Cookie.</td></tr>");
        }
      });
    } else { // A saved configuration is selected
      titleInput.val(finalSelectedValue); // Set input to the name of the saved config
      const setting = cookiesConfig[domain].find(s => s.title === finalSelectedValue);
      fillTable(setting?.cookies);
    }
    updateDeleteButtonVisibility();
  }


  function handleDeleteCurrentSetting() {
    const titleToDelete = $(`.${mainClassName} .title-select`).val();
    if (!titleToDelete || titleToDelete === LIVE_COOKIES_OPTION_VALUE || !cookiesConfig[domain] || !cookiesConfig[domain].find(s => s.title === titleToDelete)) {
      alert("没有选中的有效已保存配置可删除");
      return;
    }

    //if (confirm(`确认删除配置 "${titleToDelete}" 吗?`))
    {
      cookiesConfig[domain] = cookiesConfig[domain].filter(item => item.title !== titleToDelete);
      if (cookiesConfig[domain].length === 0) {
        delete cookiesConfig[domain];
      }
      GM_setValue("cookiesConfig", cookiesConfig);
      //alert(`配置 "${titleToDelete}" 已删除`);
      refreshSettingsUI(LIVE_COOKIES_OPTION_VALUE); // Refresh and select live cookies
    }
  }

  function createMain() {
    const titleSelect = $("<select class='title-select'>");
    const titleInput = $("<input class='titleInput' placeholder='输入新配置名称或选择现有配置' />");
    const deleteSettingBtn = $("<button class='delete-setting-btn'>删除此配置</button>")
      .click(handleDeleteCurrentSetting)
      .hide();

    titleSelect.change((e) => {
      const selectedValue = $(e.target).val();
      refreshSettingsUI(selectedValue); // Let refreshSettingsUI handle loading and input field
    });

    titleInput.change((e) => {
        const currentTypedTitle = $(e.target).val().trim();
        const titleSelectElement = $(`.${mainClassName} .title-select`);

        if (currentTypedTitle === "") { // If input is cleared
            if (titleSelectElement.val() !== LIVE_COOKIES_OPTION_VALUE) {
                // If not already on live, switch to live view
                refreshSettingsUI(LIVE_COOKIES_OPTION_VALUE);
            }
        } else if (cookiesConfig[domain] && cookiesConfig[domain].some(item => item.title === currentTypedTitle)) {
            // If typed name matches an existing saved config, select it
            if (titleSelectElement.val() !== currentTypedTitle) {
                 refreshSettingsUI(currentTypedTitle);
            }
        }
    });


    const closeBtn = $("<button>关闭</button>").click(closePannel);
    const topDiv = $("<div class='topWrapper'>").append(
      `<span>当前域名: ${domain}</span>`,
      titleSelect,
      deleteSettingBtn,
      titleInput,
      closeBtn
    );

    const cookieTable = $("<table class='cookieTable'></table>")
      .append(
        `<thead><tr><th>Name</th><th>Value</th><th>Domain</th><th>Path</th><th>Expires/Max-Age</th><th>Size</th><th>HttpOnly</th><th>Secure</th><th>SameSite</th><th>操作</th></tr></thead>`,
        `<tbody></tbody>`
      )
      .on("click", ".editable:not(.editing)", function (event) {
        const td = $(this);
        td.addClass("editing");
        const originalText = td.text();
        const textarea = $("<textarea />").val(originalText);

        // Function to auto-resize textarea
        const autoResize = (el) => {
            el.style.height = 'auto';
            el.style.height = el.scrollHeight + 'px';
        };

        textarea.blur(() => {
          td.removeClass("editing");
          td.text(textarea.val());
          checkAndAdjustNameColumnWrap();
        }).on('keydown', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                $(this).blur();
            } else if (e.key === 'Escape') {
                td.removeClass("editing");
                td.text(originalText);
                $(this).remove();
            }
        }).on('input', function() {
            autoResize(this);
        });

        td.html(textarea);
        autoResize(textarea[0]); // Set initial size
        textarea.focus();
      });

    const addBtn = $("<button>新增</button>").click(() => {
      const deleteRowBtn = $("<button>删除</button>").click(function () {
        if (confirm(`确认删除此行吗?`)) {
            $(this).closest("tr").remove();
            checkAndAdjustNameColumnWrap();
        }
      });
      const deleteTd = $("<td>").append(deleteRowBtn);
      const tr = $("<tr class='cookie-row'>").append(
        `<td class="editable cookie-name"></td><td class="editable cookie-value"></td><td class="editable">${domain}</td><td class="editable">/</td><td class="editable"></td><td></td><td class="editable">false</td><td class="editable">false</td><td class="editable">Lax</td>`,
        deleteTd
      );
      $(`.${mainClassName} tbody`).append(tr);
      checkAndAdjustNameColumnWrap();
    });

    const saveBtn = $("<button>保存</button>").click(() => {
      const currentTitle = $(`.${mainClassName} .titleInput`).val().trim();
      const savedCookies = saveCookie(); // saveCookie now handles title validation
      if (savedCookies) {
        //alert(`配置 "${currentTitle}" 已保存!`);
        refreshSettingsUI(currentTitle); // Refresh and reselect the saved/updated title
      }
    });

    const applyBtn = $("<button>保存并导入</button>").click(() => {
      applyCookie();
    });

    // --- 新增按钮 ---
    const copyBtn = $("<button>复制</button>").click(() => {
        copyCookiesToClipboard();
    });

    // --- 修改按钮容器 ---
    const btnWrapper = $("<div class='btnWrapper'></div>").append(addBtn, saveBtn, applyBtn, copyBtn);
    return $(`<div class='${mainClassName}'></div>`).append(topDiv, cookieTable, btnWrapper);
  }

  function initPage() {
    cookiesConfig = GM_getValue("cookiesConfig", {});
    const main = createMain();
    const style = createStyle();
    const cookieBtn = createCookieBtn();
    $("body").append(style, cookieBtn, main);
    refreshSettingsUI(LIVE_COOKIES_OPTION_VALUE); // Default to live cookies on initial load
  }

  function saveCookie() {
    const title = $(`.${mainClassName} .titleInput`).val().trim();
    if (!title) {
      alert("请输入配置名称");
      return undefined;
    }
    if (title === LIVE_COOKIES_OPTION_TEXT) {
        alert(`配置名称不能是 "${LIVE_COOKIES_OPTION_TEXT}". 请输入一个不同的名称`);
        return undefined;
    }

    const cookies = [];
    $(`.${mainClassName} .cookieTable .cookie-row`).each(function () {
      const tds = $(this).children("td");
      const name = tds.eq(0).text().trim();
      if (!name) return;

      let expirationDate;
      const expDateStr = tds.eq(4).text().trim();
      if (expDateStr && expDateStr.toLowerCase() !== 'session') {
        const parsedDate = Date.parse(expDateStr);
        if (!isNaN(parsedDate)) expirationDate = parsedDate / 1000;
      }

      cookies.push({
        name: name, value: tds.eq(1).text(),
        domain: tds.eq(2).text().trim() || domain,
        path: tds.eq(3).text().trim() || "/",
        expirationDate: expirationDate,
        httpOnly: tds.eq(6).text().trim().toLowerCase() === 'true',
        secure: tds.eq(7).text().trim().toLowerCase() === 'true',
        sameSite: tds.eq(8).text().trim() || 'Lax',
      });
    });

    if (!cookiesConfig[domain]) cookiesConfig[domain] = [];
    const existingSettingIndex = cookiesConfig[domain].findIndex(item => item.title === title);
    if (existingSettingIndex > -1) {
      cookiesConfig[domain][existingSettingIndex].cookies = cookies;
    } else {
      cookiesConfig[domain].push({ title, cookies });
    }
    GM_setValue("cookiesConfig", cookiesConfig);
    return cookies;
  }

  function applyCookie() {
    const currentTitle = $(`.${mainClassName} .titleInput`).val().trim();
    const cookiesToApply = saveCookie(); // This also saves the configuration.
    if (!cookiesToApply) {
        // saveCookie already showed an alert if there was a problem (e.g., no title).
        return;
    }

    // 1. Get all existing cookies that the script can access.
    GM_cookie.list({}, function(existingCookies, error) {
        if (error) {
            alert('获取现有Cookie列表失败,操作已取消');
            console.error('Error listing cookies for deletion:', error);
            return;
        }

        let deletedCount = 0;
        const totalToDelete = existingCookies.length;

        // This function will be called after all existing cookies are deleted.
        const setNewCookies = () => {
            let successCount = 0;
            let errorCount = 0;
            const totalToSet = cookiesToApply.length;

            if (totalToSet === 0) {
                alert("所有现有Cookie已被清除页面即将刷新");
                closePannel();
                location.reload();
                return;
            }

            cookiesToApply.forEach((cookie) => {
                const cookieDetails = { ...cookie };
                // Prepare cookie details for setting
                if (cookieDetails.expirationDate === undefined || isNaN(cookieDetails.expirationDate)) {
                    delete cookieDetails.expirationDate; // For session cookies
                }
                if (!cookieDetails.domain) cookieDetails.domain = domain;
                if (!cookieDetails.path) cookieDetails.path = "/";

                GM_cookie.set(cookieDetails, function (setError) {
                    if (setError) {
                        console.error("设置Cookie失败:", setError, cookieDetails);
                        errorCount++;
                    } else {
                        successCount++;
                    }
                    // Check if all new cookies have been processed
                    if (successCount + errorCount === totalToSet) {
                        //alert(`配置: ${currentTitle}\n导入完成\n\n清除现有☢: ${totalToDelete}\n导入成功✔: ${successCount}\n导入失败❌: ${errorCount}\n\n页面即将刷新`);
                        closePannel();
                        location.reload();
                    }
                });
            });
        };

        // 2. If there are no existing cookies, go straight to setting new ones.
        if (totalToDelete === 0) {
            console.log("没有需要删除的现有Cookie");
            setNewCookies();
            return;
        }

        // 3. Delete each existing cookie.
        console.log(`准备删除 ${totalToDelete} 个现有Cookie...`);
        existingCookies.forEach(cookie => {
            // Use the specific details from the listed cookie to ensure correct deletion.
            GM_cookie.delete({ name: cookie.name, domain: cookie.domain, path: cookie.path }, function(deleteError) {
                if (deleteError) {
                    console.error('删除Cookie失败:', deleteError, cookie);
                }
                deletedCount++;
                // 4. After all deletions are attempted, proceed to set the new cookies.
                if (deletedCount === totalToDelete) {
                    console.log("所有现有Cookie已处理完毕");
                    setNewCookies();
                }
            });
        });
    });
  }

  // --- 新增函数 ---
  /**
   * Copies the current set of cookies (Name and Value) to the clipboard.
   * Format: Name1=Value1;Name2=Value2;Name3=Value3;
   */
  function copyCookiesToClipboard() {
    const cookiePairs = [];
    $(`.${mainClassName} .cookieTable tbody .cookie-row`).each(function () {
        const tds = $(this).children("td");
        const name = tds.eq(0).text().trim();
        const value = tds.eq(1).text().trim();
        if (name) { // Only include if name is not empty
            cookiePairs.push(`${name}=${value}`);
        }
    });

    if (cookiePairs.length === 0) {
        alert("没有可复制的Cookie");
        return;
    }

    // Join with a semicolon and add a trailing semicolon for the correct format
    const cookieString = cookiePairs.join('; ');

    // Use the modern Clipboard API. GM_setClipboard is also an option.
    if (navigator.clipboard && window.isSecureContext) {
        navigator.clipboard.writeText(cookieString).then(() => {
        }).catch(err => {
            // Fallback for older browsers or non-secure contexts if needed
            GM_setClipboard(cookieString, "text");
        });
    } else {
        // Fallback for older browsers or non-secure contexts
        GM_setClipboard(cookieString, "text");
    }
  }


  function fillTable(cookiesArray) {
    const tbody = $(`.${mainClassName} tbody`);
    tbody.html("");
    if (!cookiesArray || cookiesArray.length === 0) {
      tbody.html("<tr><td colspan='10'>没有Cookies数据显示</td></tr>");
      checkAndAdjustNameColumnWrap();
      return;
    }
    cookiesArray.forEach((cookie) => {
      const deleteRowBtn = $("<button>删除</button>").click(function () {
        {
            $(this).closest("tr").remove();
            checkAndAdjustNameColumnWrap();
        }
      });
      const deleteTd = $("<td>").append(deleteRowBtn);
      const expirationDateString = cookie.expirationDate ? new Date(cookie.expirationDate * 1000).toLocaleString() : "Session";
      const tr = $("<tr class='cookie-row'>").append(
        `<td class="editable cookie-name">${cookie.name || ""}</td>
         <td class="editable cookie-value">${cookie.value || ""}</td>
         <td class="editable">${cookie.domain || ""}</td>
         <td class="editable">${cookie.path || ""}</td>
         <td class="editable">${expirationDateString}</td>
         <td>${String(cookie.value || "").length}</td>
         <td class="editable">${typeof cookie.httpOnly === 'boolean' ? cookie.httpOnly : false}</td>
         <td class="editable">${typeof cookie.secure === 'boolean' ? cookie.secure : false}</td>
         <td class="editable">${cookie.sameSite || "Lax"}</td>`,
        deleteTd
      );
      tbody.append(tr);
    });
    checkAndAdjustNameColumnWrap();
  }

  initPage();
})();