爬虫实现,修改class转样式,前端渲染

This commit is contained in:
2025-11-21 16:49:37 +08:00
parent 7eab82c6af
commit a492b68fa2
11 changed files with 406 additions and 45 deletions

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
新华网搜索爬虫命令行工具 新华网特别推荐爬虫命令行工具
用法: python RmrbSearch.py --key "关键词" --total 10 --type 0 用法: python XhwCommend.py --output "输出文件路径"
""" """
import argparse import argparse
@@ -20,7 +20,7 @@ from loguru import logger
def main(): def main():
"""主函数""" """主函数"""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='新华网新闻搜索工具', description='新华网特别推荐爬虫工具',
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=""" epilog="""
""" """

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
新华网搜索爬虫命令行工具 新华网热点爬虫命令行工具
用法: python RmrbSearch.py --key "关键词" --total 10 --type 0 用法: python XhwHotPoint.py --output "输出文件路径"
""" """
import argparse import argparse
@@ -20,7 +20,7 @@ from loguru import logger
def main(): def main():
"""主函数""" """主函数"""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='新华网新闻搜索工具', description='新华网热点爬虫工具',
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=""" epilog="""
""" """

View File

@@ -251,6 +251,56 @@ class XxqgCrawler(BaseCrawler):
# 相对路径,补全域名 # 相对路径,补全域名
return self.config.base_url + url return self.config.base_url + url
def _extract_inline_style(self, element) -> str:
"""
提取元素的计算样式并转换为inline style
Args:
element: Selenium WebElement
Returns:
inline style 字符串
"""
# 需要提取的CSS属性列表
css_properties = [
'text-align',
'text-indent',
'margin',
'margin-top',
'margin-bottom',
'margin-left',
'margin-right',
'padding',
'padding-top',
'padding-bottom',
'padding-left',
'padding-right',
'font-size',
'font-weight',
'font-style',
'color',
'background-color',
'line-height',
'letter-spacing',
'word-spacing'
]
styles = []
for prop in css_properties:
try:
value = element.value_of_css_property(prop)
# 过滤默认值和空值
if value and value not in ['none', 'normal', 'auto', '0px', 'rgba(0, 0, 0, 0)', 'transparent']:
# 对于 margin/padding如果都是 0px 就跳过
if 'margin' in prop or 'padding' in prop:
if value == '0px' or value == '0':
continue
styles.append(f"{prop}: {value}")
except:
continue
return "; ".join(styles) if styles else ""
def parse_news_detail(self, url: str) -> NewsItem: def parse_news_detail(self, url: str) -> NewsItem:
news_item = NewsItem(title='', contentRows=[], url=url) news_item = NewsItem(title='', contentRows=[], url=url)
if self.driver is None: if self.driver is None:
@@ -355,11 +405,21 @@ class XxqgCrawler(BaseCrawler):
text_content = child.text.strip() text_content = child.text.strip()
# 过滤空内容 # 过滤空内容
if text_content: if text_content:
# 提取计算样式并转换为inline style
inline_style = self._extract_inline_style(child)
tag_name = child.tag_name
# 构建新的HTML标签用inline style替代class
if inline_style:
content_html = f'<{tag_name} style="{inline_style}">{child.get_attribute("innerHTML")}</{tag_name}>'
else:
content_html = f'<{tag_name}>{child.get_attribute("innerHTML")}</{tag_name}>'
news_item.contentRows.append({ news_item.contentRows.append({
"type": "text", "type": "text",
"content": text_content "content": content_html
}) })
# logger.debug(f"提取文字: {text_content[:50]}...") logger.debug(f"提取文字(转换样式): {text_content[:50]}...")
except Exception as e: except Exception as e:
logger.warning(f"处理内容元素失败: {str(e)}") logger.warning(f"处理内容元素失败: {str(e)}")

View File

