SEECODER courseware quick download

快速下载 SEECODER 平台课程的课件

// ==UserScript==
// @name         SEECODER  courseware quick download
// @namespace    http://tampermonkey.net/
// @version      2025-03-08
// @description  快速下载 SEECODER 平台课程的课件
// @author       Coxine
// @match        https://p-nju.seec.seecoder.cn/course/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=seecoder.cn
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  async function fetchCourseWares(courseID) {
    const url = `https://p-nju.seec.seecoder.cn/api/courseWare/getCourseWaresByCourseId?courseId=${courseID}`;
    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      const jsonData = await response.json();
      return jsonData;
    } catch (error) {
      console.error("Error fetching course wares:", error);
      return [];
    }
  }

  function extractFileInfo(data) {
    try {
      if (data.code !== 0 || !Array.isArray(data.data)) {
        throw new Error("Invalid data format");
      }

      return data.data.map(item => {
        const courseWare = item.courseWareVO;
        return {
          name: courseWare.name,
          fileUrl: courseWare.fileUrl
        };
      });
    } catch (error) {
      console.error("Error parsing JSON:", error);
      return [];
    }
  }

  function generateTable(fileInfo) {
    const table = document.createElement('table');
    table.style.width = '100%';
    table.className = 'file-download-table';
    table.setAttribute('border', '0');

    const tbody = document.createElement('tbody');
    fileInfo.forEach(file => {
      const row = document.createElement('tr');

      const nameCell = document.createElement('td');
      nameCell.textContent = file.name;
      nameCell.style = 'padding: 0px 10px;';
      row.appendChild(nameCell);

      const linkCell = document.createElement('td');
      const link = document.createElement('a');
      link.href = file.fileUrl;
      link.textContent = '下载';
      link.style = 'color: #007bff; text-decoration: none;';
      linkCell.style = 'text-align: center;';
      linkCell.appendChild(link);
      row.appendChild(linkCell);

      tbody.appendChild(row);
    });

    table.appendChild(tbody);
    return table;
  }

  function getCourseIdFromUrl(url) {
    const urlParts = url.split('/');
    return urlParts[urlParts.length - 1];
  }

  function waitForElement(selector, callback, timeout = 5000) {
    const startTime = Date.now();
    const interval = setInterval(() => {
      const element = document.querySelector(selector);
      if (element) {
        clearInterval(interval);
        callback(element);
      } else if (Date.now() - startTime > timeout) {
        clearInterval(interval);
        console.error(`Element '${selector}' not found within timeout`);
      }
    }, 100);
  }

  function appendTable(element, table) {
    const style = document.createElement('style');
    style.textContent = `
    .file-download-table tr:nth-child(odd) {
      background-color: #E8E8E8; /* Dark gray color for odd rows */
    }
  `;
    document.head.appendChild(style);
    element.style = 'padding:10px 10px';
    element.appendChild(document.createElement('hr'));
    element.appendChild(document.createElement('h3')).textContent = '课件列表';
    element.appendChild(table);
  }

  async function main() {
    const COURSE_ID = getCourseIdFromUrl(window.location.href);
    const courseWares = await fetchCourseWares(COURSE_ID);
    const table = generateTable(extractFileInfo(courseWares));

    waitForElement('.introduce-content', (element) => {
      appendTable(element, table);
    });
  }

  main();
})();