空教室表

用于获取东秦空教室表的js脚本

// ==UserScript==
// @name         空教室表
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  用于获取东秦空教室表的js脚本
// @author       Juns
// @match        *://jwxt.neuq.edu.cn*
// @match        http://jwxt.neuq.edu.cn/eams/homeExt.action
// @match        https://jwxt.neuq.edu.cn/eams/homeExt.action
// @match        http://jwxt.neuq.edu.cn/eams/homeExt.action*
// @match        https://jwxt.neuq.edu.cn/eams/homeExt.action*
// @match        http://jwxt.neuq.edu.cn/eams/classroom/apply/free!search.action
// @match        https://jwxt.neuq.edu.cn/eams/classroom/apply/free!search.action
// @match        http://jwxt.neuq.edu.cn/eams/classroom/apply/free.action
// @match        https://jwxt.neuq.edu.cn/eams/classroom/apply/free.action
// @icon         https://www.google.com/s2/favicons?sz=64&domain=neuq.edu.cn
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";

  // 设置查询参数
  const options = [
    { start: 1, end: 2 },
    { start: 3, end: 4 },
    { start: 5, end: 6 },
    { start: 7, end: 8 },
    { start: 9, end: 10 },
    { start: 1, end: 8 },
  ];

  const weekNameArr = ["日", "一", "二", "三", "四", "五", "六"];

  const pageUrl = "https://jwxt.neuq.edu.cn/eams/classroom/apply/free.action";

  // 定义样式
  const boxStyles = {
    position: "absolute",
    bottom: "20px",
    right: "20px",
    display: "flex",
    gap: "10px",
  };

  const buttonStyles = {
    border: "none",
    borderRadius: "20px",
    background: "linear-gradient(32deg,#03a9f4,#f441a5,#ffeb3b,#03a9f4)",
    transition: "all 1.5s ease",
    fontWeight: "bold",
    letterSpacing: "0.05rem",
    padding: "0",
    cursor: "pointer",
    height: "40px",
  };

  const spanStyles = {
    padding: "15px 18px",
    fontSize: "17px",
    borderRadius: "20px",
    background: "#ffffff10",
    color: "#ffffff",
    transition: "0.4s ease-in-out",
    transitionProperty: "color",
    height: "100%",
    width: "100%",
  };

  const textStyles = {
    fontSize: "17px",
    borderRadius: "20px",
    background: "#f5f5f5",
    padding: "1.8rem",
    transition: "0.5s ease-out",
    overflow: "visible",
    position: "absolute",
    top: "20px",
    left: "20px",
    cursor: "pointer",
    backgroundColor: "rgba(255, 255, 255, 0.25)",
    backdropFilter: "blur(6px)",
    border: "1px solid rgba(255, 255, 255, 0.18)",
    boxShadow: "rgba(142, 142, 142, 0.19) 0px 6px 15px 0px",
  };

  // 补零
  function pad(time) {
    return time < 10 ? `0${time}` : time;
  }

  // 时间戳转时间函数
  function timestampToTime(timestamp) {
    let date = new Date(timestamp);
    let Y = date.getFullYear() + "-";
    let M =
      (date.getMonth() + 1 < 10
        ? "0" + (date.getMonth() + 1)
        : date.getMonth() + 1) + "-";
    let D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
    let h =
      (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
    let m =
      date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
    return Y + M + D + h + m;
  }

  function getToday() {
    const date = new Date();
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const week = weekNameArr[date.getDay()];

    return { date: `${year}-${pad(month)}-${pad(day)}`, week };
  }

  function getTomorrow() {
    const timeStamp = Date.now();
    const tomorrow = new Date(timeStamp + 24 * 60 * 60 * 1000);
    const year = tomorrow.getFullYear();
    const month = tomorrow.getMonth() + 1;
    const day = tomorrow.getDate();
    const week = weekNameArr[tomorrow.getDay()];

    return { date: `${year}-${pad(month)}-${pad(day)}`, week };
  }

  // 设置选项
  // type: 0 今天, 1 明天
  function setOptions(type) {
    let trs = document.querySelector("#actionForm").querySelectorAll("tr");
    let sel = trs[2].querySelector("select");
    sel.value = "1"; // 设置教学楼为工学馆
    let tds = trs[4].querySelectorAll("td");
    let [startDate, endDate] = tds[1].querySelectorAll("input");
    startDate.value = type === 0 ? getToday().date : getTomorrow().date;
    endDate.value = type === 0 ? getToday().date : getTomorrow().date;
  }

  // 点击查询按钮
  function query() {
    let trs = document.querySelector("#actionForm").querySelectorAll("tr");
    let queryButton = trs[5].querySelector("input");
    queryButton.click();
  }

  // 替换的函数
  function formatData(str) {
    if (str != null && str != "") {
      let reg = /工[ ]*学[ ]*馆/;
      let reg2 = /具体安排以开课部门通知为准\s*/g;
      return str.replace(reg, "G").replace(reg2, "");
      //把工学馆三个字替换成G
    }
    return "";
  }

  // 根据rooms数组获得string
  function roomsToString(rooms) {
    let str = "";

    rooms.forEach((item, index) => {
      // 形式类似于104-1的直接省略了
      if (index < 1 || rooms[index][4] === "-") return;
      if (rooms[index][1] != rooms[index - 1][1]) str += "\n";
      str += rooms[index] + " ";
    });
    return str;
  }

  // 获取当前表格内的数据
  function getClassroomString() {
    const rows = document
      .querySelector("#grid15320024301_data")
      .querySelectorAll("td"); // 获取表格数据
    let rooms = []; //存储数据
    for (let i = 1; i < rows.length; i += 6) {
      rooms.push(formatData(rows[i].innerText));
    }

    // 升序排序并去空
    rooms = rooms.filter((item) => item !== "");
    rooms.sort();

    return roomsToString(rooms);
  }

  // 设置a-b小节
  function queryClassroom(a, b) {
    let [start, end] = document
      .querySelector("#roomApplyTimeTypeTd")
      .querySelectorAll("input"); // 获取dom
    start.value = a;
    end.value = b;
  }

  function delayMs(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }

  // 获取标题
  // type 0 今天, 1 明天
  function getTitle(type) {
    const { date, week } = type === 0 ? getToday() : getTomorrow();
    const titleDate = date.replace(/-/g, ".");
    return `${titleDate} 周${week}`;
  }

  // 不在页面的话就跳转
  function jumpToPage() {
    if (window.location.href !== pageUrl) {
      window.location = pageUrl;
    }
  }

  // type 0 今天, 1 明天
  async function autoGetClassroomTable(type = 1) {
    jumpToPage();
    setOptions(type);
    let exportString = "";
    exportString += getTitle(type);
    exportString += "\n\n";
    for (let i = 0; i < options.length; i++) {
      const { start, end } = options[i];
      queryClassroom(start, end);
      query();
      await delayMs(1000);
      exportString += `${start}-${end}节:\n\n`;
      exportString += getClassroomString();
      exportString += "\n\n";
    }
    exportString += "\n\n ——不洗碗工作室";
    exportString += `\n\n 导出时间: ${timestampToTime(Date.now())}`;
    exportString += "\n\n code by Juns";
    console.log(exportString);
    showText(exportString);
  }

  // 添加button,以及样式
  function addButtons() {
    const todayButton = document.createElement("button");
    const tomorrowButton = document.createElement("button");

    const todaySpan = document.createElement("span");
    const tomorrowSpan = document.createElement("span");
    todaySpan.innerText = "今天";
    tomorrowSpan.innerText = "明天";
    todayButton.appendChild(todaySpan);
    tomorrowButton.appendChild(tomorrowSpan);

    Object.entries(spanStyles).forEach(([name, value]) => {
      todaySpan.style[name] = value;
      tomorrowSpan.style[name] = value;
    });
    Object.entries(buttonStyles).forEach(([name, value]) => {
      todayButton.style[name] = value;
      tomorrowButton.style[name] = value;
    });

    todayButton.addEventListener("click", () => {
      autoGetClassroomTable(0);
    });

    tomorrowButton.addEventListener("click", () => {
      autoGetClassroomTable(1);
    });

    const box = document.createElement("div");
    box.appendChild(todayButton);
    box.appendChild(tomorrowButton);
    Object.entries(boxStyles).forEach(([name, value]) => {
      box.style[name] = value;
    });

    document.body.appendChild(box);
  }

  // 展示结果的文本框
  function showText(text) {
    const textDiv = document.createElement("div");
    Object.entries(textStyles).forEach(([name, value]) => {
      textDiv.style[name] = value;
    });
    textDiv.addEventListener("mouseover", () => {
      textDiv.style.borderColor = "#008bf8";
    });
    textDiv.addEventListener("mouseout", () => {
      textDiv.style.border = textStyles.border;
    });

    textDiv.innerText = text;
    textDiv.addEventListener("click", () => {
      copyText(text);
      alert("已经复制到剪切板!");
    });
    document.body.appendChild(textDiv);
  }

  function copyText(text) {
    let output = document.createElement("textarea");
    const outputText = text.replace(/\n/g, "\r\n");
    output.value = outputText;
    document.body.appendChild(output);
    output.select();
    document.execCommand("copy");
    document.body.removeChild(output);
  }

  addButtons();
})();