杨东明 9 сар өмнө
parent
commit
0c4091c348
1 өөрчлөгдсөн 452 нэмэгдсэн , 400 устгасан
  1. 452 400
      page.js

+ 452 - 400
page.js

@@ -2,447 +2,499 @@ let nowFileName = "";
 let jsonInfo = {};
 let tabId = "";
 let nodeObj;
+let jslist;
 function InitTable() {
-    window.TabInstance = $("#filterTable")
-        .dxDataGrid({
-            dataSource: [],
-            keyExpr: "resource_detail_id",
-            remoteOperations: false,
-            searchPanel: {
-                visible: true,
-                highlightCaseSensitive: true,
-            },
-            groupPanel: { visible: true },
-            grouping: {
-                allowCollapsing: true,
-                autoExpandAll: true,
-                expandMode: "rowClick",
-            },
-            selection: {
-                mode: "single",
-            },
-            allowColumnReordering: true,
-            rowAlternationEnabled: true,
-            showBorders: true,
-            height: "100%",
-            columns: [
-                {
-                    dataField: "JS文件",
-                    dataType: "JS文件",
-                    groupIndex: 0,
-                },
-                {
-                    dataField: "过滤器",
-                    caption: "过滤器",
-                },
-                {
-                    dataField: "选择器类型",
-                    dataType: "选择器类型",
-                },
-                {
-                    dataField: "调用方式",
-                    dataType: "调用方式",
-                },
-                {
-                    dataField: "所在位置",
-                    dataType: "所在位置",
-                },
-                {
-                    dataField: "DOM操作分类",
-                    dataType: "DOM操作分类",
-                },
-            ],
-            onContentReady(e) { },
-            onSelectionChanged: function (selectedItems) {
-                let data = selectedItems.selectedRowsData[0];
-                if (data) {
-                    let ast = data.astJSON;
-                    if (data.JS文件 !== nowFileName) {
-                        nowFileName = data.JS文件;
-                        let code = window.fileList.find((o) => o.name === data.JS文件).code;
-                        //更改JS代码
-                        jsCode.SetCode(code);
-                        //更改ast
-                        //window.ShowASTTree(ast, document.getElementById('astJson'))
-                    }
-                    //jscode定位
-                    let {
-                        defineNode: {
-                            iid,
-                            loc: { end, start },
-                        },
-                    } = data.source_data;
-                    {
-                        //移出所有高亮
-                        jsCode.RemoveAllHighlight();
-                        //设置高亮
-                        jsCode.CreateHighlight({
-                            startLine: start?.line,
-                            startColumn: start?.column + 1,
-                            endLine: end?.line,
-                            endColumn: end?.column + 1,
-                        });
-                    }
-                    {
-                        // //ast定位
-                        // let jsonNode = document.getElementById(iid);
-                        // if (jsonNode) {
-                        //     let textNode = Array.from(jsonNode.parentNode.childNodes).find(item => item.classList.contains("node-text"));
-                        //     $("#astJson").find(".monaco-highlight").removeClass("monaco-highlight");
-                        //     textNode?.classList?.add("monaco-highlight");
-                        //     scrollTo(jsonNode)
-                        // }
-                    }
-                }
+  window.TabInstance = $("#filterTable")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "resource_detail_id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      groupPanel: { visible: true },
+      grouping: {
+        allowCollapsing: true,
+        autoExpandAll: true,
+        expandMode: "rowClick",
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      height: "100%",
+      columns: [
+        {
+          dataField: "JS文件",
+          dataType: "JS文件",
+          groupIndex: 0,
+        },
+        {
+          dataField: "过滤器",
+          caption: "过滤器",
+        },
+        {
+          dataField: "选择器类型",
+          dataType: "选择器类型",
+        },
+        {
+          dataField: "调用方式",
+          dataType: "调用方式",
+        },
+        {
+          dataField: "所在位置",
+          dataType: "所在位置",
+        },
+        {
+          dataField: "DOM操作分类",
+          dataType: "DOM操作分类",
+        },
+      ],
+      onContentReady(e) {},
+      onSelectionChanged: function (selectedItems) {
+        let data = selectedItems.selectedRowsData[0];
+        if (data) {
+          let ast = data.astJSON;
+          if (data.JS文件 !== nowFileName) {
+            nowFileName = data.JS文件;
+            let code = window.fileList.find((o) => o.name === data.JS文件).code;
+            //更改JS代码
+            jsCode.SetCode(code);
+            //更改ast
+            //window.ShowASTTree(ast, document.getElementById('astJson'))
+          }
+          //jscode定位
+          let {
+            defineNode: {
+              iid,
+              loc: { end, start },
             },
-        })
-        .dxDataGrid("instance");
+          } = data.source_data;
+          {
+            //移出所有高亮
+            jsCode.RemoveAllHighlight();
+            //设置高亮
+            jsCode.CreateHighlight({
+              startLine: start?.line,
+              startColumn: start?.column + 1,
+              endLine: end?.line,
+              endColumn: end?.column + 1,
+            });
+          }
+          {
+            // //ast定位
+            // let jsonNode = document.getElementById(iid);
+            // if (jsonNode) {
+            //     let textNode = Array.from(jsonNode.parentNode.childNodes).find(item => item.classList.contains("node-text"));
+            //     $("#astJson").find(".monaco-highlight").removeClass("monaco-highlight");
+            //     textNode?.classList?.add("monaco-highlight");
+            //     scrollTo(jsonNode)
+            // }
+          }
+        }
+      },
+    })
+    .dxDataGrid("instance");
 
-    window.CSSTabInstance = $("#cssJson")
-        .dxDataGrid({
-            dataSource: [],
-            keyExpr: "id",
-            remoteOperations: false,
-            searchPanel: {
-                visible: true,
-                highlightCaseSensitive: true,
-            },
-            selection: {
-                mode: "single",
-            },
-            allowColumnReordering: true,
-            rowAlternationEnabled: true,
-            showBorders: true,
-            height: "100%",
-            paging: {
-                enabled: false,
-                pageSize: 0,
-            },
-            columns: [
-                {
-                    dataField: "key",
-                    caption: "名称",
-                },
-                {
-                    dataField: "value",
-                    caption: "生效值",
-                },
-            ],
-            onSelectionChanged: function (selectedItems) {
-                let data = selectedItems.selectedRowsData[0];
-                if (data) {
-                    CSSBelongInstance.option({
-                        dataSource: findPropRef(data.key, jsonInfo).map((s, i) => ({
-                            ...s,
-                            id: i,
-                        })),
-                    });
-                }
-            },
-        })
-        .dxDataGrid("instance");
+  window.CSSTabInstance = $("#cssJson")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      height: "100%",
+      paging: {
+        enabled: false,
+        pageSize: 0,
+      },
+      columns: [
+        {
+          dataField: "key",
+          caption: "名称",
+        },
+        {
+          dataField: "value",
+          caption: "生效值",
+        },
+      ],
+      onSelectionChanged: function (selectedItems) {
+        let data = selectedItems.selectedRowsData[0];
+        if (data) {
+          CSSBelongInstance.option({
+            dataSource: findPropRef(data.key, jsonInfo).map((s, i) => ({
+              ...s,
+              id: i,
+            })),
+          });
+        }
+      },
+    })
+    .dxDataGrid("instance");
 
