增加用例管理、步骤管理、用例调试等功能

This commit is contained in:
seagull 2019-03-15 15:39:33 +08:00
parent bcd6ef35fa
commit 764a6aab0e
58 changed files with 2778 additions and 681 deletions

View File

@ -707,7 +707,12 @@ insert into sys_dict_type values(9, '系统状态', 'sys_common_status', '0',
insert into sys_dict_type values(10, '用例类型', 'testmanagmt_case_type', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '用例步骤类型');
insert into sys_dict_type values(11, '步骤失败策略', 'testmanagmt_case_stepfailcontinue', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '步骤失败策略');
insert into sys_dict_type values(12, '模板参数类型', 'testmanagmt_templateparams_type', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模板参数类型');
insert into sys_dict_type
values(13, '步骤HTTP操作类型', 'testmanagmt_casestep_httpoperation', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '步骤关键字操作字典');
insert into sys_dict_type
values(14, '步骤Web UI操作类型', 'testmanagmt_casestep_uioperation', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '步骤关键字操作字典');
insert into sys_dict_type
values(15, '步骤移动端操作类型', 'testmanagmt_casestep_muioperation', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '步骤关键字操作字典');
-- ----------------------------
-- 22、字典数据表
-- ----------------------------
@ -770,6 +775,101 @@ insert into sys_dict_data values(35, 3, 'JSONARR对象', '2', 'testmanagmt_tem
insert into sys_dict_data values(36, 4, 'File对象', '3', 'testmanagmt_templateparams_type', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模板参数类型 File对象');
insert into sys_dict_data values(37, 5, 'Number对象', '4', 'testmanagmt_templateparams_type', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模板参数类型 Number对象');
insert into sys_dict_data values(38, 6, 'Boolean对象', '5', 'testmanagmt_templateparams_type', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模板参数类型 Boolean对象');
insert into sys_dict_data values(39, 1, 'HttpClientPost发送Post请求', 'HttpClientPost', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpClient发送post请求');
insert into sys_dict_data values(40, 2, 'HttpClientGet发送Get请求', 'HttpClientGet', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpClient发送get请求');
insert into sys_dict_data values(41, 3, 'HttpClientPostJSON发送JSON格式Post请求', 'HttpClientPostJSON', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpClient发送JSON格式post请求');
insert into sys_dict_data values(42, 4, 'httpClientPut发送Put请求', 'httpClientPut', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用httpClientPut发送put请求');
insert into sys_dict_data values(43, 5, 'httpClientPutJson发送JSON格式Put请求', 'httpClientPutJson', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用httpClientPutJson发送put请求');
insert into sys_dict_data values(44, 6, 'httpClientUploadFile上传文件', 'httpClientUploadFile', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用httpClientUploadFile上传文件');
insert into sys_dict_data values(45, 7, 'HttpURLPost发送Post请求', 'HttpURLPost', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpURLConnection发送post请求');
insert into sys_dict_data values(46, 8, 'URLPost发送Post请求', 'URLPost', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用URLConnection发送post');
insert into sys_dict_data values(47, 9, 'GetAndSaveFile保存下载文件到客户端', 'GetAndSaveFile', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '发送get请求保存下载文件到客户端');
insert into sys_dict_data values(48, 10, 'HttpURLGet发送Get请求', 'HttpURLGet', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpURLConnection发送get请求');
insert into sys_dict_data values(49, 11, 'URLGet发送Get请求', 'URLGet', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用URLConnection发送get请求');
insert into sys_dict_data values(50, 12, 'HttpURLDelete发送Delete请求', 'HttpURLDelete', 'testmanagmt_casestep_httpoperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '使用HttpURLDelete发送delete请求');
insert into sys_dict_data values(52, 1, 'Click点击对象', 'click', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '点击对象');
insert into sys_dict_data values(53, 2, 'Sendkeys输入', 'sendkeys', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '输入');
insert into sys_dict_data values(54, 3, 'Clear清除输入框', 'clear', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '清除输入框');
insert into sys_dict_data values(55, 4, 'Gotoframe跳转iframe框架', 'gotoframe', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '跳转框架iframe');
insert into sys_dict_data values(56, 5, 'Isenabled判断对象是否可用', 'isenabled', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断对象是否可用');
insert into sys_dict_data values(57, 6, 'Isdisplayed判断对象是否可见', 'isdisplayed', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断对象是否可见');
insert into sys_dict_data values(58, 7, 'Exjsob针对对象执行JS脚本', 'exjsob', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '针对对象执行JS脚本');
insert into sys_dict_data values(59, 8, 'Gettext获取对象文本属性', 'gettext', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象文本属性');
insert into sys_dict_data values(60, 9, 'Gettagname获取对象标签类型', 'gettagname', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象标签类型');
insert into sys_dict_data values(61, 10, 'Getcaptcha获取对象中的验证码(识别率较低)', 'getcaptcha', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象中的验证码(识别率较低)');
insert into sys_dict_data values(62, 11, 'Selectbyvisibletext通过下拉框的文本进行选择', 'selectbyvisibletext', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的文本进行选择');
insert into sys_dict_data values(63, 12, 'Selectbyvalue通过下拉框的VALUE属性进行选择', 'selectbyvalue', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的VALUE属性进行选择');
insert into sys_dict_data values(64, 13, 'Selectbyindex通过下拉框的index属性进行选择(从0开始)', 'selectbyindex', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的index属性进行选择(从0开始)');
insert into sys_dict_data values(65, 14, 'Isselect判断是否已经被选择同用于单选\复选框', 'isselect', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断是否已经被选择,同用于单选\复选框');
insert into sys_dict_data values(66, 15, 'Open打开URL', 'open', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '打开URL');
insert into sys_dict_data values(67, 16, 'Exjs执行js脚本', 'exjs', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '执行js脚本');
insert into sys_dict_data values(68, 17, 'Gotodefaultcontent跳转回到默认iframe', 'gotodefaultcontent', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '跳转回到默认iframe');
insert into sys_dict_data values(69, 18, 'Gettitle获取窗口标题', 'gettitle', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取窗口标题');
insert into sys_dict_data values(70, 19, 'Getwindowhandle获取窗口句柄', 'getwindowhandle', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取窗口句柄');
insert into sys_dict_data values(71, 20, 'Gotowindow跳转窗口句柄', 'gotowindow', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '跳转窗口句柄');
insert into sys_dict_data values(72, 21, 'Timeout设置全局隐式等待时间(S)', 'timeout', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '设置全局隐式等待时间(S)');
insert into sys_dict_data values(73, 22, 'Alertaccept弹出框点击OK', 'alertaccept', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '弹出框点击OK');
insert into sys_dict_data values(74, 23, 'Alertdismiss弹出框点击取消', 'alertdismiss', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '弹出框点击取消');
insert into sys_dict_data values(75, 24, 'Alertgettext获取弹出框TEXT', 'alertgettext', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取弹出框TEXT');
insert into sys_dict_data values(76, 25, 'Mouselkclick模拟鼠标左键单击(可带页面对象)', 'mouselkclick', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标左键单击(可带页面对象)');
insert into sys_dict_data values(77, 26, 'Mouserkclick模拟鼠标右键单击(可带页面对象)', 'mouserkclick', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标右键单击(可带页面对象)');
insert into sys_dict_data values(78, 27, 'Mousedclick模拟鼠标双击(可带页面对象)', 'mousedclick', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标双击(可带页面对象)');
insert into sys_dict_data values(79, 28, 'Mouseclickhold模拟鼠标左键单击后不释放(可带页面对象)', 'mouseclickhold', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标左键单击后不释放(可带页面对象)');
insert into sys_dict_data values(80, 29, 'Mousedrag模拟鼠标拖拽(可带页面对象)', 'mousedrag', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标拖拽(可带页面对象)');
insert into sys_dict_data values(81, 30, 'Mouseto模拟鼠标移动到指定坐标(可带页面对象)', 'mouseto', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标移动到指定坐标(可带页面对象)');
insert into sys_dict_data values(82, 31, 'Mouserelease模拟鼠标释放(可带页面对象)', 'mouserelease', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟鼠标释放(可带页面对象)');
insert into sys_dict_data values(83, 32, 'Mousekey(tab)模拟键盘Tab键', 'mousekey(tab)', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟键盘Tab键');
insert into sys_dict_data values(84, 33, 'Mousekey(space)模拟键盘Space键', 'mousekey(space)', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟键盘Space键');
insert into sys_dict_data values(85, 34, 'Mousekey(ctrl)模拟键盘Ctrl键', 'mousekey(ctrl)', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟键盘Ctrl键');
insert into sys_dict_data values(86, 35, 'Mousekey(shift)模拟键盘Shift键', 'mousekey(shift)', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟键盘Shift键');
insert into sys_dict_data values(87, 36, 'Mousekey(enter)模拟键盘Enter键', 'mousekey(enter)', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '模拟键盘Enter键');
insert into sys_dict_data values(88, 37, 'Runcase调用指定接口|Web UI用例', 'runcase', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '调用指定接口|Web UI用例');
insert into sys_dict_data values(89, 38, 'Getattribute获取对象指定属性', 'getattribute', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象指定属性');
insert into sys_dict_data values(90, 39, 'Getcssvalue获取对象指定CSS属性值', 'getcssvalue', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象指定CSS属性值');
insert into sys_dict_data values(91, 40, 'Gotoparentframe跳转回到上一级iframe', 'gotoparentframe', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '跳转回到上一级iframe');
insert into sys_dict_data values(92, 41, 'Scrollto滚动到目标对象', 'scrollto', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '滚动到目标对象');
insert into sys_dict_data values(93, 42, 'Scrollintoview将目标对象滚动到可视', 'scrollintoview', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '将目标对象滚动到可视');
insert into sys_dict_data values(94, 43, 'Closewindow关闭当前浏览器窗口', 'closewindow', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '关闭当前浏览器窗口');
insert into sys_dict_data values(95, 44, 'Addcookie添加浏览器cookie', 'addcookie', 'testmanagmt_casestep_uioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '添加浏览器cookie');
insert into sys_dict_data values(96, 1, 'Selectbyvisibletext通过下拉框的文本进行选择', 'selectbyvisibletext', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的文本进行选择');
insert into sys_dict_data values(97, 2, 'Selectbyvalue通过下拉框的VALUE属性进行选择', 'selectbyvalue', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的VALUE属性进行选择');
insert into sys_dict_data values(98, 3, 'Selectbyindex通过下拉框的index属性进行选择(从0开始)', 'selectbyindex', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '通过下拉框的index属性进行选择(从0开始)');
insert into sys_dict_data values(99, 4, 'Isselect判断是否已经被选择同用于单选\复选框', 'isselect', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断是否已经被选择,同用于单选\复选框');
insert into sys_dict_data values(100, 5, 'Gettext获取对象文本属性', 'gettext', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象文本属性');
insert into sys_dict_data values(101, 6, 'Gettagname获取对象标签类型', 'gettagname', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象标签类型');
insert into sys_dict_data values(102, 7, 'Getattribute获取对象指定属性', 'getattribute', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象指定属性');
insert into sys_dict_data values(103, 8, 'Getcssvalue获取对象指定CSS属性值', 'getcssvalue', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取对象指定CSS属性值');
insert into sys_dict_data values(104, 9, 'Click点击对象', 'click', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '点击对象');
insert into sys_dict_data values(105, 10, 'Sendkeys输入', 'sendkeys', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '输入');
insert into sys_dict_data values(106, 11, 'Clear清除输入框', 'clear', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '清除输入框');
insert into sys_dict_data values(107, 12, 'Isenabled判断对象是否可用', 'isenabled', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断对象是否可用');
insert into sys_dict_data values(108, 13, 'Isdisplayed判断对象是否可见', 'isdisplayed', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '判断对象是否可见');
insert into sys_dict_data values(109, 14, 'Exjsob针对对象执行JS脚本', 'exjsob', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '针对对象执行JS脚本');
insert into sys_dict_data values(110, 15, 'Longpresselement长按指定页面对象(可设置时间)', 'longpresselement', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '长按指定页面对象(可设置时间)');
insert into sys_dict_data values(111, 16, 'Alertaccept弹出框点击OK', 'alertaccept', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '弹出框点击OK');
insert into sys_dict_data values(112, 17, 'Alertdismiss弹出框点击取消', 'alertdismiss', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '弹出框点击取消');
insert into sys_dict_data values(113, 18, 'Alertgettext获取弹出框TEXT', 'alertgettext', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取弹出框TEXT');
insert into sys_dict_data values(114, 19, 'Getcontexthandles获取指定context的值(参数指定1 第一个)', 'getcontexthandles', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取指定context的值(参数指定1 第一个)');
insert into sys_dict_data values(115, 20, 'Exjs执行JS脚本', 'exjs', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '执行JS脚本');
insert into sys_dict_data values(116, 21, 'Androidkeycode安卓模拟手机键盘发送指令同PressKeyCode', 'androidkeycode', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '安卓模拟手机键盘发送指令同PressKeyCode');
insert into sys_dict_data values(117, 22, 'Gotocontext跳转到指定的context', 'gotocontext', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '跳转到指定的context');
insert into sys_dict_data values(118, 23, 'Getcontext获取当前窗口的context', 'getcontext', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取当前窗口的context');
insert into sys_dict_data values(119, 24, 'Gettitle获取当前窗口的title', 'gettitle', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '获取当前窗口的title');
insert into sys_dict_data values(120, 25, 'Swipeup页面向上滑动(参数 持续时间|滚动次数)', 'swipeup', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '页面向上滑动(参数 持续时间|滚动次数)');
insert into sys_dict_data values(121, 26, 'Swipedown页面向下滑动(参数 持续时间|滚动次数)', 'swipedown', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '页面向下滑动(参数 持续时间|滚动次数)');
insert into sys_dict_data values(122, 27, 'Swipleft页面向左滑动(参数 持续时间|滚动次数)', 'swipleft', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '页面向左滑动(参数 持续时间|滚动次数)');
insert into sys_dict_data values(123, 28, 'Swipright页面向右滑动(参数 持续时间|滚动次数)', 'swipright', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '页面向右滑动(参数 持续时间|滚动次数)');
insert into sys_dict_data values(124, 29, 'Longpressxy长按指定坐标(参数 X坐标|Y坐标|持续时间(可选))', 'longpressxy', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '长按指定坐标(参数 X坐标|Y坐标|持续时间(可选))');
insert into sys_dict_data values(125, 30, 'Pressxy点击指定坐标(参数 X坐标|Y坐标)', 'pressxy', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '点击指定坐标(参数 X坐标|Y坐标)');
insert into sys_dict_data values(126, 31, 'Tapxy轻击指定坐标(参数 X坐标|Y坐标)', 'tapxy', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '轻击指定坐标(参数 X坐标|Y坐标)');
insert into sys_dict_data values(127, 32, 'JspressxyS方式点击指定坐标(参数 X坐标|Y坐标|持续时间(可选))', 'jspressxy', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', 'JS方式点击指定坐标(参数 X坐标|Y坐标|持续时间(可选))');
insert into sys_dict_data values(128, 33, 'Moveto拖动坐标(参数 startX,startY|X,Y|X,Y|X,Y...)', 'moveto', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '拖动坐标(参数 startX,startY|X,Y|X,Y|X,Y...)');
insert into sys_dict_data values(129, 34, 'Screenshot保存当前页面截图', 'screenshot', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '保存当前页面截图');
insert into sys_dict_data values(130, 35, 'Timeout设置全局页面加载&元素出现最大等待时间(S)', 'timeout', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '设置全局页面加载&元素出现最大等待时间(S)');
insert into sys_dict_data values(131, 36, 'HideKeyboard隐藏系统手机键盘', 'hideKeyboard', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '隐藏系统手机键盘');
insert into sys_dict_data values(132, 37, 'Runcase调用指定接口用例', 'runcase', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '调用指定接口用例');
insert into sys_dict_data values(133, 38, 'ExAdbShell执行安卓adb命令', 'exAdbShell', 'testmanagmt_casestep_muioperation', '', 'info', 'Y', '0', 'admin', '2019-02-13 10-27-32', 'luckyframe', '2019-02-13 10-27-32', '执行安卓adb命令');
-- ----------------------------
-- 23、参数配置表
@ -908,7 +1008,7 @@ create table sys_client
client_id int(8) not null AUTO_INCREMENT comment '客户端ID',
client_name varchar(30) not null comment '客户端名称',
client_ip varchar(30) not null comment '客户端IP',
status int(2) comment '客户端超时 0 正常 1 链接失败 2 状态未知',
status int(2) comment '客户端状态 0 正常 1 链接失败 2 状态未知',
checkinterval int(6) not null comment '检查客户端状态心跳间隔时间 单位:秒',
client_path varchar(100) comment '客户端测试驱动桩路径 多个;做分隔',
remark varchar(100) comment '备注',
@ -1033,3 +1133,18 @@ create table project_template_params
param_type int(4) not null comment '0 String 1 JSON对象 2 JSONARR对象 3 文件类型',
primary key (params_id)
) engine=innodb default charset=utf8 comment = '模板参数管理';
-- ----------------------------
-- 36、用例调试记录
-- ----------------------------
drop table if exists project_case_debug;
create table project_case_debug
(
debug_id int(8) not null AUTO_INCREMENT comment '调试ID',
case_id int(8) not null comment '用例ID',
user_id int(11) not null comment '用户ID',
debug_isend int(2) not null comment '调试结束标识 0 进行中 1结束 2异常',
log_level varchar(10) not null comment '日志级别 info 记录 warning 警告 error 异常',
log_detail varchar(5000) not null comment '日志',
primary key (debug_id)
) engine=innodb default charset=utf8 comment = '用例调试日志记录';

14
pom.xml
View File

@ -39,6 +39,7 @@
<jsoup.version>1.11.3</jsoup.version>
<poi.version>3.17</poi.version>
<oshi.version>3.9.1</oshi.version>
<httpclient.version>4.5.7</httpclient.version>
</properties>
<dependencies>
@ -260,6 +261,19 @@
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- httpclient工具 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- httpclient工具中上传文件需要MultipartEntityBuilder -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
</dependencies>

View File

@ -10,8 +10,10 @@ package com.luckyframe.common.constant;
* @date 2019年2月25日
*/
public class ClientConstants {
/** 客户端默认端口号 */
public final static String CLIENT_MONITOR_PORT = "6633";
/** 客户端名称是否唯一的返回结果码 */
/** 客户端名称是否唯一的返回结果码 */
public final static String CLIENT_NAME_UNIQUE = "0";
public final static String CLIENT_NAME_NOT_UNIQUE = "1";

View File

@ -367,6 +367,19 @@ public class Convert
return toStrArray(",", str);
}
/**
* 指定符号转换为String数组
* @param str
* @param setSymbol
* @return
* @author Seagull
* @date 2019年3月14日
*/
public static String[] toStrArrayBySymbol(String str,String setSymbol)
{
return toStrArray(setSymbol, str);
}
/**
* 转换为String数组<br>
*

View File

@ -0,0 +1,241 @@
package com.luckyframe.common.utils.client;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpEntity;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class HttpRequest {
/**
* 使用HttpClient以JSON格式发送post请求
* @param urlParam
* @param jsonparams
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws HttpHostConnectException
* @author Seagull
* @date 2019年3月15日
*/
public static String httpClientPost(String urlParam,String jsonparams) throws NoSuchAlgorithmException, KeyManagementException, HttpHostConnectException{
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
HttpPost httpPost = new HttpPost(urlParam);
httpPost.setHeader("Content-Type", "application/json");
// 构建请求参数
BufferedReader br = null;
try {
if(null!=jsonparams&&jsonparams.length()>0){
StringEntity entity = new StringEntity(jsonparams,"utf-8");
httpPost.setEntity(entity);
}
CloseableHttpResponse response = httpclient.execute(httpPost);
// 读取服务器响应数据
resultBuffer = new StringBuffer();
if(null!=response.getEntity()){
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
* 使用HttpClient以JSON格式发送get请求
* @param urlParam
* @param params
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws NoHttpResponseException
* @author Seagull
* @date 2019年3月15日
*/
public static String httpClientGet(String urlParam, Map<String, Object> params) throws NoSuchAlgorithmException, KeyManagementException,NoHttpResponseException {
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
BufferedReader br = null;
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry<String, Object> entry : params.entrySet()) {
sbParams.append(entry.getKey());
sbParams.append("=");
try {
sbParams.append(URLEncoder.encode(String.valueOf(entry.getValue()), "utf-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
sbParams.append("&");
}
}
if (sbParams != null && sbParams.length() > 0) {
urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1);
}
HttpGet httpGet = new HttpGet(urlParam);
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
// 读取服务器响应数据
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
resultBuffer = new StringBuffer();
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
* 上传文件
* @param urlParam
* @param loadpath
* @param file
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws HttpHostConnectException
* @author Seagull
* @date 2019年3月15日
*/
public static String httpClientUploadFile(String urlParam, String loadpath, File file) throws NoSuchAlgorithmException, KeyManagementException, HttpHostConnectException {
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
HttpPost httpPost = new HttpPost(urlParam);
// 构建请求参数
BufferedReader br = null;
try {
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
//设置请求的编码格式
entityBuilder.setCharset(Charset.forName("utf-8"));
entityBuilder.addBinaryBody("jarfile", file);
entityBuilder.addTextBody("loadpath", loadpath);
HttpEntity reqEntity =entityBuilder.build();
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
//从状态行中获取状态码
String responsecode = String.valueOf(response.getStatusLine().getStatusCode());
// 读取服务器响应数据
resultBuffer = new StringBuffer();
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
if(resultBuffer.length()==0){
resultBuffer.append("上传文件异常,响应码:"+responsecode);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
* 获取文件流
* @param urlParam
* @param params
* @return
* @throws IOException
* @throws HttpHostConnectException
* @author Seagull
* @date 2019年3月15日
*/
public static byte[] getFile(String urlParam, Map<String, Object> params) throws IOException, HttpHostConnectException{
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry<String, Object> entry : params.entrySet()) {
sbParams.append(entry.getKey());
sbParams.append("=");
try {
sbParams.append(URLEncoder.encode(String.valueOf(entry.getValue()), "utf-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
sbParams.append("&");
}
}
if (sbParams != null && sbParams.length() > 0) {
urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1);
}
URL urlConet = new URL(urlParam);
HttpURLConnection con = (HttpURLConnection)urlConet.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(4 * 1000);
InputStream inStream = con .getInputStream(); //通过输入流获取图片数据
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while( (len=inStream.read(buffer)) != -1 ){
outStream.write(buffer, 0, len);
}
inStream.close();
byte[] data = outStream.toByteArray();
return data;
}
}

View File

@ -0,0 +1,47 @@
package com.luckyframe.common.utils.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunBatchCaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String batchcase;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
public String getBatchcase() {
return batchcase;
}
public void setBatchcase(String batchcase) {
this.batchcase = batchcase;
}
}

View File

@ -0,0 +1,54 @@
package com.luckyframe.common.utils.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunCaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String testCaseExternalId;
private String version;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
public String getTestCaseExternalId() {
return testCaseExternalId;
}
public void setTestCaseExternalId(String testCaseExternalId) {
this.testCaseExternalId = testCaseExternalId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

View File

@ -0,0 +1,40 @@
package com.luckyframe.common.utils.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunTaskEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
}

View File

@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
* @date 2019年2月12日
*/
@Component
@ConfigurationProperties(prefix = "ruoyi")
@ConfigurationProperties(prefix = "luckyframe")
public class LuckyFrameConfig
{
/** 项目名称 */

View File

@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
@ -153,4 +155,20 @@ public class ClientController extends BaseController
{
return clientService.checkIpUnique(client);
}
/**
* 测试用例Debug运行
* @param listSteps
* @return
* @author Seagull
* @date 2019年3月14日
*/
@GetMapping("/getDriverPathList/{clientId}")
@ResponseBody
public String getDriverPathList(@PathVariable("clientId") Integer clientId)
{
List<String> driverPathList = clientService.selectClientDriverListById(clientId);
JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(driverPathList));
return jsonArray.toJSONString();
}
}

View File

@ -1,5 +1,7 @@
package com.luckyframe.project.system.client.domain;
import java.util.List;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.luckyframe.framework.web.domain.BaseEntity;
@ -20,7 +22,7 @@ public class Client extends BaseEntity
private String clientName;
/** 客户端IP */
private String clientIp;
/** 客户端超时 0 正常 1 链接失败 2 状态未知 */
/** 客户端状态 0 正常 1 链接失败 2 状态未知 */
private Integer status;
/** 检查客户端状态心跳间隔时间 单位:秒 */
private Integer checkinterval;
@ -30,6 +32,26 @@ public class Client extends BaseEntity
private String remark;
/** 所属项目组 */
private Integer[] projectIds;
/** 客户端状态 0 正常 1 链接失败 2 状态未知 */
private String statusStr;
/** 客户端状态 0 正常 1 链接失败 2 状态未知 */
private List<String> clientPathList;
public List<String> getClientPathList() {
return clientPathList;
}
public void setClientPathList(List<String> clientPathList) {
this.clientPathList = clientPathList;
}
public String getStatusStr() {
return statusStr;
}
public void setStatusStr(String statusStr) {
this.statusStr = statusStr;
}
public void setClientId(Integer clientId)
{

View File

@ -2,6 +2,7 @@ package com.luckyframe.project.system.client.mapper;
import java.util.List;
import com.luckyframe.project.system.client.domain.Client;
import com.luckyframe.project.system.client.domain.ClientProject;
/**
@ -77,5 +78,14 @@ public interface ClientProjectMapper
* @date 2019年2月28日
*/
public int selectClientProjectCountByProjectId(Integer projectId);
/**
* 根据projectId查询客户端列表
* @param projectId
* @return
* @author Seagull
* @date 2019年3月14日
*/
public List<Client> selectClientsByProjectId(int projectId);
}

View File

@ -1,6 +1,7 @@
package com.luckyframe.project.system.client.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
@ -41,6 +42,22 @@ public class ClientServiceImpl implements IClientService
return clientMapper.selectClientById(clientId);
}
/**
* 根据客户端ID获取驱动路径列表
* @param clientId
* @return
* @author Seagull
* @date 2019年3月14日
*/
@Override
public List<String> selectClientDriverListById(Integer clientId)
{
Client client = clientMapper.selectClientById(clientId);
String[] clientPath=Convert.toStrArrayBySymbol(client.getClientPath(), ";");
List<String> clientPathList = Arrays.asList(clientPath);
return clientPathList;
}
/**
* 查询客户端管理列表
*
@ -154,4 +171,41 @@ public class ClientServiceImpl implements IClientService
}
return ClientConstants.CLIENT_IP_UNIQUE;
}
/**
* 根据项目ID查询所有客户端列表(打标记)
* @param projectId
* @return
* @author Seagull
* @date 2019年3月14日
*/
@Override
public List<Client> selectClientsByProjectId(int projectId)
{
ClientProject clientProject = new ClientProject();
clientProject.setProjectId(projectId);;
List<ClientProject> clientProjects = clientProjectMapper.selectClientProjectList(clientProject);
List<Client> clients = clientMapper.selectClientList(new Client());
List<Client> returnClientProjects = new ArrayList<Client>();
for (ClientProject cp : clientProjects)
{
for (Client client : clients)
{
if (cp.getClientId() == client.getClientId())
{
int status=client.getStatus();
if(status==0){
client.setStatusStr(" 状态正常");
}else if(status==1){
client.setStatusStr(" 状态异常");
}else{
client.setStatusStr(" 状态未知");
}
returnClientProjects.add(client);
break;
}
}
}
return returnClientProjects;
}
}

View File

@ -19,6 +19,15 @@ public interface IClientService
*/
public Client selectClientById(Integer clientId);
/**
* 根据客户端ID获取驱动路径列表
* @param clientId
* @return
* @author Seagull
* @date 2019年3月14日
*/
public List<String> selectClientDriverListById(Integer clientId);
/**
* 查询客户端管理列表
*
@ -68,4 +77,13 @@ public interface IClientService
* @date 2019年2月25日
*/
public String checkIpUnique(Client client);
/**
* 根据项目ID查询所有客户端列表(打标记)
* @param projectId
* @return
* @author Seagull
* @date 2019年3月14日
*/
public List<Client> selectClientsByProjectId(int projectId);
}

View File

@ -1,6 +1,7 @@
package com.luckyframe.project.system.dict.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -10,6 +11,9 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
@ -18,6 +22,7 @@ import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.framework.web.page.TableDataInfo;
import com.luckyframe.project.system.dict.domain.DictData;
import com.luckyframe.project.system.dict.service.IDictDataService;
import com.luckyframe.project.system.dict.service.IDictTypeService;
/**
* 数据字典信息
@ -113,4 +118,47 @@ public class DictDataController extends BaseController
{
return toAjax(dictDataService.deleteDictDataByIds(ids));
}
/**
* Ajax前台获取操作字典
* @param stepType
* @return
* @author Seagull
* @date 2019年3月12日
*/
@GetMapping("/getDictDataListByStepType/{stepType}")
@ResponseBody
public String getDictDataListByStepType(@PathVariable("stepType") Integer stepType) {
String str = "{\"message\": \"\",\"value\": ,\"code\": 200,\"redirect\": \"\" }";
try {
JSONObject json = new JSONObject();
DictData dictData=new DictData();
if(stepType==0){
dictData.setDictType("testmanagmt_casestep_httpoperation");
}else if(stepType==1){
dictData.setDictType("testmanagmt_casestep_uioperation");
}else if(stepType==3){
dictData.setDictType("testmanagmt_casestep_muioperation");
}else{
dictData.setDictType("9999999999999999999999999999999999");
}
List<DictData> ddlist = dictDataService.selectDictDataList(dictData);
JSONArray jsonarr = new JSONArray();
for(DictData obdd:ddlist){
JSONObject jo = new JSONObject();
jo.put("name", obdd.getDictValue());
jo.put("description", obdd.getRemark());
jsonarr.add(jo);
}
String recordJson = jsonarr.toString();
json = JSONObject.parseObject("{\"message\": \"\",\"value\": "+recordJson+",\"code\": 200,\"redirect\": \"\" }");
str=json.toString();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
}

View File

@ -25,7 +25,7 @@ public class IndexController extends BaseController
private IMenuService menuService;
@Autowired
private LuckyFrameConfig ruoyiConfig;
private LuckyFrameConfig lfConfig;
// 系统首页
@GetMapping("/index")
@ -37,7 +37,7 @@ public class IndexController extends BaseController
List<Menu> menus = menuService.selectMenusByUser(user);
mmap.put("menus", menus);
mmap.put("user", user);
mmap.put("copyrightYear", ruoyiConfig.getCopyrightYear());
mmap.put("copyrightYear", lfConfig.getCopyrightYear());
return "index";
}
@ -45,7 +45,7 @@ public class IndexController extends BaseController
@GetMapping("/system/main")
public String main(ModelMap mmap)
{
mmap.put("version", ruoyiConfig.getVersion());
mmap.put("version", lfConfig.getVersion());
return "main";
}
}

View File

@ -6,12 +6,15 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.luckyframe.common.utils.ServletUtils;
import com.luckyframe.common.utils.StringUtils;
import com.luckyframe.framework.config.LuckyFrameConfig;
import com.luckyframe.framework.web.controller.BaseController;
import com.luckyframe.framework.web.domain.AjaxResult;
@ -23,15 +26,19 @@ import com.luckyframe.framework.web.domain.AjaxResult;
@Controller
public class LoginController extends BaseController
{
@Autowired
private LuckyFrameConfig lfConfig;
@GetMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response)
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
{
// 如果是Ajax请求返回Json字符串
if (ServletUtils.isAjaxRequest(request))
{
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
}
mmap.put("copyrightYear", lfConfig.getCopyrightYear());
mmap.put("version", lfConfig.getVersion());
return "login";
}

View File

@ -21,7 +21,9 @@ import com.luckyframe.framework.web.page.TableDataInfo;
import com.luckyframe.project.system.project.domain.Project;
import com.luckyframe.project.system.project.service.IProjectService;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCase;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseService;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseStepsService;
import com.luckyframe.project.testmanagmt.projectCaseModule.domain.ProjectCaseModule;
import com.luckyframe.project.testmanagmt.projectCaseModule.service.IProjectCaseModuleService;
@ -40,6 +42,9 @@ public class ProjectCaseController extends BaseController
@Autowired
private IProjectCaseService projectCaseService;
@Autowired
private IProjectCaseStepsService projectCaseStepsService;
@Autowired
private IProjectService projectService;
@ -137,6 +142,56 @@ public class ProjectCaseController extends BaseController
return toAjax(projectCaseService.updateProjectCase(projectCase));
}
/**
* 复制用例
* @param caseId
* @param mmap
* @return
* @author Seagull
* @date 2019年3月13日
*/
@GetMapping("/copy/{caseId}")
public String copy(@PathVariable("caseId") Integer caseId, ModelMap mmap)
{
ProjectCase projectCase = projectCaseService.selectProjectCaseById(caseId);
projectCase.setCaseName("Copy【"+projectCase.getCaseName()+"");
List<Project> projects=projectService.selectProjectAll(projectCase.getProjectId());
mmap.put("projects", projects);
if(projects.size()>0){
ProjectCaseModule projectCaseModule = projectCaseModuleService.selectProjectCaseModuleParentZeroByProjectId(projects.get(0).getProjectId());
mmap.put("projectCaseModule", projectCaseModule);
}
mmap.put("projectCase", projectCase);
mmap.put("projectCaseModule", projectCase.getProjectCaseModule());
return prefix + "/copy";
}
/**
* 复制协议模板
* @param projectProtocolTemplate
* @return
* @author Seagull
* @date 2019年3月9日
*/
@RequiresPermissions("testmanagmt:projectCase:add")
@Log(title = "项目测试用例管理", businessType = BusinessType.INSERT)
@PostMapping("/copy")
@ResponseBody
public AjaxResult copySave(ProjectCase projectCase)
{
ProjectCaseSteps projectCaseSteps = new ProjectCaseSteps();
projectCaseSteps.setCaseId(projectCase.getCaseId());
List<ProjectCaseSteps> listSteps = projectCaseStepsService.selectProjectCaseStepsList(projectCaseSteps);
projectCase.setCaseId(0);
int num=projectCaseService.insertProjectCase(projectCase);
for(ProjectCaseSteps step:listSteps){
step.setStepId(0);
step.setCaseId(projectCase.getCaseId());
projectCaseStepsService.insertProjectCaseSteps(step);
}
return toAjax(num+listSteps.size());
}
/**
* 删除项目测试用例管理
*/

View File

@ -0,0 +1,179 @@
package com.luckyframe.project.testmanagmt.projectCase.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import com.luckyframe.common.constant.ClientConstants;
import com.luckyframe.common.utils.StringUtils;
import com.luckyframe.common.utils.client.HttpRequest;
import com.luckyframe.common.utils.security.ShiroUtils;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
import com.luckyframe.framework.web.controller.BaseController;
import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.project.system.client.domain.Client;
import com.luckyframe.project.system.client.service.IClientService;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCase;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseDebug;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseDebugService;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseService;
/**
* 用例调试日志记录 信息操作处理
*
* @author luckyframe
* @date 2019-03-14
*/
@Controller
@RequestMapping("/testmanagmt/projectCaseDebug")
public class ProjectCaseDebugController extends BaseController
{
private String prefix = "testmanagmt/projectCase";
@Autowired
private IProjectCaseDebugService projectCaseDebugService;
@Autowired
private IProjectCaseService projectCaseService;
@Autowired
private IClientService clientService;
/**
* 测试用例Debug
* @param caseId
* @param mmap
* @return
* @author Seagull
* @date 2019年3月14日
*/
@GetMapping("/projectCaseDebug/{caseId}")
public String projectCaseDebug(@PathVariable("caseId") Integer caseId, ModelMap mmap)
{
ProjectCase projectCase = projectCaseService.selectProjectCaseById(caseId);
ProjectCaseDebug projectCaseDebug=new ProjectCaseDebug();
projectCaseDebug.setCaseId(caseId);
projectCaseDebug.setUserId(ShiroUtils.getUserId().intValue());
List<Client> clients=clientService.selectClientsByProjectId(projectCase.getProjectId());
if(clients.size()>0){
List<String> driverPathList=clientService.selectClientDriverListById(clients.get(0).getClientId());
mmap.put("driverPathList", driverPathList);
}
mmap.put("projectCaseDebug", projectCaseDebug);
mmap.put("clients", clients);
return prefix + "/debugCase";
}
/**
* 测试用例Debug运行
* @param listSteps
* @return
* @author Seagull
* @date 2019年3月14日
*/
@RequiresPermissions("testmanagmt:projectCase:edit")
@Log(title = "测试用例调试(Debug)", businessType = BusinessType.OTHER)
@PostMapping("/debugCaseRun")
@ResponseBody
public String debugCaseRun(ProjectCaseDebug projectCaseDebug)
{
JSONObject json = new JSONObject();
try {
projectCaseDebugService.deleteProjectCaseDebugById(projectCaseDebug);
if(StringUtils.isEmpty(projectCaseDebug.getDriverPath())){
projectCaseDebug.setDriverPath("/TestDriven");
}
String debugCaseJson=JSONObject.toJSONString(projectCaseDebug);
Client client = clientService.selectClientById(projectCaseDebug.getClientId());
String url= "http://"+client.getClientIp()+":"+ClientConstants.CLIENT_MONITOR_PORT+"/webdebugcase";
String result=HttpRequest.httpClientPost(url, debugCaseJson);
if(result.contains("正常")){
json.put("status", "info");
}else{
json.put("status", "warning");
}
json.put("ms", result);
return json.toString();
} catch (Exception e) {
e.printStackTrace();
json.put("status", "error");
json.put("ms", "调试用例启动出现异常!");
return json.toString();
}
}
/**
* 获取用例调试日志
* @param listSteps
* @return
* @author Seagull
* @date 2019年3月14日
*/
@RequiresPermissions("testmanagmt:projectCase:edit")
@PostMapping("/refreshDebugLog")
@ResponseBody
public String refreshDebugLog(ProjectCaseDebug projectCaseDebug)
{
JSONObject json = new JSONObject();
/*调试结束标识 0 进行中 1结束 2异常*/
String status="0";
String ms="获取调试日志失败!";
try {
List<ProjectCaseDebug> logList=projectCaseDebugService.selectProjectCaseDebugList(projectCaseDebug);
StringBuilder stringBuilder = new StringBuilder();
for(ProjectCaseDebug log:logList){
stringBuilder.append(log.getLogLevel()+": "+log.getLogDetail()+"</br>");
status=log.getDebugIsend().toString();
}
ms=stringBuilder.toString();
json.put("status", status);
json.put("ms", ms);
return json.toString();
} catch (Exception e) {
e.printStackTrace();
json.put("status", "2");
json.put("ms", "获取调试日志出现异常!");
return json.toString();
}
}
/**
* 新增保存用例调试日志记录
*/
@Log(title = "用例调试日志记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(ProjectCaseDebug projectCaseDebug)
{
return toAjax(projectCaseDebugService.insertProjectCaseDebug(projectCaseDebug));
}
/**
* 删除用例调试日志记录
*/
@Log(title = "用例调试日志记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(projectCaseDebugService.deleteProjectCaseDebugByIds(ids));
}
}

View File

@ -0,0 +1,93 @@
package com.luckyframe.project.testmanagmt.projectCase.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
import com.luckyframe.framework.web.controller.BaseController;
import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCase;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseService;
import com.luckyframe.project.testmanagmt.projectCase.service.IProjectCaseStepsService;
/**
* 测试用例步骤管理 信息操作处理
*
* @author luckyframe
* @date 2019-02-26
*/
@Controller
@RequestMapping("/testmanagmt/projectCaseSteps")
public class ProjectCaseStepsController extends BaseController
{
private String prefix = "testmanagmt/projectCase";
@Autowired
private IProjectCaseStepsService projectCaseStepsService;
@Autowired
private IProjectCaseService projectCaseService;
/**
* 修改测试用例步骤管理
*/
@GetMapping("/edit/{caseId}")
public String edit(@PathVariable("caseId") Integer caseId, ModelMap mmap)
{
ProjectCase projectCase=projectCaseService.selectProjectCaseById(caseId);
ProjectCaseSteps projectCaseSteps = new ProjectCaseSteps();
projectCaseSteps.setCaseId(caseId);
List<ProjectCaseSteps> stepsList=projectCaseStepsService.selectProjectCaseStepsList(projectCaseSteps);
if(stepsList.size()==0){
projectCaseSteps.setAction("");
projectCaseSteps.setExpectedResult("");
projectCaseSteps.setExtend("");
projectCaseSteps.setProjectId(projectCase.getProjectId());
projectCaseSteps.setStepId(0);
projectCaseSteps.setStepOperation("");
projectCaseSteps.setStepParameters("");
projectCaseSteps.setStepPath("");
projectCaseSteps.setStepSerialNumber(1);
projectCaseSteps.setStepType(projectCase.getCaseType());
stepsList.add(projectCaseSteps);
}
mmap.put("stepsList", stepsList);
mmap.put("projectCase", projectCase);
return prefix + "/projectCaseSteps";
}
/**
* 修改保存测试用例步骤管理
*/
@RequiresPermissions("testmanagmt:projectCase:edit")
@Log(title = "测试用例步骤管理", businessType = BusinessType.UPDATE)
@RequestMapping(value = "/editSave",method=RequestMethod.POST,consumes="application/json")
@ResponseBody
public AjaxResult editSave(@RequestBody List<ProjectCaseSteps> listSteps)
{
int result=0;
projectCaseStepsService.deleteProjectCaseStepsByIds(listSteps);
int stepSerialNumber=1;
for(ProjectCaseSteps projectCaseSteps:listSteps){
projectCaseSteps.setStepSerialNumber(stepSerialNumber);
result=result+projectCaseStepsService.insertProjectCaseSteps(projectCaseSteps);
stepSerialNumber++;
}
return toAjax(result);
}
}

View File

@ -0,0 +1,115 @@
package com.luckyframe.project.testmanagmt.projectCase.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.luckyframe.framework.web.domain.BaseEntity;
/**
* 用例调试日志记录表 project_case_debug
*
* @author luckyframe
* @date 2019-03-14
*/
public class ProjectCaseDebug extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 调试ID */
private Integer debugId;
/** 用例ID */
private Integer caseId;
/** 用户ID */
private Integer userId;
/** 调试结束标识 0 进行中 1结束 2异常 */
private Integer debugIsend;
/** 日志级别 info 记录 warning 警告 error 异常 */
private String logLevel;
/** 日志 */
private String logDetail;
/** 客户端ID */
private Integer clientId;
/** 客户端驱动路径 */
private String driverPath;
public Integer getClientId() {
return clientId;
}
public void setClientId(Integer clientId) {
this.clientId = clientId;
}
public String getDriverPath() {
return driverPath;
}
public void setDriverPath(String driverPath) {
this.driverPath = driverPath;
}
public void setDebugId(Integer debugId)
{
this.debugId = debugId;
}
public Integer getDebugId()
{
return debugId;
}
public void setCaseId(Integer caseId)
{
this.caseId = caseId;
}
public Integer getCaseId()
{
return caseId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public Integer getUserId()
{
return userId;
}
public void setDebugIsend(Integer debugIsend)
{
this.debugIsend = debugIsend;
}
public Integer getDebugIsend()
{
return debugIsend;
}
public void setLogLevel(String logLevel)
{
this.logLevel = logLevel;
}
public String getLogLevel()
{
return logLevel;
}
public void setLogDetail(String logDetail)
{
this.logDetail = logDetail;
}
public String getLogDetail()
{
return logDetail;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("debugId", getDebugId())
.append("caseId", getCaseId())
.append("userId", getUserId())
.append("debugIsend", getDebugIsend())
.append("logLevel", getLogLevel())
.append("logDetail", getLogDetail())
.toString();
}
}

View File

@ -1,6 +1,4 @@
package com.luckyframe.project.testmanagmt.projectCaseSteps.domain;
import java.util.Date;
package com.luckyframe.project.testmanagmt.projectCase.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@ -39,14 +37,6 @@ public class ProjectCaseSteps extends BaseEntity
private Integer stepType;
/** 扩展字段可用于备注、存储HTTP模板等 */
private String extend;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
public void setStepId(Integer stepId)
{
@ -147,42 +137,6 @@ public class ProjectCaseSteps extends BaseEntity
{
return extend;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public Date getCreateTime()
{
return createTime;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public Date getUpdateTime()
{
return updateTime;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -0,0 +1,63 @@
package com.luckyframe.project.testmanagmt.projectCase.mapper;
import java.util.List;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseDebug;
/**
* 用例调试日志记录 数据层
*
* @author luckyframe
* @date 2019-03-14
*/
public interface ProjectCaseDebugMapper
{
/**
* 查询用例调试日志记录信息
*
* @param debugId 用例调试日志记录ID
* @return 用例调试日志记录信息
*/
public ProjectCaseDebug selectProjectCaseDebugById(Integer debugId);
/**
* 查询用例调试日志记录列表
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 用例调试日志记录集合
*/
public List<ProjectCaseDebug> selectProjectCaseDebugList(ProjectCaseDebug projectCaseDebug);
/**
* 新增用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
public int insertProjectCaseDebug(ProjectCaseDebug projectCaseDebug);
/**
* 修改用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
public int updateProjectCaseDebug(ProjectCaseDebug projectCaseDebug);
/**
* 删除用例调试日志记录
*
* @param debugId 用例调试日志记录ID
* @return 结果
*/
public int deleteProjectCaseDebugById(ProjectCaseDebug projectCaseDebug);
/**
* 批量删除用例调试日志记录
*
* @param debugIds 需要删除的数据ID
* @return 结果
*/
public int deleteProjectCaseDebugByIds(String[] debugIds);
}

View File

@ -1,8 +1,8 @@
package com.luckyframe.project.testmanagmt.projectCaseSteps.mapper;
package com.luckyframe.project.testmanagmt.projectCase.mapper;
import java.util.List;
import com.luckyframe.project.testmanagmt.projectCaseSteps.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseSteps;
/**
* 测试用例步骤管理 数据层
@ -45,12 +45,13 @@ public interface ProjectCaseStepsMapper
public int updateProjectCaseSteps(ProjectCaseSteps projectCaseSteps);
/**
* 删除测试用例步骤管理
*
* @param stepId 测试用例步骤管理ID
* @return 结果
*/
public int deleteProjectCaseStepsById(Integer stepId);
* 根据用例ID删除所有步骤
* @param caseId
* @return
* @author Seagull
* @date 2019年3月13日
*/
public int deleteProjectCaseStepsByCaseId(Integer caseId);
/**
* 批量删除测试用例步骤管理

View File

@ -0,0 +1,64 @@
package com.luckyframe.project.testmanagmt.projectCase.service;
import java.util.List;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseDebug;
/**
* 用例调试日志记录 服务层
*
* @author luckyframe
* @date 2019-03-14
*/
public interface IProjectCaseDebugService
{
/**
* 查询用例调试日志记录信息
*
* @param debugId 用例调试日志记录ID
* @return 用例调试日志记录信息
*/
public ProjectCaseDebug selectProjectCaseDebugById(Integer debugId);
/**
* 查询用例调试日志记录列表
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 用例调试日志记录集合
*/
public List<ProjectCaseDebug> selectProjectCaseDebugList(ProjectCaseDebug projectCaseDebug);
/**
* 新增用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
public int insertProjectCaseDebug(ProjectCaseDebug projectCaseDebug);
/**
* 修改用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
public int updateProjectCaseDebug(ProjectCaseDebug projectCaseDebug);
/**
* 删除用例调试日志记录信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteProjectCaseDebugByIds(String ids);
/**
* 根据id,useid,caseid删除调试日志
* @param projectCaseDebug
* @return
* @author Seagull
* @date 2019年3月15日
*/
public int deleteProjectCaseDebugById(ProjectCaseDebug projectCaseDebug);
}

View File

@ -1,8 +1,8 @@
package com.luckyframe.project.testmanagmt.projectCaseSteps.service;
package com.luckyframe.project.testmanagmt.projectCase.service;
import java.util.List;
import com.luckyframe.project.testmanagmt.projectCaseSteps.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseSteps;
/**
* 测试用例步骤管理 服务层
@ -45,11 +45,12 @@ public interface IProjectCaseStepsService
public int updateProjectCaseSteps(ProjectCaseSteps projectCaseSteps);
/**
* 删除测试用例步骤管理信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteProjectCaseStepsByIds(String ids);
* 删除单条用例中的所有步骤
* @param listSteps
* @return
* @author Seagull
* @date 2019年3月13日
*/
public int deleteProjectCaseStepsByIds(List<ProjectCaseSteps> listSteps);
}

View File

@ -0,0 +1,94 @@
package com.luckyframe.project.testmanagmt.projectCase.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.luckyframe.common.support.Convert;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseDebug;
import com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseDebugMapper;
/**
* 用例调试日志记录 服务层实现
*
* @author luckyframe
* @date 2019-03-14
*/
@Service
public class ProjectCaseDebugServiceImpl implements IProjectCaseDebugService
{
@Autowired
private ProjectCaseDebugMapper projectCaseDebugMapper;
/**
* 查询用例调试日志记录信息
*
* @param debugId 用例调试日志记录ID
* @return 用例调试日志记录信息
*/
@Override
public ProjectCaseDebug selectProjectCaseDebugById(Integer debugId)
{
return projectCaseDebugMapper.selectProjectCaseDebugById(debugId);
}
/**
* 查询用例调试日志记录列表
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 用例调试日志记录集合
*/
@Override
public List<ProjectCaseDebug> selectProjectCaseDebugList(ProjectCaseDebug projectCaseDebug)
{
return projectCaseDebugMapper.selectProjectCaseDebugList(projectCaseDebug);
}
/**
* 新增用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
@Override
public int insertProjectCaseDebug(ProjectCaseDebug projectCaseDebug)
{
return projectCaseDebugMapper.insertProjectCaseDebug(projectCaseDebug);
}
/**
* 修改用例调试日志记录
*
* @param projectCaseDebug 用例调试日志记录信息
* @return 结果
*/
@Override
public int updateProjectCaseDebug(ProjectCaseDebug projectCaseDebug)
{
return projectCaseDebugMapper.updateProjectCaseDebug(projectCaseDebug);
}
/**
* 删除用例调试日志记录对象
*
* @param ids 需要删除的数据ID
* @return 结果
*/
@Override
public int deleteProjectCaseDebugByIds(String ids)
{
return projectCaseDebugMapper.deleteProjectCaseDebugByIds(Convert.toStrArray(ids));
}
/**
* 根据id,useid,caseid删除调试日志
* @param projectCaseDebug
* @return
* @author Seagull
* @date 2019年3月15日
*/
public int deleteProjectCaseDebugById(ProjectCaseDebug projectCaseDebug){
return projectCaseDebugMapper.deleteProjectCaseDebugById(projectCaseDebug);
}
}

View File

@ -13,6 +13,7 @@ import com.luckyframe.common.utils.security.ShiroUtils;
import com.luckyframe.project.system.project.mapper.ProjectMapper;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCase;
import com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseMapper;
import com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseStepsMapper;
/**
* 项目测试用例管理 服务层实现
@ -26,6 +27,9 @@ public class ProjectCaseServiceImpl implements IProjectCaseService
@Autowired
private ProjectCaseMapper projectCaseMapper;
@Autowired
private ProjectCaseStepsMapper projectCaseStepsMapper;
@Autowired
private ProjectMapper projectMapper;
@ -99,7 +103,13 @@ public class ProjectCaseServiceImpl implements IProjectCaseService
@Override
public int deleteProjectCaseByIds(String ids)
{
return projectCaseMapper.deleteProjectCaseByIds(Convert.toStrArray(ids));
String[] caseIds=Convert.toStrArray(ids);
for(String caseIdstr:caseIds){
Integer caseId=Integer.valueOf(caseIdstr);
projectCaseStepsMapper.deleteProjectCaseStepsByCaseId(caseId);
}
return projectCaseMapper.deleteProjectCaseByIds(caseIds);
}
/**

View File

@ -1,13 +1,15 @@
package com.luckyframe.project.testmanagmt.projectCaseSteps.service;
package com.luckyframe.project.testmanagmt.projectCase.service;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.luckyframe.common.support.Convert;
import com.luckyframe.project.testmanagmt.projectCaseSteps.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCaseSteps.mapper.ProjectCaseStepsMapper;
import com.luckyframe.common.utils.security.ShiroUtils;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCase;
import com.luckyframe.project.testmanagmt.projectCase.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseStepsMapper;
/**
* 测试用例步骤管理 服务层实现
@ -21,6 +23,9 @@ public class ProjectCaseStepsServiceImpl implements IProjectCaseStepsService
@Autowired
private ProjectCaseStepsMapper projectCaseStepsMapper;
@Autowired
private IProjectCaseService projectCaseService;
/**
* 查询测试用例步骤管理信息
*
@ -54,6 +59,14 @@ public class ProjectCaseStepsServiceImpl implements IProjectCaseStepsService
@Override
public int insertProjectCaseSteps(ProjectCaseSteps projectCaseSteps)
{
ProjectCase projectCase=projectCaseService.selectProjectCaseById(projectCaseSteps.getCaseId());
projectCaseService.updateProjectCase(projectCase);
projectCaseSteps.setCreateBy(ShiroUtils.getLoginName());
projectCaseSteps.setCreateTime(new Date());
projectCaseSteps.setUpdateBy(ShiroUtils.getLoginName());
projectCaseSteps.setUpdateTime(new Date());
return projectCaseStepsMapper.insertProjectCaseSteps(projectCaseSteps);
}
@ -76,9 +89,15 @@ public class ProjectCaseStepsServiceImpl implements IProjectCaseStepsService
* @return 结果
*/
@Override
public int deleteProjectCaseStepsByIds(String ids)
public int deleteProjectCaseStepsByIds(List<ProjectCaseSteps> listSteps)
{
return projectCaseStepsMapper.deleteProjectCaseStepsByIds(Convert.toStrArray(ids));
int caseId=0;
if(null!=listSteps&&listSteps.size()>0){
if(null!=listSteps.get(0).getCaseId()){
caseId=listSteps.get(0).getCaseId();
}
}
return projectCaseStepsMapper.deleteProjectCaseStepsByCaseId(caseId);
}
}

View File

@ -1,129 +0,0 @@
package com.luckyframe.project.testmanagmt.projectCaseSteps.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
import com.luckyframe.framework.web.controller.BaseController;
import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.framework.web.page.TableDataInfo;
import com.luckyframe.project.testmanagmt.projectCaseSteps.domain.ProjectCaseSteps;
import com.luckyframe.project.testmanagmt.projectCaseSteps.service.IProjectCaseStepsService;
/**
* 测试用例步骤管理 信息操作处理
*
* @author luckyframe
* @date 2019-02-26
*/
@Controller
@RequestMapping("/testmanagmt/projectCaseSteps")
public class ProjectCaseStepsController extends BaseController
{
private String prefix = "testmanagmt/projectCaseSteps";
@Autowired
private IProjectCaseStepsService projectCaseStepsService;
@RequiresPermissions("testmanagmt:projectCaseSteps:view")
@GetMapping()
public String projectCaseSteps()
{
return prefix + "/projectCaseSteps";
}
/**
* 查询测试用例步骤管理列表
*/
@RequiresPermissions("testmanagmt:projectCaseSteps:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(ProjectCaseSteps projectCaseSteps)
{
startPage();
List<ProjectCaseSteps> list = projectCaseStepsService.selectProjectCaseStepsList(projectCaseSteps);
return getDataTable(list);
}
/**
* 导出测试用例步骤管理列表
*/
@RequiresPermissions("testmanagmt:projectCaseSteps:export")
@PostMapping("/export")
@ResponseBody
public AjaxResult export(ProjectCaseSteps projectCaseSteps)
{
List<ProjectCaseSteps> list = projectCaseStepsService.selectProjectCaseStepsList(projectCaseSteps);
ExcelUtil<ProjectCaseSteps> util = new ExcelUtil<ProjectCaseSteps>(ProjectCaseSteps.class);
return util.exportExcel(list, "projectCaseSteps");
}
/**
* 新增测试用例步骤管理
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存测试用例步骤管理
*/
@RequiresPermissions("testmanagmt:projectCaseSteps:add")
@Log(title = "测试用例步骤管理", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(ProjectCaseSteps projectCaseSteps)
{
return toAjax(projectCaseStepsService.insertProjectCaseSteps(projectCaseSteps));
}
/**
* 修改测试用例步骤管理
*/
@GetMapping("/edit/{stepId}")
public String edit(@PathVariable("stepId") Integer stepId, ModelMap mmap)
{
ProjectCaseSteps projectCaseSteps = projectCaseStepsService.selectProjectCaseStepsById(stepId);
mmap.put("projectCaseSteps", projectCaseSteps);
return prefix + "/edit";
}
/**
* 修改保存测试用例步骤管理
*/
@RequiresPermissions("testmanagmt:projectCaseSteps:edit")
@Log(title = "测试用例步骤管理", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(ProjectCaseSteps projectCaseSteps)
{
return toAjax(projectCaseStepsService.updateProjectCaseSteps(projectCaseSteps));
}
/**
* 删除测试用例步骤管理
*/
@RequiresPermissions("testmanagmt:projectCaseSteps:remove")
@Log(title = "测试用例步骤管理", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(projectCaseStepsService.deleteProjectCaseStepsByIds(ids));
}
}

View File

@ -12,6 +12,9 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.luckyframe.common.utils.DateUtils;
import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
@ -199,4 +202,39 @@ public class ProjectProtocolTemplateController extends BaseController
{
return projectProtocolTemplateService.checkProjectProtocolTemplateNameUnique(projectProtocolTemplate);
}
/**
* Ajax前台获取协议模板列表
* @param projectId
* @return
* @author Seagull
* @date 2019年3月12日
*/
@GetMapping("/getTemplateListByProjectId/{projectId}")
@ResponseBody
public String getTemplateListByProjectId(@PathVariable("projectId") Integer projectId) {
String str = "{\"message\": \"\",\"value\": ,\"code\": 200,\"redirect\": \"\" }";
try {
JSONObject json = new JSONObject();
ProjectProtocolTemplate projectProtocolTemplate=new ProjectProtocolTemplate();
projectProtocolTemplate.setProjectId(projectId);
List<ProjectProtocolTemplate> ptlist = projectProtocolTemplateService.selectProjectProtocolTemplateList(projectProtocolTemplate);
JSONArray jsonarr = new JSONArray();
for(ProjectProtocolTemplate obppt:ptlist){
JSONObject jo = new JSONObject();
jo.put("templateName", ""+obppt.getTemplateId()+""+obppt.getTemplateName());
jo.put("updateBy", obppt.getUpdateBy());
jo.put("updateTime", DateUtils.parseDateToStr("yy-MM-dd HH:mm:ss", obppt.getUpdateTime()));
jsonarr.add(jo);
}
String recordJson = jsonarr.toString();
json = JSONObject.parseObject("{\"message\": \"\",\"value\": "+recordJson+",\"code\": 200,\"redirect\": \"\" }");
str=json.toString();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
}

View File

@ -1,6 +1,5 @@
package com.luckyframe.project.testmanagmt.projectProtocolTemplate.controller;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -9,7 +8,6 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -0,0 +1,255 @@
package luckyweb.seagull.util.client;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpEntity;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import com.alibaba.fastjson.JSONObject;
public class HttpRequest {
/**
* @param urlParam
* @param jsonparams
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @Description:使用HttpClient以JSON格式发送post请求
*/
public static String httpClientPost(String urlParam,String jsonparams) throws NoSuchAlgorithmException, KeyManagementException, HttpHostConnectException{
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
HttpPost httpPost = new HttpPost(urlParam);
httpPost.setHeader("Content-Type", "application/json");
// 构建请求参数
BufferedReader br = null;
try {
if(null!=jsonparams&&jsonparams.length()>0){
StringEntity entity = new StringEntity(jsonparams,"utf-8");
httpPost.setEntity(entity);
}
CloseableHttpResponse response = httpclient.execute(httpPost);
// 读取服务器响应数据
resultBuffer = new StringBuffer();
if(null!=response.getEntity()){
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
*
* @param urlParam
* @param params
* @param charset
* @param headmsg
* @param cerpath
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @Description:使用HttpClient以JSON格式发送get请求
*/
public static String httpClientGet(String urlParam, Map<String, Object> params) throws NoSuchAlgorithmException, KeyManagementException,NoHttpResponseException {
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
BufferedReader br = null;
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry<String, Object> entry : params.entrySet()) {
sbParams.append(entry.getKey());
sbParams.append("=");
try {
sbParams.append(URLEncoder.encode(String.valueOf(entry.getValue()), "utf-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
sbParams.append("&");
}
}
if (sbParams != null && sbParams.length() > 0) {
urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1);
}
HttpGet httpGet = new HttpGet(urlParam);
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
// 读取服务器响应数据
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
resultBuffer = new StringBuffer();
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
public static String httpClientUploadFile(String urlParam, String loadpath, File file) throws NoSuchAlgorithmException, KeyManagementException, HttpHostConnectException {
StringBuffer resultBuffer = null;
CloseableHttpClient httpclient=HttpClients.createDefault();
HttpPost httpPost = new HttpPost(urlParam);
// 构建请求参数
BufferedReader br = null;
try {
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
//设置请求的编码格式
entityBuilder.setCharset(Charset.forName("utf-8"));
entityBuilder.addBinaryBody("jarfile", file);
entityBuilder.addTextBody("loadpath", loadpath);
HttpEntity reqEntity =entityBuilder.build();
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
//从状态行中获取状态码
String responsecode = String.valueOf(response.getStatusLine().getStatusCode());
// 读取服务器响应数据
resultBuffer = new StringBuffer();
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
String temp;
while ((temp = br.readLine()) != null) {
resultBuffer.append(temp);
}
if(resultBuffer.length()==0){
resultBuffer.append("上传文件异常,响应码:"+responsecode);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
throw new RuntimeException(e);
}
}
}
return resultBuffer.toString();
}
/**
* 获取 文件
* @param url
* @return
* @throws IOException
*/
public static byte[] getFile(String urlParam, Map<String, Object> params) throws IOException, HttpHostConnectException{
// 构建请求参数
StringBuffer sbParams = new StringBuffer();
if (params != null && params.size() > 0) {
for (Entry<String, Object> entry : params.entrySet()) {
sbParams.append(entry.getKey());
sbParams.append("=");
try {
sbParams.append(URLEncoder.encode(String.valueOf(entry.getValue()), "utf-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
sbParams.append("&");
}
}
if (sbParams != null && sbParams.length() > 0) {
urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1);
}
URL urlConet = new URL(urlParam);
HttpURLConnection con = (HttpURLConnection)urlConet.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(4 * 1000);
InputStream inStream = con .getInputStream(); //通过输入流获取图片数据
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while( (len=inStream.read(buffer)) != -1 ){
outStream.write(buffer, 0, len);
}
inStream.close();
byte[] data = outStream.toByteArray();
return data;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
RunTaskEntity tt = new RunTaskEntity();
tt.setTaskid("10965");
tt.setProjectname("果果在明人我");
tt.setLoadpath("/test");
String aa=JSONObject.toJSONString(tt);
System.out.println(aa);
System.out.println(httpClientPost("http://localhost:16363/runtask",aa));
/* String path = System.getProperty("user.dir")+"\\";
File targetFile = new File(path+"aopalliance-1.0.jar");
System.out.println(httpClientUploadFile("http://localhost:16363/uploadjar", "\\log11", targetFile));*/
/* Map<String, Object> params = new HashMap<String, Object>(0);
params.put("imgName", "0131-044346.png");
byte[] bfis = getFile("http://localhost:16363/getlogimg", params);
String path = System.getProperty("user.dir")+"\\";
String pathName = path + "test.png";
File file = new File(pathName);
file.createNewFile();
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
os.write(bfis);
os.flush();
os.close();*/
/* Map<String, Object> params = new HashMap<String, Object>(0);
System.out.println(httpClientGet("http://localhost:16363/getclientstatus", params));*/
}
}

View File

@ -0,0 +1,49 @@
package luckyweb.seagull.util.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunBatchCaseEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String batchcase;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
public String getBatchcase() {
return batchcase;
}
public void setBatchcase(String batchcase) {
this.batchcase = batchcase;
}
}

View File

@ -0,0 +1,56 @@
package luckyweb.seagull.util.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunCaseEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String testCaseExternalId;
private String version;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
public String getTestCaseExternalId() {
return testCaseExternalId;
}
public void setTestCaseExternalId(String testCaseExternalId) {
this.testCaseExternalId = testCaseExternalId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

View File

@ -0,0 +1,42 @@
package luckyweb.seagull.util.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
*/
public class RunTaskEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String projectname;
private String taskid;
private String loadpath;
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
public String getProjectname() {
return projectname;
}
public void setProjectname(String projectname) {
this.projectname = projectname;
}
public String getTaskid() {
return taskid;
}
public void setTaskid(String taskid) {
this.taskid = taskid;
}
}

View File

@ -0,0 +1,44 @@
package luckyweb.seagull.util.client;
import java.io.Serializable;
/**
* =================================================================
* 这是一个受限制的自由软件您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途也不允许对程序代码修改后以任何形式任何目的的再发布
* 为了尊重作者的劳动成果LuckyFrame关键版权信息严禁篡改
* 有任何疑问欢迎联系作者讨论 QQ:1573584944 seagull1985
* =================================================================
* 注意对象必须继承Serializable
* @author seagull
* @date 2017年12月1日 上午9:29:40
*
*/
public class WebDebugCaseEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String sign;
private String executor;
private String loadpath;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getExecutor() {
return executor;
}
public void setExecutor(String executor) {
this.executor = executor;
}
public String getLoadpath() {
return loadpath;
}
public void setLoadpath(String loadpath) {
this.loadpath = loadpath;
}
}

View File

@ -1,13 +1,13 @@
# 项目相关配置
luckyframe:
# 名称
name: LuckyFrameWeb
name: LuckyFrame
# 版本
version: 3.0
version: 3.0 Beta
# 版权年份
copyrightYear: 2019
# 文件上传路径
profile: D:/profile/
profile: E:/profile/
# 获取ip地址开关
addressEnabled: true

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.path" value="/home/ruoyi/logs" />
<property name="log.path" value="/luckyframelogs" />
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->

View File

@ -16,8 +16,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectClientProjectList" parameterType="ClientProject" resultMap="ClientProjectResult">
<include refid="selectClientProjectVo"/>
<where>
<if test="clientId != null "> and client_id = #{clientId}</if>
<if test="projectId != null "> and project_id = #{projectId}</if>
<if test="clientId != null and clientId != 0"> and client_id = #{clientId}</if>
<if test="projectId != null and projectId != 0"> and project_id = #{projectId}</if>
</where>
</select>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseDebugMapper">
<resultMap type="ProjectCaseDebug" id="ProjectCaseDebugResult">
<result property="debugId" column="debug_id" />
<result property="caseId" column="case_id" />
<result property="userId" column="user_id" />
<result property="debugIsend" column="debug_isend" />
<result property="logLevel" column="log_level" />
<result property="logDetail" column="log_detail" />
</resultMap>
<sql id="selectProjectCaseDebugVo">
select debug_id, case_id, user_id, debug_isend, log_level, log_detail from project_case_debug
</sql>
<select id="selectProjectCaseDebugList" parameterType="ProjectCaseDebug" resultMap="ProjectCaseDebugResult">
<include refid="selectProjectCaseDebugVo"/>
<where>
<if test="debugId != null and debugId != 0 "> and debug_id = #{debugId}</if>
<if test="caseId != null and debugId != 0 "> and case_id = #{caseId}</if>
<if test="userId != null and debugId != 0 "> and user_id = #{userId}</if>
<if test="debugIsend != null "> and debug_isend = #{debugIsend}</if>
<if test="logLevel != null and logLevel != '' "> and log_level = #{logLevel}</if>
<if test="logDetail != null and logDetail != '' "> and log_detail = #{logDetail}</if>
</where>
</select>
<select id="selectProjectCaseDebugById" parameterType="Integer" resultMap="ProjectCaseDebugResult">
<include refid="selectProjectCaseDebugVo"/>
where debug_id = #{debugId}
</select>
<insert id="insertProjectCaseDebug" parameterType="ProjectCaseDebug" useGeneratedKeys="true" keyProperty="debugId">
insert into project_case_debug
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="caseId != null ">case_id,</if>
<if test="userId != null ">user_id,</if>
<if test="debugIsend != null ">debug_isend,</if>
<if test="logLevel != null and logLevel != '' ">log_level,</if>
<if test="logDetail != null and logDetail != '' ">log_detail,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="caseId != null ">#{caseId},</if>
<if test="userId != null ">#{userId},</if>
<if test="debugIsend != null ">#{debugIsend},</if>
<if test="logLevel != null and logLevel != '' ">#{logLevel},</if>
<if test="logDetail != null and logDetail != '' ">#{logDetail},</if>
</trim>
</insert>
<update id="updateProjectCaseDebug" parameterType="ProjectCaseDebug">
update project_case_debug
<trim prefix="SET" suffixOverrides=",">
<if test="caseId != null ">case_id = #{caseId},</if>
<if test="userId != null ">user_id = #{userId},</if>
<if test="debugIsend != null ">debug_isend = #{debugIsend},</if>
<if test="logLevel != null and logLevel != '' ">log_level = #{logLevel},</if>
<if test="logDetail != null and logDetail != '' ">log_detail = #{logDetail},</if>
</trim>
where debug_id = #{debugId}
</update>
<delete id="deleteProjectCaseDebugById" parameterType="ProjectCaseDebug">
delete from project_case_debug
<where>
<if test="debugId != null and debugId != 0 "> and debug_id = #{debugId}</if>
<if test="caseId != null and debugId != 0 "> and case_id = #{caseId}</if>
<if test="userId != null and debugId != 0 "> and user_id = #{userId}</if>
</where>
</delete>
<delete id="deleteProjectCaseDebugByIds" parameterType="String">
delete from project_case_debug where debug_id in
<foreach item="debugId" collection="array" open="(" separator="," close=")">
#{debugId}
</foreach>
</delete>
</mapper>

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luckyframe.project.testmanagmt.projectCaseSteps.mapper.ProjectCaseStepsMapper">
<mapper namespace="com.luckyframe.project.testmanagmt.projectCase.mapper.ProjectCaseStepsMapper">
<resultMap type="ProjectCaseSteps" id="ProjectCaseStepsResult">
<result property="stepId" column="step_id" />
@ -55,6 +55,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="insertProjectCaseSteps" parameterType="ProjectCaseSteps" useGeneratedKeys="true" keyProperty="stepId">
insert into project_case_steps
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="stepId != null and stepId !=0 ">step_id,</if>
<if test="caseId != null ">case_id,</if>
<if test="projectId != null ">project_id,</if>
<if test="stepSerialNumber != null ">step_serial_number,</if>
@ -71,6 +72,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateTime != null ">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="stepId != null and stepId !=0 ">#{stepId},</if>
<if test="caseId != null ">#{caseId},</if>
<if test="projectId != null ">#{projectId},</if>
<if test="stepSerialNumber != null ">#{stepSerialNumber},</if>
@ -109,8 +111,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where step_id = #{stepId}
</update>
<delete id="deleteProjectCaseStepsById" parameterType="Integer">
delete from project_case_steps where step_id = #{stepId}
<delete id="deleteProjectCaseStepsByCaseId" parameterType="Integer">
delete from project_case_steps where case_id = #{caseId}
</delete>
<delete id="deleteProjectCaseStepsByIds" parameterType="String">

File diff suppressed because one or more lines are too long

View File

@ -1815,6 +1815,11 @@ table.dataTable thead .sorting:after {
padding-left: 0;
}
.lf-td-div {
padding-left: 0;
padding-right: 0;
}
.form-control, .single-line {
background: #FFFFFF none;
border: 1px solid #e5e6e7;

View File

@ -431,6 +431,49 @@
}
});
},
// 弹出层指定宽度
openCaseDebug: function (title, url, width, height, dtName) {
//如果是移动端,就使用自适应大小弹窗
if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {
width = 'auto';
height = 'auto';
}
if ($.common.isEmpty(title)) {
title = false;
};
if ($.common.isEmpty(url)) {
url = "/404.html";
};
if ($.common.isEmpty(width)) {
width = 800;
};
if ($.common.isEmpty(height)) {
height = ($(window).height() - 50);
};
if ($.common.isEmpty(dtName)) {
dtName = "确定";
};
layer.open({
type: 2,
area: [width + 'px', height + 'px'],
fix: false,
//不固定
maxmin: true,
shade: 0.3,
title: title,
content: url,
btn: [dtName, '关闭'],
// 弹层外区域关闭
shadeClose: true,
yes: function(index, layero) {
var iframeWin = layero.find('iframe')[0];
iframeWin.contentWindow.submitHandler();
},
cancel: function(index) {
return true;
}
});
},
// 弹出层指定参数选项
openOptions: function (options) {
var _url = $.common.isEmpty(options.url) ? "/404.html" : options.url;

View File

@ -19,7 +19,7 @@
<div th:fragment="footer">
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<!-- bootstrap-table 表格插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js}"></script>

View File

@ -10,7 +10,7 @@
<!--[if lt IE 9]>
<meta http-equiv="refresh" content="0;ie.html"/>
<![endif]-->
<link th:href="@{favicon.ico}" rel="stylesheet"/>
<!-- <link th:href="@{favicon.ico}" rel="stylesheet"/> -->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>

View File

@ -53,7 +53,7 @@
</div>
<div class="signup-footer">
<div class="pull-left" style="background-color:#00BFFF;margin-top:5px">
&copy; 2019 All Rights Reserved. LuckyFrame V3.0 Beta<br>
&copy; [[${copyrightYear}]] All Rights Reserved. LuckyFrame [[${version}]]<br>
</div>
</div>
</div>

View File

@ -123,12 +123,6 @@
}
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-client-edit').serialize());
}
}
function submitHandler() {
if ($.validate.form()) {
edit();

View File

@ -0,0 +1,142 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-projectCase-edit" th:object="${projectCase}">
<input id="caseId" name="caseId" th:field="*{caseId}" type="hidden">
<input id="caseSerialNumber" name="caseSerialNumber" th:field="*{caseSerialNumber}" type="hidden">
<input id="caseSign" name="caseSign" th:field="*{caseSign}" type="hidden">
<input id="treeId" name="moduleId" type="hidden" th:value="${projectCaseModule.moduleId}"/>
<div class="form-group">
<label class="col-sm-3 control-label">项目名称:</label>
<div class="col-sm-8">
<select class="form-control" id="projectId" name="projectId" onchange="initializeModuleTree()">
<option th:each="project:${projects}" th:value="${project.projectId}"
th:text="${project.projectName}" th:selected="${project.flag}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">用例模块:</label>
<div class="col-sm-8">
<input class="form-control" type="text" onclick="selectModuleTree()" id="treeName" readonly="true" th:value="${projectCaseModule.moduleName}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">用例名称:</label>
<div class="col-sm-8">
<input id="caseName" name="caseName" th:field="*{caseName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">用例类型:</label>
<div class="col-sm-8">
<select class="form-control m-b" th:field="*{caseType}" id="caseType" name="caseType" th:with="type=${@dict.getType('testmanagmt_case_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">步骤失败:</label>
<div class="col-sm-8">
<label>当前用例后续步骤 &nbsp;&nbsp;</label>
<div class="radio-box" th:each="dict : ${@dict.getType('testmanagmt_case_stepfailcontinue')}">
<input type="radio" th:field="*{failcontinue}" th:id="${dict.dictCode}" name="failcontinue" th:value="${dict.dictValue}" th:checked="${dict.isDefault == 'Y' ? true : false}">
<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="col-sm-8">
<textarea id="remark" name="remark" th:field="*{remark}" class="form-control"></textarea>
</div>
</div>
</form>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript">
var prefix = ctx + "testmanagmt/projectCase";
var modulePrefix = ctx + "testmanagmt/projectCaseModule"
$("#form-projectCase-edit").validate({
rules:{
caseName:{
required:true,
minlength: 1,
maxlength: 200,
remote: {
url: prefix + "/checkProjectCaseNameUnique",
type: "post",
dataType: "json",
data: {
"caseId": function() {
return $("#caseId").val();
},
name: function () {
return $.common.trim($("#caseName").val());
}
},
dataFilter: function (data, type) {
return $.validate.unique(data);
}
}
},
remark:{
maxlength:200
}
},
messages: {
"caseName": {
remote: "用例名称已经存在"
}
}
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/copy", $('#form-projectCase-edit').serialize());
}
}
/*模块管理-新增-选择父模块树*/
function selectModuleTree() {
var options = {
title: '模块选择',
width: "380",
url: modulePrefix + "/selectProjectCaseModuleTree/" + $("#treeId").val(),
callBack: doSubmit
};
$.modal.openOptions(options);
}
function doSubmit(index, layero){
var body = layer.getChildFrame('body', index);
$("#treeId").val(body.find('#treeId').val());
$("#treeName").val(body.find('#treeName').val());
layer.close(index);
}
/*选择项目初始化模块树*/
function initializeModuleTree() {
var projectId=$("#projectId").val();
$.ajax({
cache : true,
type : "GET",
url : modulePrefix + "/getModuleByProjectId/" + projectId,
data : {},
async : false,
error : function(request) {
$.modal.alertError("系统错误");
},
success : function(data) {
$("#treeId").val(data.moduleId);
$("#treeName").val(data.moduleName);
}
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-debugCase" th:object="${projectCaseDebug}">
<input id="caseId" th:field="*{caseId}" type="hidden">
<input id="userId" th:field="*{userId}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">客户端:</label>
<div class="col-sm-8">
<select class="form-control" id="clientId" th:field="*{clientId}" onChange="getDriverPath()">
<option th:each="client:${clients}" th:value="${client.clientId}"
th:text="【+${client.clientName}+】+${client.clientIp}+${client.statusStr}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">驱动目录:</label>
<div class="col-sm-8">
<select class="form-control" id="driverPath" th:field="*{driverPath}">
<option th:each="driverPath:${driverPathList}" th:value="${driverPath}" th:text="${driverPath}"></option>
</select>
</div>
</div>
</form>
<div id="logView" style="background-color:#F5F5F5;height:300px;overflow-y:scroll;text-align:left;"></div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript">
var prefix = ctx + "testmanagmt/projectCaseDebug";
var clientPrefix = ctx + "system/client";
function submitHandler() {
var data=$('#form-debugCase').serializeArray();
var config = {
url: prefix + "/debugCaseRun",
type: "post",
dataType: "json",
data: data,
beforeSend: function () {
$.modal.loading("正在处理中,请稍后...");
$.modal.disable();
},
success: function(data) {
$.modal.closeLoading();
$.modal.enable();
if (data.status == "info") {
$.modal.msgSuccess(data.ms);
refreshlog();
} else if (data.status == "warning") {
$.modal.msgWarning(data.ms);
} else if (data.status == "error") {
$.modal.msgError(data.ms);
}
}
};
$.ajax(config)
}
/*更新调试日志*/
function refreshlog() {
var data=$('#form-debugCase').serializeArray();
var config = {
url: prefix + "/refreshDebugLog",
type: "post",
dataType: "json",
data: data,
success: function(data) {
if (data.status == "0") {
document.getElementById('logView').innerHTML = data.ms;
document.getElementById('logView').scrollTop = document.getElementById('logView').scrollHeight;
} else if (data.status == "1") {
document.getElementById('logView').innerHTML = data.ms;
document.getElementById('logView').scrollTop = document.getElementById('logView').scrollHeight;
$.modal.msgSuccess("调试程序运行完成!");
clearTimeout(t);
} else if (data.status == "2") {
$.modal.msgError(data.ms);
} else{
$.modal.msgError(data.ms);
}
}
};
$.ajax(config);
var t = setTimeout("refreshlog()", 1500);
}
//按上级ID取子列表
function getDriverPath() {
if ($("#clientId").val() == "") return;
var clientId = $("#clientId").val();
var url = clientPrefix+"/getDriverPathList/" + clientId;
jQuery.getJSON(url, null, function call(result) {
clearSel();
setClientpath(result);
});
}
//设置子列表
function setClientpath(result) {
var options = "";
jQuery.each(result, function (i, node) {
options += "<option value='" + node + "'>" + node + "</option>";
});
$("#driverPath").html(options);
}
// 清空下拉列表
function clearSel() {
while ($("#driverPath").length > 1) {
$("#driverPath option[index='1']").remove();
}
}
</script>
</body>
</html>

View File

@ -52,6 +52,12 @@
<a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="testmanagmt:projectCase:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-info btn-edit disabled" onclick="$.operate.copy()" shiro:hasPermission="testmanagmt:projectCase:add">
<i class="fa fa-copy"></i> 复制用例
</a>
<a class="btn btn-info btn-edit disabled" onclick="$.operate.customFull()" shiro:hasPermission="testmanagmt:projectCase:edit">
<i class="fa fa-edit"></i> 用例步骤
</a>
<a class="btn btn-danger btn-del btn-del disabled" onclick="$.operate.removeAll()" shiro:hasPermission="testmanagmt:projectCase:remove">
<i class="fa fa-remove"></i> 删除
</a>
@ -70,15 +76,19 @@
var removeFlag = [[${@permission.hasPermi('testmanagmt:projectCase:remove')}]];
var prefix = ctx + "testmanagmt/projectCase";
var modulePrefix = ctx + "testmanagmt/projectCaseModule"
var stepsPrefix = ctx + "testmanagmt/projectCaseSteps";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
copyUrl: prefix + "/copy/{id}",
removeUrl: prefix + "/remove",
customUrl: stepsPrefix + "/edit/{id}",
exportUrl: prefix + "/export",
modalName: "测试用例",
childrenModalName: "用例步骤编辑",
search: false,
showExport: true,
columns: [{
@ -93,23 +103,33 @@
{
field : 'project.projectName',
title : '项目名称',
width : '10%',
class : 'myTDLengthHidden'
},
{
field : 'projectCaseModule.moduleName',
title : '模块名称',
width : '10%',
class : 'myTDLengthHidden'
},
{
field : 'caseSign',
title : '用例编号',
sortable: true
sortable: true,
width : '6%',
class : 'myTDLengthHidden'
},
{
field : 'caseName',
title : '用例名称',
width : '30%',
class : 'myTDLengthHidden'
},
{
field : 'caseType',
title : '用例类型',
width : '8%',
class : 'myTDLengthHidden',
formatter: function (value, row, index) {
if (row.caseType == 0) {
return 'HTTP接口';
@ -127,6 +147,8 @@
{
field : 'failcontinue',
title : '失败处理',
width : '5%',
class : 'myTDLengthHidden',
formatter: function (value, row, index) {
if (row.failcontinue == 0) {
return '后续步骤中断';
@ -145,32 +167,27 @@
{
field : 'createTime',
title : '创建时间',
sortable: true,
visible: false
},
{
field : 'updateBy',
title : '更新者'
title : '更新者',
width : '5%',
class : 'myTDLengthHidden'
},
{
field : 'updateTime',
title : '更新时间',
sortable: true
sortable: true,
width : '10%',
class : 'myTDLengthHidden'
},
{
field : 'remark',
title : '备注'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="#" onclick="$.operate.edit(\'' + row.caseId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="#" onclick="$.operate.remove(\'' + row.caseId + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
title : '备注',
width : '16%',
class : 'myTDLengthHidden'
}]
};
$.table.init(options);
});

View File

@ -0,0 +1,413 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<h2 class="thin text-center" th:text="【+${projectCase.caseSign}+】步骤编辑"></h2>
<h3 class="thin text-center" th:text="${projectCase.caseName}"></h3>
<form class="form-horizontal m" id="form-projectCaseSteps-edit">
<div class="form-group">
<table class="table table-striped" id="stepsTable">
<thead>
<tr>
<th>步骤</th>
<th>包 | 定位路径</th>
<th>方法 | 操作</th>
<th>参数</th>
<th>步骤动作</th>
<th>预期结果</th>
<th>类型</th>
<th>扩展字段</th>
<th>操作</th>
</tr>
</thead>
<tbody id="stepsTBody">
<tr th:each="stepsOb,iterStat : ${stepsList}">
<td width="3%">
<div class="col-sm-12 lf-td-div">
<input th:id="stepId+${iterStat.count}" name="stepId" type="hidden" th:value="${stepsOb.stepId}"/>
<input th:id="caseId+${iterStat.count}" name="caseId" type="hidden" th:value="${stepsOb.caseId}"/>
<input th:id="projectId+${iterStat.count}" name="projectId" type="hidden" th:value="${stepsOb.projectId}"/>
<label th:name="stepSerialNumber" th:id="stepSerialNumber+${iterStat.count}" th:value="${stepsOb.stepSerialNumber}" th:text="${stepsOb.stepSerialNumber}"></label>
</div></td>
<td width="18%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="stepPath" th:id="stepPath+${iterStat.count}" th:value="${stepsOb.stepPath}"/></div></td>
<td width="13%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="stepOperation" th:id="stepOperation+${iterStat.count}" th:value="${stepsOb.stepOperation}"/>
<div class="input-group-btn">
<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
</div>
</div>
</td>
<td width="16%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="stepParameters" th:id="stepParameters+${iterStat.count}" th:value="${stepsOb.stepParameters}"/></div></td>
<td width="10%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="action" th:id="action+${iterStat.count}" th:value="${stepsOb.action}"/></div></td>
<td width="12%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="expectedResult" th:id="expectedResult+${iterStat.count}" th:value="${stepsOb.expectedResult}"/></div></td>
<td width="10%">
<div class="col-sm-12 lf-td-div">
<select class="form-control" th:id="stepType+${iterStat.count}" name="stepType" th:with="type=${@dict.getType('testmanagmt_case_type')}" onChange="initSuggest(this)">
<option th:each="dict:${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:selected="${dict.dictValue==stepsOb.stepType.toString()}"></option>
</select>
</div>
</td>
<td width="10%">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="extend" th:id="extend+${iterStat.count}" th:value="${stepsOb.extend}"/>
<div class="input-group-btn">
<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
</div>
</div>
</td>
<td width="8%" style="vertical-align: middle;">
<a class="fa fa-plus-circle fa-5" style="font-size: 20px; cursor: pointer;" onclick="addsteps(this,0)"></a>
<a class="fa fa-chevron-circle-down fa-5" style="font-size: 20px; cursor: pointer;" onclick="addsteps(this,1)"></a>
<a class="fa fa-minus-circle fa-5" style="font-size: 20px; cursor: pointer;" onclick="delsteps(this)"></a>
<a class="fa fa-arrow-circle-up fa-5" style="font-size: 20px; cursor: pointer;" onclick="upsteps(this)"></a>
<a class="fa fa-arrow-circle-down fa-5" style="font-size: 20px; cursor: pointer;" onclick="downsteps(this)"></a>
</td>
</tr>
</tbody>
</table>
</div>
</form>
<div class="row">
<div class="col-lg-4 text-center" style="width: 100%">
<button class="btn btn-info" id="debugButton" onclick="showDebugModal()" type="button" style="padding-left: 36px;padding-right: 36px;">&nbsp;&nbsp;&nbsp;&nbsp;</button>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<!-- bootstrap-suggest 下拉搜索框插件 -->
<script th:src="@{/ajax/libs/bootstrap-suggest/bootstrap-suggest.min.js}"></script>
<script type="text/javascript">
var prefix = ctx + "testmanagmt/projectCaseSteps";
var templatePrefix = ctx + "testmanagmt/projectProtocolTemplate";
var dictPrefix = ctx + "system/dict/data";
var debugPrefix = ctx + "testmanagmt/projectCaseDebug"
/*解决table中多个name属性一致的问题使用ID进行验证*/
$(function () {
if ($.validator) {
$.validator.prototype.elements = function () {
var validator = this,
rulesCache = {};
return $([]).add(this.currentForm.elements)
.filter(":input")
.not(":submit, :reset, :image, [disabled]")
.not(this.settings.ignore)
.filter(function () {
var elementIdentification = this.id || this.name;
!elementIdentification && validator.settings.debug && window.console && console.error("%o has no id nor name assigned", this);
if (elementIdentification in rulesCache || !validator.objectLength($(this).rules()))
return false;
rulesCache[elementIdentification] = true;
return true;
});
};
}
/*初始化下拉列表*/
var oTable = document.getElementById("stepsTable");
for (var i = 1; i < oTable.rows.length; i++) {
initSuggest(oTable.rows[i].cells[6].children[0].children[0]);
}
});
$("#form-projectCaseSteps-edit").validate({
/*解决错误提示不在输入框的问题*/
errorPlacement: function(error, element) {
error.appendTo(element.parent());
},
rules:{
stepPath:{
maxlength: 500,
required: function(value){
var num=value.getAttribute("id").substring(8);
var stepType=$("#stepType"+num).val();
if(stepType=="0" && $("#stepPath"+num).val()==""){
/*不同的校验规则,不同的错误提示*/
$.validator.messages.required = "HTTP必填请求URL";
return true;
}else if(stepType=="2" && $("#stepPath"+num).val()==""){
$.validator.messages.required = "API必填包路径";
return true;
}else{
return false;
}
}
},
stepOperation:{
required:true,
minlength: 2,
maxlength: 100
},
stepParameters:{
maxlength: 500
},
action:{
maxlength: 50
},
expectedResult:{
maxlength: 2000,
required: function(value){
var num=value.getAttribute("id").substring(14);
var stepType=$("#stepType"+num).val();
if(stepType=="0" && $("#expectedResult"+num).val()==""){
/*不同的校验规则,不同的错误提示*/
$.validator.messages.required = "HTTP接口必填";
return true;
}else if(stepType=="2" && $("#expectedResult"+num).val()==""){
$.validator.messages.required = "API接口必填";
return true;
}else{
return false;
}
}
},
extend:{
maxlength: 2000,
required: function(value,element){
var num=value.getAttribute("id").substring(6);
var stepType=$("#stepType"+num).val();
if(stepType=="0" && $("#extend"+num).val()==""){
/*不同的校验规则,不同的错误提示*/
$.validator.messages.required = "HTTP必选模板";
return true;
}else{
return false;
}
}
},
},
messages: {
"stepOperation": {
required: "【方法|操作】必填"
}
}
});
function submitHandler() {
if ($.validate.form()) {
//点击提交按钮时,表单序列化后组装JSONARR
var params = $("#form-projectCaseSteps-edit").serializeArray();
var values = [];
var tparam = {};
for ( var item in params) {
tparam[params[item].name] = params[item].value;
if (params[item].name == "extend") {
values.push(tparam);
tparam = {};
}
}
$.operate.saveJson(prefix + "/editSave", JSON.stringify(values));
} else {
$.modal.msgError("步骤提交验证不通过!");
}
}
function addsteps(obj,iscopy) {
if (obj == null)
return;
var parentTD = obj.parentNode; //parentNode是父标签的意思如果你的TD里用了很多div控制格式要多调用几次parentNode
var parentTR = parentTD.parentNode;
var parentTB = parentTR.parentNode;
var clonedNode = parentTR.cloneNode(true); // 克隆节点
clonedNode.childNodes[1].childNodes[1].childNodes[1].setAttribute("value", "0"); //修改克隆节点stepId统一为0
var clonedTR;
if (parentTB.lastChild === parentTR) {
clonedTR=parentTB.appendChild(clonedNode);
} else {
clonedTR=parentTB.insertBefore(clonedNode, parentTR.nextSibling);
}
var oTable = document.getElementById("stepsTable");
reorderTable(oTable);
initSuggest(clonedTR.cells[6].children[0].children[0]);
if(iscopy==0){
clearCells(oTable.rows.length-1);
}
}
function clearCells(index) {
$("#stepPath" + index).val('');
$("#stepOperation" + index).val('');
$("#stepParameters" + index).val('');
$("#action" + index).val('');
$("#expectedResult" + index).val('');
$("#extend" + index).val('');
}
function delsteps(obj) {
if (obj === null) return;
var parentTD = obj.parentNode; //parentNode是父标签的意思如果你的TD里用了很多div控制格式要多调用几次parentNode
var parentTR = parentTD.parentNode;
var parentTB = parentTR.parentNode;
var oTable = document.getElementById("stepsTable");
/*标题占用一行*/
if (oTable.rows.length < 3) {
$.modal.msgWarning("唯一的步骤不能删除");
return;
}else {
parentTB.removeChild(parentTR);
reorderTable(oTable);
}
}
function upsteps(obj) {
if (obj === null) return;
var parentTD = obj.parentNode; //parentNode是父标签的意思如果你的TD里用了很多div控制格式要多调用几次parentNode
var parentTR = parentTD.parentNode;
var oTable = document.getElementById("stepsTable");
if (oTable.rows.length >= 3) {
swapTr(parentTR, oTable.rows[parentTR.sectionRowIndex]);
reorderTable(oTable);
}else{
$.modal.msgWarning("只有一个步骤,无需上移");
}
}
function downsteps(obj) {
if (obj === null) return;
var parentTD = obj.parentNode; //parentNode是父标签的意思如果你的TD里用了很多div控制格式要多调用几次parentNode
var parentTR = parentTD.parentNode;
var oTable = document.getElementById("stepsTable");
if (oTable.rows.length >= 3) {
swapTr(parentTR, oTable.rows[parentTR.sectionRowIndex+2]);
reorderTable(oTable);
}else{
$.modal.msgWarning("只有一个步骤,无需下移");
}
}
/*交换tr1和tr2的位置*/
function swapTr(tr1, tr2) {
var target = (tr1.rowIndex < tr2.rowIndex) ? tr2.nextSibling : tr2;
var tBody = tr1.parentNode;
tBody.replaceChild(tr2, tr1);
tBody.insertBefore(tr1, target);
}
/*对表格里面的步骤重新排序*/
function reorderTable(oTable) {
/*对步骤进行重新排序*/
for (var i = 1; i < oTable.rows.length; i++) {
oTable.rows[i].cells[0].children[0].children[0].setAttribute("id", "stepId" + i);
oTable.rows[i].cells[0].children[0].children[1].setAttribute("id", "caseId" + i);
oTable.rows[i].cells[0].children[0].children[2].setAttribute("id", "projectId" + i);
oTable.rows[i].cells[0].children[0].children[3].setAttribute("id", "stepSerialNumber" + i);
oTable.rows[i].cells[0].children[0].children[3].setAttribute("value", i);
oTable.rows[i].cells[0].children[0].children[3].innerHTML=i;
oTable.rows[i].cells[1].children[0].children[0].setAttribute("id", "stepPath" + i);
var opob = oTable.rows[i].cells[2].children[0];
if (opob.children[0].tagName.toLocaleLowerCase() === 'input') {
opob.children[0].setAttribute("id", "stepOperation" + i);
} else {
opob.children[1].setAttribute("id", "stepOperation" + i);
}
oTable.rows[i].cells[3].children[0].children[0].setAttribute("id", "stepParameters" + i);
oTable.rows[i].cells[4].children[0].children[0].setAttribute("id", "action" + i);
oTable.rows[i].cells[5].children[0].children[0].setAttribute("id", "expectedResult" + i);
oTable.rows[i].cells[6].children[0].children[0].setAttribute("id", "stepType" + i);
var eob = oTable.rows[i].cells[7].children[0];
if (eob.children[0].tagName.toLocaleLowerCase() === 'input') {
eob.children[0].setAttribute("id", "extend" + i);
} else {
eob.children[1].setAttribute("id", "extend" + i);
}
}
}
function initSuggest(obj) {
$.validate.resetForm();
var index = obj.getAttribute("id").substring(8);
var stepType=$("#stepType"+index).val();
if (stepType === '0') {
initSuggestOperation(index,0);
initSuggestTemplate(index);
} else if (stepType === '1') {
$("#extend" + index).bsSuggest("destroy");
initSuggestOperation(index,1);
} else if (stepType === '3') {
$("#extend" + index).bsSuggest("destroy");
initSuggestOperation(index,3);
} else {
$("#stepOperation" + index).bsSuggest("destroy");
$("#extend" + index).bsSuggest("destroy");
}
}
function initSuggestTemplate(index) {
$("#extend"+index).bsSuggest("destroy");
$("#extend"+index).bsSuggest({
url: templatePrefix+"/getTemplateListByProjectId/"+$("#projectId1").val(),
/*effectiveFields: ["userName", "shortAccount"],
searchFields: [ "shortAccount"],*/
effectiveFieldsAlias: {templateName: "模板名称", updateBy: "更新人员", updateTime: "更新时间"},
ignorecase: true,
showHeader: true,
showBtn: false, //不显示下拉按钮
delayUntilKeyup: true, //获取数据的方式为 firstByUrl 时,延迟到有输入/获取到焦点时才请求数据
idField: "name",
keyField: "name",
clearable: false
}).on('onDataRequestSuccess', function (e, result) {
console.log('onDataRequestSuccess: ', result);
}).on('onSetSelectValue', function (e, keyword, data) {
console.log('onSetSelectValue: ', keyword, data);
//$('#casesteps').data('bootstrapValidator').updateStatus(extendindex, 'NOT_VALIDATED', null).validateField($("#"+templateId));
}).on('onUnsetSelectValue', function () {
console.log("onUnsetSelectValue");
});
}
function initSuggestOperation(index,stepType) {
$("#stepOperation"+index).bsSuggest("destroy");
$("#stepOperation"+index).bsSuggest({
url: dictPrefix+"/getDictDataListByStepType/" + stepType,
/*effectiveFields: ["userName", "shortAccount"],
searchFields: [ "shortAccount"],*/
effectiveFieldsAlias: {name: "操作", description: "描述"},
ignorecase: true,
showHeader: true,
showBtn: false, //不显示下拉按钮
delayUntilKeyup: true, //获取数据的方式为 firstByUrl 时,延迟到有输入/获取到焦点时才请求数据
idField: "name",
keyField: "name",
clearable: false
}).on('onDataRequestSuccess', function (e, result) {
}).on('onSetSelectValue', function (e, keyword, data) {
/* $('#casesteps').data('bootstrapValidator').updateStatus(operationindex, 'NOT_VALIDATED', null).validateField(operationindex); */
}).on('onUnsetSelectValue', function () {
});
}
function showDebugModal() {
var caseId=$("#caseId1").val();
var url = "/404.html";
if ($.common.isNotEmpty(caseId)) {
url = debugPrefix + "/projectCaseDebug/" + caseId;
}
$.modal.openCaseDebug("用例调试", url, null, null, "调试");
}
</script>
</body>
</html>

View File

@ -1,112 +0,0 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-projectCaseSteps-add">
<div class="form-group">
<label class="col-sm-3 control-label">用例ID</label>
<div class="col-sm-8">
<input id="caseId" name="caseId" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">项目ID</label>
<div class="col-sm-8">
<input id="projectId" name="projectId" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">步骤序号:</label>
<div class="col-sm-8">
<input id="stepSerialNumber" name="stepSerialNumber" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">包路径|定位路径:</label>
<div class="col-sm-8">
<input id="stepPath" name="stepPath" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">方法名|操作:</label>
<div class="col-sm-8">
<input id="stepOperation" name="stepOperation" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数:</label>
<div class="col-sm-8">
<input id="stepParameters" name="stepParameters" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">步骤动作:</label>
<div class="col-sm-8">
<input id="action" name="action" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">预期结果:</label>
<div class="col-sm-8">
<input id="expectedResult" name="expectedResult" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">0 API接口 1 Web UI 2 HTTP接口 3移动端</label>
<div class="col-sm-8">
<input id="stepType" name="stepType" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">扩展字段可用于备注、存储HTTP模板等</label>
<div class="col-sm-8">
<input id="extend" name="extend" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建者:</label>
<div class="col-sm-8">
<input id="createBy" name="createBy" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建时间:</label>
<div class="col-sm-8">
<input id="createTime" name="createTime" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新者:</label>
<div class="col-sm-8">
<input id="updateBy" name="updateBy" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新时间:</label>
<div class="col-sm-8">
<input id="updateTime" name="updateTime" class="form-control" type="text">
</div>
</div>
</form>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript">
var prefix = ctx + "system/projectCaseSteps"
$("#form-projectCaseSteps-add").validate({
rules:{
xxxx:{
required:true,
},
}
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-projectCaseSteps-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -1,113 +0,0 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-projectCaseSteps-edit" th:object="${projectCaseSteps}">
<input id="stepId" name="stepId" th:field="*{stepId}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">用例ID</label>
<div class="col-sm-8">
<input id="caseId" name="caseId" th:field="*{caseId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">项目ID</label>
<div class="col-sm-8">
<input id="projectId" name="projectId" th:field="*{projectId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">步骤序号:</label>
<div class="col-sm-8">
<input id="stepSerialNumber" name="stepSerialNumber" th:field="*{stepSerialNumber}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">包路径|定位路径:</label>
<div class="col-sm-8">
<input id="stepPath" name="stepPath" th:field="*{stepPath}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">方法名|操作:</label>
<div class="col-sm-8">
<input id="stepOperation" name="stepOperation" th:field="*{stepOperation}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数:</label>
<div class="col-sm-8">
<input id="stepParameters" name="stepParameters" th:field="*{stepParameters}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">步骤动作:</label>
<div class="col-sm-8">
<input id="action" name="action" th:field="*{action}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">预期结果:</label>
<div class="col-sm-8">
<input id="expectedResult" name="expectedResult" th:field="*{expectedResult}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">0 API接口 1 Web UI 2 HTTP接口 3移动端</label>
<div class="col-sm-8">
<input id="stepType" name="stepType" th:field="*{stepType}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">扩展字段可用于备注、存储HTTP模板等</label>
<div class="col-sm-8">
<input id="extend" name="extend" th:field="*{extend}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建者:</label>
<div class="col-sm-8">
<input id="createBy" name="createBy" th:field="*{createBy}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建时间:</label>
<div class="col-sm-8">
<input id="createTime" name="createTime" th:field="*{createTime}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新者:</label>
<div class="col-sm-8">
<input id="updateBy" name="updateBy" th:field="*{updateBy}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新时间:</label>
<div class="col-sm-8">
<input id="updateTime" name="updateTime" th:field="*{updateTime}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript">
var prefix = ctx + "system/projectCaseSteps";
$("#form-projectCaseSteps-edit").validate({
rules:{
xxxx:{
required:true,
},
}
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-projectCaseSteps-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -1,206 +0,0 @@
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
用例ID<input type="text" name="caseId"/>
</li>
<li>
项目ID<input type="text" name="projectId"/>
</li>
<li>
步骤序号:<input type="text" name="stepSerialNumber"/>
</li>
<li>
包路径|定位路径:<input type="text" name="stepPath"/>
</li>
<li>
方法名|操作:<input type="text" name="stepOperation"/>
</li>
<li>
参数:<input type="text" name="stepParameters"/>
</li>
<li>
步骤动作:<input type="text" name="action"/>
</li>
<li>
预期结果:<input type="text" name="expectedResult"/>
</li>
<li>
0 API接口 1 Web UI 2 HTTP接口 3移动端<input type="text" name="stepType"/>
</li>
<li>
扩展字段可用于备注、存储HTTP模板等<input type="text" name="extend"/>
</li>
<li>
创建者:<input type="text" name="createBy"/>
</li>
<li>
创建时间:<input type="text" name="createTime"/>
</li>
<li>
更新者:<input type="text" name="updateBy"/>
</li>
<li>
更新时间:<input type="text" name="updateTime"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm hidden-xs" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:projectCaseSteps:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="system:projectCaseSteps:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger btn-del btn-del disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:projectCaseSteps:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:projectCaseSteps:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table" data-mobile-responsive="true"></table>
</div>
</div>
</div>
<div th:include="include :: footer"></div>
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:projectCaseSteps:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:projectCaseSteps:remove')}]];
var prefix = ctx + "system/projectCaseSteps";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "测试用例步骤",
search: false,
showExport: true,
columns: [{
checkbox: true
},
{
field : 'stepId',
title : '步骤ID',
visible: false
},
{
field : 'caseId',
title : '用例ID',
sortable: true
},
{
field : 'projectId',
title : '项目ID',
sortable: true
},
{
field : 'stepSerialNumber',
title : '步骤序号',
sortable: true
},
{
field : 'stepPath',
title : '包路径|定位路径',
sortable: true
},
{
field : 'stepOperation',
title : '方法名|操作',
sortable: true
},
{
field : 'stepParameters',
title : '参数',
sortable: true
},
{
field : 'action',
title : '步骤动作',
sortable: true
},
{
field : 'expectedResult',
title : '预期结果',
sortable: true
},
{
field : 'stepType',
title : '0 API接口 1 Web UI 2 HTTP接口 3移动端',
sortable: true
},
{
field : 'extend',
title : '扩展字段可用于备注、存储HTTP模板等',
sortable: true
},
{
field : 'createBy',
title : '创建者',
sortable: true
},
{
field : 'createTime',
title : '创建时间',
sortable: true
},
{
field : 'updateBy',
title : '更新者',
sortable: true
},
{
field : 'updateTime',
title : '更新时间',
sortable: true
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="#" onclick="$.operate.edit(\'' + row.stepId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="#" onclick="$.operate.remove(\'' + row.stepId + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -69,7 +69,7 @@
removeUrl: prefix + "/remove",
customUrl: paramsPrefix + "/editParams/{id}",
modalName: "协议模板",
childrenModalName: "协议模板信息",
childrenModalName: "协议模板参数编辑",
search: false,
showExport: true,
columns: [{

View File

@ -70,15 +70,15 @@
<tbody id="paramTBody">
<tr th:each="paramob,iterStat : ${templateParams}">
<td width="20%">
<div class="col-sm-12">
<div class="col-sm-12 lf-td-div">
<input th:id="paramsId+${iterStat.count}" name="paramsId" type="hidden" th:value="${paramob.paramsId}"/>
<input th:id="templateId+${iterStat.count}" name="templateId" type="hidden" th:value="${paramob.templateId}"/>
<input type="text" class="form-control" name="paramName" th:id="paramName+${iterStat.count}" th:value="${paramob.paramName}"/></div></td>
<td width="55%">
<div class="col-sm-12">
<div class="col-sm-12 lf-td-div">
<input type="text" class="form-control" name="paramValue" th:id="paramValue+${iterStat.count}" th:value="${paramob.paramValue}"/></div></td>
<td width="15%">
<div class="col-sm-12">
<div class="col-sm-12 lf-td-div">
<select class="form-control" th:id="paramType+${iterStat.count}" name="paramType" th:with="type=${@dict.getType('testmanagmt_templateparams_type')}">
<option th:each="dict:${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:selected="${dict.dictValue==paramob.paramType.toString()}"></option>
</select>
@ -175,7 +175,6 @@
if ($.validate.form()) {
//点击提交按钮时,表单序列化后组装JSONARR
var params = $("#form-projectTemplateParams-edit").serializeArray();
var oTable = document.getElementById("paramTBody");
var values = [];
var tparam={};
for (var item in params) {