基本正常,未发现恶性bug

This commit is contained in:
lion 2022-07-20 20:02:41 +08:00
commit ed257498c2
8 changed files with 634 additions and 0 deletions

28
src/App.vue Normal file
View File

@ -0,0 +1,28 @@
<template>
<div class="app">
<el-container>
<el-aside width="500px">
<Side/>
</el-aside>
<el-main>
<DashBoard/>
</el-main>
</el-container>
</div>
</template>
<script>
import Side from "./components/Side.vue";
import DashBoard from "./components/DashBoard.vue";
export default {
name: 'App',
components:{Side, DashBoard}
}
</script>
<style>
.app{
background-color: #c6e2ff;
}
</style>

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,148 @@
<template>
<div class="DashBoard" v-show="loadComplete">
<el-row>
<el-col :span="24"> </el-col>
</el-row>
<el-row>
<el-col :span="8"></el-col>
<el-col :span="8">
<el-input v-model="link" placeholder="输入链接"></el-input>
</el-col>
<el-col :span="8"></el-col>
</el-row>
<br>
<el-row>
<el-col :span="8"></el-col>
<el-col :span="12">
<el-button @click="post">提交下载</el-button>
<el-button @click="query">查询任务</el-button>
<el-button @click="searchByLink">查找任务</el-button>
</el-col>
<el-col :span="4"></el-col>
</el-row>
<br>
<hr>
<br>
<el-row>
<el-col :span="8"></el-col>
<el-col :span="8">
<el-input v-model="keyword" placeholder="输入关键字" @change="searchByKeyword">
<template #prefix>
输入关键字查找
</template>
</el-input>
</el-col>
<el-col :span="8"></el-col>
</el-row>
<br>
<el-row>
<el-col :span="11"></el-col>
<el-col :span="7">
<el-button>确定</el-button>
</el-col>
<el-col :span="6"></el-col>
</el-row>
</div>
<div class="DashBoard" v-show="!loadComplete">
<el-col :span="20">
<el-input v-model="AuthCode" class="validate">
<template #prefix>
请输入授权码
</template>
<template #append>
<el-button @click="validate" type="primary">验证</el-button>
</template>
</el-input>
</el-col>
</div>
</template>
<script>
import store from "../store";
import {computed, ref} from "vue";
import {ElMessage} from "element-plus"
export default {
name: "DashBoard",
setup(){
const link = ref("")
const AuthCode = ref("")
const keyword = ref("")
let timer
function post(){
if(link.value.trim() === ''){
ElMessage("请输入链接后再提交")
}
else {
let gid = link.value.split('/')[4]
if (!gid || !link.value.includes("hentai")) {
ElMessage("请检查链接输入是否正确")
}
else
store.dispatch("post", link.value)
}
}
function query(){
if(link.value.trim() === ''){
ElMessage("请输入链接后再查询")
}
else
store.dispatch("query", link.value)
}
function validate(){
if(AuthCode.value.trim() === ""){
ElMessage("请输入授权码后再验证")
}
else{
store.dispatch("validate", AuthCode.value)
}
}
function searchByLink() {
if(link.value.trim() === ""){
ElMessage("请输入链接后查找")
}
else {
store.dispatch("searchByLink", link.value)
}
}
function searchByKeyword(){
if(timer)
clearTimeout(timer)
timer = setTimeout(() => {
store.dispatch("searchByKeyword", keyword.value)
}, 500)
}
const loadComplete = computed(() => {
return store.getters.loadComplete
})
return {link, post, query, validate, loadComplete, AuthCode, searchByLink, keyword, searchByKeyword, store}
}
}
</script>
<style scoped>
.DashBoard{
width: auto;
height: 90vh;
background-color: ghostwhite;
}
.validate{
width: auto;
background-color: ghostwhite;
display: block;
margin-left: 400px;
margin-top: 200px;
}
</style>

168
src/components/Side.vue Normal file
View File

