评教助手

新余学院评教

// ==UserScript==
// @name         评教助手
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  新余学院评教
// @author       xie feng
// @match        http://jwxt.xyc.edu.cn/*
// @grant        none
// ==/UserScript==

/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "./src/evaluate.js":
/*!*************************!*\
  !*** ./src/evaluate.js ***!
  \*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "confirmStart": () => (/* binding */ confirmStart),
/* harmony export */   "checkEvaluations": () => (/* binding */ checkEvaluations),
/* harmony export */   "autoEvaluate": () => (/* binding */ autoEvaluate),
/* harmony export */   "handleEvaluates": () => (/* binding */ handleEvaluates)
/* harmony export */ });
/* harmony import */ var _notificate__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./notificate */ "./src/notificate.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./src/utils.js");



const confirmStart = async () => {
  const start = window.confirm('是否开始开始评教?');
  if (start) {
    if (!await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.testOpenWindow)()) {
      (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '取消自主评教');
      return;
    }
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '即将开始自动评教');
    await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.delay)(1000);
    $('.wap a')[1].click();
  } else {
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '取消自主评教');
  }
}

const checkEvaluations = async () => {
  const links = $('tr').eq(2).find('td').eq(-1).find('a');
  if (!links.length) {
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '暂无评教,请关闭脚本。');
  } else {
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '即将进入评教页面');
    await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.delay)(800);
    links[0].click();
  }
}

const autoEvaluate = async () => {
  window.alert = () => true;
  window.confirm = () => true;
  $('#table1 tbody tr td:odd')
    .find('input:first-child')
    .click().end().eq(0).find('input:nth-child(3)').click();
  $('#tj').click();
  await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.delay)(100);
  window.close();
}

const handleEvaluates = async () => {

  // 简单考虑有人直接进入该页面的情况(测试窗口拦截),别的复杂情况就不判断了
  if (!await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.testOpenWindow)()) {
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '取消自主评教');
    return;
  }

  const count = $('.Nsb_r_list_fy3 span').html().trim().slice(1, 2);
  const cur = $('#pageIndex').val();

  // 这一页所有需要评价的列表
  const list = Array.from($('tr td a')).filter(a => a.innerText.includes('评价'));

  // 下一页评价的按钮
  const nextBtn = $('#PagingControl1_btnNextPage').get(0);
  // 查看是否有下一页
  const hasNext = nextBtn.getAttribute('disabled') !== "disabled";

  if (!list.length && hasNext) {
    nextBtn.click();
  } else if (!list.length && !hasNext) {
    window.sessionStorage.setItem('complete', 1);
    (0,_utils__WEBPACK_IMPORTED_MODULE_1__.notifySuccess)();
    return;
  }

  (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '开始评教', 1000);

  await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.delay)(500);

  (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', `正在评教 ${cur} / ${count},请等待。`, null);

  for (const a of list) {
    a.click();
    await (0,_utils__WEBPACK_IMPORTED_MODULE_1__.delay)(1000); // 慢点打开,窗口需要加载
  }
  window.location.reload();

}


/***/ }),

/***/ "./src/judge.js":
/*!**********************!*\
  !*** ./src/judge.js ***!
  \**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ "./src/utils.js");
/* harmony import */ var _evaluate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./evaluate */ "./src/evaluate.js");



const urls = ['.jsp', 'xspj_find.do', 'xspj_list.do', 'xspj_edit.do'];

const judge = () => {

  const url = window.location.pathname;

  const complete = Number(window.sessionStorage.getItem('complete') ?? 0);

  const canDoSomething = urls.some(u => url.includes(u));

  // 事不过三,不提醒超过 3 次
  if (!canDoSomething || complete > 3) {
    return;
  } else if (complete > 0) {
    if (!url.includes(urls[3])) {
      window.sessionStorage.setItem('complete', Number(complete) + 1);
      (0,_utils__WEBPACK_IMPORTED_MODULE_0__.notifySuccess)();
    }
  } else {
    if (url.endsWith(urls[0])) {
      (0,_evaluate__WEBPACK_IMPORTED_MODULE_1__.confirmStart)();
    } else if (url.includes(urls[1])) {
      (0,_evaluate__WEBPACK_IMPORTED_MODULE_1__.checkEvaluations)();
    } else if (url.includes(urls[2])) {
      (0,_evaluate__WEBPACK_IMPORTED_MODULE_1__.handleEvaluates)();
    } else if (url.includes(urls[3])) {
      (0,_evaluate__WEBPACK_IMPORTED_MODULE_1__.autoEvaluate)();
    }
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (judge);



/***/ }),

/***/ "./src/notificate.js":
/*!***************************!*\
  !*** ./src/notificate.js ***!
  \***************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "injectStyle": () => (/* binding */ injectStyle),
/* harmony export */   "notificate": () => (/* binding */ notificate)
/* harmony export */ });
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ "./src/utils.js");


const notifications = [];

const NOTIFICATION_TEMPLATE = `
<div class="inject-notification">
  <div class="inject-notification-box">
    <h2 class="inject-notification-title">{{title}}</h2>
    <div class="inject-notification-content">
      <p>{{content}}</p>
    </div>
    <div class="inject-notification-close">×</div>
  </div>
</div>`;