-    window.CSSBelongInstance = $("#cssBelong")
-        .dxDataGrid({
-            dataSource: [],
-            keyExpr: "id",
-            remoteOperations: false,
-            searchPanel: {
-                visible: true,
-                highlightCaseSensitive: true,
-            },
-            selection: {
-                mode: "single",
-            },
-            allowColumnReordering: true,
-            rowAlternationEnabled: true,
-            showBorders: true,
-            paging: {
-                enabled: false,
-                pageSize: 0,
-            },
-            height: "100%",
-            columns: [
-                {
-                    dataField: "来源",
-                    caption: "来源",
-                    width: 100,
-                },
-                {
-                    dataField: "选择器",
-                    caption: "选择器",
-                },
-                {
-                    dataField: "属性值",
-                    caption: "属性值",
-                },
-            ],
-        })
-        .dxDataGrid("instance");
+  window.CSSBelongInstance = $("#cssBelong")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      paging: {
+        enabled: false,
+        pageSize: 0,
+      },
+      height: "100%",
+      columns: [
+        {
+          dataField: "来源",
+          caption: "来源",
+          width: 100,
+        },
+        {
+          dataField: "选择器",
+          caption: "选择器",
+        },
+        {
+          dataField: "属性值",
+          caption: "属性值",
+        },
+      ],
+    })
+    .dxDataGrid("instance");
 