@ -0,0 +1,168 @@
<template>
<div class="side" style="width: 100%">
<span>下载历史</span>
<div v-show="loadComplete" class="load_complete" >
<el-table :data="data">
<el-table-column type="expand">
<template #default="props">
名字:{{ props.row.name}} <br>
链接:<el-link :href="props.row.link">Link</el-link> <br>
语言:{{props.row.language}} <br>
页数:{{props.row.pages}} <br>
文件大小:{{props.row.fileSize}}
</template>
</el-table-column>
<el-table-column label="Name" width="300">
<template #default="scoped">
{{scoped.row.name}}
</template>
</el-table-column>
<el-table-column label="link" width="80">
<template #default="scoped">
<el-link :href="scoped.row.download" v-show="scoped.row.download">download</el-link>
</template>
</el-table-column>
<el-table-column label="status" width="60">
<template #default="scoped">
{{ scoped.row.progress }}
</template>
</el-table-column>
</el-table>
<el-row class="pageChanger">
<el-col>
<el-button @click="toMin">{{min}}</el-button>
<el-button @click="previous">-</el-button>
<el-input v-model="targetPage"
@change="changePage"
v-show="isEditing"
@blur="reverse()"
class="page"
ref="input"></el-input>
<span @click="reverse" v-show="!isEditing" class="page">{{page}}</span>
<el-button @click="next">+</el-button>
<el-button @click="toMax">{{max}}</el-button>
</el-col>
</el-row>
</div>
<span v-show="!loadComplete" class="side">请输入授权码后再查看</span>
</div>
</template>
<script>
import store from "../store";
import {computed, ref} from "vue";
export default {
name: "Side",
setup(){
const targetPage = ref(1)
const isEditing = ref(false)
let input = ref(null)
let data = computed(() => {
if(store.getters.task)
return store.getters.task
else
return null
})
let min = computed(() => {
return store.getters.min
})
let max = computed(() => {
return store.getters.max
})
let page = computed(() => {
targetPage.value = store.getters.page
return store.getters.page
})
function next() {
if(targetPage.value < max.value) {
targetPage.value++
store.commit("_changePage", targetPage.value)
}
}
function previous() {
if(targetPage.value > min.value) {
targetPage.value--
store.commit("_changePage", targetPage.value)
}
}
function toMax() {
store.commit("_changePage", max.value)
targetPage.value = max.value
}
function toMin(){
store.commit("_changePage", min.value)
targetPage.value = min.value
}
let loadComplete = computed(() => {
return store.getters.loadComplete
})
function update(){
store.dispatch("update")
}
function changePage(){
if(targetPage.value >= min.value && targetPage.value <= max.value)
store.commit("_changePage", targetPage.value)
}
function reverse(){
console.log("reverse")
isEditing.value = !isEditing.value
if(isEditing){
input.value.focus()
}
targetPage.value = page.value
}
return {update,
data,
min,
max,
targetPage,
loadComplete,
page,
isEditing,
input,
reverse,
changePage,
toMax,
toMin,
previous,
next,
store
}
}
}
</script>
<style scoped>
.side{
text-align: center;
height: 300px;
}
span{
display: block;
}
.pageChanger{
position: absolute;
top:92vh;
left: 150px;
}
.page{
display: inline-block;
width: 50px;
}
</style>

8
src/index.css Normal file
View File

@ -0,0 +1,8 @@
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}

6
src/main.js Normal file
View File

@ -0,0 +1,6 @@
import { createApp } from 'vue'
import App from './App.vue'
import 'element-plus/dist/index.css'
import element from "element-plus"
createApp(App).use(element).mount('#app')

42
src/reset.css Normal file
View File

@ -0,0 +1,42 @@
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

234
src/store/index.js Normal file
View File

