修复研究院所提漏洞,删除无用文件

mobile
yujialong 2 years ago
parent 3da320db77
commit a8911002e9
  1. 7
      public/index.html
  2. BIN
      src/assets/videos/sky.mp4
  3. 134
      src/components/pdf/index.vue
  4. 255
      src/components/quill/index.vue
  5. 16
      src/components/quill/options.js
  6. 202
      src/libs/core.js
  7. 43
      src/libs/util.cookies.js
  8. 57
      src/libs/util.js
  9. 8
      src/main.js
  10. 12
      src/plugins/filters/index.js
  11. 3
      src/plugins/index.js
  12. 4
      src/plugins/requests/index.js
  13. 18
      src/plugins/throttle/index.js
  14. 5
      src/setting.js

@ -3,11 +3,10 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="职站,教学,教育,在线编程"> <meta name="keywords" content="粒子研究院">
<meta name="description" content="职站是一款辅助院校教师开展虚拟仿真实验教学的智能云实践平台。平台采用了大数据,云计算等技术,为学校搭建信息化平台提供了基础,可助力院校实现教学智能化升级。职站平台设计遵循着极简、高效的理念,可帮助老师轻松开展实验教学,并支持自定义发布考核和练习,智能统计和检验学生的日常实训练习效果;老师还可以通过可视化图表报告直观查看学生实训成绩,评估教学成果。"/> <meta name="description" content="粒子研究院"/>
<meta name="baidu-site-verification" content="code-TRfXe8xIkJ" /> <meta name="referrer" content="no-referrer">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css">
<title>粒子研究院</title> <title>粒子研究院</title>
</head> </head>
<body> <body>

Binary file not shown.

@ -1,134 +0,0 @@
<template>
<div>
<el-dialog
custom-class="pdf-dia"
:close-on-click-modal="false"
:visible.sync="visible"
@close="closePdf"
:fullscreen="true"
:modal="false"
:append-to-body="true">
<div>
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i
class="el-dialog__close el-icon el-icon-close"></i></button>
<div class="pdf">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left"
:class="{grey: currentPage==1}"></span>
{{ currentPage }} / {{ pageCount }}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right"
:class="{grey: currentPage==pageCount}"></span>
</p>
<pdf
class="pdf-wrap"
:src="src"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
>
</pdf>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import pdf from "vue-pdf";
export default {
props: ["visible", "src"],
data() {
return {
pdfVisible: false,
pdfSrc: "",
currentPage: 0,
pageCount: 0,
fileType: "pdf"
};
},
components: { pdf },
mounted() {
this.addEvent();
},
methods: {
closePdf() {
this.$emit("update:visible", false);
this.$emit("update:src", "");
this.currentPage = 1;
},
changePdfPage(val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--;
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++;
}
},
loadPdfHandler(e) {
this.currentPage = 1;
},
addEvent() {
document.onkeydown = e => {
let key = window.event.keyCode;
if (key == 37) {
this.changePdfPage(0);
} else if (key == 39) {
this.changePdfPage(1);
}
};
this.$once("hook:beforeDestroy", () => {
document.onkeydown = null;
});
}
}
};
</script>
<style lang="scss" scoped>
/deep/ .pdf-dia {
border-radius: 0 !important;
.el-dialog__header {
display: none;
}
.el-dialog__body {
padding: 0;
}
.el-dialog__headerbtn {
top: 10px;
.el-dialog__close {
color: #fff;
font-size: 16px;
}
}
.pdf {
.arrow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #fff;
background-color: #333;
.turn {
margin: 0 10px;
font-size: 18px;
cursor: pointer;
}
}
.pdf-wrap {
height: calc(100vh - 45px);
margin: 0 auto;
overflow: auto;
}
}
}
</style>

@ -1,255 +0,0 @@
<template>
<div class="quill" ref="quill" :class="classes">
<div ref="editor" :style="styles" v-loading="loading"></div>
<el-upload
:headers="headers"
:action="this.api.fileupload"
:before-upload="beforeUpload"
:on-success="editorUploadSuccess"
style="display: none"
>
<el-button class="editorUpload" type="primary">点击上传</el-button>
</el-upload>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import toolbarOptions from "./options";
export default {
name: "quill",
props: {
value: {
type: String,
default: ""
},
readonly: {
type: Boolean,
default: false
},
toTop: {
type: Boolean,
default: true
},
border: {
type: Boolean,
default: false
},
height: {
type: Number
},
minHeight: {
type: Number
},
/*
* 原本的readOnly失效,对比其他项目发现是quill版本不同导致
* 使用props传入elseRead = 'true'手动隐藏工具栏
*/
elseRead: {
type: String, default: "false"
}
},
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
Quill: null,
currentValue: "",
options: {
theme: "snow",
bounds: document.body,
debug: "warn",
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
"image": function(value) {
if (value) {
// iview
document.querySelector(".editorUpload").click();
} else {
this.Quill.format("image", false);
}
}
}
}
},
placeholder: "",
readOnly: this.readonly
},
loading: false
};
},
computed: {
classes() {
return [
{
"quill-no-border": !this.border
}
];
},
styles() {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
}
},
watch: {
value: {
handler(val) {
if (val !== this.currentValue) {
this.currentValue = val;
if (this.Quill) {
this.Quill.pasteHTML(this.value);
}
}
},
immediate: true
}
},
created() {
},
mounted() {
this.init();
//
if (this.elseRead === "true") {
let children = this.$refs.quill.children[0].style;
children.padding = "0";
children.overflow = "hidden";
children.height = "0";
children.borderTop = "0";
}
},
beforeDestroy() {
//
this.Quill = null;
},
methods: {
init () {
const editor = this.$refs.editor;
//
this.Quill = new Quill(editor, this.options);
const ins = this.Quill
//
ins.pasteHTML(this.currentValue);
if(this.toTop){
this.$nextTick(() => {
window.scrollTo(0,0)
})
}
//
ins.on('text-change', (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = ins.getText();
const quill = this.Quill;
//
this.currentValue = html;
// v-model
this.$emit('input', html);
//
this.$emit('on-change', { html, text, quill });
});
// quill
ins.on('text-change', (delta, oldDelta, source) => {
this.$emit('on-text-change', delta, oldDelta, source);
});
ins.on('selection-change', (range, oldRange, source) => {
this.$emit('on-selection-change', range, oldRange, source);
});
ins.on('editor-change', (eventName, ...args) => {
this.$emit('on-editor-change', eventName, ...args);
});
//
ins.root.addEventListener('paste', evt => {
if (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length) {
evt.preventDefault();
//
[].forEach.call(evt.clipboardData.files, file => {
if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
return
}
const param = new FormData()
param.append('file', file)
// base64
this.$post(this.api.fileupload, param, {
headers: { "Content-Type": "multipart/form-data" }
}).then(res => {
var range = ins.getSelection()
if (range) {
//
ins.insertEmbed(range.index, 'image', res.data.filesResult.fileUrl)
//
ins.setSelection(range.index + 1)
}
}).catch(res => {})
});
}
}, false)
},
beforeUpload(file) {
this.loading = true;
},
editorUploadSuccess(res) {
//
let quill = this.Quill;
//
if (res.data.filesResult.fileUrl) {
//
let length = quill.getSelection().index;
// res
quill.insertEmbed(length, "image", res.data.filesResult.fileUrl);
//
quill.setSelection(length + 1);
} else {
util.successMsg("图片插入失败");
}
this.loading = false;
}
}
};
</script>
<style lang="scss" scoped>
.quill-no-border {
.ql-toolbar.ql-snow {
border: none;
border-bottom: 1px solid #e8eaec;
}
.ql-container.ql-snow {
border: none;
}
}
.else {
.ql-toolbar.ql-snow {
height: 0;
overflow: hidden;
padding: 0;
border-top: 0;
}
}
/deep/.ql-snow {
position: relative;
.ql-tooltip {
position: absolute !important;
top: 10px !important;
left: 10px !important;
transform: translateY(10px);
}
}
</style>

@ -1,16 +0,0 @@
export default [
["bold", "italic", "underline", "strike"],
["blockquote", "code-block"],
[{ "header": 1 }, { "header": 2 }],
[{ "list": "ordered" }, { "list": "bullet" }],
[{ "script": "sub" }, { "script": "super" }],
[{ "indent": "-1" }, { "indent": "+1" }],
[{ "direction": "rtl" }],
[{ "size": ["small", false, "large", "huge"] }],
[{ "header": [1, 2, 3, 4, 5, 6, false] }],
[{ "color": [] }, { "background": [] }],
[{ "font": [] }],
[{ "align": [] }],
["clean"],
["link", "image", "video"]
];

@ -1,202 +0,0 @@
const pad2 = str => ('0' + str).substr(-2)
function fMoney (s, n) {
n = n > 0 && n <= 20 ? n : 2
s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(n) + ''
let l = s.split('.')[0].split('').reverse()
let r = s.split('.')[1]
let t = ''
for(let i = 0; i < l.length; i ++ ) {
t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? ',' : '')
}
return t.split('').reverse().join('') + '.' + r
}
function toDateTime (date, time) {
if (!date) return ''
date = date.toString()
time = time ? time.toString() : ''
let str = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
if (date.length == 14) {
str += ` ${date.substr(8, 2)}:${date.substr(10, 2)}:${date.substr(12, 2)}`
} else if (date.length == 6) {
str = `${date.substr(0, 2)}:${date.substr(2, 2)}:${date.substr(4, 2)}`
} else if (time) {
str += ` ${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
}
return str
}
function fMoney2 (m) {
return parseFloat(m).toFixed(2)
}
function orderreleaseType (sts) {
const status = {
'0': '手动发布',
'1': '定时发布',
}
return status[sts] || '未知状态'
}
function orderflag (sts) {
const status = {
'0': true,
'1': false,
}
return status[sts] || '未知状态'
}
function orderassesmentState (sts) {
const status = {
'0': '待开始',
'1': '进行中',
'2': '已结束',
}
return status[sts] || '未知状态'
}
function orderfounder (sts) {
const status = {
'0': '系统',
'1': '老师'
}
return status[sts] || '未知状态'
}
function projectPermissions (sts) {
const status = {
'1': '考核',
'2': '竞赛',
'0': '练习'
}
return status[sts] || '未知状态'
}
function roleType (type) {
const types = {
'2': '管理员',
'3': '老师',
'4': '学生'
}
return types[type] || '未知类型'
}
function educationDegreeList (id) {
const list = [
{
     name: '专科',
    value: 1
},
{
  name: '本科',
  value: 2
},
{
  name: '硕士',
  value: 3
},
{
  name: '博士',
  value: 4
},
{
  name: '其他',
  value: 5
}
]
let educationdegree = list.find((n,k) => {
return n.value == id
}).name
return educationdegree
}
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
function formatDate(fmt,date) {
var date = date ? date : new Date()
var o = {
"M+" : date.getMonth()+1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度
"S" : date.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt)) {
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o) {
if(new RegExp("("+ k +")").test(fmt)){
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
return fmt;
}
function removeByValue(arr, val) {
for(var i=0; i<arr.length; i++) {
if(arr[i] == val) {
arr.splice(i, 1);
break;
}
}
}
function formateTime(num) {
return num < 10 ? `0${num}` : num
}
function getCaption(obj){
var index=obj.lastIndexOf("\h");
obj=obj.substring(index+1,obj.length);
return obj;
}
// new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/
function dateCompatible(date) {
return date.replace(/\-/g, '/')
}
// 是否IE
function isIE() {
if (!!window.ActiveXObject || "ActiveXObject" in window) return true
return false
}
// 是否edge
function isEdge() {
let userAgent = navigator.userAgent
if (userAgent.includes("Edge")) return true
return false
}
// 是否火狐
function isFirefox() {
let userAgent = navigator.userAgent
if (userAgent.indexOf("Firefox") > -1) return true
return false
}
export default{
orderfounder,
projectPermissions,
orderassesmentState,
fMoney,
fMoney2,
toDateTime,
orderreleaseType,
orderflag,
roleType,
educationDegreeList,
removeByValue,
formateTime,
getCaption,
formatDate,
isIE,
isFirefox,
isEdge,
dateCompatible
}

@ -1,43 +0,0 @@
import Cookies from "js-cookie";
import Setting from "@/setting";
const cookies = {};
/**
* @description 存储 cookie
* @param {String} name cookie name
* @param {String} value cookie value
* @param {Object} cookieSetting cookie setting
*/
cookies.set = function(name = "default", value = "", cookieSetting = {}) {
let currentCookieSetting = {
expires: Setting.cookiesExpires
};
Object.assign(currentCookieSetting, cookieSetting);
Cookies.set(`admin-${name}`, value, currentCookieSetting);
};
/**
* @description 拿到 cookie
* @param {String} name cookie name
*/
cookies.get = function(name = "default") {
return Cookies.get(`admin-${name}`);
};
/**
* @description 拿到 cookie 全部的值
*/
cookies.getAll = function() {
return Cookies.get();
};
/**
* @description 删除 cookie
* @param {String} name cookie name
*/
cookies.remove = function(name = "default") {
return Cookies.remove(`admin-${name}`);
};
export default cookies;

@ -1,12 +1,6 @@
import cookies from "./util.cookies"; import { _local } from "./util.db";
import { _local, _session } from "./util.db";
import { Message } from "element-ui"; import { Message } from "element-ui";
import store from "@/store";
import axios from "axios";
import api from "@/api";
import Setting from "@/setting";
let logout = false;
// 文件后缀集合 // 文件后缀集合
const exts = { const exts = {
video: 'mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv', video: 'mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv',
@ -15,31 +9,7 @@ const exts = {
doc: 'doc,docx,txt,xls,xlsx,csv,xml,ppt,pptx' doc: 'doc,docx,txt,xls,xlsx,csv,xml,ppt,pptx'
} }
const util = { const util = {
cookies,
local: _local, local: _local,
session: _session,
// 传入身份证获取生日
getBirth(idCard) {
var birthday = "";
if (idCard != null && idCard != "") {
if (idCard.length == 15) {
birthday = "19" + idCard.slice(6, 12);
} else if (idCard.length == 18) {
birthday = idCard.slice(6, 14);
}
birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-");
//通过正则表达式来指定输出格式为:1990-01-01
}
return birthday;
},
// new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/
dateCompatible(date) {
return date.replace(/\-/g, "/");
},
// 日期时间前面补零
formateTime(num) {
return num < 10 ? `0${num}` : num;
},
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss" //返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
formatDate(fmt, date) { formatDate(fmt, date) {
var date = date ? date : new Date(); var date = date ? date : new Date();
@ -62,15 +32,6 @@ const util = {
} }
return fmt; return fmt;
}, },
// 移除数组中指定值
removeByValue(arr, val) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == val) {
arr.splice(i, 1);
break;
}
}
},
// 传入文件后缀判断是否是视频 // 传入文件后缀判断是否是视频
isVideo(ext) { isVideo(ext) {
if (exts.video.includes(ext)) return true; if (exts.video.includes(ext)) return true;
@ -91,22 +52,6 @@ const util = {
if (exts.doc.includes(ext)) return true; if (exts.doc.includes(ext)) return true;
return false; return false;
}, },
// 判断是否能够预览
canPreview(ext) {
if (!util.isVideo(ext) && !util.isAudio(ext) && !util.isImg(ext) && !util.isDoc(ext)) return false
return true
},
// 循环去除html标签
removeHtmlTag(list, attr) {
list.map(n => {
n[attr] = n[attr].replace(/<\/?.+?>/gi, "");
});
return list;
},
// 传入文件名获取文件后缀
getFileExt(fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
},
// 传入文件名和路径,下载图片视频,支持跨域,a标签加download不支持跨域 // 传入文件名和路径,下载图片视频,支持跨域,a标签加download不支持跨域
downloadFile(fileName, url) { downloadFile(fileName, url) {
var x = new XMLHttpRequest(); var x = new XMLHttpRequest();

@ -9,26 +9,24 @@ import { messages } from "@/i18n";
import "babel-polyfill"; import "babel-polyfill";
import "@/libs/resize"; import "@/libs/resize";
import { post, get, del, put } from "@/plugins/requests/index.js"; import { post, get, del, put } from "@/plugins/requests/index.js";
import core from '@/libs/core'
import api from "@/api"; import api from "@/api";
import store from "@/store"; import store from "@/store";
import Setting from "@/setting"; import Setting from "@/setting";
import Util from '@/libs/util' import Util from '@/libs/util'
// eval(function (p, a, c, k, e, r) { e = function (c) { return c.toString(a) }; if (!''.replace(/^/, String)) { while (c--) r[e(c)] = k[c] || e(c); k = [function (e) { return r[e] }]; e = function () { return '\\w+' }; c = 1 }; while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); return p }('2 i=\'\',3=["e",""];(4(a){a[3[0]]=3[1]})(8);2 9=["g"];!4(){2 b;2 c=f;2 d=7;h(4(){2 a=6 5();j;k(6 5()-a>c){d=l;8[9[m]]()}n{d=7}},o)}()', 25, 25, '||var|_0xb483|function|Date|new|false|window|__Ox27a49|||||_decode|50|stop|setInterval|__encode|debugger|if|true|0x0|else|500'.split('|'), 0, {}))
// 插件 // 插件
import plugins from "@/plugins"; import plugins from "@/plugins";
import filters from "@/plugins/filters";
import VueAnimateNumber from 'vue-animate-number' import VueAnimateNumber from 'vue-animate-number'
Vue.use(plugins); Vue.use(plugins);
Object.keys(filters).forEach(item => Vue.filter(item, filters[item]));
Vue.prototype.api = api; Vue.prototype.api = api;
Vue.prototype.$get = get; Vue.prototype.$get = get;
Vue.prototype.$post = post; Vue.prototype.$post = post;
Vue.prototype.$del = del; Vue.prototype.$del = del;
Vue.prototype.$put = put; Vue.prototype.$put = put;
Vue.prototype.core = core
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.use(VueI18n); Vue.use(VueI18n);
Vue.use(VueAnimateNumber); Vue.use(VueAnimateNumber);

@ -1,12 +0,0 @@
/**
* @description 返回缺省值
* 传入的如果是null就返回'--'
* 用例<Tag :default="val">text</Tag> <Tag>{{val | default}}</Tag>
* */
const defaultShow = (val) => {
return val == null ? "--" : val;
};
module.exports = {
defaultShow
};

@ -3,12 +3,9 @@
* */ * */
import directiveAuth from "@/plugins/auth"; import directiveAuth from "@/plugins/auth";
import throttle from "@/plugins/throttle";
export default { export default {
async install(Vue, options) { async install(Vue, options) {
// 指令 // 指令
Vue.directive("auth", directiveAuth); Vue.directive("auth", directiveAuth);
Vue.directive("throttle", throttle);
} }
}; };

@ -9,7 +9,9 @@ const service = axios.create({
}); });
// post请求头 // post请求头
service.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8"; service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
service.defaults.headers['X-Content-Type-Options'] = 'nosniff'
service.defaults.headers['Content-Security-Policy'] = 'script-src "self"; object-src "none";style-src cdn.example.org third-party.org; child-src https:'
// 请求拦截器 // 请求拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(config => {

@ -1,18 +0,0 @@
/**
* @description 节流指令
* 限制连续快速点击按钮
* 用例<Tag v-throttle>text</Tag>
* */
export default {
inserted(el, binding, vnode) {
el.addEventListener("click", () => {
if (!el.disabled) {
el.disabled = true;
setTimeout(() => {
el.disabled = false;
}, binding.value || 1000);
}
});
}
};

@ -4,10 +4,7 @@
const isDev = process.env.NODE_ENV === 'development' // 开发环境 const isDev = process.env.NODE_ENV === 'development' // 开发环境
let host = `${location.origin}/` let host = `${location.origin}/`
if (isDev) { if (isDev) {
host = 'http://192.168.31.136:10000/' // 测试服 host = 'http://192.168.31.51:10000/'
// host = 'https://31k70639y6.zicp.fun/' // 测试服
host = 'http://192.168.31.51:10000/' // 榕
// host = 'http://192.168.31.116/' // 赓
} }
const Setting = { const Setting = {

Loading…
Cancel
Save