-    window.eventTableInstance = $("#eventTable")
-        .dxDataGrid({
-            dataSource: [],
-            keyExpr: "id",
-            remoteOperations: false,
-            searchPanel: {
-                visible: true,
-                highlightCaseSensitive: true,
-            },
-            selection: {
-                mode: "single",
-            },
-            allowColumnReordering: true,
-            rowAlternationEnabled: true,
-            showBorders: true,
-            paging: {
-                enabled: false,
-                pageSize: 0,
-            },
-            height: "100%",
-            columns: [
-                {
-                    dataField: "事件名称",
-                    caption: "事件名称",
-                },
-                {
-                    dataField: "绑定对象",
-                    caption: "绑定对象",
-                }
-            ],
-        })
-        .dxDataGrid("instance");
+  window.eventTableInstance = $("#eventTable")
+    .dxDataGrid({
+      dataSource: [],
+      keyExpr: "id",
+      remoteOperations: false,
+      searchPanel: {
+        visible: true,
+        highlightCaseSensitive: true,
+      },
+      selection: {
+        mode: "single",
+      },
+      allowColumnReordering: true,
+      rowAlternationEnabled: true,
+      showBorders: true,
+      paging: {
+        enabled: false,
+        pageSize: 0,
+      },
+      height: "100%",
+      columns: [
+        {
+          dataField: "事件名称",
+          caption: "事件名称",
+        },
+        {
+          dataField: "绑定对象",
+          caption: "绑定对象",
+        },
+        {
+          dataField: "事件文件",
+          caption: "事件文件",
+        },
+      ],
+    })
+    .dxDataGrid("instance");
 }
 chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