@ -0,0 +1,234 @@
import vuex from "vuex"
import axios from "axios"
import {ElMessage} from "element-plus"
import qs from "qs"
const base_url = "http://107.189.14.196:8080/TaskHandler/"
const actions = {
update(context){
const AuthCode = context.state.AuthCode
axios.get(base_url, {
params:{
param:"",
type:"all",
AuthCode: AuthCode
}
}).then((res) => {
let temp = []
context.commit("_empty")
JSON.parse(res.data.data).forEach((task) => {
temp.push(JSON.parse(task))
})
context.commit("_update", temp)
})
},
post(context, link){
const AuthCode = context.state.AuthCode
axios.post(base_url, qs.stringify({
AuthCode:AuthCode,
link:link
})).then((res) => {
if(res.data.result === "success")
ElMessage("提交成功")
else{
if(res.data.data)
ElMessage(res.data.data)
else{
ElMessage("提交失败")
}
}
})
},
query(context, link){
const AuthCode = context.state.AuthCode
axios.get(base_url, {
params:{
param:link,
type:'link',
AuthCode
}
}).then((res) => {
if(res.data.result === 'success'){
const gallery = JSON.parse(res.data.data)
let message = "本子名字: " + gallery.name + "<br>"
message += "本子页数: " + gallery.pages + "<br>"
message += "gid: " + gallery.gid + "<br>"
if(gallery.language === "N/A")
message += "语言: 未知<br>"
else
message += "语言: " + gallery.language + "<br>"
message += "大小: " + gallery.fileSize + "<br>"
switch (gallery.status){
case "complete":
message += "状态: 下载完成"
break
case "posted" :
message += "状态: 等待中"
break
case "proceeding":
message += "状态: 下载中"
break
default:
break
}
console.log(gallery)
ElMessage({
dangerouslyUseHTMLString: true,
duration: 5000,
showClose: true,
message
})
}
else
ElMessage("查询失败")
})
},
validate(context, AuthCode){
axios.post(base_url + "validate?AuthCode=" + AuthCode).then((res)=>{
if(res.data.result === 'success'){
context.commit("_authed", AuthCode, context)
context.dispatch("update")
setInterval(() => {
context.dispatch("update")
}, 30000)
}
else{
context.commit("_unAuthed")
}
})
},
searchByLink(context, link){
context.commit("_searchByLink", link)
},
searchByKeyword(context, keyword){
context.commit("_searchByKeyword", keyword)
}
}
const mutations = {
_empty(state){
state.totalTask.splice(0)
},
_update(state, tasks){
const download_url = base_url + "file?link="
tasks.forEach((task) => {
if(task.status === "posted"){
task.progress = "0%"
}
else if(task.status === "downloading"){
task.progress = (Math.round((task.proceeding / task.pages)*100)).toString() + "%"
}
else if(task.status === "complete"){
task.progress = "100%"
task.download = download_url + task.link + "&AuthCode=" + state.AuthCode
}
state.totalTask.push(task)
})
if(state.isAuth && !state.loadComplete){
state.loadComplete = true
ElMessage("加载完成")
}
},
_changePage(state, targetPage){
state.page = targetPage
},
_authed(state, AuthCode){
state.AuthCode = AuthCode
state.isAuth = true
ElMessage("验证成功,加载中")
},
_unAuthed(state){
state.isAuth = false
state.AuthCode = ""
ElMessage("授权码错误")
},
_searchByLink(state, link){
let gid = link.split('/')[4]
if(!gid){
ElMessage("请检查链接输入是否正确")
}
let i = 0
let found = false
for(i=0; i<state.totalTask.length; i++){
if(state.totalTask[i].gid === gid){
state.page = Math.floor(i/state.length) + 1
found = true
break
}
}
if(!found){
ElMessage("未找到此任务")
}
},
_searchByKeyword(state, keyword){
state.searchTask.splice(0)
state.page = 1
state.totalTask.forEach((task) => {
if(task.name.includes(keyword))
state.searchTask.push(task)
})
if(state.searchTask.length === 0){
ElMessage("未找到该关键字的本子")
}
}
}
const state = {
totalTask:[], //存放数据的数组
page:1, //当前页数
length:8, //每页能有多少个链接
isAuth:false, //是否授权
AuthCode:'', //授权码
loadComplete:false, //是否加载完成
isInclude:false, //是否搜索到任务
searchTask:[] //搜索到的任务
}
const getters = {
task(state){
if(state.searchTask.length !== 0)
return state.searchTask.slice((state.page-1)*state.length, state.page*state.length)
if(state.totalTask.length !== 0)
return state.totalTask.slice((state.page-1)*state.length, state.page*state.length)
return null
},
min(){
return 1
},
max(state){
let max = 0
let tasks
if(state.searchTask.length !== 0){
tasks = state.searchTask
}
else if(state.totalTask.length !== 0){
tasks = state.totalTask
}
if(!tasks)
return 1
max = Math.floor(tasks.length/state.length)
if(tasks.length % state.length !== 0){
max += 1
}
return max
},
isAuth(state){
return state.isAuth
},
page(state){
return state.page
},
loadComplete(state){
return state.loadComplete
}
}
export default new vuex.Store({
actions,
mutations,
state,
getters
})