Greasy Fork 支持简体中文。

Kaikeba Wiki Helper

Wiki Helper

// ==UserScript==
// @name         Kaikeba Wiki Helper
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  Wiki Helper
// @author       WumaCoder
// @match        http://wiki.kaikeba.com/pages/*
// @match        https://wiki.kaikeba.com/pages/*
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
  "use strict";

  const config = {
    isAutoWrite: true, // 自动写表单
    isAutoUpdate: true, // 自动更新标题
  };

  const formData = defineState({
    title: (self) =>
      `gk-${xk}-${self.table_num}-${TYPE[self.table_type]}-${toShortDate(
        self.table_date
      )}`,
    tags: (self) => [
      self.table_teacher,
      xk,
      `${xk}-${self.table_num}`,
      "跟课课时",
      `${xk}学科`,
    ],

    table_date: "2021-04-28",
    table_name: "web全栈架构师", // 课程
    table_num: 29, // 班次
    table_type: "大班课", // 类型
    table_knob: "课节", // 课节
    table_teacher: "讲师", // 讲师
    table_group: "教研", // 教研
    table_helpTeacher: "助教", // 助教
    table_subTeacher: "班主任", // 班班
    table_startDate: "20:30", // 开始
    table_endDate: "22:30", // 结束
    table_totalTime: 2, // 总时长
    table_resultTime: "2:00", // 结算时长
    table_manNum: 90, // 峰值人数
    table_manActive: (self) => random(10, +self.table_manNum / 2), //课程互动
    table_messageActive: (self) => random(10, +self.table_manNum / 2), // 公屏互动
    table_to24h: "/",
    table_to48h: "/",
    table_liveErr: "/",
    table_note: "/",
  });

  console.log(formData);

  setTimeout(() => {
    const publish = document.querySelector("#rte-button-publish");
    publish.addEventListener("click", () => {
      save();
      writeTags();
      nextBaseDate();
    });
    publish.style["background"] = "purple";

    if (config.isAutoWrite) {
      writeTitle();
      writeTable();
    }
    if (config.isAutoUpdate) {
      setInterval(() => {
        save(false);
        writeTitle();
      }, 500);
    }
  }, 1000);

  buildUI();

  var ADAY = 24 * 1000 * 60 * 60;
  var TYPE = {
    公开课: "gkk",
    大班课: "dbk",
    点评课: "dpk",
    答疑课: "dyk",
  };
  var xk = "web";

  function buildUI() {
    const ui = `
      <button @click="add">Add Day</button>
      <button @click="dec">Dec Day</button>
      <button @click="reset">Reset</button>
      <button @click="state">State</button>
      <button @click="setting">Setting</button>
      <button @click="writeForm">Write</button>
      <button @click="save">Save</button>
    `;
    UI(ui, {
      add() {
        const { date } = dateOpe(formData.table_date, 1);
        formData.table_date = date;
        writeTitle();
        writeTable();
      },
      dec() {
        const { date } = dateOpe(formData.table_date, -1);
        formData.table_date = date;
        writeTitle();
        writeTable();
      },
      reset() {
        formData.reset();
        writeTitle();
        writeTable();
      },
      state() {
        alert("请查看控制台");
        console.log(formData);
      },
      setting() {
        xk = prompt("请输入你们部门的英文,比如: web", xk);
        writeTitle();
        writeTable();
      },
      writeForm() {
        writeTitle();
        writeTable();
      },
      save() {
        save();
      },
    });
  }

  function save(isKeep = true) {
    formData.isKeep = isKeep;
    let i = 0;
    const els = document
      .querySelector("iframe")
      .contentWindow.document.querySelectorAll(".confluenceTd");
    for (const key in formData.state) {
      if (key.startsWith("table_")) {
        const el = els[i];
        formData.state[key] = el.innerText;
        i++;
      }
    }
  }

  function nextBaseDate() {
    let f = 2;
    while (1) {
      const { datetime, date } = dateOpe(formData.table_date, f);
      formData.table_date = date;
      const week = datetime.getDay();
      if (week >= 1 && week <= 6) {
        break;
      } else {
        f = 1;
      }
    }
  }

  function writeTitle() {
    const el = document.querySelector("#content-title");
    el.value = formData.title;
  }

  function writeTable() {
    let i = 0;
    const els = document
      .querySelector("iframe")
      .contentWindow.document.querySelectorAll(".confluenceTd");
    for (const key in formData.state) {
      if (key.startsWith("table_")) {
        const el = els[i];
        el.innerHTML = formData.state[key];
        i++;
      }
    }
  }

  async function writeTags() {
    await addTags(formData.tags);
  }

  function UI(ui, handlers = {}) {
    const plan = document.createElement("div");
    plan.id = "Wiki Helper";
    plan.style["position"] = "fixed";
    plan.style["top"] = "0";
    plan.style["left"] = "40%";
    plan.style["z-index"] = "10000";
    // plan.style["background"] = "#EEE";
    plan.style["padding"] = "10px";
    plan.innerHTML = ui;
    plan.addEventListener("click", (e) => {
      const methodName = e.target.attributes["@click"].value;
      handlers[methodName]();
    });
    handlers.query = plan.querySelector.bind(plan);
    handlers.queryAll = plan.querySelectorAll.bind(plan);
    document.body.append(plan);
  }

  function defineState(data = {}, { keep = "@State" } = {}) {
    const _data = Object.assign({}, data);
    Object.assign(data, readState());
    const state = new Proxy(data, {
      get(target, key, rec) {
        const val = Reflect.get(target, key, rec);
        return typeof val === "function" ? val(state) : val;
      },
      set(target, key, val, rec) {
        if (typeof target[key] === "function") {
          return true;
        }
        const res = Reflect.set(target, key, val, rec);
        writeState();
        return res;
      },
    });
    const result = {
      state,
      reset,
      readState,
      writeState,
      isKeep: true,
    };

    for (const key in state) {
      proxyState(result, key);
    }

    return result;

    function readState() {
      let state = GM_getValue(keep);
      return state;
    }

    function writeState() {
      if (!result.isKeep) return data;
      return GM_setValue(keep, data);
    }

    function reset() {
      data = _data;
      return writeState();
    }

    function proxyState(target, key) {
      Object.defineProperty(target, key, {
        get() {
          return target.state[key];
        },
        set(v) {
          return (target.state[key] = v);
        },
      });
    }
  }

  function request(url, data = {}, opts = {}) {
    return fetch(url, {
      body: JSON.stringify(data), // must match 'Content-Type' header
      cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin", // include, same-origin, *omit
      headers: {
        "user-agent": "Mozilla/4.0 MDN Example",
        "content-type": "application/json",
      },
      method: "GET", // *GET, POST, PUT, DELETE, etc.
      mode: "cors", // no-cors, cors, *same-origin
      redirect: "follow", // manual, *follow, error
      referrer: "no-referrer", // *client, no-referrer
      ...opts,
    });
  }

  function addTags(tags) {
    return request(
      `http://wiki.kaikeba.com/rest/ui/1.0/content/${getWikiId()}/labels`,
      tags.map((tag) => ({ name: tag, id: timestamps() })),
      {
        method: "POST",
      }
    );
  }

  function getTags() {
    return request(
      `http://wiki.kaikeba.com/rest/ui/1.0/content/${getWikiId()}/labels?_=${Date.now()}`
    );
  }

  function timestamps() {
    return parseInt(Date.now() / 1000);
  }

  function getWikiId() {
    return location.href.match(/draftId=(\d+)/)[1];
  }

  function dateOpe(date, n = 1) {
    let ms = Date.parse(date + " 00:00:00");
    ms += ADAY * n;
    const d = new Date(ms);
    return {
      datetime: d,
      date: d
        .toLocaleDateString(undefined, {
          year: "numeric",
          month: "2-digit",
          day: "2-digit",
        })
        .replace(/\//gim, "-"),
    };
  }

  function random(start, end) {
    return parseInt(Math.random() * (end - start)) + start;
  }

  function toShortDate(s) {
    return s.replace(/-/gim, "");
  }
  // Your code here...
})();