added site list

This commit is contained in:
Marvin Zhang
2019-05-09 22:14:37 +08:00
parent e3d4796d8a
commit 0ad0303285
6 changed files with 299 additions and 24 deletions

View File

@@ -9,6 +9,7 @@ from flask import Flask
from flask_cors import CORS
from flask_restful import Api
# from flask_restplus import Api
from routes.sites import SiteApi
from utils.log import other
from constants.node import NodeStatus
from db.manager import db_manager
@@ -68,6 +69,9 @@ api.add_resource(StatsApi,
api.add_resource(ScheduleApi,
'/api/schedules',
'/api/schedules/<string:id>')
api.add_resource(SiteApi,
'/api/sites',
'/api/sites/<string:id>')
def monitor_nodes_status(celery_app):

64
crawlab/routes/sites.py Normal file
View File

@@ -0,0 +1,64 @@
import json
from bson import ObjectId
from pymongo import ASCENDING
from db.manager import db_manager
from routes.base import BaseApi
from utils import jsonify
class SiteApi(BaseApi):
col_name = 'sites'
arguments = (
('keyword', str),
('category', str),
)
def get(self, id: str = None, action: str = None):
# action by id
if action is not None:
if not hasattr(self, action):
return {
'status': 'ok',
'code': 400,
'error': 'action "%s" invalid' % action
}, 400
return getattr(self, action)(id)
elif id is not None:
site = db_manager.get(col_name=self.col_name, id=id)
return jsonify(site)
# list tasks
args = self.parser.parse_args()
page_size = args.get('page_size') or 10
page_num = args.get('page_num') or 1
filter_str = args.get('filter')
keyword = args.get('keyword')
filter_ = {}
if filter_str is not None:
filter_ = json.loads(filter_str)
if keyword is not None:
filter_['$or'] = [
{'description': {'$regex': keyword}},
{'name': {'$regex': keyword}}
]
items = db_manager.list(
col_name=self.col_name,
cond=filter_,
limit=page_size,
skip=page_size * (page_num - 1),
sort_key='rank',
sort_direction=ASCENDING
)
return {
'status': 'ok',
'total_count': db_manager.count(self.col_name, filter_),
'page_num': page_num,
'page_size': page_size,
'items': jsonify(items)
}

View File

@@ -36,7 +36,6 @@ class TaskApi(BaseApi):
'code': 400,
'error': 'action "%s" invalid' % action
}, 400
# other.info(f"到这了{action},{id}")
return getattr(self, action)(id)
elif id is not None:
@@ -78,9 +77,6 @@ class TaskApi(BaseApi):
sort_key='create_ts')
items = []
for task in tasks:
# celery tasks
# _task = db_manager.get('tasks_celery', id=task['_id'])
# get spider
_spider = db_manager.get(col_name='spiders', id=str(task['spider_id']))

View File

@@ -38,26 +38,6 @@
<el-option value="go" label="Go"></el-option>
</el-select>
</el-form-item>
<!--<el-form-item :label="$t('Schedule Enabled')">-->
<!--<el-switch v-model="spiderForm.cron_enabled" :disabled="isView">-->
<!--</el-switch>-->
<!--</el-form-item>-->
<!--<el-form-item :label="$t('Schedule Cron')" v-if="spiderForm.cron_enabled"-->
<!--prop="cron"-->
<!--:rules="cronRules"-->
<!--:inline-message="true">-->
<!--<template slot="label">-->
<!--<el-tooltip :content="$t('Cron Format: [second] [minute] [hour] [day of month] [month] [day of week]')"-->
<!--placement="top">-->
<!--<span>-->
<!--{{$t('Schedule Cron')}}-->
<!--<i class="fa fa-exclamation-circle"></i>-->
<!--</span>-->
<!--</el-tooltip>-->
<!--</template>-->
<!--<el-input v-model="spiderForm.cron" :placeholder="$t('Schedule Cron')"-->
<!--:disabled="isView"></el-input>-->
<!--</el-form-item>-->
</el-form>
</el-row>
<el-row class="button-container" v-if="!isView">

View File