const NOTIFICATION_STYLE = `
.inject-notification {
  display: flex;
  width: 330px;
  padding: 14px 26px 14px 13px;
  border-radius: 8px;
  box-sizing: border-box;
  border: 1px solid #ebeef5;
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 9999;
  background-color: #fff;
  box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  transition: .4s ease-in-out;
  overflow-wrap: anywhere;
  overflow: hidden;
}

.inject-notification p {
    margin: 0;
}

.inject-notification-box {
    margin-left: 13px;
    margin-right: 8px
}

.inject-notification-title {
    font-weight: 700;
    font-size: 16px;
    line-height: 24px;
    color: #303133;
    margin: 0;
}

.inject-notification-content {
    font-size: 14px;
    line-height: 24px;
    margin: 6px 0 0;
    color: #606266;
    text-align: justify;
}

.inject-notification-close {
    position: absolute;
    top: 5px;
    right: 15px;
    cursor: pointer;
    color: #909399;
    font-size: 24px;
    font-weight: 100;
}

.inject-notification-close:hover{
    color: #606266;
}`;

const initTitle = "标题";

const initContent = "这是一段提示";

// 初始定位的 top
const startTop = 16;
// 每两个 notification 的间隔
const offset = 4;

const injectStyle = () => {
  $('<style></style>')
    .attr('id', "inject")
    .html(NOTIFICATION_STYLE)
    .appendTo('body');
}

const notificate = async (title = initTitle, content = initContent, duration = 2000) => {
  const NOTIFICATION_ELEMENT = NOTIFICATION_TEMPLATE.replace(
    /{{title}}|{{content}}/g,
    match => match.includes('title') ? title : content
  );

  // outerHeight -> 边框盒高度
  const top = notifications.reduce((acc, cur) => acc + cur.outerHeight() + offset, startTop);

  const notification = $(NOTIFICATION_ELEMENT).css({
    transform: 'translateX(110%)',
    top: top + 'px'
  }).appendTo('body');

  notifications.push(notification);
  await (0,_utils__WEBPACK_IMPORTED_MODULE_0__.delay)(100);
  notification
    .css('transform', 'translateX(0)')
    .find('.inject-notification-close')
    .one('click', () => close(notification));
  if (duration != null) {
    await (0,_utils__WEBPACK_IMPORTED_MODULE_0__.delay)(duration);
    close(notification);
  }
}

const close = (notification) => {
  const index = notifications.indexOf(notification);
  if (index !== -1) {
    notification.one('transitionend', () => {
      const height = notification.outerHeight() + offset;
      notifications.splice(index, 1);
      // 更新后面所有 notification 的位置
      notifications.forEach((n, i) => {
        if (i >= index) {
          n.css('top', parseInt(n.css('top')) - height + 'px');
        }
      });
      notification.remove();
    });
    notification.css('transform', 'translateX(110%)');
  }
}




/***/ }),

/***/ "./src/utils.js":
/*!**********************!*\
  !*** ./src/utils.js ***!
  \**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "delay": () => (/* binding */ delay),
/* harmony export */   "notifySuccess": () => (/* binding */ notifySuccess),
/* harmony export */   "openWindow": () => (/* binding */ openWindow),
/* harmony export */   "testOpenWindow": () => (/* binding */ testOpenWindow)
/* harmony export */ });
/* harmony import */ var _notificate__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./notificate */ "./src/notificate.js");


const delay = n => new Promise(resolve => setTimeout(resolve, n));

const notifySuccess = () => (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '评教完成,请注意关闭脚本。', 5000);

const openWindow = url => {

  const width = 500, height = 500;

  const left = (window.screen.availWidth - 10 - width) / 2;

  const top = (window.screen.availHeight - 30 - height) / 2;

  const windowFeatures1 = 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no';

  const windowFeatures2 = `top=${top},left=${left},width=${width}px,height=${height}px`;

  const windowFeatures = `${windowFeatures1},${windowFeatures2}`;

  return window.open(url, "_blank", windowFeatures);
}

const testOpenWindow = async () => {
  let count = 0;
  if (!window.sessionStorage.getItem('canOpenWindow')) {
    (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '开始弹窗测试,以检查是否允许该站点弹窗');
    await delay(1000);
    while (count < 3) {
      const newWindow = openWindow('/');
      if (newWindow === null) {
        if (count === 0) {
          (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '弹窗被拦截,请手动开启', 5000);
          (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '请查看浏览器提醒(例如地址栏右侧),手动允许该站点弹窗', 5000);
          await delay(1000); // 不 delay 的画,confirm 会先出来,阻塞 notification的渲染
        }
        const confirm = window.confirm('允许弹窗后点击确认'); // 别骗我
        if (!confirm) {
          return false;
        }
        count++;
      } else {
        (0,_notificate__WEBPACK_IMPORTED_MODULE_0__.notificate)('提示', '弹窗测试通过');
        await delay(500);
        newWindow.close();
        window.sessionStorage.setItem('canOpenWindow', true);
        return true;
      }
    }
  } else {
    return true;
  }
  return false;
}

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!*********************!*\
  !*** ./src/main.js ***!
  \*********************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _judge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./judge */ "./src/judge.js");
/* harmony import */ var _notificate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./notificate */ "./src/notificate.js");



(0,_notificate__WEBPACK_IMPORTED_MODULE_1__.injectStyle)();

(0,_judge__WEBPACK_IMPORTED_MODULE_0__.default)();






})();

/******/ })()
;