top推荐
This commit is contained in:
@@ -185,16 +185,15 @@
|
||||
<div class="form-item">
|
||||
<span class="form-label required">爬虫模板</span>
|
||||
<el-select
|
||||
v-model="selectedTemplate"
|
||||
v-model="selectedCategory"
|
||||
placeholder="请选择爬虫模板"
|
||||
style="width: 100%"
|
||||
|
||||
>
|
||||
<el-option
|
||||
v-for="template in crawlerTemplates"
|
||||
:key="template.name"
|
||||
:label="template.name"
|
||||
:value="template"
|
||||
:value="template.name"
|
||||
/>
|
||||
</el-select>
|
||||
<span class="form-tip">
|
||||
@@ -226,75 +225,10 @@
|
||||
<!-- 动态参数表单 -->
|
||||
<div class="form-item" v-if="selectedMethod && selectedMethod.params && selectedMethod.params.length > 0">
|
||||
<span class="form-label">方法参数</span>
|
||||
<div class="params-container">
|
||||
<div v-for="param in selectedMethod.params" :key="param.name" class="param-item">
|
||||
<span class="param-label">
|
||||
{{ param.description }}
|
||||
<span class="param-type">({{ param.type }})</span>
|
||||
</span>
|
||||
<!-- 文本输入框 -->
|
||||
<el-input
|
||||
v-if="param.type === 'Input'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
:placeholder="`请输入${param.description}`"
|
||||
clearable
|
||||
/>
|
||||
<!-- 数字输入框 -->
|
||||
<el-input-number
|
||||
v-else-if="param.type === 'InputNumber'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
:placeholder="`请输入${param.description}`"
|
||||
controls-position="right"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<!-- 日期选择器 -->
|
||||
<el-date-picker
|
||||
v-else-if="param.type === 'DatePicker'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
type="date"
|
||||
:placeholder="`请选择${param.description}`"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
<!-- 日期范围选择器 -->
|
||||
<el-date-picker
|
||||
v-else-if="param.type === 'DateRangePicker'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
<!-- 布尔开关 -->
|
||||
<el-switch
|
||||
v-else-if="param.type === 'Switch'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
/>
|
||||
<!-- 下拉选择器 -->
|
||||
<el-select
|
||||
v-else-if="param.type === 'Select'"
|
||||
v-model="dynamicParams[param.name]"
|
||||
:placeholder="`请选择${param.description}`"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in param.options"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<DynamicParamForm
|
||||
v-model="dynamicParams"
|
||||
:params-schema="selectedMethod.params"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
@@ -405,7 +339,7 @@ import { crontabApi } from '@/apis/crontab';
|
||||
import { userApi } from '@/apis/system/user';
|
||||
import type { CrontabTask, TaskMeta, CrontabItem, CrontabMethod, CrontabParam, PageParam, CreateTaskRequest, RecipientUserInfo, UserVO, ResultDomain, EmailDefault } from '@/types';
|
||||
import { AdminLayout } from '@/views/admin';
|
||||
import { GenericSelector } from '@/components';
|
||||
import { GenericSelector, DynamicParamForm } from '@/components';
|
||||
defineOptions({
|
||||
name: 'NewsCrawlerView'
|
||||
});
|
||||
@@ -417,11 +351,17 @@ const crawlerList = ref<CrontabTask[]>([]);
|
||||
// 爬虫元数据
|
||||
const taskMetaList = ref<TaskMeta[]>([]);
|
||||
const crawlerTemplates = ref<CrontabItem[]>([]); // 转换后的模板结构
|
||||
const selectedTemplate = ref<CrontabItem | null>(null);
|
||||
const selectedMethodId = ref<string>(''); // 选中的方法ID(metaId)
|
||||
const selectedMetaId = ref<string>(''); // 选中的元数据ID
|
||||
const selectedCategory = ref<string>(''); // 选中的模板分类名称
|
||||
const selectedMethodId = ref<string>(''); // 选中的方法ID(metaId)
|
||||
const selectedMetaId = ref<string>(''); // 选中的元数据ID
|
||||
const dynamicParams = ref<Record<string, any>>({});
|
||||
|
||||
// 当前选中的模板对象(通过 category 查找)
|
||||
const selectedTemplate = computed<CrontabItem | null>(() => {
|
||||
if (!selectedCategory.value) return null;
|
||||
return crawlerTemplates.value.find(t => t.name === selectedCategory.value) || null;
|
||||
});
|
||||
|
||||
// 邮件接收人相关
|
||||
const useDefaultRecipients = ref<boolean>(false);
|
||||
const defaultRecipients = ref<RecipientUserInfo[]>([]);
|
||||
@@ -512,10 +452,9 @@ const selectedRecipients = computed(() => {
|
||||
});
|
||||
|
||||
// 监听模板选择变化
|
||||
watch(selectedTemplate, (newTemplate, oldTemplate) => {
|
||||
// 只在用户手动切换模板时重置(oldTemplate存在且不为null时才重置)
|
||||
// 编辑回填时oldTemplate为null,不会触发重置
|
||||
if (newTemplate && oldTemplate) {
|
||||
watch(selectedCategory, (newCategory, oldCategory) => {
|
||||
// 只在用户手动切换模板时重置(oldCategory存在且不为空时才重置)
|
||||
if (newCategory && oldCategory) {
|
||||
selectedMethodId.value = '';
|
||||
dynamicParams.value = {};
|
||||
}
|
||||
@@ -732,7 +671,7 @@ async function loadCrawlerTemplates() {
|
||||
params: meta.paramSchema ? JSON.parse(meta.paramSchema) : []
|
||||
}))
|
||||
}));
|
||||
|
||||
console.log(" crawlerTemplates.value",crawlerTemplates.value);
|
||||
|
||||
} else {
|
||||
ElMessage.error(result.message || '加载爬虫模板失败');
|
||||
@@ -801,7 +740,7 @@ function handleSizeChange(size: number) {
|
||||
function handleAdd() {
|
||||
isEdit.value = false;
|
||||
resetFormData();
|
||||
selectedTemplate.value = null;
|
||||
selectedCategory.value = '';
|
||||
selectedMethodId.value = '';
|
||||
dynamicParams.value = {};
|
||||
dialogVisible.value = true;
|
||||
@@ -813,7 +752,7 @@ async function handleEdit(row: CrontabTask) {
|
||||
Object.assign(formData, row);
|
||||
|
||||
// 重置选择
|
||||
selectedTemplate.value = null;
|
||||
selectedCategory.value = '';
|
||||
selectedMethodId.value = '';
|
||||
dynamicParams.value = {};
|
||||
|
||||
@@ -844,7 +783,7 @@ async function handleEdit(row: CrontabTask) {
|
||||
const method = template.methods.find(m => m.metaId === row.metaId);
|
||||
if (method) {
|
||||
// 找到匹配的方法,设置template和method
|
||||
selectedTemplate.value = template;
|
||||
selectedCategory.value = template.name;
|
||||
selectedMethodId.value = method.metaId || '';
|
||||
selectedMetaId.value = method.metaId || '';
|
||||
|
||||
|
||||
@@ -244,11 +244,10 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="任务参数" prop="methodParams">
|
||||
<el-input
|
||||
v-model="taskForm.methodParams"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入JSON格式的参数,例如:{}"
|
||||
<DynamicParamForm
|
||||
class="dynamic-params"
|
||||
v-model="dynamicParams"
|
||||
:params-schema="currentParamSchema"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -285,6 +284,7 @@ import {
|
||||
} from '@element-plus/icons-vue';
|
||||
import { crontabApi } from '@/apis/crontab';
|
||||
import AdminLayout from '@/views/admin/AdminLayout.vue';
|
||||
import { DynamicParamForm } from '@/components';
|
||||
import type { CrontabTask, TaskMeta, PageParam, CreateTaskRequest } from '@/types';
|
||||
|
||||
// 搜索表单
|
||||
@@ -306,6 +306,10 @@ const taskList = ref<CrontabTask[]>([]);
|
||||
const taskMetaList = ref<TaskMeta[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
// 动态任务参数
|
||||
const dynamicParams = ref<Record<string, any>>({});
|
||||
const currentParamSchema = ref<any[]>([]);
|
||||
|
||||
// 对话框
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增任务');
|
||||
@@ -395,6 +399,9 @@ function handleAddTask() {
|
||||
methodParams: '{}',
|
||||
status: 1
|
||||
});
|
||||
|
||||
dynamicParams.value = {};
|
||||
currentParamSchema.value = [];
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
@@ -412,6 +419,25 @@ function handleEdit(task: CrontabTask) {
|
||||
methodParams: task.methodParams || '{}',
|
||||
status: task.status
|
||||
});
|
||||
|
||||
// 根据 metaId 加载参数 schema
|
||||
const meta = taskMetaList.value.find(m => m.metaId === task.metaId);
|
||||
if (meta) {
|
||||
try {
|
||||
currentParamSchema.value = meta.paramSchema ? JSON.parse(meta.paramSchema) : [];
|
||||
} catch {
|
||||
currentParamSchema.value = [];
|
||||
}
|
||||
} else {
|
||||
currentParamSchema.value = [];
|
||||
}
|
||||
|
||||
// 回填动态参数
|
||||
try {
|
||||
dynamicParams.value = task.methodParams ? JSON.parse(task.methodParams) : {};
|
||||
} catch {
|
||||
dynamicParams.value = {};
|
||||
}
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
@@ -421,6 +447,34 @@ function handleMetaChange(metaId: string) {
|
||||
if (meta) {
|
||||
taskForm.taskName = meta.name;
|
||||
taskForm.description = meta.description;
|
||||
|
||||
// 解析参数 schema
|
||||
try {
|
||||
currentParamSchema.value = meta.paramSchema ? JSON.parse(meta.paramSchema) : [];
|
||||
} catch {
|
||||
currentParamSchema.value = [];
|
||||
}
|
||||
|
||||
// 根据 schema 默认值初始化 dynamicParams
|
||||
const baseParams: Record<string, any> = {};
|
||||
if (Array.isArray(currentParamSchema.value)) {
|
||||
currentParamSchema.value.forEach((p: any) => {
|
||||
if (p && p.name !== undefined && p.value !== undefined) {
|
||||
baseParams[p.name] = p.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 如果表单中已有 methodParams,合并覆盖默认值
|
||||
try {
|
||||
const exist = taskForm.methodParams ? JSON.parse(taskForm.methodParams) : {};
|
||||
dynamicParams.value = { ...baseParams, ...exist };
|
||||
} catch {
|
||||
dynamicParams.value = baseParams;
|
||||
}
|
||||
} else {
|
||||
currentParamSchema.value = [];
|
||||
dynamicParams.value = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,11 +486,11 @@ async function handleSubmit() {
|
||||
if (!valid) return;
|
||||
|
||||
try {
|
||||
// 验证JSON格式
|
||||
// 根据动态参数生成 methodParams
|
||||
try {
|
||||
JSON.parse(taskForm.methodParams || '{}');
|
||||
taskForm.methodParams = JSON.stringify(dynamicParams.value || {});
|
||||
} catch {
|
||||
ElMessage.error('任务参数必须是有效的JSON格式');
|
||||
ElMessage.error('任务参数序列化失败');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -614,7 +668,9 @@ onMounted(() => {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dynamic-params{
|
||||
width: 100%;
|
||||
}
|
||||
.crawler-list {
|
||||
min-height: 400px;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user