-    if (request.msgToPopup === "发送页面") {
-        //初始化JS代码编辑器
-        window.jsCode = new CodeEditor();
-        jsCode.InitEditor($("#jscode")[0], false, false, [], false);
-        jsCode.dataType = 3;
-        InitTable();
-        let ret = request.data;
-        console.log(ret);
-        let { jslist, targe, csslist, tabId: _tabId, path } = ret;
-        tabId = _tabId;
-        parseCodeToAST(
-            jslist.map((item) => {
-                return {
-                    code: item.data,
-                    name: item.fileName,
-                };
-            })
-        );
+  if (request.msgToPopup === "发送页面") {
+    //初始化JS代码编辑器
+    window.jsCode = new CodeEditor();
+    jsCode.InitEditor($("#jscode")[0], false, false, [], false);
+    jsCode.dataType = 3;
+    InitTable();
+    let ret = request.data;
+    console.log(ret);
+    let { jslist: _jslist, targe, csslist, tabId: _tabId, path } = ret;
+    jslist = _jslist;
+    tabId = _tabId;
+    parseCodeToAST(
+      jslist.map((item) => {
+        return {
+          code: item.data,
+          name: item.fileName,
+        };
+      })
+    );
 
-        let data = window.findSelector();
-        let id = $(targe).attr("id");
-        let classList = $(targe).attr("class").split(" ");
-        data = data.filter((m) => {
-            let v = m.过滤器;
-            if (v.includes(id)) return true;
+    let data = window.findSelector();
+    let id = $(targe).attr("id");
+    let classList = $(targe).attr("class").split(" ");
+    data = data.filter((m) => {
+      let v = m.过滤器;
+      if (v.includes(id)) return true;
 
-            if (classList.length > 0) {
-                for (const classitem of classList) {
-                    if (v.includes(classitem)) return true;
-                }
-            }
-        });
+      if (classList.length > 0) {
+        for (const classitem of classList) {
+          if (v.includes(classitem)) return true;
+        }
+      }
+    });
 
-        await attach();
-        await getPathNodeInfo(path);
-        let events = await findEvent();
-        TabInstance.option({
-            dataSource: data,
-        });
+    await attach();
+    await getPathNodeInfo(path);
+    let events = await findEvent();
+    TabInstance.option({
+      dataSource: data,
+    });
 
-        CSSTabInstance.option({
-            dataSource: Object.entries(csslist).map((a, index) => ({
-                id: index,
-                key: a[0],
-                value: a[1],
-            })),
-        });
+    CSSTabInstance.option({
+      dataSource: Object.entries(csslist).map((a, index) => ({
+        id: index,
+        key: a[0],
+        value: a[1],
+      })),
+    });
 
-        eventTableInstance.option({
-            dataSource: translateEventData(events)
-        })
-    }
+    eventTableInstance.option({
+      dataSource: translateEventData(events),
+    });
+  }
 });
 
 function findPropRef(key, json) {
-    let matchedCSSRules = json.matchedCSSRules;
-    let retArr = [];
-    for (const matchedCSSRule of matchedCSSRules) {
-        let cssProperties = matchedCSSRule.rule.style.cssProperties;
-        let cssProp = cssProperties.find((m) => m.name == key);
-        if (!cssProp) continue;
-        let ret = {
-            来源: "CSS",
-            选择器: matchedCSSRule.rule.selectorList.text,
-            选中选择器: matchedCSSRule.matchingSelectors[0],
-            属性值: cssProp.value,
-        };
-        retArr.push(ret);
-    }
-    return retArr;
+  let matchedCSSRules = json.matchedCSSRules;
+  let retArr = [];
+  for (const matchedCSSRule of matchedCSSRules) {
+    let cssProperties = matchedCSSRule.rule.style.cssProperties;
+    let cssProp = cssProperties.find((m) => m.name == key);
+    if (!cssProp) continue;
+    let ret = {
+      来源: "CSS",
+      选择器: matchedCSSRule.rule.selectorList.text,
+      选中选择器: matchedCSSRule.matchingSelectors[0],
+      属性值: cssProp.value,
+    };
+    retArr.push(ret);
+  }
+  return retArr;
 }
 
 async function getPathNodeInfo(path) {
-    const doc = await getDocument();
-    // const htmlInfo = doc.children.find((m) => m.localName === "html");
-    let info = doc;
-    for (const index of path) {
-        info = getpath(info, index);
-    }
-    nodeObj = info;
-    let nodeId = info.nodeId;
-    let cssInfo = await getMatchedStylesForNode(nodeId);
-    jsonInfo = cssInfo;
+  const doc = await getDocument();
+  // const htmlInfo = doc.children.find((m) => m.localName === "html");
+  let info = doc;
+  for (const index of path) {
+    info = getpath(info, index);
+  }
+  nodeObj = info;
+  let nodeId = info.nodeId;
+  let cssInfo = await getMatchedStylesForNode(nodeId);
+  jsonInfo = cssInfo;
 
-    function getpath(info, index) {
-        let children = info.children;
-        return children[index];
-    }
+  function getpath(info, index) {
+    let children = info.children;
+    return children[index];
+  }
 }
 
 async function getMatchedStylesForNode(nodeId) {
-    let ret = await chrome.debugger.sendCommand(
-        { tabId },
-        "CSS.getMatchedStylesForNode",
-        {
-            nodeId,
-        }
-    );
-    return ret;
+  let ret = await chrome.debugger.sendCommand(
+    { tabId },
+    "CSS.getMatchedStylesForNode",
+    {
+      nodeId,
+    }
+  );
+  return ret;
 }
 
 async function getDocument() {
-    const doc = await chrome.debugger.sendCommand({ tabId }, "DOM.getDocument", {
-        pierce: true,
-        depth: -1,
-    });
-    return doc.root;
+  const doc = await chrome.debugger.sendCommand({ tabId }, "DOM.getDocument", {
+    pierce: true,
+    depth: -1,
+  });
+  return doc.root;
 }
 
 async function attach() {
-    //   const targets = await chrome.debugger.getTargets();
-    //   let target = targets.find((m) => m.tabId == tabId);
-    //   if (target?.attached === true) {
-    //   } else {
-    //     await chrome.debugger.attach({ tabId }, "1.3");
-    //   }
-    await chrome.debugger.attach({ tabId }, "1.3").catch(() => { });
-    await chrome.debugger.sendCommand({ tabId }, "DOM.enable");
-    await chrome.debugger.sendCommand({ tabId }, "CSS.enable");
+  //   const targets = await chrome.debugger.getTargets();
+  //   let target = targets.find((m) => m.tabId == tabId);
+  //   if (target?.attached === true) {
+  //   } else {
+  //     await chrome.debugger.attach({ tabId }, "1.3");
+  //   }
+  await chrome.debugger.attach({ tabId }, "1.3").catch(() => {});
+  await chrome.debugger.sendCommand({ tabId }, "DOM.enable");
+  await chrome.debugger.sendCommand({ tabId }, "CSS.enable");
+  await chrome.debugger.sendCommand({ tabId }, "Debugger.enable");
 }
 
 async function findEvent() {
-    let winObj = await chrome.debugger.sendCommand(
-        { tabId },
-        "Runtime.evaluate",
-        {
-            expression: "self",
-            objectGroup: "",
-            includeCommandLineAPI: false,
-            silent: true,
-            returnByValue: false,
-            generatePreview: false,
-            userGesture: false,
-            awaitPromise: false,
-        }
-    );
-    let winEvents = await chrome.debugger.sendCommand(
-        { tabId },
-        "DOMDebugger.getEventListeners",
-        {
-            objectId: winObj.result.objectId,
-        }
-    );
-    let documentObj = await chrome.debugger.sendCommand(
-        { tabId },
-        "Runtime.evaluate",
-        {
-            expression: "document",
-            objectGroup: "",
-            includeCommandLineAPI: false,
-            silent: true,
-            returnByValue: false,
-            generatePreview: false,
-            userGesture: false,
-            awaitPromise: false,
-        }
-    );
-    let documentEvents = await chrome.debugger.sendCommand(
-        { tabId },
-        "DOMDebugger.getEventListeners",
-        {
-            objectId: documentObj.result.objectId,
-        }
-    );
-    let selfObj = await chrome.debugger.sendCommand(
-        { tabId },
-        "DOM.resolveNode",
-        {
-            nodeId: nodeObj.nodeId,
-        }
-    );
-    let selfEvents = await chrome.debugger.sendCommand(
-        { tabId },
-        "DOMDebugger.getEventListeners",
-        {
-            objectId: selfObj.object.objectId,
-        }
-    );
-    return {
-        winEvents: winEvents.listeners,
-        documentEvents: documentEvents.listeners,
-        selfEvents: selfEvents.listeners,
-    };
+  let winObj = await chrome.debugger.sendCommand(
+    { tabId },
+    "Runtime.evaluate",
+    {
+      expression: "self",
+      objectGroup: "",
+      includeCommandLineAPI: false,
+      silent: true,
+      returnByValue: false,
+      generatePreview: false,
+      userGesture: false,
+      awaitPromise: false,
+    }
+  );
+  let winEvents = await chrome.debugger.sendCommand(
+    { tabId },
+    "DOMDebugger.getEventListeners",
+    {
+      objectId: winObj.result.objectId,
+    }
+  );
+  let documentObj = await chrome.debugger.sendCommand(
+    { tabId },
+    "Runtime.evaluate",
+    {
+      expression: "document",
+      objectGroup: "",
+      includeCommandLineAPI: false,
+      silent: true,
+      returnByValue: false,
+      generatePreview: false,
+      userGesture: false,
+      awaitPromise: false,
+    }
+  );
+  let documentEvents = await chrome.debugger.sendCommand(
+    { tabId },
+    "DOMDebugger.getEventListeners",
+    {
+      objectId: documentObj.result.objectId,
+    }
+  );
+  let selfObj = await chrome.debugger.sendCommand(
+    { tabId },
+    "DOM.resolveNode",
+    {
+      nodeId: nodeObj.nodeId,
+    }
+  );
+  let selfEvents = await chrome.debugger.sendCommand(
+    { tabId },
+    "DOMDebugger.getEventListeners",
+    {
+      objectId: selfObj.object.objectId,
+    }
+  );
+  for (const listener of winEvents.listeners) {
+    await listenerGetFile(listener);
+  }
+  for (const listener of documentEvents.listeners) {
+    await listenerGetFile(listener);
+  }
+  for (const listener of selfEvents.listeners) {
+    await listenerGetFile(listener);
+  }
+  return {
+    winEvents: winEvents.listeners,
+    documentEvents: documentEvents.listeners,
+    selfEvents: selfEvents.listeners,
+  };
 }
 
