mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-26 17:49:15 +01:00
updated README.md
code cleanup
This commit is contained in:
@@ -1,228 +0,0 @@
|
||||
<template>
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">OOPS!</div>
|
||||
<div class="bullshit__info">版权所有
|
||||
<a class="link-type" href="https://wallstreetcn.com" target="_blank">华尔街见闻</a>
|
||||
</div>
|
||||
<div class="bullshit__headline">{{ message }}</div>
|
||||
<div class="bullshit__info">请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告</div>
|
||||
<a href="" class="bullshit__return-home">返回首页</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Page404',
|
||||
computed: {
|
||||
message () {
|
||||
return '网管说这个页面你不能进......'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-text">name:{{ name }}</div>
|
||||
<div class="dashboard-text">roles:<span v-for="role in roles" :key="role">{{ role }}</span></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'name',
|
||||
'roles'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.dashboard {
|
||||
&-container {
|
||||
margin: 30px;
|
||||
}
|
||||
&-text {
|
||||
font-size: 30px;
|
||||
line-height: 46px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-text">name:{{ name }}</div>
|
||||
<div class="dashboard-text">roles:<span v-for="role in roles" :key="role">{{ role }}</span></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'name',
|
||||
'roles'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.dashboard {
|
||||
&-container {
|
||||
margin: 30px;
|
||||
}
|
||||
&-text {
|
||||
font-size: 30px;
|
||||
line-height: 46px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<div class="">
|
||||
NodeDetail
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'NodeDetail'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,84 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form ref="form" :model="form" label-width="120px">
|
||||
<el-form-item label="Activity name">
|
||||
<el-input v-model="form.name"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity zone">
|
||||
<el-select v-model="form.region" placeholder="please select your zone">
|
||||
<el-option label="Zone one" value="shanghai"/>
|
||||
<el-option label="Zone two" value="beijing"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity time">
|
||||
<el-col :span="11">
|
||||
<el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;"/>
|
||||
</el-col>
|
||||
<el-col :span="2" class="line">-</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;"/>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="Instant delivery">
|
||||
<el-switch v-model="form.delivery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity type">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="Online activities" name="type"/>
|
||||
<el-checkbox label="Promotion activities" name="type"/>
|
||||
<el-checkbox label="Offline activities" name="type"/>
|
||||
<el-checkbox label="Simple brand exposure" name="type"/>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Resources">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="Sponsor"/>
|
||||
<el-radio label="Venue"/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity form">
|
||||
<el-input v-model="form.desc" type="textarea"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">Create</el-button>
|
||||
<el-button @click="onCancel">Cancel</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit () {
|
||||
this.$message('submit!')
|
||||
},
|
||||
onCancel () {
|
||||
this.$message({
|
||||
message: 'cancel!',
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.line{
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,84 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form ref="form" :model="form" label-width="120px">
|
||||
<el-form-item label="Activity name">
|
||||
<el-input v-model="form.name"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity zone">
|
||||
<el-select v-model="form.region" placeholder="please select your zone">
|
||||
<el-option label="Zone one" value="shanghai"/>
|
||||
<el-option label="Zone two" value="beijing"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity time">
|
||||
<el-col :span="11">
|
||||
<el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;"/>
|
||||
</el-col>
|
||||
<el-col :span="2" class="line">-</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;"/>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="Instant delivery">
|
||||
<el-switch v-model="form.delivery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity type">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="Online activities" name="type"/>
|
||||
<el-checkbox label="Promotion activities" name="type"/>
|
||||
<el-checkbox label="Offline activities" name="type"/>
|
||||
<el-checkbox label="Simple brand exposure" name="type"/>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Resources">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="Sponsor"/>
|
||||
<el-radio label="Venue"/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Activity form">
|
||||
<el-input v-model="form.desc" type="textarea"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">Create</el-button>
|
||||
<el-button @click="onCancel">Cancel</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit () {
|
||||
this.$message('submit!')
|
||||
},
|
||||
onCancel () {
|
||||
this.$message({
|
||||
message: 'cancel!',
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.line{
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row>
|
||||
<ul class="metric-list">
|
||||
<li class="metric-item" v-for="m in metrics" @click="onClickMetric(m)" :key="m.name">
|
||||
<el-card class="metric-card" shadow="hover">
|
||||
<el-col :span="6" class="icon-col">
|
||||
<i :class="m.icon" :style="{color:m.color}"></i>
|
||||
</el-col>
|
||||
<el-col :span="18" class="text-col">
|
||||
<el-row>
|
||||
<label class="label">{{$t(m.label)}}</label>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="value">{{overviewStats[m.name]}}</div>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-card>
|
||||
</li>
|
||||
</ul>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-card shadow="hover">
|
||||
<h4 class="title">{{$t('Daily New Tasks')}}</h4>
|
||||
<div id="echarts-daily-tasks" class="echarts-box"></div>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '../../api/request'
|
||||
import echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
data () {
|
||||
return {
|
||||
echarts: {},
|
||||
overviewStats: {},
|
||||
dailyTasks: [],
|
||||
metrics: [
|
||||
{ name: 'task_count', label: 'Total Tasks', icon: 'fa fa-play', color: '#f56c6c', path: 'tasks' },
|
||||
{ name: 'spider_count', label: 'Spiders', icon: 'fa fa-bug', color: '#67c23a', path: 'spiders' },
|
||||
{ name: 'node_count', label: 'Active Nodes', icon: 'fa fa-server', color: '#409EFF', path: 'nodes' },
|
||||
{ name: 'deploy_count', label: 'Total Deploys', icon: 'fa fa-cloud', color: '#409EFF', path: 'deploys' }
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initEchartsDailyTasks () {
|
||||
const option = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: this.dailyTasks.map(d => d.date)
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [{
|
||||
data: this.dailyTasks.map(d => d.count),
|
||||
type: 'line',
|
||||
areaStyle: {},
|
||||
smooth: true
|
||||
}],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
show: true
|
||||
}
|
||||
}
|
||||
this.echarts.dailyTasks = echarts.init(this.$el.querySelector('#echarts-daily-tasks'))
|
||||
this.echarts.dailyTasks.setOption(option)
|
||||
},
|
||||
onClickMetric (m) {
|
||||
this.$router.push(`/${m.path}`)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
request.get('/stats/get_home_stats')
|
||||
.then(response => {
|
||||
// overview stats
|
||||
this.overviewStats = response.data.overview_stats
|
||||
|
||||
// daily tasks
|
||||
this.dailyTasks = response.data.daily_tasks
|
||||
this.initEchartsDailyTasks()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.metric-list {
|
||||
margin-top: 0;
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
|
||||
.metric-item:last-child .metric-card {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
flex-basis: 25%;
|
||||
|
||||
.metric-card:hover {
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
margin-right: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
.icon-col {
|
||||
text-align: right;
|
||||
|
||||
i {
|
||||
margin-bottom: 15px;
|
||||
font-size: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-col {
|
||||
padding-left: 20px;
|
||||
height: 76px;
|
||||
text-align: center;
|
||||
|
||||
.label {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
display: block;
|
||||
height: 24px;
|
||||
color: grey;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 24px;
|
||||
display: block;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#echarts-daily-tasks {
|
||||
height: 360px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-card {
|
||||
/*border: 1px solid lightgrey;*/
|
||||
}
|
||||
</style>
|
||||
@@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"></div>
|
||||
<sidebar class="sidebar-container"/>
|
||||
<div class="main-container">
|
||||
<navbar/>
|
||||
<!--<tags-view/>-->
|
||||
<app-main/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
Navbar,
|
||||
Sidebar,
|
||||
AppMain
|
||||
// TagsView
|
||||
} from './components'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
Navbar,
|
||||
Sidebar,
|
||||
// TagsView,
|
||||
AppMain
|
||||
},
|
||||
mixins: [ResizeMixin],
|
||||
computed: {
|
||||
sidebar () {
|
||||
return this.$store.state.app.sidebar
|
||||
},
|
||||
device () {
|
||||
return this.$store.state.app.device
|
||||
},
|
||||
classObj () {
|
||||
return {
|
||||
hideSidebar: !this.sidebar.opened,
|
||||
openSidebar: this.sidebar.opened,
|
||||
withoutAnimation: this.sidebar.withoutAnimation,
|
||||
mobile: this.device === 'mobile'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickOutside () {
|
||||
this.$store.dispatch('CloseSideBar', { withoutAnimation: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "../../../src/styles/mixin.scss";
|
||||
|
||||
.app-wrapper {
|
||||
@include clearfix;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
&.mobile.openSidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-bg {
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
||||
@@ -1,29 +0,0 @@
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<!-- or name="fade" -->
|
||||
<router-view :key="key"></router-view>
|
||||
<!--<router-view/>-->
|
||||
</transition>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AppMain',
|
||||
computed: {
|
||||
key () {
|
||||
return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-main {
|
||||
/*50 = navbar */
|
||||
min-height: calc(100vh - 50px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -1,34 +0,0 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
functional: true,
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
render (h, context) {
|
||||
const { icon, title } = context.props
|
||||
const vnodes = []
|
||||
|
||||
if (icon) {
|
||||
// vnodes.push(<svg-icon icon-class={icon}/>)
|
||||
const style = {
|
||||
'margin-right': '5px',
|
||||
'z-index': 999
|
||||
}
|
||||
vnodes.push(<span class={icon} style={style}/>)
|
||||
}
|
||||
|
||||
if (title) {
|
||||
vnodes.push(<span class="title" slot='title'>{(title)}</span>)
|
||||
}
|
||||
return vnodes
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,41 +0,0 @@
|
||||
import store from '@/store'
|
||||
|
||||
const { body } = document
|
||||
const WIDTH = 1024
|
||||
const RATIO = 3
|
||||
|
||||
export default {
|
||||
watch: {
|
||||
$route (route) {
|
||||
if (this.device === 'mobile' && this.sidebar.opened) {
|
||||
store.dispatch('CloseSideBar', { withoutAnimation: false })
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount () {
|
||||
window.addEventListener('resize', this.resizeHandler)
|
||||
},
|
||||
mounted () {
|
||||
const isMobile = this.isMobile()
|
||||
if (isMobile) {
|
||||
store.dispatch('ToggleDevice', 'mobile')
|
||||
store.dispatch('CloseSideBar', { withoutAnimation: true })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isMobile () {
|
||||
const rect = body.getBoundingClientRect()
|
||||
return rect.width - RATIO < WIDTH
|
||||
},
|
||||
resizeHandler () {
|
||||
if (!document.hidden) {
|
||||
const isMobile = this.isMobile()
|
||||
store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
|
||||
|
||||
if (isMobile) {
|
||||
store.dispatch('CloseSideBar', { withoutAnimation: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
|
||||
label-position="left">
|
||||
<h3 class="title">Crawlab</h3>
|
||||
<el-form-item prop="username">
|
||||
<span class="svg-container">
|
||||
<svg-icon icon-class="user"/>
|
||||
</span>
|
||||
<el-input v-model="loginForm.username" name="username" type="text" auto-complete="on"
|
||||
placeholder="username"/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<span class="svg-container">
|
||||
<svg-icon icon-class="password"/>
|
||||
</span>
|
||||
<el-input
|
||||
:type="pwdType"
|
||||
v-model="loginForm.password"
|
||||
name="password"
|
||||
auto-complete="on"
|
||||
placeholder="password"
|
||||
@keyup.enter.native="handleLogin"/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon :icon-class="pwdType === 'password' ? 'eye' : 'eye-open'"/>
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :loading="loading" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
|
||||
Sign in
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<div class="tips">
|
||||
<span style="margin-right:20px;">username: admin</span>
|
||||
<span> password: admin</span>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isvalidUsername } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
data () {
|
||||
const validateUsername = (rule, value, callback) => {
|
||||
if (!isvalidUsername(value)) {
|
||||
callback(new Error('请输入正确的用户名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (value.length < 5) {
|
||||
callback(new Error('密码不能小于5位'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
loginForm: {
|
||||
username: 'admin',
|
||||
password: 'admin'
|
||||
},
|
||||
loginRules: {
|
||||
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
||||
password: [{ required: true, trigger: 'blur', validator: validatePass }]
|
||||
},
|
||||
loading: false,
|
||||
pwdType: 'password',
|
||||
redirect: undefined
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// $route: {
|
||||
// handler: function (route) {
|
||||
// this.redirect = route.query && route.query.redirect
|
||||
// },
|
||||
// immediate: true
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
showPwd () {
|
||||
if (this.pwdType === 'password') {
|
||||
this.pwdType = ''
|
||||
} else {
|
||||
this.pwdType = 'password'
|
||||
}
|
||||
},
|
||||
handleLogin () {
|
||||
this.$router.push('/')
|
||||
|
||||
// this.$refs.loginForm.validate(valid => {
|
||||
// if (valid) {
|
||||
// this.loading = true
|
||||
// this.$store.dispatch('Login', this.loginForm).then(() => {
|
||||
// this.loading = false
|
||||
// this.$router.push({ path: this.redirect || '/' })
|
||||
// }).catch(() => {
|
||||
// this.loading = false
|
||||
// })
|
||||
// } else {
|
||||
// console.log('error submit!!')
|
||||
// return false
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss">
|
||||
$bg: #2d3a4b;
|
||||
$light_gray: #eee;
|
||||
|
||||
/* reset element-ui css */
|
||||
.login-container {
|
||||
.el-input {
|
||||
display: inline-block;
|
||||
height: 47px;
|
||||
width: 85%;
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
border: 0px;
|
||||
-webkit-appearance: none;
|
||||
border-radius: 0px;
|
||||
padding: 12px 5px 12px 15px;
|
||||
color: $light_gray;
|
||||
height: 47px;
|
||||
|
||||
&:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
|
||||
-webkit-text-fill-color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
color: #454545;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
$bg: #2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #eee;
|
||||
.login-container {
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: $bg;
|
||||
|
||||
.login-form {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 520px;
|
||||
max-width: 100%;
|
||||
padding: 35px 35px 15px 35px;
|
||||
margin: 120px auto;
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
|
||||
span {
|
||||
&:first-of-type {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.svg-container {
|
||||
padding: 6px 5px 6px 15px;
|
||||
color: $dark_gray;
|
||||
vertical-align: middle;
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 26px;
|
||||
font-weight: 400;
|
||||
color: $light_gray;
|
||||
margin: 0px auto 40px auto;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.show-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 7px;
|
||||
font-size: 16px;
|
||||
color: $dark_gray;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template >
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template >
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template >
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-1" type="success">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template >
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-1" type="success">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2" type="success">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2" type="success">
|
||||
<router-view />
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2-1" type="warning" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2-1" type="warning" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2-2" type="warning" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-2-2" type="warning" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-3" type="success" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template functional>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 1-3" type="success" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 2" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div style="padding:30px;">
|
||||
<el-alert :closable="false" title="menu 2" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--selector-->
|
||||
<div class="selector">
|
||||
<label class="label">{{$t('Node')}}: </label>
|
||||
<el-select v-model="nodeForm._id" @change="onNodeChange">
|
||||
<el-option v-for="op in nodeList" :key="op._id" :value="op._id" :label="op.name"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTabName" @tab-click="onTabClick" type="card">
|
||||
<el-tab-pane :label="$t('Overview')" name="overview">
|
||||
<node-overview></node-overview>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Deployed Spiders')" name="spiders" v-if="false">
|
||||
{{$t('Deployed Spiders')}}
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import NodeOverview from '../../components/Overview/NodeOverview'
|
||||
|
||||
export default {
|
||||
name: 'NodeDetail',
|
||||
components: {
|
||||
NodeOverview
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeTabName: 'overview'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('node', [
|
||||
'nodeList',
|
||||
'nodeForm'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
onTabClick () {
|
||||
},
|
||||
onNodeChange (id) {
|
||||
this.$router.push(`/nodes/${id}`)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// get list of nodes
|
||||
this.$store.dispatch('node/getNodeList')
|
||||
|
||||
// get node basic info
|
||||
this.$store.dispatch('node/getNodeData', this.$route.params.id)
|
||||
|
||||
// get node deploy list
|
||||
this.$store.dispatch('node/getDeployList', this.$route.params.id)
|
||||
|
||||
// get node task list
|
||||
this.$store.dispatch('node/getTaskList', this.$route.params.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
margin-top: -7px;
|
||||
/*float: right;*/
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.selector .el-select {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.selector {
|
||||
.el-select {
|
||||
.el-input {
|
||||
.el-input_inner {
|
||||
height: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,95 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--selector-->
|
||||
<div class="selector">
|
||||
<label class="label">Spider: </label>
|
||||
<el-select v-model="spiderForm._id" @change="onSpiderChange">
|
||||
<el-option v-for="op in spiderList" :key="op._id" :value="op._id" :label="op.name"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTabName" @tab-click="onTabClick" type="card">
|
||||
<el-tab-pane label="Overview" name="overview">
|
||||
<spider-overview/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Files" name="files">
|
||||
<file-list/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import FileList from '../../components/FileList/FileList'
|
||||
import SpiderOverview from '../../components/Overview/SpiderOverview'
|
||||
|
||||
export default {
|
||||
name: 'NodeDetail',
|
||||
components: {
|
||||
FileList,
|
||||
SpiderOverview
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeTabName: 'overview'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('spider', [
|
||||
'spiderList',
|
||||
'spiderForm'
|
||||
]),
|
||||
...mapState('file', [
|
||||
'currentPath'
|
||||
]),
|
||||
...mapState('deploy', [
|
||||
'deployList'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
onTabClick () {
|
||||
},
|
||||
onSpiderChange (id) {
|
||||
this.$router.push(`/spiders/${id}`)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// get the list of the spiders
|
||||
this.$store.dispatch('spider/getSpiderList')
|
||||
|
||||
// get spider basic info
|
||||
this.$store.dispatch('spider/getSpiderData', this.$route.params.id)
|
||||
.then(() => {
|
||||
// get spider file info
|
||||
this.$store.dispatch('file/getFileList', this.spiderForm.src)
|
||||
})
|
||||
|
||||
// get spider deploys
|
||||
this.$store.dispatch('spider/getDeployList', this.$route.params.id)
|
||||
|
||||
// get spider tasks
|
||||
this.$store.dispatch('spider/getTaskList', this.$route.params.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
/*float: right;*/
|
||||
z-index: 999;
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
.selector .el-select {
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
Schedule List
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ScheduleList'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,99 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--selector-->
|
||||
<div class="selector">
|
||||
<label class="label">{{$t('Spider')}}: </label>
|
||||
<el-select v-model="spiderForm._id" @change="onSpiderChange">
|
||||
<el-option v-for="op in spiderList" :key="op._id" :value="op._id" :label="op.name"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTabName" @tab-click="onTabClick" type="card">
|
||||
<el-tab-pane :label="$t('Overview')" name="overview">
|
||||
<spider-overview/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Files')" name="files">
|
||||
<file-list/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import FileList from '../../components/FileList/FileList'
|
||||
import SpiderOverview from '../../components/Overview/SpiderOverview'
|
||||
|
||||
export default {
|
||||
name: 'NodeDetail',
|
||||
components: {
|
||||
FileList,
|
||||
SpiderOverview
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeTabName: 'overview'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('spider', [
|
||||
'spiderList',
|
||||
'spiderForm'
|
||||
]),
|
||||
...mapState('file', [
|
||||
'currentPath'
|
||||
]),
|
||||
...mapState('deploy', [
|
||||
'deployList'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
onTabClick () {
|
||||
},
|
||||
onSpiderChange (id) {
|
||||
this.$router.push(`/spiders/${id}`)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// get the list of the spiders
|
||||
this.$store.dispatch('spider/getSpiderList')
|
||||
|
||||
// get spider basic info
|
||||
this.$store.dispatch('spider/getSpiderData', this.$route.params.id)
|
||||
.then(() => {
|
||||
// get spider file info
|
||||
this.$store.dispatch('file/getFileList', this.spiderForm.src)
|
||||
})
|
||||
|
||||
// get spider deploys
|
||||
this.$store.dispatch('spider/getDeployList', this.$route.params.id)
|
||||
|
||||
// get spider tasks
|
||||
this.$store.dispatch('spider/getTaskList', this.$route.params.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
/*float: right;*/
|
||||
z-index: 999;
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
.selector .el-select {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.label {
|
||||
text-align: right;
|
||||
width: 80px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,78 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row>
|
||||
<el-table-column align="center" label="ID" width="95">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Title">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.author }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Pageviews" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.pageviews }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column class-name="status-col" label="Status" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="created_at" label="Display_time" width="200">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time"/>
|
||||
<span>{{ scope.row.display_time }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getList } from '@/api/table'
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
statusFilter (status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
this.listLoading = true
|
||||
getList(this.listQuery).then(response => {
|
||||
this.list = response.data.items
|
||||
this.listLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,78 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row>
|
||||
<el-table-column align="center" label="ID" width="95">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Title">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.author }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Pageviews" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.pageviews }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column class-name="status-col" label="Status" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="created_at" label="Display_time" width="200">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time"/>
|
||||
<span>{{ scope.row.display_time }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getList } from '@/api/table'
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
statusFilter (status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
this.listLoading = true
|
||||
getList(this.listQuery).then(response => {
|
||||
this.list = response.data.items
|
||||
this.listLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTabName" @tab-click="onTabClick" type="card">
|
||||
<el-tab-pane :label="$t('Overview')" name="overview">
|
||||
<task-overview/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Log')" name="log">
|
||||
<div class="log-view">
|
||||
<pre>
|
||||
{{taskLog}}
|
||||
</pre>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Results')" name="results">
|
||||
<general-table-view :data="taskResultsData"
|
||||
:columns="taskResultsColumns"
|
||||
:page-num="resultsPageNum"
|
||||
:page-size="resultsPageSize"
|
||||
:total="taskResultsTotalCount"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import TaskOverview from '../../components/Overview/TaskOverview'
|
||||
import GeneralTableView from '../../components/TableView/GeneralTableView'
|
||||
|
||||
export default {
|
||||
name: 'TaskDetail',
|
||||
components: {
|
||||
GeneralTableView,
|
||||
TaskOverview
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeTabName: 'overview'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('task', [
|
||||
'taskLog',
|
||||
'taskResultsData',
|
||||
'taskResultsColumns',
|
||||
'taskResultsTotalCount'
|
||||
]),
|
||||
...mapState('file', [
|
||||
'currentPath'
|
||||
]),
|
||||
...mapState('deploy', [
|
||||
'deployList'
|
||||
]),
|
||||
resultsPageNum: {
|
||||
get () {
|
||||
return this.$store.state.task.resultsPageNum
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_NUM', value)
|
||||
}
|
||||
},
|
||||
resultsPageSize: {
|
||||
get () {
|
||||
return this.$store.state.task.resultsPageSize
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_SIZE', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onTabClick () {
|
||||
},
|
||||
onSpiderChange (id) {
|
||||
this.$router.push(`/spiders/${id}`)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.$store.dispatch('task/getTaskData', this.$route.params.id)
|
||||
this.$store.dispatch('task/getTaskLog', this.$route.params.id)
|
||||
this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
/*float: right;*/
|
||||
z-index: 999;
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
.selector .el-select {
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;"/>
|
||||
|
||||
<el-tree
|
||||
ref="tree2"
|
||||
:data="data2"
|
||||
:props="defaultProps"
|
||||
:filter-node-method="filterNode"
|
||||
class="filter-tree"
|
||||
default-expand-all
|
||||
/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
data () {
|
||||
return {
|
||||
filterText: '',
|
||||
data2: [{
|
||||
id: 1,
|
||||
label: 'Level one 1',
|
||||
children: [{
|
||||
id: 4,
|
||||
label: 'Level two 1-1',
|
||||
children: [{
|
||||
id: 9,
|
||||
label: 'Level three 1-1-1'
|
||||
}, {
|
||||
id: 10,
|
||||
label: 'Level three 1-1-2'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
id: 2,
|
||||
label: 'Level one 2',
|
||||
children: [{
|
||||
id: 5,
|
||||
label: 'Level two 2-1'
|
||||
}, {
|
||||
id: 6,
|
||||
label: 'Level two 2-2'
|
||||
}]
|
||||
}, {
|
||||
id: 3,
|
||||
label: 'Level one 3',
|
||||
children: [{
|
||||
id: 7,
|
||||
label: 'Level two 3-1'
|
||||
}, {
|
||||
id: 8,
|
||||
label: 'Level two 3-2'
|
||||
}]
|
||||
}],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
filterText (val) {
|
||||
this.$refs.tree2.filter(val)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
filterNode (value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;"/>
|
||||
|
||||
<el-tree
|
||||
ref="tree2"
|
||||
:data="data2"
|
||||
:props="defaultProps"
|
||||
:filter-node-method="filterNode"
|
||||
class="filter-tree"
|
||||
default-expand-all
|
||||
/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
data () {
|
||||
return {
|
||||
filterText: '',
|
||||
data2: [{
|
||||
id: 1,
|
||||
label: 'Level one 1',
|
||||
children: [{
|
||||
id: 4,
|
||||
label: 'Level two 1-1',
|
||||
children: [{
|
||||
id: 9,
|
||||
label: 'Level three 1-1-1'
|
||||
}, {
|
||||
id: 10,
|
||||
label: 'Level three 1-1-2'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
id: 2,
|
||||
label: 'Level one 2',
|
||||
children: [{
|
||||
id: 5,
|
||||
label: 'Level two 2-1'
|
||||
}, {
|
||||
id: 6,
|
||||
label: 'Level two 2-2'
|
||||
}]
|
||||
}, {
|
||||
id: 3,
|
||||
label: 'Level one 3',
|
||||
children: [{
|
||||
id: 7,
|
||||
label: 'Level two 3-1'
|
||||
}, {
|
||||
id: 8,
|
||||
label: 'Level two 3-2'
|
||||
}]
|
||||
}],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
filterText (val) {
|
||||
this.$refs.tree2.filter(val)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
filterNode (value, data) {
|
||||
if (!value) return true
|
||||
return data.label.indexOf(value) !== -1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user