Kaikeba Wiki Helper

Wiki Helper

  1. // ==UserScript==
  2. // @name Kaikeba Wiki Helper
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.8
  5. // @description Wiki Helper
  6. // @author WumaCoder
  7. // @match http://wiki.kaikeba.com/pages/*
  8. // @match https://wiki.kaikeba.com/pages/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. "use strict";
  15.  
  16. const config = {
  17. isAutoWrite: true, // 自动写表单
  18. isAutoUpdate: true, // 自动更新标题
  19. };
  20.  
  21. const formData = defineState({
  22. title: (self) =>
  23. `gk-${xk}-${self.table_num}-${TYPE[self.table_type]}-${toShortDate(
  24. self.table_date
  25. )}`,
  26. tags: (self) => [
  27. self.table_teacher,
  28. xk,
  29. `${xk}-${self.table_num}`,
  30. "跟课课时",
  31. `${xk}学科`,
  32. ],
  33.  
  34. table_date: "2021-04-28",
  35. table_name: "web全栈架构师", // 课程
  36. table_num: 29, // 班次
  37. table_type: "大班课", // 类型
  38. table_knob: "课节", // 课节
  39. table_teacher: "讲师", // 讲师
  40. table_group: "教研", // 教研
  41. table_helpTeacher: "助教", // 助教
  42. table_subTeacher: "班主任", // 班班
  43. table_startDate: "20:30", // 开始
  44. table_endDate: "22:30", // 结束
  45. table_totalTime: 2, // 总时长
  46. table_resultTime: "2:00", // 结算时长
  47. table_manNum: 90, // 峰值人数
  48. table_manActive: (self) => random(10, +self.table_manNum / 2), //课程互动
  49. table_messageActive: (self) => random(10, +self.table_manNum / 2), // 公屏互动
  50. table_to24h: "/",
  51. table_to48h: "/",
  52. table_liveErr: "/",
  53. table_note: "/",
  54. });
  55.  
  56. console.log(formData);
  57.  
  58. setTimeout(() => {
  59. const publish = document.querySelector("#rte-button-publish");
  60. publish.addEventListener("click", () => {
  61. save();
  62. writeTags();
  63. nextBaseDate();
  64. });
  65. publish.style["background"] = "purple";
  66.  
  67. if (config.isAutoWrite) {
  68. writeTitle();
  69. writeTable();
  70. }
  71. if (config.isAutoUpdate) {
  72. setInterval(() => {
  73. save(false);
  74. writeTitle();
  75. }, 500);
  76. }
  77. }, 1000);
  78.  
  79. buildUI();
  80.  
  81. var ADAY = 24 * 1000 * 60 * 60;
  82. var TYPE = {
  83. 公开课: "gkk",
  84. 大班课: "dbk",
  85. 点评课: "dpk",
  86. 答疑课: "dyk",
  87. };
  88. var xk = "web";
  89.  
  90. function buildUI() {
  91. const ui = `
  92. <button @click="add">Add Day</button>
  93. <button @click="dec">Dec Day</button>
  94. <button @click="reset">Reset</button>
  95. <button @click="state">State</button>
  96. <button @click="setting">Setting</button>
  97. <button @click="writeForm">Write</button>
  98. <button @click="save">Save</button>
  99. `;
  100. UI(ui, {
  101. add() {
  102. const { date } = dateOpe(formData.table_date, 1);
  103. formData.table_date = date;
  104. writeTitle();
  105. writeTable();
  106. },
  107. dec() {
  108. const { date } = dateOpe(formData.table_date, -1);
  109. formData.table_date = date;
  110. writeTitle();
  111. writeTable();
  112. },
  113. reset() {
  114. formData.reset();
  115. writeTitle();
  116. writeTable();
  117. },
  118. state() {
  119. alert("请查看控制台");
  120. console.log(formData);
  121. },
  122. setting() {
  123. xk = prompt("请输入你们部门的英文,比如: web", xk);
  124. writeTitle();
  125. writeTable();
  126. },
  127. writeForm() {
  128. writeTitle();
  129. writeTable();
  130. },
  131. save() {
  132. save();
  133. },
  134. });
  135. }
  136.  
  137. function save(isKeep = true) {
  138. formData.isKeep = isKeep;
  139. let i = 0;
  140. const els = document
  141. .querySelector("iframe")
  142. .contentWindow.document.querySelectorAll(".confluenceTd");
  143. for (const key in formData.state) {
  144. if (key.startsWith("table_")) {
  145. const el = els[i];
  146. formData.state[key] = el.innerText;
  147. i++;
  148. }
  149. }
  150. }
  151.  
  152. function nextBaseDate() {
  153. let f = 2;
  154. while (1) {
  155. const { datetime, date } = dateOpe(formData.table_date, f);
  156. formData.table_date = date;
  157. const week = datetime.getDay();
  158. if (week >= 1 && week <= 6) {
  159. break;
  160. } else {
  161. f = 1;
  162. }
  163. }
  164. }
  165.  
  166. function writeTitle() {
  167. const el = document.querySelector("#content-title");
  168. el.value = formData.title;
  169. }
  170.  
  171. function writeTable() {
  172. let i = 0;
  173. const els = document
  174. .querySelector("iframe")
  175. .contentWindow.document.querySelectorAll(".confluenceTd");
  176. for (const key in formData.state) {
  177. if (key.startsWith("table_")) {
  178. const el = els[i];
  179. el.innerHTML = formData.state[key];
  180. i++;
  181. }
  182. }
  183. }
  184.  
  185. async function writeTags() {
  186. await addTags(formData.tags);
  187. }
  188.  
  189. function UI(ui, handlers = {}) {
  190. const plan = document.createElement("div");
  191. plan.id = "Wiki Helper";
  192. plan.style["position"] = "fixed";
  193. plan.style["top"] = "0";
  194. plan.style["left"] = "40%";
  195. plan.style["z-index"] = "10000";
  196. // plan.style["background"] = "#EEE";
  197. plan.style["padding"] = "10px";
  198. plan.innerHTML = ui;
  199. plan.addEventListener("click", (e) => {
  200. const methodName = e.target.attributes["@click"].value;
  201. handlers[methodName]();
  202. });
  203. handlers.query = plan.querySelector.bind(plan);
  204. handlers.queryAll = plan.querySelectorAll.bind(plan);
  205. document.body.append(plan);
  206. }
  207.  
  208. function defineState(data = {}, { keep = "@State" } = {}) {
  209. const _data = Object.assign({}, data);
  210. Object.assign(data, readState());
  211. const state = new Proxy(data, {
  212. get(target, key, rec) {
  213. const val = Reflect.get(target, key, rec);
  214. return typeof val === "function" ? val(state) : val;
  215. },
  216. set(target, key, val, rec) {
  217. if (typeof target[key] === "function") {
  218. return true;
  219. }
  220. const res = Reflect.set(target, key, val, rec);
  221. writeState();
  222. return res;
  223. },
  224. });
  225. const result = {
  226. state,
  227. reset,
  228. readState,
  229. writeState,
  230. isKeep: true,
  231. };
  232.  
  233. for (const key in state) {
  234. proxyState(result, key);
  235. }
  236.  
  237. return result;
  238.  
  239. function readState() {
  240. let state = GM_getValue(keep);
  241. return state;
  242. }
  243.  
  244. function writeState() {
  245. if (!result.isKeep) return data;
  246. return GM_setValue(keep, data);
  247. }
  248.  
  249. function reset() {
  250. data = _data;
  251. return writeState();
  252. }
  253.  
  254. function proxyState(target, key) {
  255. Object.defineProperty(target, key, {
  256. get() {
  257. return target.state[key];
  258. },
  259. set(v) {
  260. return (target.state[key] = v);
  261. },
  262. });
  263. }
  264. }
  265.  
  266. function request(url, data = {}, opts = {}) {
  267. return fetch(url, {
  268. body: JSON.stringify(data), // must match 'Content-Type' header
  269. cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
  270. credentials: "same-origin", // include, same-origin, *omit
  271. headers: {
  272. "user-agent": "Mozilla/4.0 MDN Example",
  273. "content-type": "application/json",
  274. },
  275. method: "GET", // *GET, POST, PUT, DELETE, etc.
  276. mode: "cors", // no-cors, cors, *same-origin
  277. redirect: "follow", // manual, *follow, error
  278. referrer: "no-referrer", // *client, no-referrer
  279. ...opts,
  280. });
  281. }
  282.  
  283. function addTags(tags) {
  284. return request(
  285. `http://wiki.kaikeba.com/rest/ui/1.0/content/${getWikiId()}/labels`,
  286. tags.map((tag) => ({ name: tag, id: timestamps() })),
  287. {
  288. method: "POST",
  289. }
  290. );
  291. }
  292.  
  293. function getTags() {
  294. return request(
  295. `http://wiki.kaikeba.com/rest/ui/1.0/content/${getWikiId()}/labels?_=${Date.now()}`
  296. );
  297. }
  298.  
  299. function timestamps() {
  300. return parseInt(Date.now() / 1000);
  301. }
  302.  
  303. function getWikiId() {
  304. return location.href.match(/draftId=(\d+)/)[1];
  305. }
  306.  
  307. function dateOpe(date, n = 1) {
  308. let ms = Date.parse(date + " 00:00:00");
  309. ms += ADAY * n;
  310. const d = new Date(ms);
  311. return {
  312. datetime: d,
  313. date: d
  314. .toLocaleDateString(undefined, {
  315. year: "numeric",
  316. month: "2-digit",
  317. day: "2-digit",
  318. })
  319. .replace(/\//gim, "-"),
  320. };
  321. }
  322.  
  323. function random(start, end) {
  324. return parseInt(Math.random() * (end - start)) + start;
  325. }
  326.  
  327. function toShortDate(s) {
  328. return s.replace(/-/gim, "");
  329. }
  330. // Your code here...
  331. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址