mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-22 17:31:03 +01:00
加入前端可配置编辑器
This commit is contained in:
@@ -6,6 +6,7 @@ type Field struct {
|
||||
Xpath string `yaml:"xpath" json:"xpath"`
|
||||
Attr string `yaml:"attr" json:"attr"`
|
||||
NextStage string `yaml:"next_stage" json:"next_stage"`
|
||||
Remark string `yaml:"remark" json:"remark"`
|
||||
}
|
||||
|
||||
type Stage struct {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"cross-env": "^5.2.0",
|
||||
"dayjs": "^1.8.6",
|
||||
"echarts": "^4.1.0",
|
||||
"element-ui": "2.4.6",
|
||||
"element-ui": "2.13.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"js-cookie": "2.2.0",
|
||||
"normalize.css": "7.0.0",
|
||||
|
||||
@@ -42,97 +42,159 @@
|
||||
|
||||
<!--config detail-->
|
||||
<el-row>
|
||||
<el-form label-width="150px" ref="form" :model="spiderForm">
|
||||
<el-form label-width="150px" ref="form" :model="spiderForm.config">
|
||||
<el-col :span="11" :offset="1">
|
||||
<el-form-item :label="$t('Crawl Type')">
|
||||
<el-button-group>
|
||||
<el-button v-for="type in crawlTypeList"
|
||||
:key="type.value"
|
||||
:type="type.value === spiderForm.crawl_type ? 'primary' : ''"
|
||||
@click="onSelectCrawlType(type.value)">
|
||||
{{$t(type.label)}}
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Start URL')" prop="start_url" required>
|
||||
<el-input v-model="spiderForm.start_url" :placeholder="$t('Start URL')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Obey robots.txt')">
|
||||
<el-switch v-model="spiderForm.obey_robots_txt" :placeholder="$t('Obey robots.txt')"></el-switch>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item :label="$t('Crawl Type')">-->
|
||||
<!-- <el-button-group>-->
|
||||
<!-- <el-button v-for="type in crawlTypeList"-->
|
||||
<!-- :key="type.value"-->
|
||||
<!-- :type="type.value === spiderForm.crawl_type ? 'primary' : ''"-->
|
||||
<!-- @click="onSelectCrawlType(type.value)">-->
|
||||
<!-- {{$t(type.label)}}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </el-button-group>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item :label="$t('Start URL')" prop="start_url" required>-->
|
||||
<!-- <el-input v-model="spiderForm.config.start_url" :placeholder="$t('Start URL')"></el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item :label="$t('Obey robots.txt')">-->
|
||||
<!-- <el-switch v-model="spiderForm.obey_robots_txt" :placeholder="$t('Obey robots.txt')"></el-switch>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!--<el-form-item :label="$t('URL Pattern')">-->
|
||||
<!--<el-input v-model="spiderForm.url_pattern" :placeholder="$t('URL Pattern')"></el-input>-->
|
||||
<!--</el-form-item>-->
|
||||
</el-col>
|
||||
<el-col :span="11" :offset="1">
|
||||
<el-form-item :label="$t('Item Selector')"
|
||||
v-if="['list','list-detail'].includes(spiderForm.crawl_type)">
|
||||
<el-select style="width: 35%;margin-right: 10px;"
|
||||
v-model="spiderForm.item_selector_type"
|
||||
:placeholder="$t('Item Selector Type')">
|
||||
<el-option value="xpath" :label="$t('XPath')"></el-option>
|
||||
<el-option value="css" :label="$t('CSS')"></el-option>
|
||||
</el-select>
|
||||
<el-input style="width: calc(65% - 10px);"
|
||||
v-model="spiderForm.item_selector"
|
||||
:placeholder="$t('Item Selector')">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Pagination Selector')"
|
||||
v-if="['list','list-detail'].includes(spiderForm.crawl_type)">
|
||||
<el-select style="width: 35%;margin-right: 10px;"
|
||||
v-model="spiderForm.pagination_selector_type"
|
||||
:placeholder="$t('Pagination Selector Type')">
|
||||
<el-option value="xpath" :label="$t('XPath')"></el-option>
|
||||
<el-option value="css" :label="$t('CSS')"></el-option>
|
||||
</el-select>
|
||||
<el-input style="width: calc(65% - 10px);"
|
||||
v-model="spiderForm.pagination_selector"
|
||||
:placeholder="$t('Pagination Selector')">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Item Threshold')"
|
||||
v-if="['list','list-detail'].includes(spiderForm.crawl_type)">
|
||||
<el-input-number v-model="spiderForm.item_threshold"/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item :label="$t('Item Selector')"-->
|
||||
<!-- v-if="['list','list-detail'].includes(spiderForm.crawl_type)">-->
|
||||
<!-- <el-select style="width: 35%;margin-right: 10px;"-->
|
||||
<!-- v-model="spiderForm.item_selector_type"-->
|
||||
<!-- :placeholder="$t('Item Selector Type')">-->
|
||||
<!-- <el-option value="xpath" :label="$t('XPath')"></el-option>-->
|
||||
<!-- <el-option value="css" :label="$t('CSS')"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- <el-input style="width: calc(65% - 10px);"-->
|
||||
<!-- v-model="spiderForm.item_selector"-->
|
||||
<!-- :placeholder="$t('Item Selector')">-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item :label="$t('Pagination Selector')"-->
|
||||
<!-- v-if="['list','list-detail'].includes(spiderForm.crawl_type)">-->
|
||||
<!-- <el-select style="width: 35%;margin-right: 10px;"-->
|
||||
<!-- v-model="spiderForm.page"-->
|
||||
<!-- :placeholder="$t('Pagination Selector Type')">-->
|
||||
<!-- <el-option value="xpath" :label="$t('XPath')"></el-option>-->
|
||||
<!-- <el-option value="css" :label="$t('CSS')"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- <el-input style="width: calc(65% - 10px);"-->
|
||||
<!-- v-model="spiderForm.pagination_selector"-->
|
||||
<!-- :placeholder="$t('Pagination Selector')">-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item :label="$t('Item Threshold')"-->
|
||||
<!-- v-if="['list','list-detail'].includes(spiderForm.crawl_type)">-->
|
||||
<!-- <el-input-number v-model="spiderForm.item_threshold"/>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-col>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<!--./config detail-->
|
||||
|
||||
<!--button group-->
|
||||
<el-row class="button-group-container">
|
||||
<div class="button-group">
|
||||
<el-button type="danger" @click="onCrawl">{{$t('Run')}}</el-button>
|
||||
<el-button type="primary" @click="onExtractFields" v-loading="extractFieldsLoading">{{$t('Extract Fields')}}
|
||||
</el-button>
|
||||
<el-button type="warning" @click="onPreview" v-loading="previewLoading">{{$t('Preview')}}</el-button>
|
||||
<el-button type="success" @click="onSave" v-loading="saveLoading">{{$t('Save')}}</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--./button group-->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-row>
|
||||
<span class="selector-type-item" @click="onClickSelectorType('css')">
|
||||
<el-tag
|
||||
:class="isCss ? 'active' : 'inactive'"
|
||||
type="success"
|
||||
>
|
||||
CSS
|
||||
</el-tag>
|
||||
</span>
|
||||
<span class="selector-type-item" @click="onClickSelectorType('xpath')">
|
||||
<el-tag
|
||||
:class="isXpath ? 'active' : 'inactive'"
|
||||
type="primary"
|
||||
>
|
||||
XPath
|
||||
</el-tag>
|
||||
</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
|
||||
<!--list field list-->
|
||||
<el-row v-if="['list','list-detail'].includes(spiderForm.crawl_type)"
|
||||
class="list-fields-container">
|
||||
<fields-table-view
|
||||
type="list"
|
||||
title="List Page Fields"
|
||||
:fields="spiderForm.fields"
|
||||
/>
|
||||
<el-col :span="12">
|
||||
<!--button group-->
|
||||
<el-row class="button-group-container">
|
||||
<div class="button-group">
|
||||
<el-button type="danger" @click="onCrawl">{{$t('Run')}}</el-button>
|
||||
<el-button type="primary" @click="onExtractFields" v-loading="extractFieldsLoading">{{$t('Extract Fields')}}
|
||||
</el-button>
|
||||
<el-button type="warning" @click="onPreview" v-loading="previewLoading">{{$t('Preview')}}</el-button>
|
||||
<el-button type="success" @click="onSave" v-loading="saveLoading">{{$t('Save')}}</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--./button group-->
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-collapse
|
||||
v-model="activeNames"
|
||||
>
|
||||
<el-collapse-item
|
||||
v-for="(stage, stageName) in spiderForm.config.stages"
|
||||
:key="stageName"
|
||||
>
|
||||
<template slot="title">
|
||||
{{stageName}}
|
||||
</template>
|
||||
<fields-table-view
|
||||
type="list"
|
||||
title="List Page Fields"
|
||||
:fields="stage.fields"
|
||||
:stage-names="Object.keys(spiderForm.config.stages)"
|
||||
/>
|
||||
<!-- <el-table-->
|
||||
<!-- :data="stage.fields"-->
|
||||
<!-- >-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- v-for="fCol in fieldColumns"-->
|
||||
<!-- :key="fCol.name"-->
|
||||
<!-- :label="$t(fCol.label)"-->
|
||||
<!-- >-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- <template v-if="fCol.name === 'selector_type'">-->
|
||||
<!-- <el-tag :class="scope.row.css ? 'active' : 'inactive'" type="success">CSS</el-tag>-->
|
||||
<!-- <el-tag :class="scope.row.xpath ? 'active' : 'inactive'" type="primary">XPath</el-tag>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template v-else>-->
|
||||
<!-- {{scope.row[fCol.name]}}-->
|
||||
<!-- </template>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<!--list field list-->
|
||||
<!-- <el-row v-if="['list','list-detail'].includes(spiderForm.crawl_type)"-->
|
||||
<!-- class="list-fields-container">-->
|
||||
<!-- <fields-table-view-->
|
||||
<!-- type="list"-->
|
||||
<!-- title="List Page Fields"-->
|
||||
<!-- :fields="spiderForm.fields"-->
|
||||
<!-- />-->
|
||||
<!-- </el-row>-->
|
||||
<!--./list field list-->
|
||||
|
||||
<!--detail field list-->
|
||||
<el-row v-if="['detail','list-detail'].includes(spiderForm.crawl_type)"
|
||||
class="detail-fields-container"
|
||||
style="margin-top: 10px;">
|
||||
<fields-table-view
|
||||
type="detail"
|
||||
title="Detail Page Fields"
|
||||
:fields="spiderForm.detail_fields"
|
||||
/>
|
||||
</el-row>
|
||||
<!-- <el-row v-if="['detail','list-detail'].includes(spiderForm.crawl_type)"-->
|
||||
<!-- class="detail-fields-container"-->
|
||||
<!-- style="margin-top: 10px;">-->
|
||||
<!-- <fields-table-view-->
|
||||
<!-- type="detail"-->
|
||||
<!-- title="Detail Page Fields"-->
|
||||
<!-- :fields="spiderForm.detail_fields"-->
|
||||
<!-- />-->
|
||||
<!-- </el-row>-->
|
||||
<!--./detail field list-->
|
||||
</div>
|
||||
</template>
|
||||
@@ -146,9 +208,13 @@ import CrawlConfirmDialog from '../Common/CrawlConfirmDialog'
|
||||
|
||||
export default {
|
||||
name: 'ConfigList',
|
||||
components: { CrawlConfirmDialog, FieldsTableView },
|
||||
components: {
|
||||
CrawlConfirmDialog,
|
||||
FieldsTableView
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeNames: [],
|
||||
crawlTypeList: [
|
||||
{ value: 'list', label: 'List Only' },
|
||||
{ value: 'detail', label: 'Detail Only' },
|
||||
@@ -159,7 +225,15 @@ export default {
|
||||
saveLoading: false,
|
||||
dialogVisible: false,
|
||||
crawlConfirmDialogVisible: false,
|
||||
columnsDict: {}
|
||||
columnsDict: {},
|
||||
fieldColumns: [
|
||||
{ name: 'name', label: 'Name' },
|
||||
{ name: 'selector_type', label: 'Selector Type' },
|
||||
{ name: 'selector', label: 'Selector' },
|
||||
{ name: 'is_attr', label: 'Is Attribute' },
|
||||
{ name: 'attr', label: 'Attribute' },
|
||||
{ name: 'next_stage', label: 'Next Stage' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -177,6 +251,24 @@ export default {
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
},
|
||||
isCss () {
|
||||
let i = 0
|
||||
Object.values(this.spiderForm.config.stages).forEach(stage => {
|
||||
stage.fields.forEach(field => {
|
||||
if (!field.css) i++
|
||||
})
|
||||
})
|
||||
return i === 0
|
||||
},
|
||||
isXpath () {
|
||||
let i = 0
|
||||
Object.values(this.spiderForm.config.stages).forEach(stage => {
|
||||
stage.fields.forEach(field => {
|
||||
if (!field.xpath) i++
|
||||
})
|
||||
})
|
||||
return i === 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -294,7 +386,20 @@ export default {
|
||||
value = value.trim()
|
||||
if (value.length > 20) return value.substr(0, 20) + '...'
|
||||
return value
|
||||
}
|
||||
},
|
||||
onClickSelectorType (selectorType) {
|
||||
Object.values(this.spiderForm.config.stages).forEach(stage => {
|
||||
stage.fields.forEach(field => {
|
||||
if (selectorType === 'css') {
|
||||
if (field.xpath) field.xpath = ''
|
||||
if (!field.css) field.css = 'body'
|
||||
} else {
|
||||
if (field.css) field.css = ''
|
||||
if (!field.xpath) field.xpath = '//body'
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
created () {
|
||||
// fields for list page
|
||||
@@ -327,6 +432,9 @@ export default {
|
||||
if (!this.spiderForm.pagination_selector_type) this.$set(this.spiderForm, 'pagination_selector_type', 'css')
|
||||
if (this.spiderForm.obey_robots_txt == null) this.$set(this.spiderForm, 'obey_robots_txt', true)
|
||||
if (this.spiderForm.item_threshold == null) this.$set(this.spiderForm, 'item_threshold', 10)
|
||||
},
|
||||
mounted () {
|
||||
this.activeNames = Object.keys(this.spiderForm.config.stages)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -335,7 +443,7 @@ export default {
|
||||
|
||||
.button-group-container {
|
||||
margin-top: 10px;
|
||||
border-bottom: 1px dashed #dcdfe6;
|
||||
/*border-bottom: 1px dashed #dcdfe6;*/
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
@@ -345,7 +453,7 @@ export default {
|
||||
|
||||
.list-fields-container {
|
||||
margin-top: 20px;
|
||||
border-bottom: 1px dashed #dcdfe6;
|
||||
/*border-bottom: 1px dashed #dcdfe6;*/
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
@@ -369,4 +477,17 @@ export default {
|
||||
.el-table.table-header >>> .el-input .el-input__inner {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.selector-type-item {
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector-type-item > .el-tag.active {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.selector-type-item > .el-tag.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,73 +1,104 @@
|
||||
<template>
|
||||
<div class="fields-table-view">
|
||||
<el-row class="button-group-container">
|
||||
<label class="title">{{$t(this.title)}}</label>
|
||||
<div class="button-group">
|
||||
<el-button type="primary" size="small" @click="addField" icon="el-icon-plus">{{$t('Add Field')}}</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<!-- <el-row class="button-group-container">-->
|
||||
<!-- <label class="title">{{$t(this.title)}}</label>-->
|
||||
<!-- <div class="button-group">-->
|
||||
<!-- <el-button type="primary" size="small" @click="addField" icon="el-icon-plus">{{$t('Add Field')}}</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-row>-->
|
||||
<el-row>
|
||||
<el-table :data="fields"
|
||||
class="table edit"
|
||||
:header-cell-style="{background:'rgb(48, 65, 86)',color:'white'}"
|
||||
border>
|
||||
<el-table-column v-if="type === 'list' && spiderForm.crawl_type === 'list-detail'"
|
||||
:label="$t('Detail Page URL')"
|
||||
align="center">
|
||||
>
|
||||
<el-table-column class-name="action" width="80px" align="right">
|
||||
<template slot-scope="scope">
|
||||
<el-checkbox v-model="scope.row.is_detail"
|
||||
@change="onCheck(scope.row)">
|
||||
</el-checkbox>
|
||||
<i class="action-item el-icon-copy-document" @click="onCopyField(scope.row)"></i>
|
||||
<i class="action-item el-icon-remove-outline" @click="onRemoveField(scope.row)"></i>
|
||||
<i class="action-item el-icon-circle-plus-outline" @click="onAddField(scope.row)"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Field Name')" width="200px">
|
||||
<el-table-column :label="$t('Field Name')" width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.name" :placeholder="$t('Field Name')"
|
||||
@change="onNameChange(scope.row)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Query Type')" width="200px">
|
||||
<el-table-column :label="$t('Selector Type')" width="150px" align="center" class-name="selector-type">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.type" :placeholder="$t('Query Type')">
|
||||
<el-option value="css" :label="$t('CSS Selector')"></el-option>
|
||||
<el-option value="xpath" :label="$t('XPath')"></el-option>
|
||||
</el-select>
|
||||
<span class="button-selector-item" @click="onClickSelectorType(scope.row, 'css')">
|
||||
<el-tag
|
||||
:class="scope.row.css ? 'active' : 'inactive'"
|
||||
type="success"
|
||||
>
|
||||
CSS
|
||||
</el-tag>
|
||||
</span>
|
||||
<span class="button-selector-item" @click="onClickSelectorType(scope.row, 'xpath')">
|
||||
<el-tag
|
||||
:class="scope.row.xpath ? 'active' : 'inactive'"
|
||||
type="primary"
|
||||
>
|
||||
XPath
|
||||
</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Query')" width="250px">
|
||||
<el-table-column :label="$t('Selector')" width="200px">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.query" :placeholder="$t('Query')"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Extract Type')" width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.extract_type" :placeholder="$t('Extract Type')">
|
||||
<el-option value="text" :label="$t('Text')"></el-option>
|
||||
<el-option value="attribute" :label="$t('Attribute')"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Attribute')" width="250px">
|
||||
<template slot-scope="scope">
|
||||
<template v-if="scope.row.extract_type === 'attribute'">
|
||||
<el-input v-model="scope.row.attribute"
|
||||
:placeholder="$t('Attribute')">
|
||||
</el-input>
|
||||
<template v-if="scope.row.css">
|
||||
<el-input v-model="scope.row.css" :placeholder="$t('CSS')"></el-input>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input v-model="scope.row.xpath" :placeholder="$t('XPath')"></el-input>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Action')" fixed="right" min-width="100px">
|
||||
<el-table-column :label="$t('Is Attribute')" width="150px" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div class="action-button-group">
|
||||
<el-button size="mini"
|
||||
style="margin-left:10px"
|
||||
icon="el-icon-delete"
|
||||
type="danger"
|
||||
@click="deleteField(scope.$index)">
|
||||
</el-button>
|
||||
</div>
|
||||
<span class="button-selector-item" @click="onClickIsAttribute(scope.row, false)">
|
||||
<el-tag
|
||||
:class="!scope.row.attr ? 'active' : 'inactive'"
|
||||
type="success"
|
||||
>
|
||||
{{$t('Text')}}
|
||||
</el-tag>
|
||||
</span>
|
||||
<span class="button-selector-item" @click="onClickIsAttribute(scope.row, true)">
|
||||
<el-tag
|
||||
:class="scope.row.attr ? 'active' : 'inactive'"
|
||||
type="primary"
|
||||
>
|
||||
{{$t('Attribute')}}
|
||||
</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Attribute')" width="200px">
|
||||
<template slot-scope="scope">
|
||||
<template v-if="scope.row.attr">
|
||||
<el-input v-model="scope.row.attr" :placeholder="$t('Attribute')"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span style="margin-left: 15px">
|
||||
N/A
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Next Stage')" width="250px">
|
||||
<template slot-scope="scope">
|
||||
<el-select
|
||||
v-model="scope.row.next_stage"
|
||||
>
|
||||
<el-option :label="$t('No Next Stage')" value=""/>
|
||||
<el-option v-for="n in stageNames" :key="n" :label="n" :value="n"/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('Remark')" width="auto" min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" :placeholder="$t('Remark')"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -91,6 +122,12 @@ export default {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
stageNames: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
type: Array,
|
||||
default () {
|
||||
@@ -128,6 +165,57 @@ export default {
|
||||
}
|
||||
})
|
||||
this.$st.sendEv('爬虫详情-配置', '设置详情页URL')
|
||||
},
|
||||
onClickSelectorType (row, selectorType) {
|
||||
if (selectorType === 'css') {
|
||||
if (row.xpath) row.xpath = ''
|
||||
if (!row.css) row.css = 'body'
|
||||
} else {
|
||||
if (row.css) row.css = ''
|
||||
if (!row.xpath) row.xpath = '//body'
|
||||
}
|
||||
},
|
||||
onClickIsAttribute (row, isAttribute) {
|
||||
if (!isAttribute) {
|
||||
// 文本
|
||||
if (row.attr) row.attr = ''
|
||||
} else {
|
||||
// 属性
|
||||
if (!row.attr) row.attr = 'href'
|
||||
}
|
||||
},
|
||||
onCopyField (row) {
|
||||
for (let i = 0; i < this.fields.length; i++) {
|
||||
if (row.name === this.fields[i].name) {
|
||||
this.fields.splice(i, 0, JSON.parse(JSON.stringify(row)))
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
onRemoveField (row) {
|
||||
for (let i = 0; i < this.fields.length; i++) {
|
||||
if (row.name === this.fields[i].name) {
|
||||
this.fields.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (this.fields.length === 0) {
|
||||
this.fields.push({
|
||||
css: 'body',
|
||||
next_stage: ''
|
||||
})
|
||||
}
|
||||
},
|
||||
onAddField (row) {
|
||||
for (let i = 0; i < this.fields.length; i++) {
|
||||
if (row.name === this.fields[i].name) {
|
||||
this.fields.splice(i + 1, 0, {
|
||||
css: 'body',
|
||||
next_stage: ''
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,6 +246,50 @@ export default {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.el-table.edit >>> .button-selector-item {
|
||||
cursor: pointer;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.el-table.edit >>> .el-tag.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.el-table.edit >>> .action {
|
||||
background: none !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.el-table.edit >>> tr {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.el-table.edit >>> tr th {
|
||||
border-right: 1px solid rgb(220, 223, 230);
|
||||
}
|
||||
|
||||
.el-table.edit >>> tr td:nth-child(2) {
|
||||
border-left: 1px solid rgb(220, 223, 230);
|
||||
}
|
||||
|
||||
.el-table.edit >>> tr td {
|
||||
border-right: 1px solid rgb(220, 223, 230);
|
||||
}
|
||||
|
||||
.el-table.edit::before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.el-table.edit >>> .action-item {
|
||||
font-size: 14px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-table.edit >>> .action-item:last-child {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.button-group-container {
|
||||
/*display: inline-block;*/
|
||||
/*width: 100%;*/
|
||||
|
||||
@@ -111,17 +111,24 @@
|
||||
<div class="filter">
|
||||
<div class="left">
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-select clearable @change="onSpiderTypeChange" placeholder="爬虫类型" size="small" v-model="filter.type">
|
||||
<el-option v-for="item in types" :value="item.type" :key="item.type"
|
||||
:label="item.type === 'customized'? '自定义':item.type "/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <el-select clearable @change="onSpiderTypeChange" placeholder="爬虫类型" size="small" v-model="filter.type">-->
|
||||
<!-- <el-option v-for="item in types" :value="item.type" :key="item.type"-->
|
||||
<!-- :label="item.type === 'customized'? '自定义':item.type "/>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item>
|
||||
<el-input clearable @keyup.enter.native="onSearch" size="small" placeholder="名称" v-model="filter.keyword">
|
||||
<i slot="suffix" class="el-input__icon el-icon-search"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="small" type="success"
|
||||
class="btn refresh"
|
||||
@click="onRefresh">
|
||||
{{$t('Search')}}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
@@ -134,18 +141,13 @@
|
||||
@click="onAdd">
|
||||
{{$t('Add Spider')}}
|
||||
</el-button>
|
||||
<el-button size="small" type="success"
|
||||
icon="el-icon-refresh"
|
||||
class="btn refresh"
|
||||
@click="onRefresh">
|
||||
{{$t('Refresh')}}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!--./filter-->
|
||||
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTab" @tab-click="onClickTab">
|
||||
<el-tabs v-model="filter.type" @tab-click="onClickTab">
|
||||
<el-tab-pane :label="$t('All')" name="all"></el-tab-pane>
|
||||
<el-tab-pane :label="$t('Configurable')" name="configurable"></el-tab-pane>
|
||||
<el-tab-pane :label="$t('Customized')" name="customized"></el-tab-pane>
|
||||
@@ -282,10 +284,9 @@ export default {
|
||||
activeSpiderId: undefined,
|
||||
filter: {
|
||||
keyword: '',
|
||||
type: ''
|
||||
type: 'all'
|
||||
},
|
||||
types: [],
|
||||
// tableData,
|
||||
columns: [
|
||||
{ name: 'display_name', label: 'Name', width: '160', align: 'left' },
|
||||
{ name: 'type', label: 'Spider Type', width: '120' },
|
||||
@@ -297,8 +298,7 @@ export default {
|
||||
spiderFormRules: {
|
||||
name: [{ required: true, message: 'Required Field', trigger: 'change' }]
|
||||
},
|
||||
fileList: [],
|
||||
activeTab: 'all'
|
||||
fileList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -499,6 +499,10 @@ export default {
|
||||
this.onView(row)
|
||||
}
|
||||
},
|
||||
onClickTab (tab) {
|
||||
this.filter.type = tab.name
|
||||
this.getList()
|
||||
},
|
||||
getList () {
|
||||
let params = {
|
||||
pageNum: this.pagination.pageNum,
|
||||
|
||||
@@ -2954,9 +2954,10 @@ electron-to-chromium@^1.3.103:
|
||||
version "1.3.113"
|
||||
resolved "http://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9"
|
||||
|
||||
element-ui@2.4.6:
|
||||
version "2.4.6"
|
||||
resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.4.6.tgz#524d3d4cac0b68745dda87311ef0d8fe541b5fc4"
|
||||
element-ui@2.13.0:
|
||||
version "2.13.0"
|
||||
resolved "https://registry.npm.taobao.org/element-ui/download/element-ui-2.13.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felement-ui%2Fdownload%2Felement-ui-2.13.0.tgz#f6bb04e5b0a76ea5f62466044b774407ba4ebd2d"
|
||||
integrity sha1-9rsE5bCnbqX2JGYES3dEB7pOvS0=
|
||||
dependencies:
|
||||
async-validator "~1.8.1"
|
||||
babel-helper-vue-jsx-merge-props "^2.0.0"
|
||||
|
||||
Reference in New Issue
Block a user