diff --git a/frontend/src/components/Config/ConfigList.vue b/frontend/src/components/Config/ConfigList.vue index cc405950..e54469a0 100644 --- a/frontend/src/components/Config/ConfigList.vue +++ b/frontend/src/components/Config/ConfigList.vue @@ -43,75 +43,63 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CSS - - - + + + + {{$t('Start URL')}}: + + + + {{$t('Start Stage')}}: + + + + + + {{$t('Engine')}}: + + + + + + {{$t('Selector Type')}}: + + + + CSS + + + - - + + + + - - - - - {{$t('Run')}} - {{$t('Extract Fields')}} - - {{$t('Preview')}} - {{$t('Save')}} - - - - + + + {{$t('Run')}} + {{$t('Extract Fields')}} + + {{$t('Preview')}} + {{$t('Save')}} + + d.name) + }, + startUrlClass () { + if (!this.spiderForm.config.start_url) { + return 'invalid' + } else if (!this.spiderForm.config.start_url.match(/^https?:\/\/.+|^\/\/.+/i)) { + return 'invalid' + } + + return '' + }, + startStageClass () { + if (!this.spiderForm.config.start_stage) { + return 'invalid' + } else if (!this.activeNames.includes(this.spiderForm.config.start_stage)) { + return 'invalid' + } + return '' } }, methods: { @@ -408,8 +411,27 @@ export default { const stages = JSON.parse(JSON.stringify(this.spiderForm.config.stages)) delete stages[stage.name] this.$set(this.spiderForm.config, 'stages', stages) + if (Object.keys(stages).length === 0) { + this.onAddStage() + } }, onAddStage (stage) { + const stages = JSON.parse(JSON.stringify(this.spiderForm.config.stages)) + const ts = Math.floor(new Date().getTime()).toString() + const newStageName = `stage_${ts}` + const newField = { name: `field_${ts}`, next_stage: '' } + if (this.isCss) { + newField['css'] = 'body' + } else if (this.isXpath) { + newField['xpath'] = '//body' + } else { + newField['css'] = 'body' + } + stages[newStageName] = { + name: newStageName, + fields: [newField] + } + this.$set(this.spiderForm.config, 'stages', stages) } }, created () { @@ -492,9 +514,6 @@ export default { .selector-type-item { margin: 0 5px; cursor: pointer; - } - - .selector-type-item > .el-tag.active { font-weight: bolder; } @@ -572,4 +591,39 @@ export default { height: 32px; line-height: 32px; } + + .top-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + } + + .top-wrapper .list { + list-style: none; + display: flex; + flex-wrap: wrap; + align-items: center; + padding: 0; + } + + .top-wrapper .list .item { + margin-bottom: 10px; + display: flex; + align-items: center; + } + + .top-wrapper .list .item label { + width: 100px; + text-align: right; + margin-right: 10px; + font-size: 12px; + } + + .top-wrapper .list .item label + * { + width: 240px; + } + + .invalid >>> .el-input__inner { + border: 1px solid red !important; + } diff --git a/frontend/src/components/TableView/FieldsTableView.vue b/frontend/src/components/TableView/FieldsTableView.vue index 7b1ef9f5..220deda8 100644 --- a/frontend/src/components/TableView/FieldsTableView.vue +++ b/frontend/src/components/TableView/FieldsTableView.vue @@ -10,6 +10,7 @@ @@ -20,8 +21,10 @@ - + @@ -47,10 +50,10 @@ - + - + @@ -168,20 +171,20 @@ export default { }, onClickSelectorType (row, selectorType) { if (selectorType === 'css') { - if (row.xpath) row.xpath = '' - if (!row.css) row.css = 'body' + if (row.xpath) this.$set(row, 'xpath', '') + if (!row.css) this.$set(row, 'css', 'body') } else { - if (row.css) row.css = '' - if (!row.xpath) row.xpath = '//body' + if (row.css) this.$set(row, 'css', '') + if (!row.xpath) this.$set(row, 'xpath', '//body') } }, onClickIsAttribute (row, isAttribute) { if (!isAttribute) { // 文本 - if (row.attr) row.attr = '' + if (row.attr) this.$set(row, 'attr', '') } else { // 属性 - if (!row.attr) row.attr = 'href' + if (!row.attr) this.$set(row, 'attr', 'href') } }, onCopyField (row) { @@ -210,12 +213,30 @@ export default { for (let i = 0; i < this.fields.length; i++) { if (row.name === this.fields[i].name) { this.fields.splice(i + 1, 0, { + name: `field_${Math.floor(new Date().getTime()).toString()}`, css: 'body', next_stage: '' }) break } } + }, + getCellClassStyle ({ row, columnIndex }) { + if (columnIndex === 1) { + // 字段名称 + if (!row.name) { + return { + 'border': '1px solid red' + } + } + } else if (columnIndex === 3) { + // 选择器 + if (!row.css && !row.xpath) { + return { + 'border': '1px solid red' + } + } + } } } }