|
@@ -0,0 +1,334 @@
|
|
|
+<template>
|
|
|
+ <Navigator pageTitle="爬虫列表"></Navigator>
|
|
|
+ <div class="space"></div>
|
|
|
+ <el-card>
|
|
|
+ <el-header>
|
|
|
+ <div class="action-bar-container">
|
|
|
+ <el-space class="action-bar-item-container action-bar-action-left">
|
|
|
+ <el-button size="small" type="success" @click="resetFilterAndRefreshTableList">
|
|
|
+ 刷新
|
|
|
+ </el-button>
|
|
|
+ </el-space>
|
|
|
+ <el-space class="action-bar-item-container action-bar-action-right">
|
|
|
+ <div class="action-bar-item">
|
|
|
+ <span class="action-bar-name">维护人:</span>
|
|
|
+ <el-select v-model="filters.modifyuser" placeholder="维护人" style="width: 140px" @change="onModifyUserSelectChange">
|
|
|
+ <el-option
|
|
|
+ v-for="item in filterConfig.modifyUserList"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="action-bar-item">
|
|
|
+ <span class="action-bar-name">爬虫状态:</span>
|
|
|
+ <el-select v-model="filters.state" placeholder="爬虫状态" style="width: 140px" @change="onStateSelectChange">
|
|
|
+ <el-option
|
|
|
+ v-for="item in filterConfig.stateOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="action-bar-item">
|
|
|
+ <el-input v-model="filters.search" placeholder="按照爬虫代码搜索" @keydown.enter="onInputSearch" />
|
|
|
+ </div>
|
|
|
+ </el-space>
|
|
|
+ </div>
|
|
|
+ </el-header>
|
|
|
+ <el-main>
|
|
|
+ <el-table ref="spiderTable" :data="listState.list" stripe :row-style="getRowStyle" :loading="listState.loading">
|
|
|
+ <el-table-column prop="code" label="代码" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="site" label="网站" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="channel" label="栏目" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="href" label="栏目地址" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="modifyuser" label="维护人" width="80" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column label="操作" width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button size="small" type="success" @click="tableEvents.handleDataTag(scope.$index, scope.row)">
|
|
|
+ 标注
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="warning" @click="tableEvents.handleEdit(scope.$index, scope.row)">
|
|
|
+ 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="danger" @click="tableEvents.handleDebug(scope.$index, scope.row)">
|
|
|
+ 调试
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div class="space"></div>
|
|
|
+ <div class="pagination-container">
|
|
|
+ <el-pagination align="right" @size-change="handleSizeChange" @current-change="handleCurrentChange"
|
|
|
+ :current-page="listState.pageNum" :page-sizes="[10, 20, 30, 40]" :page-size="listState.pageSize"
|
|
|
+ layout="total, prev, pager, next, jumper" :total="listState.total" hide-on-single-page>
|
|
|
+ </el-pagination>
|
|
|
+ </div>
|
|
|
+ </el-main>
|
|
|
+ </el-card>
|
|
|
+ <EditSpider ref="editSpiderDialog" @custom-event="dialogEvents.editSpiderConfigSaveEvent" />
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted, onUnmounted, reactive } from 'vue'
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { useStore } from 'vuex';
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import { BrowserOpenURL, EventsOn } from "../../wailsjs/runtime"
|
|
|
+import { SaveOrUpdateSpiderConfig } from "../../wailsjs/go/main/App"
|
|
|
+import { SwitchSpiderConfig } from "../../wailsjs/go/main/App"
|
|
|
+import Navigator from "../components/Navigator.vue"
|
|
|
+import EditSpider from "../components/EditSpider.vue"
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+const store = useStore();
|
|
|
+const spiderTable = ref(null)
|
|
|
+
|
|
|
+const filterConfig = reactive({
|
|
|
+ // 爬虫状态
|
|
|
+ stateOptions: [
|
|
|
+ {
|
|
|
+ label: '全部',
|
|
|
+ value: -1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '待完成',
|
|
|
+ value: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '待审核',
|
|
|
+ value: 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '未通过',
|
|
|
+ value: 2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '已通过',
|
|
|
+ value: 3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '已上线',
|
|
|
+ value: 11,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '无法标注',
|
|
|
+ value: 12,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ modifyUserList: [
|
|
|
+ // {
|
|
|
+ // label: '全部',
|
|
|
+ // value: ''
|
|
|
+ // }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 选择器数据
|
|
|
+const filters = reactive({
|
|
|
+ search: '',
|
|
|
+ state: -1,
|
|
|
+ modifyuser: '',
|
|
|
+})
|
|
|
+// 选择器数据(用来重置)
|
|
|
+const defaultFilters = {
|
|
|
+ search: '',
|
|
|
+ state: -1,
|
|
|
+ modifyuser: '',
|
|
|
+}
|
|
|
+
|
|
|
+// 列表数据
|
|
|
+const listState = reactive({
|
|
|
+ loaded: false,
|
|
|
+ loading: false,
|
|
|
+ pageNum: 1, // 页码
|
|
|
+ pageSize: 10, // 每页多少条
|
|
|
+ total: 0, // 返回的总数据条数
|
|
|
+ list: [ // 数据列表
|
|
|
+ // {
|
|
|
+ // code: '爬虫代码',
|
|
|
+ // site: '网站',
|
|
|
+ // channel: '栏目',
|
|
|
+ // href: '栏目地址',
|
|
|
+ // modifyuser: '维护人',
|
|
|
+ // _id: 'asfasf',
|
|
|
+ // },
|
|
|
+ ],
|
|
|
+})
|
|
|
+// 列表默认数据(用来重置)
|
|
|
+const defaultListState = {
|
|
|
+ loaded: false,
|
|
|
+ loading: false,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ list: [],
|
|
|
+}
|
|
|
+
|
|
|
+const editSpiderDialog = ref(null)
|
|
|
+
|
|
|
+const dialogEvents = {
|
|
|
+ editSpiderConfigSaveEvent: function (data) {
|
|
|
+ console.log("change data:", data)
|
|
|
+ SaveOrUpdateSpiderConfig(data).then(result => {
|
|
|
+ ElMessage({
|
|
|
+ message: `成功更新爬虫 ${data.site} /${data.channel}/${data.code}`,
|
|
|
+ showClose: true,
|
|
|
+ duration: 3000,
|
|
|
+ });
|
|
|
+ //表格数据更新
|
|
|
+ listState.list.forEach((v, i) => {
|
|
|
+ if (v.code == data.code) v = data
|
|
|
+ })
|
|
|
+ //更新当前选择
|
|
|
+ SwitchSpiderConfig(data.code).then(result => { })
|
|
|
+ })
|
|
|
+ },
|
|
|
+}
|
|
|
+
|
|
|
+const tableEvents = {
|
|
|
+ handleDataTag(index, row) {
|
|
|
+ // 自定义关闭时间
|
|
|
+ ElMessage({
|
|
|
+ message: `${row.site} ${row.channel} ${row.href}`,
|
|
|
+ showClose: true,
|
|
|
+ duration: 3000,
|
|
|
+ });
|
|
|
+ BrowserOpenURL(row.href)
|
|
|
+ },
|
|
|
+ handleEdit: (index, row) => {
|
|
|
+ ElMessage({
|
|
|
+ message: `${row.site} ${row.channel} ${row.href}`,
|
|
|
+ showClose: true,
|
|
|
+ duration: 3000,
|
|
|
+ });
|
|
|
+ editSpiderDialog.value.dialogVisible = true
|
|
|
+ editSpiderDialog.value.formData = row
|
|
|
+ },
|
|
|
+ handleDebug(index, row) {
|
|
|
+ router.push({
|
|
|
+ path: '/run'
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const getRowStyle = ({ row }) => {
|
|
|
+ return row.selected ? { backgroundColor: '#F7F7F7' } : {};
|
|
|
+};
|
|
|
+
|
|
|
+// 获取列表数据
|
|
|
+const getTableList = async () => {
|
|
|
+ const r = await store.dispatch('rulesList/getCodeList', {
|
|
|
+ modifyuser: filters.modifyuser, // 维护人
|
|
|
+ state: filters.state, // 爬虫状态
|
|
|
+ search: filters.search, // 搜索内容
|
|
|
+ pageSize: listState.pageSize,
|
|
|
+ pageNum: listState.pageNum
|
|
|
+ });
|
|
|
+ const { data, code } = r
|
|
|
+ if (data) {
|
|
|
+ listState.total = data.total || 0
|
|
|
+ if (Array.isArray(data.list)) {
|
|
|
+ listState.list = data.list || []
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 重置列表数据
|
|
|
+const resetListState = () => {
|
|
|
+ Object.assign(listState, defaultListState)
|
|
|
+}
|
|
|
+// 重置选择器数据
|
|
|
+const resetFilterState = () => {
|
|
|
+ Object.assign(filters, defaultFilters)
|
|
|
+}
|
|
|
+
|
|
|
+// 刷新列表(不重置选择器)
|
|
|
+const refreshTableList = () => {
|
|
|
+ resetListState()
|
|
|
+ getTableList()
|
|
|
+}
|
|
|
+// 刷新列表(并重置选择器)
|
|
|
+const resetFilterAndRefreshTableList = () => {
|
|
|
+ resetFilterState()
|
|
|
+ resetListState()
|
|
|
+ getTableList()
|
|
|
+}
|
|
|
+
|
|
|
+getTableList()
|
|
|
+
|
|
|
+const handleSizeChange = (val) => {
|
|
|
+ listState.pageSize = val;
|
|
|
+ listState.pageNum = 1;
|
|
|
+};
|
|
|
+
|
|
|
+const handleCurrentChange = (val) => {
|
|
|
+ listState.pageNum = val;
|
|
|
+ getTableList()
|
|
|
+};
|
|
|
+
|
|
|
+const getModifyUserList = async () => {
|
|
|
+ const r = await store.dispatch('rulesList/getModifyUserList')
|
|
|
+ const { data, code } = r
|
|
|
+ if (data) {
|
|
|
+ if (Array.isArray(data.list)) {
|
|
|
+ const arr = [{ s_name: '全部', value: '' }]
|
|
|
+ const reqArr = data.list.map(r => {
|
|
|
+ return {
|
|
|
+ name: r.s_name,
|
|
|
+ value: r.s_name,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ filterConfig.modifyUserList = arr.concat(reqArr)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+getModifyUserList()
|
|
|
+
|
|
|
+const onModifyUserSelectChange = () => {
|
|
|
+ refreshTableList()
|
|
|
+}
|
|
|
+const onStateSelectChange = () => {
|
|
|
+ refreshTableList()
|
|
|
+}
|
|
|
+const onInputSearch = () => {
|
|
|
+ refreshTableList()
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//Wails事件绑定
|
|
|
+EventsOn("spiderConfigChange", data => {
|
|
|
+ listState.list.forEach((v, i) => {
|
|
|
+ if (v.code == data.code) {
|
|
|
+ let rowData = { ...data }
|
|
|
+ listState.list[i] = rowData
|
|
|
+ spiderTable.value.toggleRowSelection(listState.list[i], true);
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.pagination-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+}
|
|
|
+.action-bar-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+.action-bar-item-container {
|
|
|
+
|
|
|
+}
|
|
|
+.action-bar-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.action-bar-name {
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+</style>
|