-function translateEventData(eventObj) {
-    let { winEvents, documentEvents, selfEvents } = eventObj;
-    let result = [];
-    result.push(...winEvents.map((even) => ({ 事件名称: even.type, 绑定对象: "window" })));
-    result.push(...documentEvents.map((even) => ({ 事件名称: even.type, 绑定对象: "document" })))
-    result.push(...selfEvents.map((even) => ({ 事件名称: even.type, 绑定对象: "selft" })))
-    return result.map((a, index) => ({ ...a, id: index }));
+async function listenerGetFile(listener) {
+  let ret = await chrome.debugger.sendCommand(
+    { tabId },
+    "Debugger.getScriptSource",
+    {
+      scriptId: listener.scriptId,
+    }
+  );
+  let js = jslist.find((m) => m.data == ret.scriptSource);
+  if (js) {
+    debugger;
+    js.scriptId = listener.scriptId;
+    listener.fileName = js.fileName;
+    listener.fileUrl = js.url;
+    listener.fileData = js.data;
+  }
 }
 
-
-window.onload = function(){
-    InitTabOperation()
+function translateEventData(eventObj) {
+  debugger;
+  let { winEvents, documentEvents, selfEvents } = eventObj;
+  let result = [];
+  result.push(
+    ...winEvents.map((even) => ({
+      事件名称: even.type,
+      绑定对象: "window",
+      事件文件: even.fileName,
+    }))
+  );
+  result.push(
+    ...documentEvents.map((even) => ({
+      事件名称: even.type,
+      绑定对象: "document",
+      事件文件: even.fileName,
+    }))
+  );
+  result.push(
+    ...selfEvents.map((even) => ({
+      事件名称: even.type,
+      绑定对象: "selft",
+      事件文件: even.fileName,
+    }))
+  );
+  return result.map((a, index) => ({ ...a, id: index }));
 }
 
+window.onload = function () {
+  InitTabOperation();
+};
+
 /**
  * 设置操作页卡功能
  */
 function InitTabOperation() {
-    document.querySelector('.tabs').addEventListener('click', function (e) {
-        let target = e.target;
-        if (target.classList.contains('tab')) {
-            showContent(target);
-        }
-    })
+  document.querySelector(".tabs").addEventListener("click", function (e) {
+    let target = e.target;
+    if (target.classList.contains("tab")) {
+      showContent(target);
+    }
+  });
 }
 
 function showContent(tab) {
-    let id = tab.dataset.id; // 获取点击的页卡ID
-    // 获取选中的页卡元素
-    let activeTab = document.querySelector('.tabs .active');
-    if (activeTab !== null) {
-        if (id === activeTab.dataset.id) return;
-        activeTab.classList.remove('active');
-    }
-    // 获取选中的容器的元素
-    let activeContent = document.querySelector('.tab-container .active');
-    if (activeContent !== null) {
-        if (activeContent.id === id) return;
-        activeContent.classList.remove('active');
-    }
-    // 给新选中的页卡加入选中效果
-    tab.classList.add('active');
-    let curActiveContent = document.querySelector(`.tab-container #${id}`);
-    if (curActiveContent !== null) {
-        curActiveContent.classList.add('active')
-    }
-}
+  let id = tab.dataset.id; // 获取点击的页卡ID
+  // 获取选中的页卡元素
+  let activeTab = document.querySelector(".tabs .active");
+  if (activeTab !== null) {
+    if (id === activeTab.dataset.id) return;
+    activeTab.classList.remove("active");
+  }
+  // 获取选中的容器的元素
+  let activeContent = document.querySelector(".tab-container .active");
+  if (activeContent !== null) {
+    if (activeContent.id === id) return;
+    activeContent.classList.remove("active");
+  }
+  // 给新选中的页卡加入选中效果
+  tab.classList.add("active");
+  let curActiveContent = document.querySelector(`.tab-container #${id}`);
+  if (curActiveContent !== null) {
+    curActiveContent.classList.add("active");
+  }
+}