@@ -0,0 +1,59 @@
import request from '../../api/request'
const state = {
tableData: [],
// filter
filter: {},
keyword: '',
// pagination
pageNum: 1,
pageSize: 10,
totalCount: 0
}
const getters = {}
const mutations = {
SET_KEYWORD (state, value) {
state.keyword = value
},
SET_TABLE_DATA (state, value) {
state.tableData = value
},
SET_PAGE_NUM (state, value) {
state.pageNum = value
},
SET_PAGE_SIZE (state, value) {
state.pageSize = value
},
SET_TOTAL_COUNT (state, value) {
state.totalCount = value
}
}
const actions = {
getSiteList ({ state, commit }) {
return request.get('/sites', {
page_num: state.pageNum,
page_size: state.pageSize,
keyword: state.keyword || undefined,
filter: {
category: state.filter.category || undefined
}
})
.then(response => {
commit('SET_TABLE_DATA', response.data.items)
commit('SET_TOTAL_COUNT', response.data.total_count)
})
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}

View File

@@ -0,0 +1,172 @@
<template>
<div class="app-container">
<!--filter-->
<div class="filter">
<el-input prefix-icon="el-icon-search"
:placeholder="$t('Search')"
class="filter-search"
v-model="keyword">
</el-input>
<el-button type="success"
icon="el-icon-refresh"
class="btn refresh"
@click="onSearch">
{{$t('Search')}}
</el-button>
</div>
<!--table list-->
<el-table :data="tableData"
class="table"
:header-cell-style="{background:'rgb(48, 65, 86)',color:'white'}"
border>
<template v-for="col in columns">
<el-table-column v-if="col.name === 'category'"
:key="col.name"
:label="$t(col.label)"
:width="col.width"
:align="col.align">
<template slot-scope="scope">
<el-select v-model="scope.row[col.name]" :placeholder="$t('Select')">
<el-option v-for="op in categoryList"
:key="op"
:value="op"
:label="op">
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column v-else
:key="col.name"
:property="col.name"
:label="$t(col.label)"
:sortable="col.sortable"
:align="col.align || 'center'"
:width="col.width">
</el-table-column>
</template>
<el-table-column :label="$t('Action')" align="left" width="200">
<template slot-scope="scope">
<el-tooltip :content="$t('View')" placement="top">
<el-button type="primary" icon="el-icon-search" size="mini" @click="onView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip :content="$t('Remove')" placement="top">
<el-button type="danger" icon="el-icon-delete" size="mini" @click="onRemove(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
@current-change="onPageChange"
@size-change="onPageChange"
:current-page.sync="pageNum"
:page-sizes="[10, 20, 50, 100]"
:page-size.sync="pageSize"
layout="sizes, prev, pager, next"
:total="totalCount">
</el-pagination>
</div>
</div>
</template>
<script>
import {
mapState
} from 'vuex'
export default {
name: 'SiteList',
data () {
return {
categoryList: [
'新闻',
'搜索引擎',
'综合',
'金融',
'购物',
'社交',
'视频',
'音乐',
'资讯',
'政企官网',
'其他'
],
columns: [
{ name: 'rank', label: 'Rank', align: 'center', width: '80' },
{ name: 'name', label: 'Name', align: 'left', width: '120' },
{ name: 'domain', label: 'Domain', align: 'left', width: '150' },
{ name: 'description', label: 'Description', align: 'left' },
{ name: 'category', label: 'Category', align: 'center', width: '180' }
]
}
},
computed: {
...mapState('site', [
'tableData',
'totalCount'
]),
keyword: {
get () {
return this.$store.state.site.keyword
},
set (value) {
this.$store.commit('site/SET_KEYWORD', value)
}
},
pageNum: {
get () {
return this.$store.state.site.pageNum
},
set (value) {
this.$store.commit('site/SET_PAGE_NUM', value)
}
},
pageSize: {
get () {
return this.$store.state.site.pageSize
},
set (value) {
this.$store.commit('site/SET_PAGE_SIZE', value)
}
}
},
methods: {
onSearch () {
this.$store.dispatch('site/getSiteList')
},
onPageChange () {
this.$store.dispatch('site/getSiteList')
}
},
created () {
this.$store.dispatch('site/getSiteList')
}
}
</script>
<style scoped>
.filter {
display: flex;
}
.filter .filter-search {
width: 180px;
}
.filter .btn {
margin-left: 20px;
}
.table {
margin-top: 20px;
}
.table >>> .el-select .el-input__inner {
height: 32px;
}
.table >>> .el-select .el-select__caret {
line-height: 32px;
}
</style>