新增工具‘HTTP请求头管理器’,支持设置HTTP请求头数据
This commit is contained in:
parent
17eb6f7b70
commit
3db0ae1b24
|
@ -6,6 +6,7 @@ from app.cores.logger import DispatcherLogger
|
|||
from app.cores.dictionaries import DISPATCHER_TYPE, REPORT_RESULT
|
||||
from app.cores.dispatcher import AbstractCaseDispatcher
|
||||
from app.cores.case.http.request_util import handle_url
|
||||
from app.cores.case.http.http_request_header_pool_manager import HTTPRequestHeaderPoolManager
|
||||
from app.cores.case.base.script import exec_postprocessor_script, exec_preprocessor_script
|
||||
from app.cores.case.base.last_result import LastResult
|
||||
from app.cores.case.base.expectation import get_expectations_result
|
||||
|
@ -39,6 +40,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
|
|||
|
||||
# cookie数据
|
||||
self.rcj = None
|
||||
# http请求头
|
||||
self.headers = None
|
||||
|
||||
# http请求字段
|
||||
self.protocol = None
|
||||
|
@ -59,6 +62,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
|
|||
super().set_up()
|
||||
# 获取cookie
|
||||
self.rcj = http_cookie_manager.get_request_cookie_jar(type=self.dispatcher_type)
|
||||
# 获取HTTP请求头
|
||||
self.headers = HTTPRequestHeaderPoolManager.get_http_request_header(project_id=self.case.scene.module.project.id)
|
||||
# 预处理脚本执行
|
||||
preprocessor_script = self.case.specific_case.preprocessor_script_
|
||||
exec_preprocessor_script(
|
||||
|
@ -96,7 +101,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
|
|||
message_body=self.message_body,
|
||||
cookies=self.rcj,
|
||||
file_upload=self.file_upload,
|
||||
content_type=self.content_type)
|
||||
content_type=self.content_type,
|
||||
headers=self.headers)
|
||||
self.request_.send()
|
||||
|
||||
def tear_down(self):
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
# coding=utf-8
|
||||
|
||||
from typing import Dict
|
||||
from flask import session
|
||||
|
||||
from app.extensions import session_id_manager
|
||||
from app.cores.dictionaries import DISPATCHER_TRIGGER_TYPE
|
||||
|
||||
|
||||
class HTTPRequestHeaderPoolManager:
|
||||
|
||||
"""
|
||||
HTTPRequestHeaderPool = {
|
||||
session_id: {
|
||||
project_id: {
|
||||
key: value,
|
||||
key1: value1,
|
||||
...
|
||||
},
|
||||
project_id2: {
|
||||
...
|
||||
}
|
||||
},
|
||||
session_id2:{
|
||||
...
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
ScheduleHTTPRequestHeaderPool = {
|
||||
project_id: {
|
||||
key: value,
|
||||
key1: value1,
|
||||
...
|
||||
},
|
||||
project_id2: {
|
||||
...
|
||||
},
|
||||
...
|
||||
}
|
||||
"""
|
||||
# HTTP请求头数据池
|
||||
HTTPRequestHeaderPool = {}
|
||||
|
||||
# 定时任务HTTP请求头数据池
|
||||
ScheduleHTTPRequestHeaderPool = {}
|
||||
|
||||
@classmethod
|
||||
def get_http_request_header(cls, project_id):
|
||||
"""
|
||||
获取项目中HTTP请求头数据
|
||||
:param project_id: 项目id
|
||||
:type project_id: int
|
||||
:return: 项目定义的HTTP请求头数据
|
||||
:rtype: Dict
|
||||
"""
|
||||
cls._set_default_http_request_header(project_id=project_id)
|
||||
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
|
||||
project_id = session.get('project_id')
|
||||
if project_id:
|
||||
return cls.ScheduleHTTPRequestHeaderPool.get(project_id)
|
||||
else:
|
||||
session_id = session_id_manager.get_session_id()
|
||||
return cls.HTTPRequestHeaderPool.get(session_id).get(project_id)
|
||||
|
||||
@classmethod
|
||||
def set_http_request_header(cls, project_id, key, value):
|
||||
"""
|
||||
设置HTTP请求头
|
||||
:param project_id: 项目id
|
||||
:type project_id: int
|
||||
:param key: 变量名
|
||||
:type key: str
|
||||
:param value: 变量值
|
||||
:type value: str
|
||||
"""
|
||||
cls._set_default_http_request_header(project_id=project_id)
|
||||
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
|
||||
project_id = session.get('project_id')
|
||||
if project_id:
|
||||
cls.ScheduleHTTPRequestHeaderPool.get(project_id).update({
|
||||
key: value
|
||||
})
|
||||
else:
|
||||
session_id = session_id_manager.get_session_id()
|
||||
cls.HTTPRequestHeaderPool.get(session_id).get(project_id).update({
|
||||
key: value
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def _set_default_http_request_header(cls, project_id):
|
||||
"""当RequestHeaderPool为空时,为其设置默认值,避免取出值为None"""
|
||||
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
|
||||
project_id = session.get('project_id')
|
||||
if project_id:
|
||||
project_var = cls.ScheduleHTTPRequestHeaderPool.get(project_id)
|
||||
if project_var is None:
|
||||
cls.ScheduleHTTPRequestHeaderPool.update({
|
||||
project_id: {}
|
||||
})
|
||||
else:
|
||||
session_id = session_id_manager.get_session_id()
|
||||
session_var = cls.HTTPRequestHeaderPool.get(session_id)
|
||||
if session_var is None:
|
||||
cls.HTTPRequestHeaderPool.update({
|
||||
session_id: {
|
||||
project_id: {}
|
||||
}
|
||||
})
|
||||
else:
|
||||
project_var = cls.HTTPRequestHeaderPool.get(session_id).get(project_id)
|
||||
if project_var is None:
|
||||
cls.HTTPRequestHeaderPool.get(session_id).update({
|
||||
project_id: {}
|
||||
})
|
|
@ -211,7 +211,6 @@ def make_request(method, url, *, parameters=None, content_type=None, message_bod
|
|||
|
||||
:rtype: HTTPRequest
|
||||
"""
|
||||
headers = kwargs.get('headers', {})
|
||||
# 选择适当的参数数据, 如果parameters没有数据,则取message_body作为入参数据
|
||||
params = []
|
||||
if (parameters is not None) and (len(parameters) > 0):
|
||||
|
@ -222,6 +221,7 @@ def make_request(method, url, *, parameters=None, content_type=None, message_bod
|
|||
if method.lower() == 'get':
|
||||
return Get(url=url, params=handle_params(params), **kwargs)
|
||||
if method.lower() == 'post':
|
||||
headers = kwargs.pop('headers', {})
|
||||
files = handle_file_upload(file_upload) if file_upload else None
|
||||
if content_type == CONTENT_TYPE.FORM_DATA:
|
||||
data = MultipartEncoder(handle_data(params, content_type=CONTENT_TYPE.FORM_DATA))
|
||||
|
|
|
@ -101,6 +101,7 @@ class TOOL_TYPE:
|
|||
TIMER = 'TIMER'
|
||||
VARIABLE_DEFINITION = 'VARIABLE_DEFINITION'
|
||||
SCRIPT = 'SCRIPT'
|
||||
HTTP_REQUEST_HEADER_MANAGER = 'HTTP_REQUEST_HEADER_MANAGER'
|
||||
|
||||
|
||||
class CONTENT_TYPE:
|
||||
|
|
|
@ -867,7 +867,8 @@ class SceneDispatcher(AbstractSceneDispatcher):
|
|||
"""
|
||||
if tool.status in [STATUS.NORMAL] and tool.tool_type in [TOOL_TYPE.TIMER,
|
||||
TOOL_TYPE.SCRIPT,
|
||||
TOOL_TYPE.VARIABLE_DEFINITION]:
|
||||
TOOL_TYPE.VARIABLE_DEFINITION,
|
||||
TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER]:
|
||||
# ReportToolData表数据字段
|
||||
report_id = self.dispatcher.report.id
|
||||
try:
|
||||
|
@ -884,6 +885,11 @@ class SceneDispatcher(AbstractSceneDispatcher):
|
|||
from app.cores.tool.dispatcher import VariableDefinitionToolDispatcher
|
||||
VariableDefinitionToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.BUILD,
|
||||
logger=self.dispatcher_logger, dispatcher=self.dispatcher).run()
|
||||
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
from app.cores.tool.dispatcher import HTTPRequestHeaderManagerToolDispatcher
|
||||
HTTPRequestHeaderManagerToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.BUILD,
|
||||
logger=self.dispatcher_logger,
|
||||
dispatcher=self.dispatcher).run()
|
||||
finally:
|
||||
# 工具增加调度子数据
|
||||
dispatcher_detail_id = DispatcherDetail.add(element_type=ELEMENT_TYPE.TOOL, element_id=tool.id,
|
||||
|
|
|
@ -5,6 +5,7 @@ from app.cores.dispatcher import AbstractToolDispatcher
|
|||
from app.cores.tool.script import Script
|
||||
from app.cores.tool.timer import Timer
|
||||
from app.cores.tool.variable_definition import VariableDefinition
|
||||
from app.cores.tool.http_request_header_manager import HTTPRequestHeaderManager
|
||||
|
||||
|
||||
class ScriptToolDispatcher(AbstractToolDispatcher):
|
||||
|
@ -95,3 +96,31 @@ class VariableDefinitionToolDispatcher(AbstractToolDispatcher):
|
|||
|
||||
def run(self):
|
||||
super().run()
|
||||
|
||||
|
||||
class HTTPRequestHeaderManagerToolDispatcher(AbstractToolDispatcher):
|
||||
def __init__(self, tool, dispatcher_type=DISPATCHER_TYPE.BUILD, logger=None, dispatcher=None):
|
||||
"""
|
||||
:param tool: 单个HTTPRequestHeaderManager Tool工具组件
|
||||
:type tool: Tool
|
||||
:param dispatcher_type: 标识构建是通过单独组件调试(DISPATCHER_TYPE.DEBUG)还是通过模块/项目构建测试(DISPATCHER_TYPE.BUILD)
|
||||
:type dispatcher_type: str
|
||||
:param logger: 当dispatcher_type为DISPATCHER_TYPE.BUILD时,需要传入调度日志
|
||||
:type logger: DispatcherLogger
|
||||
:param dispatcher: 当dispatcher_type为DISPATCHER_TYPE.BUILD时,需要传入调度数据
|
||||
:type dispatcher: Dispatcher
|
||||
"""
|
||||
super().__init__(tool=tool, dispatcher_type=dispatcher_type, logger=logger, dispatcher=dispatcher)
|
||||
|
||||
def set_up(self):
|
||||
super().set_up()
|
||||
|
||||
def execute(self):
|
||||
super().execute()
|
||||
HTTPRequestHeaderManager(tool=self.tool, dispatcher_logger=self.dispatcher_logger).exec_tool()
|
||||
|
||||
def tear_down(self):
|
||||
super().tear_down()
|
||||
|
||||
def run(self):
|
||||
super().run()
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# coding=utf-8
|
||||
from flask import session
|
||||
|
||||
from app.cores.case.http.http_request_header_pool_manager import HTTPRequestHeaderPoolManager
|
||||
|
||||
|
||||
class HTTPRequestHeaderManager:
|
||||
|
||||
def __init__(self, tool, dispatcher_logger, project_id=None):
|
||||
"""
|
||||
初始化HTTP请求头工具对象
|
||||
:param tool: 工具
|
||||
:type tool: Tool
|
||||
:param dispatcher_logger: 日志
|
||||
:type dispatcher_logger: DispatcherLogger
|
||||
:param project_id: 工具所在项目id
|
||||
:type project_id: int
|
||||
"""
|
||||
self.http_request_header_manager_tool = tool.specific_tool
|
||||
self.dispatcher_logger = dispatcher_logger
|
||||
if project_id is None:
|
||||
self.project_id = session.get('project_id')
|
||||
else:
|
||||
self.project_id = project_id
|
||||
|
||||
def exec_tool(self):
|
||||
self.dispatcher_logger.logger.info('[HTTP请求头管理器][执行]')
|
||||
variables = HTTPRequestHeaderPoolManager.get_http_request_header(project_id=self.project_id)
|
||||
for row in self.http_request_header_manager_tool.http_request_header_manager_list:
|
||||
variables[row.name_] = row.value_
|
|
@ -979,6 +979,8 @@ class Tool(db.Model):
|
|||
return ScriptTool.query.filter_by(tool_id=self.id).first()
|
||||
if self.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
|
||||
return VariableDefinitionTool.query.filter_by(tool_id=self.id).first()
|
||||
if self.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
return HTTPRequestHeaderManagerTool.query.filter_by(tool_id=self.id).first()
|
||||
|
||||
@classmethod
|
||||
def exist_and_status_not_delete(cls, tool_id) -> bool:
|
||||
|
@ -1023,6 +1025,9 @@ class Tool(db.Model):
|
|||
elif tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
|
||||
specific_tool = VariableDefinitionTool.new_tool()
|
||||
specific_tool.tool = tool
|
||||
elif tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
specific_tool = HTTPRequestHeaderManagerTool.new_tool()
|
||||
specific_tool.tool = tool
|
||||
else:
|
||||
raise ValueError('不支持当前tool_type类型, tool_type=%s' % tool_type)
|
||||
db.session.add(specific_tool)
|
||||
|
@ -1358,6 +1363,10 @@ class VariableDefinitionList(db.Model):
|
|||
value = db.Column(db.String(512), nullable=False, default='', server_default='')
|
||||
description = db.Column(db.Text, nullable=False, default='', server_default='')
|
||||
|
||||
# relationship
|
||||
variable_definition_tool_id = db.Column(db.Integer, db.ForeignKey('variable_definition_tool.id'))
|
||||
variable_definition_tool = db.relationship('VariableDefinitionTool', back_populates='variable_definition_list')
|
||||
|
||||
@property
|
||||
def name_(self):
|
||||
return _p(self.name)
|
||||
|
@ -1366,9 +1375,149 @@ class VariableDefinitionList(db.Model):
|
|||
def value_(self):
|
||||
return _p(self.value)
|
||||
|
||||
|
||||
class HTTPRequestHeaderManagerTool(db.Model):
|
||||
"""
|
||||
关系说明
|
||||
tool: HTTP请求头对应的工具对象 HTTPRequestHeaderManagerTool:Tool is 1:1
|
||||
http_request_header_manager_list: HTTP请求头工具所包含的所有变量与值数据 HTTPRequestHeaderManagerTool:HTTPRequestHeaderManagerList is 1:N
|
||||
"""
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
# relationship
|
||||
variable_definition_tool_id = db.Column(db.Integer, db.ForeignKey('variable_definition_tool.id'))
|
||||
variable_definition_tool = db.relationship('VariableDefinitionTool', back_populates='variable_definition_list')
|
||||
tool_id = db.Column(db.Integer, db.ForeignKey('tool.id'))
|
||||
tool = db.relationship('Tool')
|
||||
http_request_header_manager_list = db.relationship('HTTPRequestHeaderManagerList',
|
||||
back_populates='http_request_header_manager_tool',
|
||||
cascade='all, delete-orphan')
|
||||
|
||||
@property
|
||||
def variables(self):
|
||||
return [{
|
||||
'name': row.name,
|
||||
'value': row.value,
|
||||
'description': row.description,
|
||||
} for row in self.http_request_header_manager_list]
|
||||
|
||||
@classmethod
|
||||
def new_tool(cls):
|
||||
"""新增默认"""
|
||||
http_request_header_manager_tool = cls()
|
||||
http_request_header_manager_tool.http_request_header_manager_list = []
|
||||
http_request_header_manager_tool.http_request_header_manager_list.append(
|
||||
HTTPRequestHeaderManagerList(name='header_name', value='header_value', description='')
|
||||
)
|
||||
db.session.add(http_request_header_manager_tool)
|
||||
db.session.commit()
|
||||
return http_request_header_manager_tool
|
||||
|
||||
@classmethod
|
||||
def update(cls, name, description, tool_id, variables):
|
||||
"""
|
||||
更新工具数据
|
||||
:param tool_id: 工具编号
|
||||
:type tool_id: int
|
||||
:param name: 名称
|
||||
:type name: str
|
||||
:param description: 注释
|
||||
:type description: str
|
||||
:param variables: 请求头键值对列表
|
||||
:type variables: List[Mapping[str, str]]
|
||||
"""
|
||||
tool = Tool.query.filter_by(id=tool_id).first()
|
||||
if tool:
|
||||
tool.name = name
|
||||
tool.description = description
|
||||
http_request_header_manager_tool = tool.specific_tool
|
||||
http_request_header_manager_tool.http_request_header_manager_list = []
|
||||
for var in variables:
|
||||
http_request_header_manager_tool.http_request_header_manager_list.append(
|
||||
HTTPRequestHeaderManagerList(name=var.get('name', ''),
|
||||
value=var.get('value', ''),
|
||||
description=var.get('description', ''))
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def add(cls, name, description, variables, status=STATUS.NORMAL):
|
||||
"""
|
||||
新增一条工具数据
|
||||
:param name: 名称
|
||||
:type name: str
|
||||
:param description: 注释
|
||||
:type description: str
|
||||
:param variables: 请求头键值对
|
||||
:type variables: List[Mapping[str, str]]
|
||||
:param status: 案例状态(删除 正常)
|
||||
:type status: str
|
||||
"""
|
||||
tool = Tool(
|
||||
name=name,
|
||||
description=description,
|
||||
status=status,
|
||||
tool_type=TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER,
|
||||
)
|
||||
http_request_header_manager_tool = cls()
|
||||
http_request_header_manager_tool.http_request_header_manager_list = []
|
||||
for var in variables:
|
||||
http_request_header_manager_tool.http_request_header_manager_list.append(
|
||||
HTTPRequestHeaderManagerList(name=var.get('name', ''),
|
||||
value=var.get('value', ''),
|
||||
description=var.get('description', ''))
|
||||
)
|
||||
http_request_header_manager_tool.tool = tool
|
||||
db.session.add(tool)
|
||||
db.session.add(http_request_header_manager_tool)
|
||||
db.session.commit()
|
||||
return http_request_header_manager_tool
|
||||
|
||||
def copy_from_self(self):
|
||||
"""
|
||||
复制一个新的工具
|
||||
:return: 新的工具
|
||||
:rtype: Tool
|
||||
"""
|
||||
# 先获取变量键值对数据
|
||||
copy_tool = self.add(
|
||||
# Tool
|
||||
name='Copy' + self.tool.name,
|
||||
description=self.tool.description,
|
||||
status=self.tool.status,
|
||||
# HTTPRequestHeaderManagerTool
|
||||
variables=self.variables,
|
||||
)
|
||||
return copy_tool
|
||||
|
||||
|
||||
class HTTPRequestHeaderManagerList(db.Model):
|
||||
"""
|
||||
字段说明
|
||||
name: 名称
|
||||
value: 值
|
||||
description: 注释
|
||||
关系说明
|
||||
http_request_header_manager_tool: HTTP请求头数据列表对应的HTTP请求头管理工具对象 HTTPRequestHeaderManagerList:HTTPRequestHeaderManagerTool is N:1
|
||||
"""
|
||||
# 需要转换为json数据格式的字段
|
||||
render_field_list = ['name', 'value', 'description']
|
||||
# filed
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(512), nullable=False, default='', server_default='')
|
||||
value = db.Column(db.String(512), nullable=False, default='', server_default='')
|
||||
description = db.Column(db.Text, nullable=False, default='', server_default='')
|
||||
|
||||
# relationship
|
||||
http_request_header_manager_tool_id = db.Column(db.Integer, db.ForeignKey('http_request_header_manager_tool.id'))
|
||||
http_request_header_manager_tool = db.relationship('HTTPRequestHeaderManagerTool',
|
||||
back_populates='http_request_header_manager_list')
|
||||
|
||||
@property
|
||||
def name_(self):
|
||||
return _p(self.name)
|
||||
|
||||
@property
|
||||
def value_(self):
|
||||
return _p(self.value)
|
||||
|
||||
|
||||
class Case(db.Model):
|
||||
|
@ -2983,6 +3132,10 @@ class ReportToolData(db.Model):
|
|||
back_populates='report_tool_data',
|
||||
uselist=False,
|
||||
cascade='all, delete-orphan')
|
||||
report_http_request_header_manager_tool_data = db.relationship('ReportHTTPRequestHeaderManagerToolData',
|
||||
back_populates='report_tool_data',
|
||||
uselist=False,
|
||||
cascade='all, delete-orphan')
|
||||
|
||||
@classmethod
|
||||
def add(cls, tool, report_id, dispatcher_detail_id):
|
||||
|
@ -2996,6 +3149,9 @@ class ReportToolData(db.Model):
|
|||
ReportScriptToolData.add(script=tool.specific_tool.script, report_tool_data_id=report_tool_data.id)
|
||||
elif tool.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
|
||||
ReportVariableDefinitionToolData.add(variables=tool.specific_tool.variables, report_tool_data_id=report_tool_data.id)
|
||||
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
ReportHTTPRequestHeaderManagerToolData.add(variables=tool.specific_tool.variables,
|
||||
report_tool_data_id=report_tool_data.id)
|
||||
return report_tool_data
|
||||
|
||||
|
||||
|
@ -3076,6 +3232,53 @@ class ReportVariableDefinitionToolListData(db.Model):
|
|||
back_populates='report_variable_definition_tool_data_list')
|
||||
|
||||
|
||||
class ReportHTTPRequestHeaderManagerToolData(db.Model):
|
||||
# field
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
# relationship
|
||||
report_tool_data_id = db.Column(db.Integer, db.ForeignKey('report_tool_data.id'))
|
||||
report_tool_data = db.relationship('ReportToolData', back_populates='report_http_request_header_manager_tool_data')
|
||||
report_http_request_header_manager_tool_list_data = db.relationship('ReportHTTPRequestHeaderManagerToolListData',
|
||||
back_populates='report_http_request_header_manager_tool_data',
|
||||
cascade='all, delete-orphan')
|
||||
|
||||
@property
|
||||
def variables(self):
|
||||
return [{
|
||||
'name': row.name,
|
||||
'value': row.value,
|
||||
'description': row.description,
|
||||
} for row in self.report_http_request_header_manager_tool_list_data]
|
||||
|
||||
@classmethod
|
||||
def add(cls, variables, report_tool_data_id):
|
||||
report_http_request_header_manager_tool_data = ReportHTTPRequestHeaderManagerToolData(report_tool_data_id=report_tool_data_id)
|
||||
db.session.add(report_http_request_header_manager_tool_data)
|
||||
db.session.commit() # commit后report_http_request_header_manager_tool_data.id才有值,否则为None
|
||||
for variable in variables:
|
||||
db.session.add(ReportHTTPRequestHeaderManagerToolListData(
|
||||
name=variable.get('name', ''),
|
||||
value=variable.get('value', ''),
|
||||
description=variable.get('description', ''),
|
||||
report_http_request_header_manager_tool_data_id=report_http_request_header_manager_tool_data.id,
|
||||
))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
class ReportHTTPRequestHeaderManagerToolListData(db.Model):
|
||||
# field
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(512), nullable=False, default='', server_default='')
|
||||
value = db.Column(db.String(512), nullable=False, default='', server_default='')
|
||||
description = db.Column(db.Text, nullable=False, default='', server_default='')
|
||||
|
||||
# relationship
|
||||
report_http_request_header_manager_tool_data_id = db.Column(db.Integer, db.ForeignKey('report_http_request_header_manager_tool_data.id'))
|
||||
report_http_request_header_manager_tool_data = db.relationship('ReportHTTPRequestHeaderManagerToolData',
|
||||
back_populates='report_http_request_header_manager_tool_list_data')
|
||||
|
||||
|
||||
class Scheduler(db.Model):
|
||||
"""
|
||||
调度定时任务
|
||||
|
|
|
@ -19,7 +19,7 @@ from app.utils.util import get_form_from_request, exception_handle
|
|||
from app.models import Case, Project, Module, Scene, HTTPCase, SSHCase, SQLCase, Dispatcher, DispatcherDetail, Report, \
|
||||
SubElementInLogicController, LogicController, IfController, WhileController, LoopController, SimpleController, \
|
||||
Scheduler, DingTalkRobotSetting, DingTalkRobotSettingAssociationProject, DebugCase, Tool, TimerTool, ScriptTool, \
|
||||
VariableDefinitionTool, EmailReceiverSetting, EmailReceiverSettingAssociationProject
|
||||
VariableDefinitionTool, EmailReceiverSetting, EmailReceiverSettingAssociationProject, HTTPRequestHeaderManagerTool
|
||||
from app.template_global import render_to_json
|
||||
from app.extensions import http_cookie_manager, dispatcher_scheduler
|
||||
from app.template_global import sort_by_order_in_project, sort_by_order_in_module, sort_by_order_in_logic_controller
|
||||
|
@ -761,6 +761,39 @@ def save_variable_definition_tool():
|
|||
})
|
||||
|
||||
|
||||
@bp.route('/tool/http_request_header_manager/save', methods=['POST'])
|
||||
@login_required
|
||||
def save_http_request_header_manager_tool():
|
||||
# 参数校验
|
||||
exist, form_tool_id = get_form_from_request(request, 'tool_id')
|
||||
if not exist: return form_tool_id
|
||||
exist, form_tool_name = get_form_from_request(request, 'tool_name')
|
||||
if not exist: return form_tool_name
|
||||
exist, form_tool_description = get_form_from_request(request, 'tool_description')
|
||||
if not exist: return form_tool_description
|
||||
exist, form_vars = get_form_from_request(request, 'vars')
|
||||
if not exist: return form_vars
|
||||
try:
|
||||
variables = json.loads(form_vars)
|
||||
HTTPRequestHeaderManagerTool.update(
|
||||
tool_id=form_tool_id,
|
||||
name=form_tool_name,
|
||||
description=form_tool_description,
|
||||
variables=variables,
|
||||
)
|
||||
except Exception as e:
|
||||
exception_handle(current_app, e)
|
||||
return jsonify({
|
||||
'error_no': -1,
|
||||
'error_msg': '错误信息 [' + repr(e) + ']',
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
'error_no': 0,
|
||||
'error_msg': '',
|
||||
})
|
||||
|
||||
|
||||
@bp.route('/tool/script/run', methods=['POST'])
|
||||
@login_required
|
||||
def run_script_tool():
|
||||
|
@ -775,7 +808,7 @@ def run_script_tool():
|
|||
'error_no': -1,
|
||||
'error_msg': '错误信息 [脚本工具状态不是正常状态 tool_id=%s, status=%s]' % (form_tool_id, tool.status),
|
||||
})
|
||||
result = ScriptToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.DEBUG).run()
|
||||
result = ScriptToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.DEBUG).run() # TODO BUG 未传project_id
|
||||
log_text = result.get('log_text', '')
|
||||
else:
|
||||
return jsonify({
|
||||
|
@ -2264,6 +2297,11 @@ def get_report_detail_tool():
|
|||
dispatcher_detail=dispatcher_detail,
|
||||
report_tool_data=report_tool_data)
|
||||
variables = report_tool_data.report_variable_definition_tool_data.variables
|
||||
elif report_tool_data.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
html_text = render_template('report/_report_detail_http_request_header_manager_tool.html',
|
||||
dispatcher_detail=dispatcher_detail,
|
||||
report_tool_data=report_tool_data)
|
||||
variables = report_tool_data.report_http_request_header_manager_tool_data.variables
|
||||
else:
|
||||
html_text = ''
|
||||
except Exception as e:
|
||||
|
@ -2508,6 +2546,9 @@ def tool():
|
|||
elif tool.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
|
||||
html_text = render_template('tool/variable_definition.html', tool=tool)
|
||||
data_variables = json.loads(render_to_json(tool.specific_tool.variable_definition_list))
|
||||
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
|
||||
html_text = render_template('tool/http_request_header_manager.html', tool=tool)
|
||||
data_variables = json.loads(render_to_json(tool.specific_tool.http_request_header_manager_list))
|
||||
else:
|
||||
return jsonify({
|
||||
'error_no': -1,
|
||||
|
|
|
@ -196,6 +196,9 @@ body {
|
|||
.icon-tool-variable-definition{
|
||||
background-image: url(/static/icon/variable.svg);
|
||||
}
|
||||
.icon-tool-http-request-header-manager{
|
||||
background-image: url(/static/icon/http-request-header.svg);
|
||||
}
|
||||
|
||||
/*div边框样式*/
|
||||
.border-left-primary {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" >
|
||||
<path d="M372.706 187.621v60.569h429.327v-60.569H372.706z m-185.096 0v60.208h125.356v-60.208H187.61z m740.386 185.096H64.212V64.223h863.783v308.494zM125.911 866.308H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.397H64.212v-61.699h61.699v61.699z m0 431.891H64.212v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m123.397 0h-61.699v-61.699h61.699v61.699z m123.398 0h-61.699v-61.699h61.699v61.699z m308.494 0H681.2v-61.699h61.699v61.699z m-123.397 0h-61.699v-61.699h61.699v61.699z m246.795 0h-61.699v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m0-61.698h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.397h-61.699v-61.699h61.699v61.699z" />
|
||||
</svg>
|
After Width: | Height: | Size: 969 B |
|
@ -233,6 +233,9 @@ function renderToolReportDetail(node){
|
|||
}else if(data.tool_type === 'VARIABLE_DEFINITION'){
|
||||
// 渲染VariableDefinitionTool工具组件页面
|
||||
renderVariableDefinitionToolPage(node.data.dispatcher_detail_id, data.variables);
|
||||
}else if(data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
|
||||
// 渲染HTTPRequestHeaderManagerTool工具组件页面
|
||||
renderHTTPRequestHeaderManagerToolPage(node.data.dispatcher_detail_id, data.variables);
|
||||
}
|
||||
resolve(['成功了', 'success']); // 也可以传递其他类型参数
|
||||
}else{
|
||||
|
@ -643,6 +646,81 @@ function renderVariableDefinitionToolPage(dispatcher_detail_id, data_variables)
|
|||
table_variable_definition = $container.handsontable(option_table_variable_definition).handsontable('getInstance');
|
||||
}
|
||||
}
|
||||
// 渲染HTTPRequestHeaderManagerTool工具组件页面
|
||||
function renderHTTPRequestHeaderManagerToolPage(dispatcher_detail_id, data_variables) {
|
||||
// HTTP请求头表格对象
|
||||
let table_http_request_header_manager = null;
|
||||
|
||||
// 渲染HTTP请求头表格
|
||||
renderHTTPRequestHeaderManagerTable();
|
||||
|
||||
// 渲染HTTP请求头表格
|
||||
function renderHTTPRequestHeaderManagerTable() {
|
||||
const option_table_http_request_header_manager = {
|
||||
data: data_variables,
|
||||
rowHeaders: true,
|
||||
// colHeaders: true,
|
||||
licenseKey: 'non-commercial-and-evaluation',
|
||||
// 表格宽度
|
||||
// width: '95vw', // 不指定宽度使其自适应容器
|
||||
// 拉伸方式
|
||||
stretchH: 'all',
|
||||
// tab键自动换行切换
|
||||
autoWrapRow: true,
|
||||
height: '55vh',
|
||||
// 最大行数
|
||||
maxRows: 999,
|
||||
// 允许手工移动行或列
|
||||
manualRowResize: true,
|
||||
manualColumnResize: true,
|
||||
// 列名
|
||||
colHeaders: [
|
||||
'名称',
|
||||
'值',
|
||||
'描述',
|
||||
],
|
||||
// 为列设置默认值
|
||||
dataSchema: {
|
||||
name: '',
|
||||
value: '',
|
||||
url_encode: false,
|
||||
content_type: 'text/plain',
|
||||
include_equals: true,
|
||||
},
|
||||
// 设置列数据类型
|
||||
columns: [
|
||||
{
|
||||
data: 'name',
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
data: 'value',
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
data: 'description',
|
||||
readOnly: true,
|
||||
},
|
||||
],
|
||||
// 列宽比例
|
||||
colWidths: [1, 1, 1],
|
||||
manualRowMove: true,
|
||||
manualColumnMove: false,
|
||||
// 右键菜单
|
||||
// contextMenu: ['row_above', 'row_below', '---------', 'remove_row', '---------', 'undo', 'redo', '---------', 'alignment', '---------', 'copy', 'cut'],
|
||||
// 列是否支持过滤
|
||||
filters: false,
|
||||
// 下拉菜单
|
||||
// dropdownMenu: ['make_read_only', '---------', 'alignment'],
|
||||
// 语言
|
||||
language: 'zh-CN',
|
||||
// 是否允许无效数据 默认 true
|
||||
allowInvalid: false,
|
||||
};
|
||||
let $container = $(`#table-http-request-header-manager-${dispatcher_detail_id}`);
|
||||
table_http_request_header_manager = $container.handsontable(option_table_http_request_header_manager).handsontable('getInstance');
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染报告图表
|
||||
function renderEcharts() {
|
||||
|
@ -792,6 +870,8 @@ function renderReportTree() {
|
|||
$element.css('display', '');
|
||||
if(element_type === 'TOOL' && node.data.tool_type === 'VARIABLE_DEFINITION'){
|
||||
$(`#table-variable-definition-${dispatcher_detail_id}`).handsontable('getInstance').render();
|
||||
}else if(element_type === 'TOOL' && node.data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
|
||||
$(`#table-http-request-header-manager-${dispatcher_detail_id}`).handsontable('getInstance').render();
|
||||
}
|
||||
},
|
||||
1000,
|
||||
|
@ -873,6 +953,8 @@ function renderReportTree() {
|
|||
return 'icon-tool-script';
|
||||
}else if(tool_type === 'VARIABLE_DEFINITION'){
|
||||
return 'icon-tool-variable-definition';
|
||||
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
|
||||
return 'icon-tool-http-request-header-manager';
|
||||
}
|
||||
}else if(element_type === undefined) {
|
||||
return true;
|
||||
|
|
|
@ -474,6 +474,8 @@ function renderElementCopyTree() {
|
|||
return 'icon-tool-script';
|
||||
}else if(tool_type === 'VARIABLE_DEFINITION'){
|
||||
return 'icon-tool-variable-definition';
|
||||
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
|
||||
return 'icon-tool-http-request-header-manager';
|
||||
}
|
||||
}else if(element_type === undefined) {
|
||||
return true;
|
||||
|
@ -1509,6 +1511,8 @@ function showTool(tool_id, tool_type) {
|
|||
$element.css('display', '');
|
||||
if(tool_type === 'VARIABLE_DEFINITION'){
|
||||
$(`#table-variable-definition-${tool_id}`).handsontable('getInstance').render();
|
||||
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
|
||||
$(`#table-http-request-header-manager-${tool_id}`).handsontable('getInstance').render();
|
||||
}
|
||||
},
|
||||
1000,
|
||||
|
@ -1882,7 +1886,11 @@ function addToolElement(tool_id) {
|
|||
let element = getVariableDefinitionToolElement(data.tool_id);
|
||||
element.init(data.data_variables);
|
||||
element_tool_dict[data.tool_id] = element;
|
||||
}
|
||||
}else if(data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER') {
|
||||
let element = getHTTPRequestHeaderManagerToolElement(data.tool_id);
|
||||
element.init(data.data_variables);
|
||||
element_tool_dict[data.tool_id] = element;
|
||||
}
|
||||
resolve(['成功了', 'success']); // 也可以传递其他类型参数
|
||||
}else{
|
||||
message("工具组件加载失败: " + data.error_msg, "error");
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
function getHTTPRequestHeaderManagerToolElement(tool_id) {
|
||||
let element = new Object;
|
||||
element.dom = new Object;
|
||||
element.obj = new Object;
|
||||
|
||||
// 案例页面元素
|
||||
element.dom.$input_tool_name = $(`#input-tool-name-${tool_id}`);
|
||||
element.dom.$input_tool_description = $(`#input-tool-description-${tool_id}`);
|
||||
element.dom.$btn_tool_save = $(`#btn-tool-save-${tool_id}`);
|
||||
element.dom.$div_navigation_tool_name = $(`.tool-name[data-tool-id=${tool_id}]`);
|
||||
|
||||
// 对象
|
||||
element.obj.table_http_request_header_manager = null; // 变量定义表格
|
||||
|
||||
// 初始化
|
||||
element.init = function(data_variables) {
|
||||
// 事件绑定
|
||||
eventBinding();
|
||||
// 渲染HTTP请求头管理器表格
|
||||
renderHTTPRequestHeaderManagerTable(data_variables);
|
||||
};
|
||||
|
||||
// 事件绑定
|
||||
function eventBinding() {
|
||||
element.dom.$input_tool_name.on('change keyup', handleKeyUpAndChange);
|
||||
element.dom.$btn_tool_save.on('click', saveTool);
|
||||
|
||||
function handleKeyUpAndChange(){
|
||||
let tool_name = element.dom.$input_tool_name.val();
|
||||
element.dom.$div_navigation_tool_name.children().text(tool_name);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染HTTP请求头管理器表格
|
||||
function renderHTTPRequestHeaderManagerTable(data_variables) {
|
||||
const option_table_http_request_header_manager = {
|
||||
data: data_variables,
|
||||
rowHeaders: true,
|
||||
// colHeaders: true,
|
||||
licenseKey: 'non-commercial-and-evaluation',
|
||||
// 表格宽度
|
||||
// width: '95vw', // 不指定宽度使其自适应容器
|
||||
// 拉伸方式
|
||||
stretchH: 'all',
|
||||
// tab键自动换行切换
|
||||
autoWrapRow: true,
|
||||
height: '65vh',
|
||||
// 最大行数
|
||||
maxRows: 999,
|
||||
// 允许手工移动行或列
|
||||
manualRowResize: true,
|
||||
manualColumnResize: true,
|
||||
// 列名
|
||||
colHeaders: [
|
||||
'名称',
|
||||
'值',
|
||||
'描述',
|
||||
],
|
||||
// 为列设置默认值
|
||||
dataSchema: {
|
||||
name: '',
|
||||
value: '',
|
||||
url_encode: false,
|
||||
content_type: 'text/plain',
|
||||
include_equals: true,
|
||||
},
|
||||
// 设置列数据类型
|
||||
columns: [
|
||||
{
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
data: 'value',
|
||||
},
|
||||
{
|
||||
data: 'description',
|
||||
},
|
||||
],
|
||||
// 列宽比例
|
||||
colWidths: [1, 1, 1],
|
||||
manualRowMove: true,
|
||||
manualColumnMove: false,
|
||||
// 右键菜单
|
||||
contextMenu: ['row_above', 'row_below', '---------', 'remove_row', '---------', 'undo', 'redo', '---------', 'alignment', '---------', 'copy', 'cut'],
|
||||
// 列是否支持过滤
|
||||
filters: false,
|
||||
// 下拉菜单
|
||||
dropdownMenu: ['make_read_only', '---------', 'alignment'],
|
||||
// 语言
|
||||
language: 'zh-CN',
|
||||
// 是否允许无效数据 默认 true
|
||||
allowInvalid: false,
|
||||
};
|
||||
let $container = $(`#table-http-request-header-manager-${tool_id}`);
|
||||
element.obj.table_http_request_header_manager = $container.handsontable(option_table_http_request_header_manager).handsontable('getInstance');
|
||||
}
|
||||
|
||||
function saveTool() {
|
||||
let tool_name = element.dom.$input_tool_name.val();
|
||||
let tool_description = element.dom.$input_tool_description.val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/ajax/tool/http_request_header_manager/save',
|
||||
data: {
|
||||
tool_id: tool_id,
|
||||
tool_name: tool_name,
|
||||
tool_description: tool_description,
|
||||
vars: JSON.stringify(element.obj.table_http_request_header_manager.getSourceData()),
|
||||
},
|
||||
success: function (data, status, xhr) {
|
||||
if (data.error_no === 0){
|
||||
message('HTTP请求头保存成功', 'success');
|
||||
}else{
|
||||
message("HTTP请求头保存失败: " + data.error_msg, "error");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关键词查找
|
||||
element.mark = function (text) {
|
||||
// 匹配到则返回true
|
||||
let pat = new RegExp(text);
|
||||
let value = '';
|
||||
let markFlag = false;
|
||||
// 名称
|
||||
value = element.dom.$input_tool_name.val();
|
||||
if (pat.test(value)) return true;
|
||||
// 注释
|
||||
value = element.dom.$input_tool_description.val();
|
||||
if (pat.test(value)) return true;
|
||||
// 期望表格
|
||||
markFlag = false;
|
||||
value = element.obj.table_http_request_header_manager.getSourceData();
|
||||
$.each(value, function (index, row) {
|
||||
$.each(row, function (column, data) {
|
||||
if (pat.test(data)){
|
||||
markFlag = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (markFlag) return true;
|
||||
|
||||
// 未匹配到返回false
|
||||
return false;
|
||||
};
|
||||
|
||||
return element;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<div class="container-fluid report-detail-data" id="dispatcher-detail-{{ dispatcher_detail.id }}" data-element-type="TOOL" style="display: none;">
|
||||
<h4>定时器名称: {{ dispatcher_detail.element_name }}</h4>
|
||||
<h6>开始时间: {{ dispatcher_detail.start_time }}</h6>
|
||||
<h6>调度编号: {{ dispatcher_detail.dispatcher_id }}</h6>
|
||||
<h6>元素编号: {{ dispatcher_detail.element_id }}</h6>
|
||||
<h6>HTTP请求头管理器:</h6>
|
||||
<div class="container-fluid p-0 mt-2">
|
||||
<div id="table-http-request-header-manager-{{ dispatcher_detail.id }}"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -100,6 +100,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="v-pills-tool" role="tabpanel">
|
||||
<div class="btn btn-outline-primary" data-scene-id="{{ scene.id }}" onclick="addTool({{ scene.scene_controller.logic_controller.id }}, 'HTTP_REQUEST_HEADER_MANAGER')">
|
||||
<h5 class="text-left">
|
||||
HTTPRequestHeaderManager
|
||||
<svg class="icon float-right" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" >
|
||||
<path d="M372.706 187.621v60.569h429.327v-60.569H372.706z m-185.096 0v60.208h125.356v-60.208H187.61z m740.386 185.096H64.212V64.223h863.783v308.494zM125.911 866.308H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.397H64.212v-61.699h61.699v61.699z m0 431.891H64.212v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m123.397 0h-61.699v-61.699h61.699v61.699z m123.398 0h-61.699v-61.699h61.699v61.699z m308.494 0H681.2v-61.699h61.699v61.699z m-123.397 0h-61.699v-61.699h61.699v61.699z m246.795 0h-61.699v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m0-61.698h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.397h-61.699v-61.699h61.699v61.699z"></path>
|
||||
</svg>
|
||||
</h5>
|
||||
<p class="text-left">定义HTTP请求头.</p>
|
||||
</div>
|
||||
<div class="btn btn-outline-primary" data-scene-id="{{ scene.id }}" onclick="addTool({{ scene.scene_controller.logic_controller.id }}, 'VARIABLE_DEFINITION')">
|
||||
<h5 class="text-left">
|
||||
VariableDefinition
|
||||
|
|
|
@ -145,6 +145,7 @@ class="bg-gradient-grey"
|
|||
<script src="{{ url_for('static', filename='js/tool/timer.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/tool/script.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/tool/variable_definition.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/tool/http_request_header_manager.js') }}"></script>
|
||||
<script>
|
||||
let project_id = {{ project.id }};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<div class="row container-fluid element-data element-tool mt-2 ml-0" data-tool-id="{{ tool.id }}" data-tool-type="{{ tool.tool_type }}" style="display: none">
|
||||
<h4>HTTP请求头管理器</h4>
|
||||
<div class="input-group input-group-sm">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="input-tool-name-{{ tool.id }}">名称</label>
|
||||
</div>
|
||||
<input id="input-tool-name-{{ tool.id }}" type="text" class="form-control" placeholder="这里填写案例名称" value="{{ tool.name }}">
|
||||
</div>
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="input-tool-description-{{ tool.id }}">注释</label>
|
||||
</div>
|
||||
<input id="input-tool-description-{{ tool.id }}" type="text" class="form-control" placeholder="这里填写注释说明" value="{{ tool.description }}">
|
||||
</div>
|
||||
<div class="container-fluid d-flex align-items-center justify-content-between pr-0 mr-0 pl-0 ml-0 mt-2">
|
||||
<label class=" control-label">定义HTTP请求头:</label>
|
||||
<div class="btn-toolbar pr-0 mr-2" role="toolbar">
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btn-tool-save-{{ tool.id }}" type="button" class="btn btn-primary">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid p-0 mt-2">
|
||||
<div id="table-http-request-header-manager-{{ tool.id }}"></div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue