您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
try to take over the world!
当前为
// ==UserScript== // @name SZU mailbox // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author nut // @match https://www1.szu.edu.cn/mailbox/* // @grant unsafeWindow // @require https://cdn.bootcss.com/vue/2.6.11/vue.min.js // @require https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/index.min.js // @run-at document-start // ==/UserScript== unsafeWindow.onload = function () { function getQueryVariable(variable) { const query = window.location.search.substring(1); const vars = query.split("&"); for (let i = 0; i < vars.length; i++) { const pair = vars[i].split("="); if (pair[0] == variable) { return pair[1]; } } return (false); } if (!getQueryVariable("id")) return let scriptCss = document.createElement('link'); scriptCss.setAttribute('rel', 'stylesheet'); scriptCss.setAttribute('type', 'text/css'); scriptCss.href = "https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css"; document.documentElement.appendChild(scriptCss); let classCss = document.createElement('Style'); classCss.innerHTML = ` .cell { font-size: 14px; } .el-message-box__btns span { color: #000000; font-size: 12px; line-height: 100%; } .text-buttonSelect span { color: #409eff; font-family: 微软雅黑; font-size: 14px; line-height: 100%; } .text-dangerous-buttonSelect span { color: #F56C6C; font-family: 微软雅黑; font-size: 14px; line-height: 100%; } .text-buttonSelect:active span { color: #006dda; } .text-dangerous-buttonSelect:active span { color: #d33d3d; } .buttonSelect span { color: #fff; font-family: 微软雅黑; font-size: 14px; line-height: 100%; } .userName { margin: 7px 0 9px 0; } .avatar { margin-top: 12px; width: 80px; height: 80px; } .avatar2 { margin-top: 5px; width: 32px; height: 32px; } .commentContent { min-height: 97px; } ` document.documentElement.appendChild(classCss); let father = document.querySelector("body > table > tbody > tr:nth-child(2) > td > table > tbody > tr:nth-child(3) > td > table > tbody > tr:nth-child(2) > td") let divApp = document.createElement('div') divApp.id = 'app' divApp.style = "width:980px;" divApp.innerHTML = ` <el-main v-if="postId!=0" class="my_table" style="width:90%;padding:0;"> <el-table :header-cell-style="headerStyle" :stripe="false" :data="comment" v-loading="loading" :cell-style="columnStyle"> <el-table-column align="center" :label="'评论:' + total" width="98"> <template slot-scope="scope"> <el-col> <el-image class="avatar" src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png" fit="cover" lazy> </el-image> </el-col> <el-col class="userName">{{ scope.row.user }}</el-col> </template> </el-table-column> <el-table-column className="cols" label="content"> <template slot="header" slot-scope="scope"> <el-row type="flex" align="middle"> <el-col :span="18"></el-col> <el-col :span="3"> <el-button class="buttonSelect" size="small" type="primary" @click="postComment()">评论</el-button> </el-col> <el-col :span="3"> <el-button class="buttonSelect" size="small" type="primary" @click="getComment()">刷新</el-button> </el-col> <el-col :span="3"> <el-button class="buttonSelect" size="small" :disabled="true" type="primary" @click="sortComment(scope.$index, scope.row)"> 按时间: {{ sort == "id" ? "旧" : "新" }}</el-button> </el-col> </el-row> </template> <template slot-scope="scope"> <div class="commentContent">{{scope.row.content}}</div> <el-row type="flex" align="middle"> <el-col :span="2"> <div style="min-width: 27px"> {{ scope.row.level + "楼" }} </div> </el-col> <el-col :span="18"> {{ scope.row.time.substring(0, 10) }} {{ scope.row.time.substring(11, 16) }} </el-col> <el-col :span="3"> <el-button class="buttonSelect" v-if="uuid==scope.row.uuid" size="mini" @click="deleteComment(scope.row.id, scope.$index)" type="danger"> 删除 </el-button> </el-col> <el-col :span="3"> <el-badge :value="scope.row.replies.total" type="primary"> <el-button class="buttonSelect" size="mini" type="primary" @click="popReply(scope.$index)">回复 </el-button> </el-badge> </el-col> </el-row> <el-row> <el-collapse-transition> <div v-show="comment[scope.$index].reply.showReply" style="margin-top:10px;"> <el-table :data="scope.row.replies.replies" :show-header="false" :cell-style="replycolumnStyle" v-loading="comment[scope.$index].reply.loading"> <el-table-column align="center" width="52" label="head"> <template> <el-image class="avatar2" src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png" fit="cover" lazy> </el-image> </template> </el-table-column> <el-table-column className="cols" label="content"> <template slot-scope="item"> <el-row :style="'height:'+ item.row.height +'px'"> {{ item.row.user + " : "+ (item.row.number?('@' + item.row.repliedUser+' : '):"") + item.row.content}} </el-row> <el-row style="height:23px" type="flex" align="middle" justify="end"> <el-col :span="16"> <div style="min-width: 27px"> {{ item.row.level + "层" }} </div> </el-col> <el-col :span="2"> <el-button v-if="uuid==scope.row.uuid" style="padding: 0;" type="text" class="text-dangerous-buttonSelect" @click="deleteReply(item.row.id, item.$index,scope.$index)"> 删除 </el-button> </el-col> <el-col :span="4" style="font-family: Avenir, Helvetica, Arial, sans-serif;"> {{ item.row.time.substring(0, 10) }} {{ item.row.time.substring(11, 16) }} </el-col> <el-col :span="2"> <el-button style="padding: 0;" type="text" class="text-buttonSelect" @click="postReply(scope.$index,item.row.level,item.row.user,item.row.id)">回复 </el-button> </el-col> </el-row> </template> </el-table-column> </el-table> <el-row type="flex" align="middle" justify="end"> <el-col> <el-pagination v-if="comment[scope.$index].replies.total != 0" small layout="prev, pager, next" :total="comment[scope.$index].replies.total" :current-page.sync="comment[scope.$index].reply.currentPage" :page-size="limit" @current-change="getReply(scope.$index)"> </el-pagination> </el-col> <el-col :span="3"> <el-button style="padding: 0;" type="text" class="text-buttonSelect" @click="postReply(scope.$index,0,scope.row.user,scope.row.id)"> 回复一下 </el-button> </el-col> </el-row> <el-collapse-transition> <el-card v-show="comment[scope.$index].reply.showInput"> <el-row style="margin-bottom:10px"> <el-input v-model="scope.row.reply.content" placeholder="请写下你的回复"> <template v-if="scope.row.reply.number" slot="prepend">{{'@'+scope.row.reply.repliedUser}}</template> </el-input> </el-row> <el-row type="flex" align="middle"> <el-col :span="2" :offset="19"> <el-checkbox v-model="scope.row.reply.isAnonymous">匿名</el-checkbox> </el-col> <el-col :span="2"> <el-button class="buttonSelect" size="mini" type="primary" @click="replySubmit(scope.$index)"> 发送 </el-button> </el-col> </el-row> </el-card> </el-collapse-transition> </div> </el-collapse-transition> </el-row> </template> </el-table-column> </el-table> <el-pagination style="text-align: center; margin: 10px 0 10px 0" background layout="prev, pager, next" :total="total" :current-page.sync="currentPage" :page-size="limit" @current-change="getComment()"> </el-pagination> <el-card> <el-row style="margin-bottom:10px"> <el-input type="textarea" :autosize="{ minRows: 3}" v-model="content" placeholder="请写下你的评论"> </el-input> </el-row> <el-row type="flex" align="middle"> <el-col :span="2" :offset="20"> <el-checkbox v-model="isAnonymous">匿名</el-checkbox> </el-col> <el-col :span="2"> <el-button class="buttonSelect" size="mini" type="primary" @click="commentSubmit()">发送</el-button> </el-col> </el-row> <div id="commentEdit" style="position:relative;top:80px"></div> <div id='textLength' style='font-family: Avenir, Helvetica, Arial, sans-serif; white-space: nowrap; position:fixed;z-index:-1;bottom:0;opacity:0;height:0;font-size:14px'></div> </el-card> </el-main> ` father.append(divApp) new Vue({ el: '#app', data() { return { loading: true, currentPage: 1, total: 0, limit: 10, postId: 0, comment: [], sort: "id", uuid: '1', input: '', content: '', isAnonymous: 0, } }, mounted() { this.init().then(res => { sessionStorage.setItem('uuid', JSON.parse(res).uuid) this.uuid = sessionStorage.getItem('uuid') }) if (!this.getQueryVariable("id")) return else this.postId = this.getQueryVariable("id") this.getComment() }, methods: { async init() { const xml = new XMLHttpRequest(); xml.open('GET', "https://mailbox.nutvii.top/login/"); xml.withCredentials = true xml.setRequestHeader('Authorization', this.getASPSESSION()); xml.send(); return new Promise((resolve) => { xml.onload = () => { resolve(xml.responseText) } }) }, getASPSESSION() { let cookieStr = document.cookie.split('; '); let cookies = "null"; let isFirst = true; for (const i in cookieStr) { if (cookieStr[i].indexOf("ASPSESSION") !== -1) { if (isFirst) { cookies = cookieStr[i]; isFirst = false; } else { cookies += '; ' + cookieStr[i]; } } } return cookies }, async httpMethod(method, url, data) { url = 'https://mailbox.nutvii.top/' + url const xml = new XMLHttpRequest(); xml.withCredentials = true let str = ''; let isFirst = true; for (const i in data) { if (isFirst) { isFirst = false; str += i + '=' + data[i] } else str += '&' + i + '=' + data[i] } if (method == 'GET' || method == 'DELETE') { xml.open(method, url + '?' + str); xml.send(null); } else if (method == 'POST') { xml.open(method, url); xml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xml.send(str); } return new Promise((resolve, reject) => { xml.onload = () => { if (xml.status == 200) resolve(JSON.parse(xml.responseText)) else reject(xml.responseText); } }) }, getComment() { this.loading = true; this.httpMethod('GET', 'comment/', { 'postId': this.postId, 'limit': this.limit, 'offset': this.currentPage, }).then((data) => { this.comment = data.comments for (const i in this.comment) { this.$set(this.comment[i], 'reply', { 'commentId': this.comment[i].id, 'content': '', 'number': 0, 'repliedId': this.comment[i].id, 'isAnonymous': 0, 'repliedUser': '', 'showReply': false, 'showInput': false, 'loading': false, 'currentPage': 1 }) const rArr = this.comment[i].replies.replies for (const j in rArr) { let str = rArr[j].user + " : " str += (rArr[j].number ? ('@' + rArr[j].repliedUser + ' : ') : "") + rArr[j].content this.$set(rArr[j], 'height', this.getLength(str)) } this.comment[i].reply.showReply = this.comment[i].replies.total != 0 } this.total = data.total this.loading = false }).catch((e) => { this.$message.error(e) }) }, postComment() { document.getElementById("commentEdit").scrollIntoView({ block: 'end', behavior: 'smooth' }) }, commentSubmit() { if (this.content.length >= 3) { this.httpMethod('POST', 'comment/', { 'postId': this.postId, 'content': this.content, 'isAnonymous': this.isAnonymous ? 1 : 0, }).then((data) => { this.$message.success('评论成功') this.total++; if (Math.ceil((this.total) / 10) > this.currentPage) { this.currentPage = Math.ceil(this.total / 10) this.getComment() } else { data['replies'] = {} this.$set(data, 'reply', { 'commentId': data.id, 'content': '', 'number': 0, 'repliedId': data.id, 'isAnonymous': 0, 'repliedUser': '', 'showReply': false, 'showInput': false, 'loading': false, 'currentPage': 1 }) this.comment.push(data) } this.content = '' }).catch((e) => { this.$message.error(e) }) } else { this.$message.error("字数少于3") } }, deleteComment(id, index) { this.$confirm('确认删除?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.httpMethod('DELETE', 'comment/', { 'id': id }).then((data) => { this.$message.success('删除成功') this.comment.splice(index, 1) this.total--; }).catch((e) => { this.$message.error(e) }) }) }, getReply(index) { this.comment[index].reply.loading = true this.httpMethod('GET', 'reply/', { 'commentId': this.comment[index].id, 'limit': this.limit, 'offset': this.comment[index].reply.currentPage, }).then((data) => { for (const i in data) { if (i == 'replies') { for (const j in data[i]) { let str = data[i][j].user + " : " str += (data[i][j].number ? ('@' + data[i][j].repliedUser + ' : ') : "") + data[i][j].content this.$set(data[i][j], 'height', this.getLength(str)) } } this.comment[index].replies[i] = data[i] } this.comment[index].reply.loading = false }).catch((e) => { this.$message.error(e) }) }, popReply(index) { this.comment[index].reply.showReply = !this.comment[index].reply.showReply }, postReply(index, level, repliedUser, repliedId) { if (this.comment[index].reply.showInput && level == this.comment[index].reply.number) this.comment[index].reply.showInput = false else this.comment[index].reply.showInput = true this.comment[index].reply.number = level this.comment[index].reply.repliedUser = repliedUser this.comment[index].reply.repliedId = repliedId }, replySubmit(index) { if (this.comment[index].reply.content.length >= 3) { this.httpMethod('POST', 'reply/', { 'commentId': this.comment[index].reply.commentId, 'content': this.comment[index].reply.content, 'number': this.comment[index].reply.number, 'repliedId': this.comment[index].reply.repliedId, 'isAnonymous': this.comment[index].reply.isAnonymous ? 1 : 0, }).then((data) => { this.$message.success('回复成功') this.comment[index].replies.total++; if (Math.ceil((this.comment[index].replies.total) / 10) > this.comment[index].reply.currentPage) { this.comment[index].reply.currentPage = Math.ceil(this.comment[index].replies.total / 10) this.getReply(index) } else { let str = data.user + " : " str += (data.number ? ('@' + data.repliedUser + ' : ') : "") + data.content this.$set(data, 'height', this.getLength(str)) this.comment[index].replies.replies.push(data) } this.comment[index].reply.content = '' this.content = '' }).catch((e) => { this.$message.error(e) }) } else { this.$message.error("字数少于3") } }, deleteReply(id, index, commentIndex) { this.$confirm('确认删除?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.httpMethod('DELETE', 'reply/', { 'id': id }).then((data) => { this.$message.success('删除成功') this.comment[commentIndex].replies.replies.splice(index, 1) this.comment[commentIndex].replies.total--; }).catch((e) => { this.$message.error(e) }) }) }, sortComment(index, row) { this.sort = this.sort == 'id' ? '-id' : 'id'; this.$set(this.comment, index, row) this.getComment() }, columnStyle({ row, column, rowIndex, columnIndex }) { if (columnIndex == 0) return 'background:#cddade;vertical-align:top;' else return 'background:#fff;vertical-align:top;' }, replycolumnStyle({ row, column, rowIndex, columnIndex }) { return 'background:#f5f6f7;vertical-align:top;padding:5px;' }, headerStyle({ row, column, rowIndex, columnIndex }) { if (columnIndex == 0) return 'background:#ebeef5;' }, getQueryVariable(variable) { const query = window.location.search.substring(1); const vars = query.split("&"); for (let i = 0; i < vars.length; i++) { const pair = vars[i].split("="); if (pair[0] == variable) { return pair[1]; } } return (false); }, getLength(str) { const ele = document.getElementById('textLength') ele.textContent = str const length = ele.clientWidth ele.textContent = '' return Math.ceil(length / 682) * 23 } } }) }