@@ -7,7 +7,7 @@
-- 1. 关键字搜索爬取 -- 1. 关键字搜索爬取
INSERT INTO `tb_crontab_task_meta` ( INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`, `id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time` `sort_order`, `creator`, `create_time`
) VALUES ( ) VALUES (
'1', '1',
@@ -22,19 +22,22 @@ INSERT INTO `tb_crontab_task_meta` (
{ {
"name": "query", "name": "query",
"description": "搜索关键字", "description": "搜索关键字",
"type": "String", "type": "Input",
"valueType": "String",
"value": "", "value": "",
"required": true "required": true
}, },
{ {
"name": "total", "name": "total",
"description": "总新闻数量", "description": "总新闻数量",
"type": "Integer", "type": "InputNumber",
"valueType": "Integer",
"value": 10, "value": 10,
"required": true "required": true
} }
]', ]',
1, 1,
1,
'system', 'system',
NOW() NOW()
); );
@@ -42,7 +45,7 @@ INSERT INTO `tb_crontab_task_meta` (
-- 2. 排行榜爬取 -- 2. 排行榜爬取
INSERT INTO `tb_crontab_task_meta` ( INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`, `id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time` `sort_order`, `creator`, `create_time`
) VALUES ( ) VALUES (
'2', '2',
@@ -54,6 +57,7 @@ INSERT INTO `tb_crontab_task_meta` (
'execute', 'execute',
'crawler/rmrb/RmrbHotPoint.py', 'crawler/rmrb/RmrbHotPoint.py',
'[]', '[]',
1,
2, 2,
'system', 'system',
NOW() NOW()
@@ -62,7 +66,7 @@ INSERT INTO `tb_crontab_task_meta` (
-- 3. 往日精彩头条爬取 -- 3. 往日精彩头条爬取
INSERT INTO `tb_crontab_task_meta` ( INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`, `id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time` `sort_order`, `creator`, `create_time`
) VALUES ( ) VALUES (
'3', '3',
@@ -75,28 +79,199 @@ INSERT INTO `tb_crontab_task_meta` (
'crawler/rmrb/RmrbTrending.py', 'crawler/rmrb/RmrbTrending.py',
'[ '[
{ {
"name": "startDate", "name": "dateRange",
"description": "开始日期", "description": "日期范围",
"type": "String", "type": "DateRangePicker",
"valueType": "String",
"value": "", "value": "",
"required": false "required": false,
}, "startKey": "startDate",
{ "endKey": "endDate"
"name": "endDate",
"description": "结束日期",
"type": "String",
"value": "",
"required": false
}, },
{ {
"name": "yesterday", "name": "yesterday",
"description": "是否是昨天", "description": "是否是昨天",
"type": "Boolean", "type": "Switch",
"valueType": "Boolean",
"value": true, "value": true,
"required": false "required": false
} }
]', ]',
1,
3, 3,
'system', 'system',
NOW() NOW()
); );
-- 4. 新华网关键字搜索爬取
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'4',
'xhw_keyword_search',
'关键字搜索爬取',
'根据关键字搜索新华网新闻内容',
'新华网新闻爬取',
'newsCrewerTask',
'execute',
'crawler/xhw/XhwSearch.py',
'[
{
"name": "query",
"description": "搜索关键字",
"type": "Input",
"valueType": "String",
"value": "",
"required": true
},
{
"name": "total",
"description": "抓取数量",
"type": "InputNumber",
"valueType": "Integer",
"value": 10,
"required": true
}
]',
1,
4,
'system',
NOW()
);
-- 5. 新华网热点新闻爬取
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'5',
'xhw_hot_point',
'热点新闻爬取',
'爬取新华网热点新闻',
'新华网新闻爬取',
'newsCrewerTask',
'execute',
'crawler/xhw/XhwHotPoint.py',
'[]',
1,
5,
'system',
NOW()
);
-- 6. 新华网推荐新闻爬取
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'6',
'xhw_commend',
'推荐新闻爬取',
'爬取新华网推荐新闻',
'新华网新闻爬取',
'newsCrewerTask',
'execute',
'crawler/xhw/XhwCommend.py',
'[]',
1,
6,
'system',
NOW()
);
-- 7. 学习强国关键字搜索爬取
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'7',
'xxqg_keyword_search',
'关键字搜索爬取',
'根据关键字搜索学习强国新闻内容',
'学习强国新闻爬取',
'newsCrewerTask',
'execute',
'crawler/xxqg/XxqgSearch.py',
'[
{
"name": "query",
"description": "搜索关键字",
"type": "Input",
"valueType": "String",
"value": "",
"required": true
},
{
"name": "total",
"description": "抓取数量",
"type": "InputNumber",
"valueType": "Integer",
"value": 10,
"required": true
}
]',
1,
7,
'system',
NOW()
);
-- 8. 学习强国栏目新闻爬取
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'8',
'xxqg_column_crawl',
'栏目新闻爬取',
'爬取学习强国指定栏目的新闻内容',
'学习强国新闻爬取',
'newsCrewerTask',
'execute',
'crawler/xxqg/XxqgColumn.py',
'[
{
"name": "column",
"description": "栏目名称",
"type": "Select",
"valueType": "String",
"value": "important",
"required": true,
"options": [
{"label": "重要新闻", "value": "important"},
{"label": "学习时评", "value": "xuexishiping"},
{"label": "综合新闻", "value": "zonghexinwen"},
{"label": "中宣部发布", "value": "zhongxuanbu"}
]
},
{
"name": "yesterday",
"description": "是否抓取昨天的数据",
"type": "Switch",
"valueType": "Boolean",
"value": true,
"required": false
},
{
"name": "dateRange",
"description": "日期范围",
"type": "DateRangePicker",
"valueType": "String",
"value": "",
"required": false,
"startKey": "start",
"endKey": "end"
}
]',
1,
8,
'system',
NOW()
);

View File

@@ -46,7 +46,7 @@ public class TbCrontabLog extends BaseDTO {
private String methodParams; private String methodParams;
/** /**
* @description 执行状态0:失败 1:成功) * @description 执行状态0:失败 1:成功,2 运行中
*/ */
private Integer executeStatus; private Integer executeStatus;

View File

@@ -58,7 +58,7 @@ public class TaskExecutor {
log.setDeleted(false); log.setDeleted(false);
try { try {
log.setExecuteStatus(0); log.setExecuteStatus(2);
log.setExecuteMessage("执行中"); log.setExecuteMessage("执行中");
int i = logMapper.insertLog(log); int i = logMapper.insertLog(log);

View File

@@ -15,6 +15,7 @@ import org.xyzh.api.system.role.RoleService;
import org.xyzh.common.core.domain.ResultDomain; import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault; import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient; import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
import org.xyzh.common.dto.crontab.TbCrontabLog;
import org.xyzh.common.dto.crontab.TbCrontabTask; import org.xyzh.common.dto.crontab.TbCrontabTask;
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta; import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
import org.xyzh.common.dto.crontab.TbDataCollectionItem; import org.xyzh.common.dto.crontab.TbDataCollectionItem;
@@ -25,6 +26,7 @@ import org.xyzh.common.utils.NonUtils;
import org.xyzh.common.vo.DataCollectionItemVO; import org.xyzh.common.vo.DataCollectionItemVO;
import org.xyzh.common.vo.ResourceVO; import org.xyzh.common.vo.ResourceVO;
import org.xyzh.common.vo.UserDeptRoleVO; import org.xyzh.common.vo.UserDeptRoleVO;
import org.xyzh.crontab.mapper.CrontabLogMapper;
import org.xyzh.crontab.pojo.TaskParams; import org.xyzh.crontab.pojo.TaskParams;
import org.xyzh.crontab.task.PythonCommandTask; import org.xyzh.crontab.task.PythonCommandTask;
@@ -79,6 +81,8 @@ public class NewsCrawlerTask extends PythonCommandTask {
@Autowired @Autowired
private RoleService roleService; private RoleService roleService;
@Autowired
private CrontabLogMapper logMapper;
/** /**
* 构建Python脚本参数 * 构建Python脚本参数
*/ */
@@ -132,9 +136,12 @@ public class NewsCrawlerTask extends PythonCommandTask {
String pythonArg = "--"+key; String pythonArg = "--"+key;
if (pythonArg != null && value != null) { if (pythonArg != null && value != null) {
if (value instanceof Boolean) { if (value instanceof Boolean) {
// Boolean类型: true时只传参数名false时不传
if ((Boolean) value) { if ((Boolean) value) {
args.add(pythonArg); args.add(pythonArg);
args.add("true");
}else{
args.add(pythonArg);
args.add("false");
} }
} else { } else {
// String/Integer类型: 传参数名+值 // String/Integer类型: 传参数名+值
@@ -305,6 +312,13 @@ public class NewsCrawlerTask extends PythonCommandTask {
} else { } else {
logger.warn("没有有效的新闻数据需要保存"); logger.warn("没有有效的新闻数据需要保存");
} }
if(passList.isEmpty() && notPassList.isEmpty()){
TbCrontabLog log = new TbCrontabLog();
log.setID(logId);
log.setExecuteStatus(1);
log.setExecuteMessage("未爬取到数据");
int i = logMapper.updateLog(log);
}
// 自动发布并记录成功发布的 URL 集合 // 自动发布并记录成功发布的 URL 集合
Set<String> publishedUrls = new HashSet<>(); Set<String> publishedUrls = new HashSet<>();

View File

@@ -64,7 +64,7 @@ export interface CrontabLog extends BaseDTO {
methodName?: string; methodName?: string;
/** 方法参数 */ /** 方法参数 */
methodParams?: string; methodParams?: string;
/** 执行状态0:失败 1:成功) */ /** 执行状态0:失败 1:成功 2运行中 */
executeStatus?: number; executeStatus?: number;
/** 执行结果信息 */ /** 执行结果信息 */
executeMessage?: string; executeMessage?: string;
@@ -162,11 +162,38 @@ export interface CrontabParam {
name: string; name: string;
/** 参数描述 */ /** 参数描述 */
description: string; description: string;
/** 参数类型 */ /**
type: string; * 前端渲染的组件类型
* - Input: 文本输入框
* - InputNumber: 数字输入框
* - DatePicker: 日期选择器
* - DateRangePicker: 日期范围选择器
* - Switch: 布尔开关
* - Select: 下拉选择器
*/
type: 'Input' | 'InputNumber' | 'DatePicker' | 'DateRangePicker' | 'Switch' | 'Select';
/**
* 参数值的数据类型(后端处理使用)
* - String: 字符串
* - Integer: 整数
* - Boolean: 布尔值
*/
valueType: 'String' | 'Integer' | 'Boolean';
/** 默认值 */ /** 默认值 */
value: any; value: any;
/** 是否必填 */
required: boolean; required: boolean;
/** Select类型的选项列表 */
options?: Array<{
/** 选项显示文本 */
label: string;
/** 选项值 */
value: string;
}>;
/** DateRangePicker的开始日期参数名startDate, start */
startKey?: string;
/** DateRangePicker的结束日期参数名endDate, end */
endKey?: string;
} }
/** /**

View File

@@ -41,6 +41,7 @@
> >
<el-option label="成功" :value="1" /> <el-option label="成功" :value="1" />
<el-option label="失败" :value="0" /> <el-option label="失败" :value="0" />
<el-option label="运行中" :value="2" />
</el-select> </el-select>
</div> </div>
<div class="search-actions"> <div class="search-actions">
@@ -69,8 +70,11 @@
<el-table-column prop="methodName" label="方法名称" width="120" /> <el-table-column prop="methodName" label="方法名称" width="120" />
<el-table-column label="执行状态" width="100"> <el-table-column label="执行状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.executeStatus === 1 ? 'success' : 'danger'" size="small"> <el-tag
{{ row.executeStatus === 1 ? '成功' : '失败' }} :type="row.executeStatus === 1 ? 'success' : row.executeStatus === 2 ? 'warning' : 'danger'"
size="small"
>
{{ row.executeStatus === 1 ? '成功' : row.executeStatus === 2 ? '运行中' : '失败' }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
@@ -152,8 +156,11 @@
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="detail-label">执行状态</span> <span class="detail-label">执行状态</span>
<el-tag :type="currentLog.executeStatus === 1 ? 'success' : 'danger'" size="small"> <el-tag
{{ currentLog.executeStatus === 1 ? '成功' : '失败' }} :type="currentLog.executeStatus === 1 ? 'success' : currentLog.executeStatus === 2 ? 'warning' : 'danger'"
size="small"
>
{{ currentLog.executeStatus === 1 ? '成功' : currentLog.executeStatus === 2 ? '运行中' : '失败' }}
</el-tag> </el-tag>
</div> </div>
<div class="detail-item"> <div class="detail-item">

View File

@@ -232,25 +232,67 @@
{{ param.description }} {{ param.description }}
<span class="param-type">({{ param.type }})</span> <span class="param-type">({{ param.type }})</span>
</span> </span>
<!-- 文本输入框 -->
<el-input <el-input
v-if="param.type === 'String'" v-if="param.type === 'Input'"
v-model="dynamicParams[param.name]" v-model="dynamicParams[param.name]"
:placeholder="`请输入${param.description}`" :placeholder="`请输入${param.description}`"
clearable clearable
/> />
<!-- 数字输入框 -->
<el-input-number <el-input-number
v-else-if="param.type === 'Integer'" v-else-if="param.type === 'InputNumber'"
v-model="dynamicParams[param.name]" v-model="dynamicParams[param.name]"
:placeholder="`请输入${param.description}`" :placeholder="`请输入${param.description}`"
controls-position="right" controls-position="right"
style="width: 100%" 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 <el-switch
v-else-if="param.type === 'Boolean'" v-else-if="param.type === 'Switch'"
v-model="dynamicParams[param.name]" v-model="dynamicParams[param.name]"
active-text="" active-text=""
inactive-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>
</div> </div>
</div> </div>
@@ -819,6 +861,24 @@ async function handleEdit(row: CrontabTask) {
const params = JSON.parse(row.methodParams); const params = JSON.parse(row.methodParams);
// 排除系统参数 // 排除系统参数
const { scriptPath, taskId, logId, ...restParams } = params; const { scriptPath, taskId, logId, ...restParams } = params;
// 处理DateRangePicker参数将startKey和endKey合并为dateRange数组
if (method.params) {
for (const param of method.params) {
if (param.type === 'DateRangePicker' && param.startKey && param.endKey) {
const startValue = restParams[param.startKey];
const endValue = restParams[param.endKey];
if (startValue && endValue) {
// 合并为数组
restParams[param.name] = [startValue, endValue];
// 删除原始的start和end字段
delete restParams[param.startKey];
delete restParams[param.endKey];
}
}
}
}
// 延迟设置确保watch先执行完 // 延迟设置确保watch先执行完
setTimeout(() => { setTimeout(() => {
dynamicParams.value = restParams; dynamicParams.value = restParams;
@@ -971,11 +1031,12 @@ async function handleSubmit() {
for (const param of selectedMethod.value.params) { for (const param of selectedMethod.value.params) {
const value = dynamicParams.value[param.name]; const value = dynamicParams.value[param.name];
if (param.required && param.type === 'String' && (!value || value.trim() === '')) { // 使用valueType判断值类型
if (param.required && param.valueType === 'String' && (!value || value.trim() === '')) {
ElMessage.warning(`请输入${param.description}`); ElMessage.warning(`请输入${param.description}`);
return; return;
} }
if (param.required && param.type === 'Integer' && (value === undefined || value === null || value === '')) { if (param.required && param.valueType === 'Integer' && (value === undefined || value === null || value === '')) {
ElMessage.warning(`请输入${param.description}`); ElMessage.warning(`请输入${param.description}`);
return; return;
} }
@@ -984,15 +1045,32 @@ async function handleSubmit() {
submitting.value = true; submitting.value = true;
try { try {
// 处理DateRangePicker参数将数组拆分为开始和结束日期
const processedParams = { ...dynamicParams.value };
if (selectedMethod.value.params) {
for (const param of selectedMethod.value.params) {
if (param.type === 'DateRangePicker' && processedParams[param.name]) {
const dateRange = processedParams[param.name];
if (Array.isArray(dateRange) && dateRange.length === 2) {
// 拆分为startKey和endKey
const startKey = (param as any).startKey || 'startDate';
const endKey = (param as any).endKey || 'endDate';
processedParams[startKey] = dateRange[0];
processedParams[endKey] = dateRange[1];
// 删除原始的range参数
delete processedParams[param.name];
}
}
}
}
// 构建CreateTaskRequest // 构建CreateTaskRequest
const requestData: CreateTaskRequest = { const requestData: CreateTaskRequest = {
metaId: selectedMetaId.value, metaId: selectedMetaId.value,
task: { task: {
...formData, ...formData,
defaultRecipient: useDefaultRecipients.value, defaultRecipient: useDefaultRecipients.value,
methodParams: JSON.stringify({ methodParams: JSON.stringify(processedParams)
...dynamicParams.value
})
} as CrontabTask, } as CrontabTask,
additionalRecipients: additionalRecipients.value additionalRecipients: additionalRecipients.value
}; };

View File

@@ -6,11 +6,11 @@
<div class="article-management"> <div class="article-management">
<div class="action-bar"> <div class="action-bar">
<el-button type="primary" @click="showCreateDialog">+ 新增文章</el-button> <el-button type="primary" @click="showCreateDialog">+ 新增文章</el-button>
<el-button @click="handleDataCollection">数据采集</el-button>
<el-input <el-input
v-model="searchKeyword" v-model="searchKeyword"
placeholder="搜索文章..." placeholder="搜索文章..."
style="width: 300px" style="width: 300px"
onkeydown=""
clearable clearable
/> />
</div> </div>