From ea4c19fc89dbb8f5aac3272f1706ed7905052149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A4=E5=87=B0=E9=99=A2=E5=A4=A7=E7=99=BD?= Date: Thu, 28 Nov 2019 17:16:30 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E9=87=8D=E8=A6=81=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/webapp/resource/message/messageScene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/resource/message/messageScene.js b/src/main/webapp/resource/message/messageScene.js index a61ac5c..a5f6a3b 100644 --- a/src/main/webapp/resource/message/messageScene.js +++ b/src/main/webapp/resource/message/messageScene.js @@ -328,7 +328,7 @@ var eventList = { }); if (JSON.stringify(updateConfig) != JSON.stringify(data.config)) { - $.post(REQUEST_URL.COMPLEX_SCENE.UPDATE_CONFIG_INFO, {id:complexSceneId, sequenceNum:data.sequenceNum, config:JSON.stringify(updateConfig)}, function (json) { + $.post(REQUEST_URL.COMPLEX_SCENE.UPDATE_SCENE_CONFIG, {id:complexSceneId, sequenceNum:data.sequenceNum, config:JSON.stringify(updateConfig)}, function (json) { if (json.returnCode == 0) { layer.msg("已更新配置信息", {icon:1, time:1800}); refreshTable(); -- Gitee From 1f9be5237401a4ad460bd0eede9ce13582a7ef76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A4=E5=87=B0=E9=99=A2=E5=A4=A7=E7=99=BD?= Date: Fri, 29 Nov 2019 00:03:52 +0800 Subject: [PATCH 02/30] =?UTF-8?q?!4=20v0.2.2beta=20*=20v0.2.2beta-?= =?UTF-8?q?=E5=BE=85=E6=B5=8B=E8=AF=95=20*=20=E6=9B=B4=E6=96=B0=20*=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20*=20=E6=9B=B4=E6=96=B0=20*=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20*=20=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3Mock?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=20*=20=E4=BB=8E=E5=9C=BA=E6=99=AF=E4=B8=AD?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8E=A5=E5=8F=A3Mock(=E5=BE=85=E9=AA=8C?= =?UTF-8?q?=E8=AF=81)=20*=20=E6=9B=B4=E6=96=B0=20*=20=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E5=B1=95=E7=A4=BAWeb=E8=87=AA=E5=8A=A8=E5=8C=96?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=B3=BB=E7=BB=9F=20*=20=E5=A2=9E=E5=8A=A0we?= =?UTF-8?q?bsocket=E6=A8=A1=E5=9D=97;=E5=85=B6=E4=BB=96=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20*=20=E6=9B=B4=E6=96=B0=20*=20=E6=9D=83=E9=99=90=E7=B2=BE?= =?UTF-8?q?=E7=A1=AE=E5=88=B0=E9=A1=B5=E9=9D=A2=E6=8C=89=E9=92=AE=E7=9A=84?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=92=8C=E9=9A=90=E8=97=8F=20*=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=87=AA=E5=8A=A8=E5=8C=96=E6=9B=B4=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=20*=20=E6=9B=B4=E6=96=B0=20*=20Merge=20remot?= =?UTF-8?q?e-tracking=20branch=20'origin/dev'=20into=20dev=20*=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0WebSockets=E7=9A=84=E6=8E=A5=E5=8F=A3Mock=20*=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20*=20=E4=BF=AE=E6=94=B9=20*=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0xss=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- pom.xml | 13 + .../advanced/action/InterfaceMockAction.java | 94 +++-- .../business/advanced/action/MockAction.java | 21 +- .../business/advanced/bean/InterfaceMock.java | 17 +- .../config/mock/MockGenerateRuleConfig.java | 11 +- .../config/mock/MockValidateRuleConfig.java | 47 ++- .../advanced/dao/InterfaceMockDao.java | 18 +- .../dao/impl/InterfaceMockDaoImpl.java | 20 +- .../advanced/enums/InterfaceProbeStatus.java | 2 +- .../advanced/enums/MockConfigSettingType.java | 12 + .../service/InterfaceMockService.java | 29 +- .../impl/InterfaceMockServiceImpl.java | 154 +++++++- .../action/SceneValidateRuleAction.java | 38 +- .../business/message/bean/MessageScene.java | 19 +- .../business/message/bean/Parameter.java | 43 ++- .../message/bean/SceneValidateRule.hbm.xml | 3 + .../message/bean/SceneValidateRule.java | 15 +- .../message/dao/SceneValidateRuleDao.java | 13 +- .../dao/impl/SceneValidateRuleDaoImpl.java | 10 +- .../service/SceneValidateRuleService.java | 13 +- .../impl/SceneValidateRuleServiceImpl.java | 10 +- .../action/OperationInterfaceAction.java | 35 +- .../system/bean/OperationInterface.hbm.xml | 6 + .../system/bean/OperationInterface.java | 26 ++ .../system/dao/OperationInterfaceDao.java | 9 + .../dao/impl/OperationInterfaceDaoImpl.java | 7 + .../service/OperationInterfaceService.java | 9 +- .../impl/OperationInterfaceServiceImpl.java | 6 +- .../testconfig/bean/TestConfig.hbm.xml | 15 +- .../business/testconfig/bean/TestConfig.java | 75 +++- .../testconfig/dao/TestConfigDao.java | 2 +- .../business/user/action/MailAction.java | 10 +- .../business/user/action/RoleAction.java | 37 +- .../business/user/action/UserAction.java | 26 +- .../user/service/impl/MailServiceImpl.java | 17 +- .../java/yi/master/constant/MessageKeys.java | 69 ++-- .../java/yi/master/constant/SystemConsts.java | 105 +++--- .../message/protocol/HTTPTestClient.java | 45 ++- .../entity/ClientTestResponseObject.java | 2 +- .../message/test/MessageAutoTest.java | 53 +-- .../message/test/MessageValidateResponse.java | 19 +- .../message/test/mock/MockServer.java | 245 ++++++++++++ .../message/test/mock/MockSocketServer.java | 210 ++++------- .../test/mock/MockWebSocketServer.java | 95 +++++ .../yi/master/exception/AppErrorCode.java | 10 + .../interceptor/CallMethodInterceptor.java | 53 +-- .../interceptor/InterfaceMockInterceptor.java | 17 +- .../yi/master/listener/InitWebListener.java | 50 +-- .../yi/master/listener/VersionUpdateUtil.java | 130 +++++++ .../java/yi/master/util/PracticalUtils.java | 104 +++--- .../java/yi/master/util/cache/CacheUtil.java | 96 +++-- .../java/yi/master/util/xss/XssFilter.java | 46 +++ .../xss/XssHttpServletRequestWrapper.java | 124 +++++++ .../java/yi/master/util/xss/XssUtils.java | 70 ++++ .../yi/master/websocket/MailDataPush.java | 72 ++++ src/main/resources/struts.xml | 2 + src/main/resources/update/0.2.2beta | 85 +++++ src/main/webapp/WEB-INF/web.xml | 213 ++++++----- src/main/webapp/index.html | 336 +---------------- src/main/webapp/index.js | 271 ++++++++++++++ src/main/webapp/js/ajaxErrorHandler.js | 20 + src/main/webapp/js/bak/explanationMarks.json | 33 -- src/main/webapp/js/bak/messageProcess.json | 6 - src/main/webapp/js/bak/protocol.json | 37 -- src/main/webapp/js/bak/readme.txt | 8 - src/main/webapp/js/bak/requestUrls.js | 297 --------------- src/main/webapp/js/bak/webStepParameter.json | 147 -------- src/main/webapp/js/dcits.js | 199 ++++++++-- src/main/webapp/js/globalConstant.js | 48 ++- src/main/webapp/js/handlebarsHelpers.js | 84 +++++ .../webapp/js/json/HttpRequestHeader.json | 188 +++++----- .../webapp/js/json/HttpResponseHeader.json | 148 ++++---- src/main/webapp/login.html | 22 +- .../resource/advanced/chooseMessageScene.js | 27 +- .../webapp/resource/advanced/mockTest.html | 6 +- src/main/webapp/resource/advanced/mockTest.js | 348 +++++++++++------- .../resource/advanced/performanceTest.js | 2 +- .../webapp/resource/message/autoTest.html | 2 +- .../webapp/resource/message/complexScene.js | 6 +- src/main/webapp/resource/message/message.js | 20 +- src/main/webapp/resource/message/setScene.js | 112 +++--- .../resource/message/validateParameters.js | 70 ++-- .../webapp/resource/system/opInterface.js | 12 + .../resource/template/customTemplate.htm | 58 ++- src/main/webapp/resource/user/mail.js | 8 +- src/main/webapp/welcome.html | 126 +------ src/main/webapp/welcome.js | 165 +++++++++ update.md | 33 ++ 89 files changed, 3484 insertions(+), 2157 deletions(-) create mode 100644 src/main/java/yi/master/business/advanced/enums/MockConfigSettingType.java create mode 100644 src/main/java/yi/master/coretest/message/test/mock/MockServer.java create mode 100644 src/main/java/yi/master/coretest/message/test/mock/MockWebSocketServer.java create mode 100644 src/main/java/yi/master/listener/VersionUpdateUtil.java create mode 100644 src/main/java/yi/master/util/xss/XssFilter.java create mode 100644 src/main/java/yi/master/util/xss/XssHttpServletRequestWrapper.java create mode 100644 src/main/java/yi/master/util/xss/XssUtils.java create mode 100644 src/main/java/yi/master/websocket/MailDataPush.java create mode 100644 src/main/resources/update/0.2.2beta create mode 100644 src/main/webapp/index.js create mode 100644 src/main/webapp/js/ajaxErrorHandler.js delete mode 100644 src/main/webapp/js/bak/explanationMarks.json delete mode 100644 src/main/webapp/js/bak/messageProcess.json delete mode 100644 src/main/webapp/js/bak/protocol.json delete mode 100644 src/main/webapp/js/bak/readme.txt delete mode 100644 src/main/webapp/js/bak/requestUrls.js delete mode 100644 src/main/webapp/js/bak/webStepParameter.json create mode 100644 src/main/webapp/js/handlebarsHelpers.js create mode 100644 src/main/webapp/welcome.js diff --git a/README.md b/README.md index 666ca9f..db2b364 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,14 @@ QQ群交流:468324085,加群验证:易大师 [演示地址](http://www.xuwangcheng.com/yi)(账号 tester/11111111) -#### 一键安装包 +#### 一键安装 for windows 百度云: https://pan.baidu.com/s/1i8siuIuPXsjlnawYFc4c6A **账号 admin/q708162543** **安装完成进入安装根目录,双击执行start.bat,弹出两个cmd窗口不要关闭,打开浏览器输入http://localhost:8080** +#### Linux安装教程 +https://www.xuwangcheng.com/articles/2019/11/20/1574239339298.html + #### 主要功能 - 接口、报文、场景三层分离,接口测试更加灵活多变; - 支持Http/Https/Socket/WebService/WebSocket/Dubbo协议接口,后续支持更多; diff --git a/pom.xml b/pom.xml index fd7182c..2721043 100644 --- a/pom.xml +++ b/pom.xml @@ -435,6 +435,13 @@ Java-WebSocket 1.4.0 + + javax.websocket + javax.websocket-api + 1.1 + provided + + @@ -444,6 +451,12 @@ + + org.jsoup + jsoup + 1.11.3 + + + + diff --git a/src/main/resources/update/0.2.2beta b/src/main/resources/update/0.2.2beta new file mode 100644 index 0000000..6099797 --- /dev/null +++ b/src/main/resources/update/0.2.2beta @@ -0,0 +1,85 @@ +ALTER TABLE `at_operation_interface` ADD COLUMN `permission_mark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'jquery选择器标识' AFTER `parent_op_id`; +ALTER TABLE `at_operation_interface` ADD COLUMN `page_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '所属页面' AFTER `permission_mark`; +UPDATE `at_operation_interface` SET `op_name` = '接口信息编辑', `call_name` = 'interface-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑指定接口信息', `status` = '0', `parent_op_id` = 3, `permission_mark` = '.object-edit', `page_name` = 'interface' WHERE `op_id` = 25; +UPDATE `at_operation_interface` SET `op_name` = '删除接口', `call_name` = 'interface-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定接口', `status` = '0', `parent_op_id` = 3, `permission_mark` = '.object-del', `page_name` = 'interface' WHERE `op_id` = 27; +UPDATE `at_operation_interface` SET `op_name` = '获取接口的参数', `call_name` = 'param-getParams', `is_parent` = 'false', `op_type` = NULL, `mark` = '获取指定接口的所有入参节点信息', `status` = '0', `parent_op_id` = 5, `permission_mark` = '.edit-params', `page_name` = 'interface' WHERE `op_id` = 33; +UPDATE `at_operation_interface` SET `op_name` = '保存参数', `call_name` = 'param-save', `is_parent` = 'false', `op_type` = NULL, `mark` = '保存单个接口入参信息', `status` = '0', `parent_op_id` = 5, `permission_mark` = '#add-object', `page_name` = 'interfaceParameter' WHERE `op_id` = 34; +UPDATE `at_operation_interface` SET `op_name` = '删除参数', `call_name` = 'param-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定参数', `status` = '0', `parent_op_id` = 5, `permission_mark` = '.object-del', `page_name` = 'interfaceParameter' WHERE `op_id` = 35; +UPDATE `at_operation_interface` SET `op_name` = '编辑参数', `call_name` = 'param-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑指定参数信息', `status` = '0', `parent_op_id` = 5, `permission_mark` = '.object-edit', `page_name` = 'interfaceParameter' WHERE `op_id` = 36; +UPDATE `at_operation_interface` SET `op_name` = '导入报文串入参', `call_name` = 'param-batchImportParams', `is_parent` = 'false', `op_type` = NULL, `mark` = '根据报文串批量导入入参', `status` = '0', `parent_op_id` = 5, `permission_mark` = '#batch-add-object', `page_name` = 'interfaceParameter' WHERE `op_id` = 37; +UPDATE `at_operation_interface` SET `op_name` = '批量删除', `call_name` = 'param-delInterfaceParams', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定接口下的所有入参', `status` = '0', `parent_op_id` = 5, `permission_mark` = '#batch-del-object', `page_name` = 'interfaceParameter' WHERE `op_id` = 38; +UPDATE `at_operation_interface` SET `op_name` = '编辑报文信息', `call_name` = 'message-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑报文信息', `status` = '0', `parent_op_id` = 6, `permission_mark` = '.object-edit', `page_name` = 'message' WHERE `op_id` = 40; +UPDATE `at_operation_interface` SET `op_name` = '删除报文', `call_name` = 'message-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定报文', `status` = '0', `parent_op_id` = 6, `permission_mark` = '.object-del', `page_name` = 'message' WHERE `op_id` = 42; +UPDATE `at_operation_interface` SET `op_name` = '场景信息编辑', `call_name` = 'scene-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑指定测试场景', `status` = '0', `parent_op_id` = 7, `permission_mark` = '.object-edit', `page_name` = 'messageScene' WHERE `op_id` = 46; +UPDATE `at_operation_interface` SET `op_name` = '删除测试场景', `call_name` = 'scene-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定测试场景', `status` = '0', `parent_op_id` = 7, `permission_mark` = '.object-del', `page_name` = 'messageScene' WHERE `op_id` = 48; +UPDATE `at_operation_interface` SET `op_name` = '删除指定测试数据', `call_name` = 'data-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定测试数据', `status` = '0', `parent_op_id` = 8, `permission_mark` = '.object-del', `page_name` = 'testData' WHERE `op_id` = 55; +UPDATE `at_operation_interface` SET `op_name` = '编辑测试数据信息', `call_name` = 'data-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑测试数据信息', `status` = '0', `parent_op_id` = 8, `permission_mark` = '.object-edit', `page_name` = 'testData' WHERE `op_id` = 59; +UPDATE `at_operation_interface` SET `op_name` = '删除测试报告', `call_name` = 'report-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定测试报告', `status` = '0', `parent_op_id` = 9, `permission_mark` = '.object-del', `page_name` = 'report' WHERE `op_id` = 62; +UPDATE `at_operation_interface` SET `op_name` = '查看离线测试报告', `call_name` = 'report-generateStaticReportHtml', `is_parent` = 'false', `op_type` = NULL, `mark` = '查看离线测试报告', `status` = '0', `parent_op_id` = 9, `permission_mark` = '.download-report', `page_name` = 'report' WHERE `op_id` = 63; +UPDATE `at_operation_interface` SET `op_name` = '查看在线测试报告', `call_name` = 'report-getReportDetail', `is_parent` = 'false', `op_type` = NULL, `mark` = '查看动态生成的在线测试报告', `status` = '0', `parent_op_id` = 9, `permission_mark` = '.view-report', `page_name` = 'report' WHERE `op_id` = 64; +UPDATE `at_operation_interface` SET `op_name` = '操作测试集场景', `call_name` = 'set-opScene', `is_parent` = 'false', `op_type` = NULL, `mark` = '添加到测试集或者从测试集删除', `status` = '0', `parent_op_id` = 11, `permission_mark` = '.op-scene,#batch-op', `page_name` = 'setScene' WHERE `op_id` = 67; +UPDATE `at_operation_interface` SET `op_name` = '编辑测试集信息', `call_name` = 'set-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑指定测试集信息', `status` = '0', `parent_op_id` = 11, `permission_mark` = '#edit-set-info', `page_name` = 'setScene' WHERE `op_id` = 71; +UPDATE `at_operation_interface` SET `op_name` = '删除测试集', `call_name` = 'set-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定测试集', `status` = '0', `parent_op_id` = 11, `permission_mark` = '#del-this-set', `page_name` = 'setScene' WHERE `op_id` = 73; +UPDATE `at_operation_interface` SET `op_name` = '设定测试集运行时配置', `call_name` = 'set-settingConfig', `is_parent` = 'false', `op_type` = NULL, `mark` = '设定指定测试集的运行时配置(默认还是自定义)', `status` = '0', `parent_op_id` = 11, `permission_mark` = '#setting-set-config', `page_name` = 'setScene' WHERE `op_id` = 75; +UPDATE `at_operation_interface` SET `op_name` = '编辑验证规则信息', `call_name` = 'validate-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑验证规则信息', `status` = '0', `parent_op_id` = 12, `permission_mark` = '.object-edit', `page_name` = 'validateParameters' WHERE `op_id` = 84; +UPDATE `at_operation_interface` SET `op_name` = '删除验证规则信息', `call_name` = 'validate-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定验证规则信息', `status` = '0', `parent_op_id` = 12, `permission_mark` = '.object-del', `page_name` = 'validateParameters' WHERE `op_id` = 86; +UPDATE `at_operation_interface` SET `op_name` = '编辑定时任务', `call_name` = 'task-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑定时任务', `status` = '0', `parent_op_id` = 14, `permission_mark` = '.object-edit', `page_name` = 'autoTask' WHERE `op_id` = 89; +UPDATE `at_operation_interface` SET `op_name` = '删除指定定时任务', `call_name` = 'task-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定定时任务', `status` = '0', `parent_op_id` = 14, `permission_mark` = '.object-del', `page_name` = 'autoTask' WHERE `op_id` = 90; +UPDATE `at_operation_interface` SET `op_name` = '停止运行中的定时任务', `call_name` = 'task-stopRunningTask', `is_parent` = 'false', `op_type` = NULL, `mark` = '停止运行中的定时任务', `status` = '0', `parent_op_id` = 14, `permission_mark` = '.start-stop-task', `page_name` = 'autoTask' WHERE `op_id` = 93; +UPDATE `at_operation_interface` SET `op_name` = '运行可运行的定时任务', `call_name` = 'task-startRunableTask', `is_parent` = 'false', `op_type` = NULL, `mark` = '运行可运行的定时任务', `status` = '0', `parent_op_id` = 14, `permission_mark` = '.start-stop-task', `page_name` = 'autoTask' WHERE `op_id` = 94; +UPDATE `at_operation_interface` SET `op_name` = '更新定时规则', `call_name` = 'task-updateCronExpression', `is_parent` = 'false', `op_type` = NULL, `mark` = '更新定时规则', `status` = '0', `parent_op_id` = 14, `permission_mark` = '.setting-cron-expression', `page_name` = 'autoTask' WHERE `op_id` = 98; +UPDATE `at_operation_interface` SET `op_name` = '更新全局配置信息', `call_name` = 'global-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '更新全局配置信息', `status` = '0', `parent_op_id` = 15, `permission_mark` = '.save-setting', `page_name` = 'globalSetting' WHERE `op_id` = 99; +UPDATE `at_operation_interface` SET `op_name` = '测试指定数据源是否可连接', `call_name` = 'db-testDB', `is_parent` = 'false', `op_type` = NULL, `mark` = '测试指定数据源是否可连接', `status` = '0', `parent_op_id` = 17, `permission_mark` = '.db-test', `page_name` = 'queryDbList' WHERE `op_id` = 102; +UPDATE `at_operation_interface` SET `op_name` = '删除指定查询数据库信息', `call_name` = 'db-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定查询数据库信息', `status` = '0', `parent_op_id` = 17, `permission_mark` = '.object-del', `page_name` = 'queryDbList' WHERE `op_id` = 103; +UPDATE `at_operation_interface` SET `op_name` = '编辑指定查询数据库信息', `call_name` = 'db-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑指定查询数据库信息', `status` = '0', `parent_op_id` = 17, `permission_mark` = '.object-edit', `page_name` = 'queryDbList' WHERE `op_id` = 105; +UPDATE `at_operation_interface` SET `op_name` = '编辑变量信息', `call_name` = 'variable-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑变量模板信息', `status` = '0', `parent_op_id` = 18, `permission_mark` = '.object-edit', `page_name` = 'variable' WHERE `op_id` = 109; +UPDATE `at_operation_interface` SET `op_name` = '删除变量信息', `call_name` = 'variable-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定变量模板信息', `status` = '0', `parent_op_id` = 18, `permission_mark` = '.object-del', `page_name` = 'variable' WHERE `op_id` = 110; +UPDATE `at_operation_interface` SET `op_name` = '删除站内信', `call_name` = 'mail-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除信息', `status` = '0', `parent_op_id` = 20, `permission_mark` = '.object-del', `page_name` = 'mail' WHERE `op_id` = 116; +UPDATE `at_operation_interface` SET `op_name` = '删除指定角色信息', `call_name` = 'role-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除指定角色信息', `status` = '0', `parent_op_id` = 21, `permission_mark` = '.object-del', `page_name` = 'role' WHERE `op_id` = 118; +UPDATE `at_operation_interface` SET `op_name` = '编辑指定角色信息', `call_name` = 'role-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑指定角色信息', `status` = '0', `parent_op_id` = 21, `permission_mark` = '.object-edit', `page_name` = 'role' WHERE `op_id` = 120; +UPDATE `at_operation_interface` SET `op_name` = '锁定用户或者解锁用户', `call_name` = 'user-lock', `is_parent` = 'false', `op_type` = NULL, `mark` = '锁定用户或者解锁用户', `status` = '0', `parent_op_id` = 22, `permission_mark` = '.user-lock', `page_name` = 'user' WHERE `op_id` = 126; +UPDATE `at_operation_interface` SET `op_name` = '编辑用户信息', `call_name` = 'user-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '新增或者编辑用户信息', `status` = '0', `parent_op_id` = 22, `permission_mark` = '.object-edit', `page_name` = 'user' WHERE `op_id` = 128; +UPDATE `at_operation_interface` SET `op_name` = '重置用户密码', `call_name` = 'user-resetPwd', `is_parent` = 'false', `op_type` = NULL, `mark` = '重置指定用户的密码为111111', `status` = '0', `parent_op_id` = 22, `permission_mark` = '.reset-pass', `page_name` = 'user' WHERE `op_id` = 129; +UPDATE `at_operation_interface` SET `op_name` = '从excel导入数据', `call_name` = 'interface-importFromExcel', `is_parent` = 'false', `op_type` = NULL, `mark` = '从上传的Excel中导入接口信息数据', `status` = '0', `parent_op_id` = 3, `permission_mark` = '#import-data-from-excel', `page_name` = 'interface' WHERE `op_id` = 130; +UPDATE `at_operation_interface` SET `op_name` = '从excel导入数据', `call_name` = 'message-importFromExcel', `is_parent` = 'false', `op_type` = NULL, `mark` = '从上传的Excel中导入报文信息数据', `status` = '0', `parent_op_id` = 6, `permission_mark` = '#import-data-from-excel', `page_name` = 'message' WHERE `op_id` = 131; +UPDATE `at_operation_interface` SET `op_name` = '从excel导入数据', `call_name` = 'scene-importFromExcel', `is_parent` = 'false', `op_type` = NULL, `mark` = '从上传的Excel中导入测试场景信息数据', `status` = '0', `parent_op_id` = 7, `permission_mark` = '#import-data-from-excel', `page_name` = 'messageScene' WHERE `op_id` = 132; +UPDATE `at_operation_interface` SET `op_name` = '移动测试集', `call_name` = 'set-moveFolder', `is_parent` = 'false', `op_type` = NULL, `mark` = '将指定测试集移动到指定的目录文件夹下', `status` = '0', `parent_op_id` = 11, `permission_mark` = '#batch-move-folder', `page_name` = 'testSet' WHERE `op_id` = 135; +UPDATE `at_operation_interface` SET `op_name` = '导出接口文档', `call_name` = 'interface-exportInterfaceDocument', `is_parent` = 'false', `op_type` = NULL, `mark` = '批量导出接口文档', `status` = '0', `parent_op_id` = 3, `permission_mark` = '#export-interface-document', `page_name` = 'interface' WHERE `op_id` = 136; +UPDATE `at_operation_interface` SET `op_name` = '编辑或新增组合场景', `call_name` = 'complexScene-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑或新增组合场景', `status` = '0', `parent_op_id` = 998, `permission_mark` = '.object-edit', `page_name` = 'complexScene' WHERE `op_id` = 1001; +UPDATE `at_operation_interface` SET `op_name` = '删除组合场景', `call_name` = 'complexScene-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除组合场景', `status` = '0', `parent_op_id` = 998, `permission_mark` = '.object-del', `page_name` = 'complexScene' WHERE `op_id` = 1002; +UPDATE `at_operation_interface` SET `op_name` = '测试环境', `call_name` = 'system', `is_parent` = 'true', `op_type` = NULL, `mark` = '测试环境、业务系统', `status` = '0', `parent_op_id` = 13, `permission_mark` = '', `page_name` = '' WHERE `op_id` = 1019; +UPDATE `at_operation_interface` SET `op_name` = '编辑或者新增测试环境', `call_name` = 'system-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '.object-edit', `page_name` = 'businessSystem' WHERE `op_id` = 1020; +UPDATE `at_operation_interface` SET `op_name` = '获取测试环境信息', `call_name` = 'system-get', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '', `page_name` = '' WHERE `op_id` = 1022; +UPDATE `at_operation_interface` SET `op_name` = '查询测试环境列表', `call_name` = 'system-list', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '', `page_name` = '' WHERE `op_id` = 1023; +UPDATE `at_operation_interface` SET `op_name` = '删除测试环境信息', `call_name` = 'system-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '.object-del', `page_name` = 'businessSystem' WHERE `op_id` = 1024; +UPDATE `at_operation_interface` SET `op_name` = '查询所有测试环境列表', `call_name` = 'system-listAll', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '', `page_name` = '' WHERE `op_id` = 1025; +UPDATE `at_operation_interface` SET `op_name` = '删除操作接口', `call_name` = 'op-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 16, `permission_mark` = '.object-del', `page_name` = 'opInterface' WHERE `op_id` = 1027; +UPDATE `at_operation_interface` SET `op_name` = '编辑操作接口', `call_name` = 'op-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 16, `permission_mark` = '.object-edit', `page_name` = 'opInterface' WHERE `op_id` = 1029; +UPDATE `at_operation_interface` SET `op_name` = '编辑或者新增探测任务', `call_name` = 'probe-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '编辑或者新增探测任务', `status` = '0', `parent_op_id` = 1032, `permission_mark` = '.object-edit', `page_name` = 'interfaceProbe' WHERE `op_id` = 1034; +UPDATE `at_operation_interface` SET `op_name` = '删除探测任务信息', `call_name` = 'probe-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '删除探测任务信息', `status` = '0', `parent_op_id` = 1032, `permission_mark` = '.object-del', `page_name` = 'interfaceProbe' WHERE `op_id` = 1035; +UPDATE `at_operation_interface` SET `op_name` = '开启探测任务', `call_name` = 'probe-startTask', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1032, `permission_mark` = '.start-probe-task', `page_name` = 'interfaceProbe' WHERE `op_id` = 1039; +UPDATE `at_operation_interface` SET `op_name` = '停止探测任务', `call_name` = 'probe-stopTask', `is_parent` = 'false', `op_type` = NULL, `mark` = '停止探测任务', `status` = '0', `parent_op_id` = 1032, `permission_mark` = '.stop-probe-task', `page_name` = 'interfaceProbe' WHERE `op_id` = 1040; +UPDATE `at_operation_interface` SET `op_name` = '组合场景单个测试', `call_name` = 'test-complexSceneTest', `is_parent` = 'false', `op_type` = NULL, `mark` = '组合场景单个测试', `status` = '0', `parent_op_id` = 4, `permission_mark` = '.object-test', `page_name` = 'complexScene' WHERE `op_id` = 1044; +UPDATE `at_operation_interface` SET `op_name` = '业务系统删除或者增加接口信息', `call_name` = 'system-opInterface', `is_parent` = 'false', `op_type` = NULL, `mark` = '从指定的业务系统中删除或者增加接口信息', `status` = '0', `parent_op_id` = 1019, `permission_mark` = '#batch-op,.op-interface', `page_name` = 'manageSystemInterface' WHERE `op_id` = 1058; +UPDATE `at_operation_interface` SET `op_name` = '删除指定操作日志信息', `call_name` = 'log-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1059, `permission_mark` = '.object-del,#batch-del-object', `page_name` = 'logRecord' WHERE `op_id` = 1062; +UPDATE `at_operation_interface` SET `op_name` = '编辑mock接口基本信息', `call_name` = 'mock-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1064, `permission_mark` = '.object-edit', `page_name` = 'mockTest' WHERE `op_id` = 1066; +UPDATE `at_operation_interface` SET `op_name` = '删除指定mock接口信息', `call_name` = 'mock-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1064, `permission_mark` = '.object-del', `page_name` = 'mockTest' WHERE `op_id` = 1068; +UPDATE `at_operation_interface` SET `op_name` = '更新mock规则', `call_name` = 'mock-updateSetting', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1064, `permission_mark` = '#save-setting-mock-validate', `page_name` = 'mockTest' WHERE `op_id` = 1070; +UPDATE `at_operation_interface` SET `op_name` = '删除性能测试配置', `call_name` = 'ptc-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1073, `permission_mark` = '.object-del', `page_name` = 'performanceTest' WHERE `op_id` = 1075; +UPDATE `at_operation_interface` SET `op_name` = '编辑性能测试配置信息', `call_name` = 'ptc-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1073, `permission_mark` = '.object-edit', `page_name` = 'performanceTest' WHERE `op_id` = 1076; +UPDATE `at_operation_interface` SET `op_name` = '删除性能测试结果', `call_name` = 'ptr-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1078, `permission_mark` = '.object-del,#batch-del', `page_name` = 'performanceTestResult' WHERE `op_id` = 1082; +UPDATE `at_operation_interface` SET `op_name` = '停止指定性能测试任务', `call_name` = 'ptc-stopTest', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1084, `permission_mark` = '.stop-test', `page_name` = 'performanceTestTaskList' WHERE `op_id` = 1086; +UPDATE `at_operation_interface` SET `op_name` = '删除指定性能测试任务', `call_name` = 'ptc-delTest', `is_parent` = 'false', `op_type` = NULL, `mark` = '被删除的性能测试任务不会保存本次测试结果', `status` = '0', `parent_op_id` = 1084, `permission_mark` = '.del-test', `page_name` = 'performanceTestTaskList' WHERE `op_id` = 1087; +UPDATE `at_operation_interface` SET `op_name` = '初始化性能测试任务', `call_name` = 'ptc-initTest', `is_parent` = 'false', `op_type` = NULL, `mark` = '包括初始化配置、加载配置文件、预加载请求报文等', `status` = '0', `parent_op_id` = 1084, `permission_mark` = '.object-test', `page_name` = 'performanceTest' WHERE `op_id` = 1088; +UPDATE `at_operation_interface` SET `op_name` = '邮件推送离线报告', `call_name` = 'report-sendMail', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 9, `permission_mark` = '.send-mail', `page_name` = 'report' WHERE `op_id` = 1093; +UPDATE `at_operation_interface` SET `op_name` = '更新菜单与角色之间的关系', `call_name` = 'role-updateRoleMenu', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 21, `permission_mark` = '.show-role-menu', `page_name` = 'role' WHERE `op_id` = 1133; +UPDATE `at_operation_interface` SET `op_name` = '编辑或新增菜单信息', `call_name` = 'menu-edit', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1134, `permission_mark` = '.object-edit', `page_name` = 'menu' WHERE `op_id` = 1135; +UPDATE `at_operation_interface` SET `op_name` = '删除指定菜单信息', `call_name` = 'menu-del', `is_parent` = 'false', `op_type` = NULL, `mark` = '', `status` = '0', `parent_op_id` = 1134, `permission_mark` = '.object-del', `page_name` = 'menu' WHERE `op_id` = 1138; +DELETE FROM `at_operation_interface` WHERE `op_id` = 81; +DELETE FROM `at_operation_interface` WHERE `op_id` = 82; +UPDATE at_busi_menu_info SET status='0' WHERE menu_id=27; +ALTER TABLE `at_test_config` ADD COLUMN `public_data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '属于该测试集的公共测试数据,json串存储' AFTER `mail_copy_address`; +ALTER TABLE `at_test_config` ADD COLUMN `public_header` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '属于该测试集的公共请求头,只对HTTP/HTTPS有效,json串存储' AFTER `public_data`; +ALTER TABLE `at_scene_validate_rule` ADD COLUMN `config_id` int(11) NULL DEFAULT NULL COMMENT '所属测试配置' AFTER `validate_id`; +ALTER TABLE `at_scene_validate_rule` ADD INDEX `at_scene_validate_rule_fk_config_id`(`config_id`) USING BTREE; +ALTER TABLE `at_scene_validate_rule` ADD CONSTRAINT `at_scene_validate_rule_fk_config_id` FOREIGN KEY (`config_id`) REFERENCES `at_test_config` (`config_id`) ON DELETE RESTRICT ON UPDATE RESTRICT; \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index ef5d143..ed91172 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,100 +1,121 @@ - - yi - - login.html - - - 180 - - - log4jConfigLocation - classpath:log4j.properties - - - - - org.springframework.web.util.Log4jConfigListener - - - - contextConfigLocation - classpath:applicationContext.xml - - - org.springframework.web.context.ContextLoaderListener - - - yi.master.listener.InitWebListener - - - - - DruidWebStatFilter - com.alibaba.druid.support.http.WebStatFilter - - exclusions - *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* - - - + + yi + + login.html + + + 180 + + + log4jConfigLocation + classpath:log4j.properties + + + log4jRefreshInterval + 60000 + + + contextConfigLocation + classpath:applicationContext.xml + + + + + org.springframework.web.util.Log4jConfigListener + + + + + org.springframework.web.context.ContextLoaderListener + + + + yi.master.listener.InitWebListener + + + + + + + DruidWebStatFilter + com.alibaba.druid.support.http.WebStatFilter + + exclusions + *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* + + + + + DruidWebStatFilter + /* + + + + + DruidStatView + com.alibaba.druid.support.http.StatViewServlet + + + + DruidStatView + /druid/* + + + + + encodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + forceEncoding + true + + - DruidWebStatFilter - /* - - - - - DruidStatView - com.alibaba.druid.support.http.StatViewServlet - + encodingFilter + /* + + + + + + + + + + + + + + + + openSessionInView + org.springframework.orm.hibernate4.support.OpenSessionInViewFilter + + sessionFactoryBeanName + sessionFactory + + + + openSessionInView + /* + + + + + struts2 + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter + + + struts2 + /* + + - - DruidStatView - /druid/* - - - - - encodingFilter - org.springframework.web.filter.CharacterEncodingFilter - - encoding - UTF-8 - - - forceEncoding - true - - - - encodingFilter - /* - - - openSessionInView - org.springframework.orm.hibernate4.support.OpenSessionInViewFilter - - sessionFactoryBeanName - sessionFactory - - - - openSessionInView - /* - - - struts2 - org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter - - - struts2 - /* - - - - \ No newline at end of file diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 31a217c..b9827cb 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -87,9 +87,6 @@ - - -
@@ -103,340 +100,15 @@ - - + + + + \ No newline at end of file diff --git a/src/main/webapp/index.js b/src/main/webapp/index.js new file mode 100644 index 0000000..54e62b9 --- /dev/null +++ b/src/main/webapp/index.js @@ -0,0 +1,271 @@ +//方便子页面调用 +var loadMenuFun; + +//菜单信息 +var menuJson; + +//////////////////////////////////可全局用到的信息 +//当前登陆用户的权限信息列表 +var currentUserPermissionList; +//首页地址 +var homeUrl; +//用户id +var userId; +//第三方token登陆 +var token; +//退出时返回的页面 +var backUrl; + +//全部的handlebars模版,子页面调用 +var templates; +//全部的html模板,子页面调用 +var htmls; +////////////////////////////////// +$(document).ready(function() { + //打开welcome页面 + $('iframe').attr("src", "welcome.html"); + + /***********通过外部token登录的方式打开首页****************/ + token = GetQueryString("token"); + backUrl = GetQueryString("backUrl"); + backUrl = (backUrl == null ? "login.html" : "http://" + backUrl); + if (token != null && token != "") { + $(".redirect-to-page").hide(); + } + /******************************************************/ + + $(".openIframeNew").on("click",function(){ + Hui_admin_tab(this); + }); + + + /*******************初始化子iFrame中的模板和远程子页面html代码***************************/ + //模板id + templates = initHandlebarsTemplate(); + + + //页面名 + htmls = loadChildrenHtml(["interfaceParameter-viewTree", + "messageScene-test", + "messageScene-validateFullJson", + "messageScene-validateKeyword", + "role-power", + "viewWindow"]); + /*****************************************************/ +}); + + +/*************预先编译子iframe中的模板***************/ +function initHandlebarsTemplate () { + var loadingIndex = layer.msg('正在初始化系统...', {icon:16, shade:0.45, time:999999999}); + var templates = {}; + $("#templates-page").load("./resource/template/customTemplate.htm", function() { + $("#templates-page > script").each(function(i, n){ + templates[$(n).attr('id')] = Handlebars.compile($(n).html()); + }); + layer.close(loadingIndex); + }); + return templates; +} + +/*****加载子页面代码到内存*******/ +function loadChildrenHtml (options) { + if (options == null || typeof options != 'object') { + return false; + } + var htmls = {}; + $.each(options, function (i, n) { + $("#children-page").append('
'); + $("#" + n).load("./resource/template/" + n + ".htm", function() { + htmls[n] = $("#" + n).html(); + $("#" + n).html(''); + }); + }); + return htmls; +} + +/********************加载菜单***************************/ +loadMenuFun = function() { + $.get(REQUEST_URL.MENU.GET_USER_MENUS, function(data){ + if (data.returnCode == 0) { + menuJson = data.data; + var systemSwitchDom = $('#system-type-name').siblings('ul'); + var defaultTypeKey = null; + $.each(menuJson, function(systemKey, content){ + defaultTypeKey == null && (defaultTypeKey = systemKey); + systemSwitchDom.append('
  • ' + content.name + '
  • '); + }); + + $("#menu-page").load("./resource/template/menuTemplate.htm", function(){ + templates['menu-template'] = Handlebars.compile($("#menu-page > script").html()); + switchMenu(getCookie('menuType') == null ? defaultTypeKey : getCookie('menuType'), true, defaultTypeKey); + $(".switch-system").click(function(){ + var name = switchMenu($(this).attr('system-type')); + name && (layer.msg('已切换至系统:' + name, {time:2000})); + }); + }) + } + }); +} +/** + * 根据配置切换菜单显示 + * @param menuType + * @param init + * @param defaultTypeKey + * @returns {*} + */ +function switchMenu(menuType, init, defaultTypeKey) { + if (menuType == null) { + menuType = "interface"; + } + if (menuType == getCookie('menuType') && !init) { + return null; + } + if (menuJson[menuType] == null) { + menuType = defaultTypeKey; + } + $("#menu").html(templates['menu-template'](menuJson[menuType]['menu'])); + //重新初始化菜单效果 + $.Huifold(".menu_dropdown dl dt",".menu_dropdown dl dd","fast",3,"click"); + //第一个菜单为打开状态 + $("#menu dt:eq(0)").click(); + //如果切换的是其他的系统菜单,则关闭全部的Tab选项卡 + //$("#min_title_list li i").trigger("click"); + setCookie("menuType", menuType); + $("#system-type-name").html(menuJson[menuType]['name'] + ''); + return menuJson[menuType]['name']; +} + + + +/***********修改密码*********/ +function to_changePasswd() { + layer.prompt({ + formType: 1, + value: '', + title: '验证旧密码' + }, function(value, index, elem){ + layer.close(index); + $.post(REQUEST_URL.USER.VERIFY_PASSWORD, {password: value}, function (data) { + if (data.returnCode == 0) { + layer.prompt({ + formType: 1, + value: '', + title: '请输入新密码' + }, function(value1, index1, elem){ + layer.close(index1); + layer.confirm('确定要将密码修改为"' + value1 + '"吗?', {icon:0, title:'警告'}, function(index2) { + layer.close(index2); + $.get(REQUEST_URL.USER.MODIFY_PASSWORD,{password:value1}, function(data) { + if (data.returnCode == 0) { + layer.msg('密码修改成功,设置自动登录的需要重新输入密码!', {icon:1, time:1500}); + } else { + layer.alert(data.msg, {icon: 5}); + } + }); + + }); + }); + }else{ + layer.alert(data.msg, {icon:5}); + } + }); + }); +} + +/***********手动点击logout会清除登录信息cookie*********/ +function to_logout(){ + $.get(REQUEST_URL.LOGIN.LOGOUT,function(data){ + if(data.returnCode==0){ + clearCookie("username"); + clearCookie("password"); + window.location.href = backUrl; + } + }); +} + +/***********切换用户*********/ +function to_changeUser(){ + var loginHtml ='
    '+ + '
    '+ + ''+ + '
    '+ + ''+ + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    '+ + ''+ + '
    '+ + '
    '+ + '
    ' + + '' + + '
    ' + + ' ' + + '' + + '
    ' + + '
    ' + + '
    '+ + '
    '+ + ' '+ + ''+ + '

    '+ + '
    '+ + '
    '+ + '
    '; + + var index = layer.open({ + title:'切换用户', + type: 1, + area: ['569px', '317px'], + content: loginHtml, + success:function(layero, index){ + $("#loginBtn").click(userLogin); + //监听键盘回车事件 + $(layero).keyup(function (event) { + var keyCode = event.which; + if(keyCode == 13){ + $("#loginBtn").click(); + } + }); + + $("#verifyCode").siblings('img').click(function(){ + var that = this; + $.get(REQUEST_URL.LOGIN.CREATE_VERIFY_CODE, function(data){ + if (data.returnCode == 0) { + $(that).attr('src', 'data:image/png;base64,' + data.data); + } + }); + }); + + $("#username").trigger("focus").trigger("select"); + $("#verifyCode").siblings('img').click(); + } + }); +} + +/**切换用户时的登录页面*/ +function userLogin(){ + var username = $("#username").val(); + var password = $("#password").val(); + var verifyCode = $("#verifyCode").val(); + var tipMsg = $("#loginTip"); + if(username != "" && username != null && password != "" && password != null && verifyCode != "" && verifyCode != null){ + $.post(REQUEST_URL.LOGIN.LOGIN,{ + username:username, + password:password, + verifyCode: verifyCode + },function(data){ + if(data.returnCode==0){ + location.reload(); + }else if (data.returnCode==2){ + layer.alert(data.msg, {icon: 4}); + }else { + tipMsg.text(data.msg); + } + }); + }else{ + tipMsg.text("请填写完整再提交登录"); + } +} \ No newline at end of file diff --git a/src/main/webapp/js/ajaxErrorHandler.js b/src/main/webapp/js/ajaxErrorHandler.js new file mode 100644 index 0000000..2954415 --- /dev/null +++ b/src/main/webapp/js/ajaxErrorHandler.js @@ -0,0 +1,20 @@ +//设置jQuery Ajax全局的参数 +$.ajaxSetup({ + error: function (jqXHR, textStatus, errorThrown) { + layer.closeAll('dialog'); + switch (jqXHR.status) { + case(403): + let needrestart = jqXHR.getResponseHeader("needrestart"); + if (needrestart != null && needrestart == "true") { + top.layer.alert("系统升级完成,请联系管理重启服务器!", {offset: '60px', title: "升级完成提示!", icon: 0, closeBtn: 0}, function(index, layero){ + return; + }); + return; + } + + break; + default: + break; + } + } +}); \ No newline at end of file diff --git a/src/main/webapp/js/bak/explanationMarks.json b/src/main/webapp/js/bak/explanationMarks.json deleted file mode 100644 index c4c9100..0000000 --- a/src/main/webapp/js/bak/explanationMarks.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "parameterizedFilePath":{ - "title":"关于参数化文件的说明", - "content":"上传的参数化文件需为 txt 格式。
    第一行为参数化节点路径(路径名称大小写敏感,请与参数标识符保持一致),从第二列开始为参数化数据,默认数据分隔符为英文下逗号,你可以自行设定不同的分隔符。" - }, - "mock-validate-path":{ - "title":"Mock入参验证节点路径的填写说明", - "content":"根据入参报文的格式不同,该项需要填写不同的内容:
    JSON、XML: 完整的入参节点路径,例如ROOT.INFO.USERNAME;
    URL: 留空;
    不限格式: 例如Socket报文,可使用关联规则来获取。
    对于URL参数和请求头,此处可忽略。" - }, - "settingMailStyle":{ - "title":"自定义推送邮件的模板", - "content":"你可以自定义设定定时任务和探测任务的推送的邮件模板,模板类型为Html,同时可以在模板中插入相关测试结果变量。" - }, - "webStepConfig":{ - "title":"测试步骤配置", - "html":true, - "content":"explanation-mark-webstep-config", - "width":915, - "height":500 - }, - "webTestConfig":{ - "title":"Web自动化运行时配置说明", - "content":"1、如果你的浏览器driver文件路径没有放置到环境变量下,请在此配置, 请填写全路径,注意填写的是自动化执行客户端所在机器上的driver路径 .
    2、如何你的浏览器不是安装在默认路径或者安装的是绿色版,请指定各浏览器的执行bin文件的绝对路径(其他同上)。" - }, - "webCustomVariableSetting":{ - "title":"Web自动化自定义变量说明", - "content":"在测试用例、测试用例集、用例与用例集的关联对象中可以配置自定义的变量,变量以key-value形式保存(其中value可以使用全局变量),自定义的变量可以在下属的测试步骤中使用:
    优先级 用例集自定义变量 > 用例与用例集关联对象自定义变量 > 用例自定义变量" - }, - "webSuiteCaseSetting":{ - "title":"测试集用例自定义 配置说明", - "content":"执行顺序:默认按照设定的数字大小来排序,数字越小的先执行,越大的后执行。
    分组名:在进行分布式执行时,会将组名相同的用例分配到同一个远程执行机执行。
    跳过标记:方便在不需要执行某个用例时排除而不是删除掉。" - } -} \ No newline at end of file diff --git a/src/main/webapp/js/bak/messageProcess.json b/src/main/webapp/js/bak/messageProcess.json deleted file mode 100644 index 33c7cbe..0000000 --- a/src/main/webapp/js/bak/messageProcess.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ShanXiOpenApi":{ - }, - "AnhuiApp":{ - } -} \ No newline at end of file diff --git a/src/main/webapp/js/bak/protocol.json b/src/main/webapp/js/bak/protocol.json deleted file mode 100644 index c0492a0..0000000 --- a/src/main/webapp/js/bak/protocol.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "HTTP":{ - "Headers":{ - }, - "Querys":{ - }, - "Authorization":{ - }, - "Method":"POST", - "ConnectTimeOut":"", - "ReadTimeOut":"", - "RecEncType":"UTF-8", - "EncType":"UTF-8" - }, - "HTTPS":{ - "Headers":{ - }, - "Authorization":{ - }, - "Method":"POST", - "ConnectTimeOut":"", - "ReadTimeOut":"", - "RecEncType":"UTF-8", - "EncType":"UTF-8" - }, - "Socket":{ - "ConnectTimeOut":"", - "ReadTimeOut":"" - }, - "WebService":{ - "ConnectTimeOut":"", - "Namespace":"", - "Method":"", - "Username":"", - "Password":"" - } -} diff --git a/src/main/webapp/js/bak/readme.txt b/src/main/webapp/js/bak/readme.txt deleted file mode 100644 index 03a5bc7..0000000 --- a/src/main/webapp/js/bak/readme.txt +++ /dev/null @@ -1,8 +0,0 @@ -explanationMarks.json 页面表单的说明文档 -HttpRequestHeader.json http常用的请求头说明 -HttpResponseHeader.json http常用的响应头说明 -menu.json 首页菜单数据 -messageProcess.json 接口报文后置处理器参数定义 -protocol.json 接口报文的格式定义 -webStepParameter.json Web自动化测试步骤的一些选择参数说明 -zh_CN.txt Datatables的本地化文件-中文 \ No newline at end of file diff --git a/src/main/webapp/js/bak/requestUrls.js b/src/main/webapp/js/bak/requestUrls.js deleted file mode 100644 index 148f714..0000000 --- a/src/main/webapp/js/bak/requestUrls.js +++ /dev/null @@ -1,297 +0,0 @@ -var BATCH_AUTO_TEST_URL = "test-scenesTest"; //批量测试 测试集或者全量 -var GET_TEST_CONFIG_URL = "test-getConfig";//获取当前用户的测试配置 -var UPDATE_TEST_CONFIG_URL = "test-updateConfig";//更新指定测试配置 -var CHECK_DATA_URL = "test-checkHasData";//测试之前检查指定的测试集中所有的测试场景是否有足够的测试数据 -var TEST_SCENE_URL = "test-sceneTest";//单场景测试 -var TEST_COMPLEX_SCENE_URL = "test-complexSceneTest";//测试组合场景 - -var PARAMS_GET_URL = "param-getParams"; //根据interfaceId来 获取parameters -var PARAM_SAVE_URL = "param-save"; //保存新增的接口参数 -var PARAM_DEL_URL = "param-del"; //删除指定参数 -var PARAM_GET_URL = "param-get"; -var PARAM_EDIT_URL = "param-edit"; //编辑参数的指定属性 -var PARAM_JSON_IMPORT_URL = "param-batchImportParams"; //导入json串 -var PARAM_DEL_ALL_URL = "param-delInterfaceParams";//删除指定接口下的所有参数 - - -var INTERFACE_LIST_URL = "interface-list"; //获取接口列表 -var INTERFACE_CHECK_NAME_URL = "interface-checkName"; //检查新增接口名是否重复 -var INTERFACE_EDIT_URL = "interface-edit"; //接口编辑 -var INTERFACE_GET_URL = "interface-get"; //获取指定接口信息 -var INTERFACE_DEL_URL = "interface-del"; //删除指定接口 -var INTERFACE_IMPORT_FROM_EXCEL_URL = "interface-importFromExcel";//从已经上传完成的excel中导入接口数据 -var INTERFACE_EXPORT_DOCUMENT_EXCEL_URL = "interface-exportInterfaceDocument";//批量导出接口文档 -var INTERFACE_GET_PARAMETERS_JSON_TREE_URL = "interface-getParametersJsonTree";//获取jsonTree数据 -var INTERFACE_UPDATE_CHILDREN_BUSINESS_SYSTEMS_URL = "interface-updateChildrenBusinessSystems";//更新接口下属报文场景等的测试环境信息 - - - -var MESSAGE_LIST_URL = "message-list"; //获取报文列表 -var MESSAGE_EDIT_URL = "message-edit"; //报文信息编辑 -var MESSAGE_GET_URL = "message-get"; //获取指定报文信息 -var MESSAGE_DEL_URL = "message-del"; //删除指定报文 -var MESSAGE_FORMAT_URL = "message-format";//格式化报文串 -var MESSAGE_VALIDATE_JSON_URL = "message-validateJson";//报文串验证 -var MESSAGE_IMPORT_FROM_EXCEL = "message-importFromExcel";//从已经上传完成的excel中导入接口数据 -var MESSAGE_CREATE_MESSAE_BY_NODES_URL = "message-createMessage"; - - -var SCENE_LIST_URL = "scene-list"; //获取场景列表 -var SCENE_EDIT_URL = "scene-edit"; //场景编辑 -var SCENE_GET_URL = "scene-get"; //获取指定场景信息 -var SCENE_DEL_URL = "scene-del"; //删除指定场景 -var SCENE_GET_TEST_OBJECT_URL = "scene-getTestObject"; //获取场景的测试数据和测试地址 -var SCENE_LIST_NO_DATA_SCENES_URL = "scene-listNoDataScenes"; //获取指定测试集中没有测试数据的测试场景列表 -var SCENE_IMPORT_FROM_EXCEL = "scene-importFromExcel";//从已经上传完成的excel中导入场景数据 -var SCENE_UPDATE_RESPONSE_EXAMPLE = "scene-updateResponseExample";//更新返回示例 -var SCENE_GET_REQUEST_MSG_JSON_TREE_URL = "scene-getRequestMsgJsonTree";//获取请求入参节点树信息 -var SCENE_GET_RESPONSE_MSG_JSON_TREE_URL = "scene-getResponseMsgJsonTree";//获取请求入参节点树信息 - - -var GET_SETTING_DATA_URL = "data-getSettingData"; //获取当前场景所属报文的所有可编辑入参节点 包含其他信息 -var IMPORT_DATA_VALUES_URL = "data-importDatas";//批量导入测试数据 -var DATA_LIST_URL = "data-list"; //获取指定测试场景数据列表 -var DATA_EDIT_URL = "data-edit"; //测试数据编辑 -var DATA_GET_URL = "data-get"; //获取指定测试数据信息 -var DATA_DEL_URL = "data-del"; //删除指定测试数据 -var DATA_CHECK_NAME_URL = "data-checkName"; //验证数据标记是否重复 -var GET_SETTING_DATA_URL = "data-getSettingData";//获取设置参数数据时需要用到的相关数据 -var CREATE_NEW_DATA_MSG_URL = "data-createDataMsg";//根据传入的json数据字符串和场景id生成新得带有数据的报文 -var DATA_CHANGE_STATUS_URL = "data-changeStatus";//修改指定数据状态 -var DATA_UPDATE_PARAMS_DATA_URL = "data-updateParamsData";//修改设置数据内容 - -var REPORT_LIST_URL = "report-list";//测试报告列表 -var REPORT_GET_URL = "report-get";//获取指定测试报告信息 -var REPORT_DEL_URL = "report-del";//删除指定测试报告 -var REPORT_DOWNLOAD_STATIS_HTML = "report-generateStaticReportHtml";//获取静态测试报告路径(不存在就后台执行生成) -var REPORT_GET_DETAILS_URL = "report-getReportDetail";//获取生成完整测试报告所需数据 -var REPORT_SEND_MAIL_URL = "report-sendMail";//将生成的离线报告进行邮件推送 - -var RESULT_LIST_URL = "result-list";//获取测试结果列表 -var RESULT_GET_URL = "result-get";//获取指定测试结果详情信息 - - -var SET_OP_SCENE_URL = "set-opScene";//操作测试场景,添加到测试集或者从测试集删除 -var LIST_MY_SETS_URL = "set-getMySet";//获取测试集列表 -var SET_SCENE_LIST_URL = "set-listScenes";//展示存在测试集或者不存在于测试集的测试场景 -var SET_LIST_URL = "set-list"; //获取测试集列表 -var SET_EDIT_URL = "set-edit"; //测试集信息编辑 -var SET_GET_URL = "set-get"; //获取指定测试集信息 -var SET_DEL_URL = "set-del"; //删除指定测试集 -var SET_NAME_CHECK_URL = "set-checkName"; //验证测试集名称是否重复 -var SET_RUN_SETTING_CONFIG_URL = "set-settingConfig";//配置测试集运行时配置 -var SET_GET_CATEGORY_NODES_URL = "set-getCategoryNodes";//获取测试集目录树 -var SET_MOVE_TO_FOLDER = "set-moveFolder"; //将指定测试集移动到指定的目录文件夹下 - -//组合场景信息 -var COMPLEX_SCENE_LIST_URL = "complexScene-list"; -var COMPLEX_SCENE_GET_URL = "complexScene-get"; -var COMPLEX_SCENE_EDIT_URL = "complexScene-edit"; -var COMPLEX_SCENE_DEL_URL = "complexScene-del"; -var COMPLEX_SCENE_LIST_SET_SCENES_URL="complexScene-listSetScenes";//获取指定测试集的组合场景 -var COMPLEX_SCENE_ADD_TO_SET_URL = "complexScene-addToSet";//添加组合场景到指定测试集 -var COMPLEX_SCENE_DEL_FROM_SET_URL = "complexScene-delFromSet";//从测试集中删除组合场景 -var COMPLEX_SCENE_LIST_SCENES_URL = "complexScene-listScenes";//获取组合场景中的所有测试场景 -var COMPLEX_SCENE_UPDATE_CONFIG_INFO_URL = "complexScene-updateConfigInfo";//更新配置信息 -var COMPLEX_SCENE_ADD_SCENE_URL = "complexScene-addScene";//添加测试场景到组合场景 -var COMPLEX_SCENE_DEL_SCENE_URL = "complexScene-delScene";//从组合场景中删除测试场景 -var COMPLEX_SCENE_SORT_SCENES_URL = "complexScene-sortScenes";//测试场景执行顺序排序 -var COMPLEX_SCENE_UPDATE_SCENE_CONFIG_URL = "complexScene-updateSceneConfig";//更新指定测试场景的配置信息 -var COMPLEX_SCENE_LIST_SAVE_VARIABLES_URL = "complexScene-getSaveVariables";//获取组合场景中指定的保存变量名称 - -//场景验证 -var VALIDATE_GET_URL = "validate-getValidate";//获取指定测试场景的验证规则(只限全文验证和边界验证) -var VALIDATE_FULL_EDIT_URL = "validate-validateFullEdit";//全文验证规则更新 -var VALIDATE_RULE_LIST_URL = "validate-getValidates"; //获取验证规则列表 -var VALIDATE_RULE_EDIT_URL = "validate-edit";//新增或者编辑验证规则 -var VALIDATE_RULE_GET_URL = "validate-get";//获取指定验证规则信息 -var VALIDATE_RULE_DEL_URL = "validate-del";//删除指定验证规则 -var VALIDATE_FULL_RULE_GET_URL = "validate-getValidate";//获取全文验证规则 -var VALIDATE_RULE_UPDATE_STATUS = "validate-updateValidateStatus";//更新验证规则状态 - -//定时任务 -var TASK_CHECK_NAME_URL = "task-checkName";//验证测试任务是否重名 -var TASK_EDIT_URL = "task-edit";//编辑定时任务 -var TASK_DEL_URL = "task-del";//删除指定定时任务 -var TASK_LIST_URL = "task-list";//定时任务列表 -var TASK_GET_URL = "task-get";//获取指定定时任务列表 -var TASK_STOP_TASK_URL = "task-stopRunningTask";//停止运行中的定时任务 -var TASK_ADD_RUNABLE_TASK_URL = "task-startRunableTask";//运行可运行的定时任务 -var TASK_START_QUARTZ_URL = "task-startQuartz";//开启quartz定时器 -var TASK_STOP_QUARTZ_URL = "task-stopQuartz";//停止quartz定时器 -var TASK_GET_QUARTZ_STATUS_URL = "task-getQuartzStatus";//获取quartz定时器当前的状态 -var TASK_UPDATE_CRON_EXPRESSION_URL = "task-updateCronExpression";//更新定时规则 - -var GLOBAL_SETTING_EDIT_URL = "global-edit";//全局配置编辑 -var GLOBAL_SETTING_LIST_ALL_URL = "global-listAll";//获取全部的全局配置 - -var OP_INTERFACE_LIST_URL = "op-listOp"; //操作接口列表 -var OP_INTERFACE_DEL_URL = "op-del"; //删除操作接口 -var OP_INTERFACE_GET_URL = "op-get"; //获取操作接口详细信息 -var OP_INTERFACE_EDIT_URL = "op-edit"; //编辑操作接口 -var OP_INTERFACE_DEIT_GET_NODE_TREE_URL = "op-getNodeTree";//获取节点树数据 -var OP_INTERFACE_LIST_ALL_URL = "op-listAll"; //获取全部的操作接口 - -var QUERY_DB_LINK_TEST_URL = "db-testDB";//测试指定查询数据库是否可连接 -var QUERY_DB_DEL_URL = "db-del";//删除指定查询数据库信息 -var QUERY_DB_LIST_URL = "db-list"//查询数据库列表 -var QUERY_DB_EDIT_URL = "db-edit"//编辑指定查询数据库信息 -var QUERY_DB_GET_URL = "db-get";//获取指定查询数据库信息 -var QUERY_DB_LIST_ALL_URL = "db-listAll";//获取所有当前可用的查询数据数据信息 - - -var MAIL_LIST_URL = "mail-list";//信息列表 -var MAIL_DEL_URL = "mail-del";//删除信息 -var MAIL_CHANGE_STATUS = "mail-changeStatus";//改变已读状态 - -var ROLE_DEL_URL = "role-del";//删除指定角色信息 -var ROLE_GET_NODES_INTERFACE_URL = "role-getInterfaceNodes";//获取当前所有操作接口,并标记哪些是当前角色拥有的 -var ROLE_GET_NODES_MENU_URL = "role-getMenuNodes"; //获取当前所有菜单,并标记哪些是当前角色拥有的 -var ROLE_EDIT_URL = "role-edit";//编辑指定角色信息 -var ROLE_LIST_URL = "role-list";//角色信息列表 -var ROLE_GET_URL = "role-get";//指定角色信息 -var ROLE_UPDATE_POWER_URL = "role-updateRolePower";//更新操作接口与角色之间的关系(角色的权限信息) -var ROLE_UPDATE_MENU_URL = "role-updateRoleMenu";//更新菜单与角色之间的关系 -var ROLE_LIST_ALL_URL = "role-listAll";//展示所有角色 - -var USER_LIST_URL = "user-list";//用户列表 -var USER_LOCK_URL = "user-lock";//锁定用户或者解锁用户 -var USER_GET_URL = "user-get";//获取用户信息 -var USER_EDIT_URL = "user-edit";//编辑用户信息 -var USER_RESET_PASSWD_URL = "user-resetPwd";//重置指定用户的密码为111111 - - -var GLOBAL_VARIABLE_LIST_URL = "variable-listAll"; -var GLOBAL_VARIABLE_EDIT_URL = "variable-edit"; -var GLOBAL_VARIABLE_DEL_URL = "variable-del"; -var GLOBAL_VARIABLE_GET_URL = "variable-get"; -var GLOBAL_VARIABLE_CHECK_NAME_URL = "variable-checkName";//检查key是否重复 -var GLOBAL_VARIABLE_UPDATE_VALUE_URL = "variable-updateValue";//更新指定变量模板的value值 -var GLOBAL_VARIABLE_CREATE_VARIABLE_URL = "variable-createVariable";//生成变量结果 - -var BUSINESS_SYSTEM_EDIT_URL = "system-edit";//编辑或者新增测试环境信息 -var BUSINESS_SYSTEM_GET_URL = "system-get";//获取测试环境信息 -var BUSINESS_SYSTEM_LIST_URL = "system-list";//查询测试环境列表 -var BUSINESS_SYSTEM_LIST_ALL_URL = "system-listAll";//查询所有测试环境列表 -var BUSINESS_SYSTEM_DEL_URL = "system-del";//删除测试环境信息 - -var BUSINESS_SYSTEM_INTERFACE_LIST_URL = "system-listInterface";//根据mode来查询当前测试环境包含的或者不包含的接口信息 -var BUSINESS_SYSTEM_OP_INTERFACE_URL = "system-opInterface";//从指定的测试环境中删除或者增加接口信息 - -var PROBE_TASK_GET_URL = "probe-get"; -var PROBE_TASK_EDIT_URL = "probe-edit"; -var PROBE_TASK_DEL_URL = "probe-del"; -var PROBE_TASK_LIST_ALL_URL = "probe-listAll"; -var PROBE_TASK_LIST_URL = "probe-list"; -var PROBE_TASK_UPDATE_CONFIG = "probe-updateConfig"//更新探测配置 -var PROBE_TASK_START_URL = "probe-startTask";//开启任务 -var PROBE_TASK_STOP_URL = "probe-stopTask";//停止任务 -var PROBE_TASK_GET_SINGLE_REPORT_DATA_URL = "probe-getProbeResultReportData"; -var PROBE_TASK_GET_PROBE_RESULT_SYSNOPSIS_VIEW_DATA_URL = "probe-getProbeResultSynopsisViewData"; -var PROBE_TASK_BATCH_ADD_URL = "probe-batchAdd"; - -var UPLOAD_FILE_URL = "file-upload";//上传文件 -var DOWNLOAD_FILE_URL = "file-download";//下载文件 - - -//系统日志记录 -var LOG_RECORD_LIST_URL = "log-list"; -var LOG_RECORD_GET_URL = "log-get"; -var LOG_RECORD_DEL_URL = "log-del"; - -//接口mock功能 -var INTERFACE_MOCK_LIST_URL = "mock-list"; -var INTERFACE_MOCK_EDIT_URL = "mock-edit"; -var INTERFACE_MOCK_GET_URL = "mock-get"; -var INTERFACE_MOCK_DEL_URL = "mock-del"; -var INTERFACE_MOCK_CHECK_NAME_URL = "mock-checkName"; -var INTERFACE_MOCK_UPDATE_STATUS_URL = "mock-updateStatus"; -var INTERFACE_MOCK_UPDATE_SETTING_URL = "mock-updateSetting"; -var INTERFACE_MOCK_PARSE_MESSAGE_TO_CONFIG_URL = "mock-parseMessageToConfig"; -var INTERFACE_MOCK_PARSE_MESSAGE_TO_NODES_URL = "mock-parseMessageToNodes"; - - -//性能测试配置 -var PERFORMANCE_TEST_CONFIG_EDIT_URL = "ptc-edit"; -var PERFORMANCE_TEST_CONFIG_LIST_URL = "ptc-list"; -var PERFORMANCE_TEST_CONFIG_DEL_URL = "ptc-del"; -var PERFORMANCE_TEST_CONFIG_GET_URL = "ptc-get"; - -var PERFORMANCE_TEST_TASK_LIST_URL = "ptc-listTest" //获取当前用户的性能测试任务列表 -var PERFORMANCE_TEST_TASK_STOP_URL = "ptc-stopTest";//停止指定性能测试任务 -var PERFORMANCE_TEST_TASK_DEL_URL = "ptc-delTest";//删除指定性能测试任务-并且不会保存测试结果 -var PERFORMANCE_TEST_TASK_INIT_URL = "ptc-initTest";//初始化性能测试任务 -var PERFORMANCE_TEST_TASK_ACTION_URL = "ptc-actionTest";//开始执行性能测试任务 -var PERFORMANCE_TEST_TASK_VIEW_URL = "ptc-viewTest";//查看性能测试任务的实时状态 - -//性能测试结果 -var PERFORMANCE_TEST_RESULT_LIST_URL = "ptr-list"; -var PERFORMANCE_TEST_RESULT_GET_URL = "ptr-get"; -var PERFORMANCE_TEST_RESULT_DEL_URL = "ptr-del"; -var PERFORMANCE_TEST_RESULT_ANAYLZE_URL = "ptr-anaylzeView";//分析结果 -var PERFORMANCE_TEST_RESULT_SUMMARIZED_URL = "ptr-summarizedView";//汇总结果到excel -var PERFORMANCE_TEST_RESULT_DETAILS_LIST_ALL_URL = "ptr-detailsList";//详细结果查看 - - -/*************************************WEB自动化**************************************************************/ -//web自动化-山西-模块管理 -var WEB_SCRIPT_MODULE_LIST_URL = "webModule-list"; -var WEB_SCRIPT_MODULE_GET_URL = "webModule-get"; -var WEB_SCRIPT_MODULE_DEL_URL = "webModule-del"; -var WEB_SCRIPT_MODULE_EDIT_URL = "webModule-edit"; -var WEB_SCRIPT_MODULE_CHECK_NAME_URL = "webModule-checkName"; //检查moduleCode是否重复 - -//web自动化-山西-任务管理 -var WEB_SCRIPT_TASK_LIST_URL = "webTask-list"; -var WEB_SCRIPT_TASK_DEL_URL = "webTask-del"; - - -//元素对象管理 -var WEB_ELEMENT_LIST_ALL_URL = "element-listAll"; -var WEB_ELEMENT_LIST_URL = "element-list"; -var WEB_ELEMENT_GET_URL = "element-get"; -var WEB_ELEMENT_DEL_URL = "element-del"; -var WEB_ELEMENT_EDIT_URL = "element-edit"; -var WEB_ELEMENT_MOVE_URL = "element-move"; -var WEB_ELEMENT_COPY_URL = "element-copy"; - - -//测试用例 -var WEB_CASE_LIST_ALL_URL = "webcase-listAll"; -var WEB_CASE_LIST_URL = "webcase-list"; -var WEB_CASE_GET_URL = "webcase-get"; -var WEB_CASE_DEL_URL = "webcase-del"; -var WEB_CASE_EDIT_URL = "webcase-edit"; -var WEB_CASE_CHANGE_BROSWER_TYPE_URL = "webcase-changeBroswerType"; -var WEB_CASE_UPDATE_CONFIG_JSON_URL = "webcase-updateConfig"; - -//测试步骤 -var WEB_STEP_LIST_ALL_URL = "webstep-listAll"; -var WEB_STEP_LIST_URL = "webstep-list"; -var WEB_STEP_GET_URL = "webstep-get"; -var WEB_STEP_DEL_URL = "webstep-del"; -var WEB_STEP_EDIT_URL = "webstep-edit"; -var WEB_STEP_UPDATE_CONFIG_URL = "webstep-updateConfig"; - -//测试用例集 -var WEB_SUITE_LIST_ALL_URL = "websuite-listAll"; -var WEB_SUITE_LIST_URL = "websuite-list"; -var WEB_SUITE_GET_URL = "websuite-get"; -var WEB_SUITE_DEL_URL = "websuite-del"; -var WEB_SUITE_EDIT_URL = "websuite-edit"; -var WEB_SUITE_CHANGE_BROSWER_TYPE_URL = "websuite-changeBroswerType"; -var WEB_SUITE_UPDATE_CONFIG_JSON_URL = "websuite-updateConfig"; -var WEB_SUITE_LIST_CASE_URL = "websuite-listCase"; -var WEB_SUITE_OP_CASE_URL = "websuite-opCase"; -var WEB_SUITE_CASE_UPDATE_SETTING_URL = "websuite-updateCaseSetting"; - -//运行时配置 -var WEB_CONFIG_GET_URL = "webconfig-get"; -var WEB_CONFIG_EDIT_URL = "webconfig-edit"; - -//菜单相关 -var BUSI_MENU_EDIT_URL = "menu-edit"; -var BUSI_MENU_GET_URL = "menu-get"; -var BUSI_MENU_LIST_ALL_URL = "menu-listAll"; -var BUSI_MENU_DEL_URL = "menu-del"; -var BUSI_MENU_GET_USER_MENUS_URL = "menu-getUserMenus"; diff --git a/src/main/webapp/js/bak/webStepParameter.json b/src/main/webapp/js/bak/webStepParameter.json deleted file mode 100644 index 4ff1859..0000000 --- a/src/main/webapp/js/bak/webStepParameter.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "dataType":{ - "string":{ - "dataType":true, - "text":"字符串常量", - "example":"xuwangcheng14@163.com", - "mark":"普通的字符串,根据操作类型不同可能代表不同含义,请根据操作类型的说明来填写." - }, - "keyboard":{ - "dataType":true, - "text":"键盘组合按键", - "example":"Keys.ENTER 模拟键盘Enter按键", - "mark":"模拟键盘按键,支持组合按键,常用键如下:
    回车键 Keys.ENTER
    删除键 Keys.BACK_SPACE
    空格键 Keys.SPACE
    制表键 Keys.TAB
    回退键 Keys.ESCAPE
    刷新键 Keys.F5
    更多按键说明请参考说明文档!" - }, - "gloablVariable":{ - "dataType":true, - "text":"全局变量", - "example":"${__current_timestamp}", - "mark":"等同于字符串常量,但是需要在 全局变量 模块中提前定义." - }, - "regexp":{ - "dataType":true, - "text":"正则表达式", - "example":"[0-9]{1,3}", - "mark":"根据正则表达式来生成指定的字符串." - }, - "attribute":{ - "dataType":true, - "text":"元素属性/文本值", - "example":"name", - "mark":"获取选择的指定元素上的指定属性的值,其中text表示该元素的文本值." - }, - "saveVariable":{ - "dataType":true, - "text":"测试变量", - "example":"order_id", - "mark":"在本次测试中定义的、保存的上下文变量,如果有同名的变量,取值优先级如下:
    同个测试用例中不同步骤保存的变量 > 不同测试用例中步骤保存的值 > 测试集中定义的变量 > 测试用例中定义的变量." - }, - "dbSql":{ - "dataType":true, - "text":"数据库取值", - "example":"select order_id from order_info where order_type='0' and user_id=<user_id> and op_time>${__current_date};", - "mark":"可选择指定的数据源执行指定的SQL查询,如果返回多条记录,则只会取第一条内容,如果一条结果中包含多列也只会去第一列内容.
    同时在SQL语句你可以使用 <user_id> 格式来表示测试变量,同时可以使用全局变量." - } - - }, - "opType":{ - "open":{ - "opType":true, - "text":"打开", - "mark":"打开一个正确的浏览器地址", - "requiredData":"可选 如果填入该值,则会使用该处地址", - "validateData":"不需要" - }, - "check":{ - "opType":true, - "text":"检查", - "mark":"判断获取到的内容和预期值是否匹配", - "requiredData":"需要 该值可以为任何类型", - "validateData":"需要 该值可以为任何类型,如果该值类型为正则表达式,则会进行正则匹配来验证" - }, - "action":{ - "opType":true, - "text":"执行用例片段", - "mark":"执行一个用例片段", - "requiredData":"不需要", - "validateData":"不需要" - }, - "script":{ - "opType":true, - "text":"执行js脚本", - "mark":"执行一段JS脚本", - "requiredData":"不需要", - "validateData":"不需要" - }, - "input":{ - "opType":true, - "text":"输入", - "mark":"向输入框输入文本内容", - "requiredData":"需要 该值可为任何类型", - "validateData":"不需要" - }, - "save":{ - "opType":true, - "text":"保存值", - "mark":"获取内容并保存,可以获取窗口标题、当前浏览器地址、元素文本、元素属性等", - "requiredData":"可选 当元素类型为TAG时,如果该值为空,默认取元素的文本内容;如果该值不为空,则该值为元素的属性名称", - "validateData":"不需要" - }, - "click":{ - "opType":true, - "text":"点击", - "mark":"点击元素", - "requiredData":"不需要", - "validateData":"不需要" - }, - "hover":{ - "opType":true, - "text":"鼠标悬停", - "mark":"将鼠标移动到某个元素上", - "requiredData":"不需要", - "validateData":"不需要" - }, - "alertCancel":{ - "opType":true, - "text":"弹出框-取消", - "mark":"对于系统级(非页面元素)的弹出框(包含警告框、确认框、对话框),进行取消操作", - "requiredData":"不需要", - "validateData":"不需要" - }, - "alertConfirm":{ - "opType":true, - "text":"弹出框-确认", - "mark":"对于系统级(非页面元素)的弹出框(包含确认框、对话框),进行确认操作", - "requiredData":"不需要", - "validateData":"不需要" - }, - "alertClose":{ - "opType":true, - "text":"弹出框-关闭", - "mark":"对于系统级(非页面元素)的弹出框(包含警告框、确认框、对话框),进行关闭操作", - "requiredData":"不需要", - "validateData":"不需要" - }, - "alertInput":{ - "opType":true, - "text":"对话框-输入", - "mark":"对于系统级(非页面元素)的对话框,进行输入操作,默认自动点击确认按钮", - "requiredData":"需要", - "validateData":"不需要" - }, - "upload":{ - "opType":true, - "text":"上传文件", - "mark":"进行文件上传操作", - "requiredData":"需要 该值为文件的绝对路径(文件应该位于执行机中而不是服务器上)", - "validateData":"不需要" - }, - "slide":{ - "opType":true, - "text":"滑动", - "mark":"拖动元素在 x,y 方向上移动移动一段距离", - "requiredData":"需要 例如:x=500,y=100,代表在x/y轴上个拖动500px的距离", - "validateData":"不需要" - } - } -} \ No newline at end of file diff --git a/src/main/webapp/js/dcits.js b/src/main/webapp/js/dcits.js index dcd5395..3e7d9d0 100644 --- a/src/main/webapp/js/dcits.js +++ b/src/main/webapp/js/dcits.js @@ -53,11 +53,13 @@ var advancedQueryFormHtml = "";//高级查询页面代码,防止重复渲染 * */ /********************************************/ +var thisPageName; +var thisPagePermissionList; $(function() { //加载对应的js文件 var r = (window.location.pathname.split("."))[0].split("/"); - r = r[r.length-1] + ".js"; - dynamicLoadScript(r); + thisPageName = r[r.length-1]; + dynamicLoadScript(thisPageName + ".js"); }); /** @@ -75,16 +77,20 @@ var publish = { df1.done(function(){ var df = $.Deferred(); df.done(function(){ + //自定义数据渲染 that.renderData(that.renderParams.customCallBack); - //防止事件被绑定多次 + //事件代理绑定,防止事件被绑定多次 (that.renderParams.ifFirst == true) && (that.initListeners(that.renderParams.eventList)); - }); + }); + + //渲染之前的自定义初始化 if (that.renderParams.renderType == "list") { that.renderParams.listPage.beforeInit(df); } else if (that.renderParams.renderType == "edit") { that.renderParams.editPage.beforeInit(df); } }); + if (that.renderParams.ifFirst == true) { that.renderTemplate(df1,that.renderParams.templateCallBack); } else { @@ -115,6 +121,7 @@ var publish = { * columnsJson:不参与排序的列 * dtOtherSetting:DT其他的自定义设置 * dtAjaxCallback:DataTables在每次通过ajax.reload返回之后的回调 + * dtDrawCallback: DataTables每次重绘之后的回调 * exportExcel:是否在工具栏添加 导出到excel 的按钮工具 默认为true * dblclickEdit:开启双击行打开编辑页面 默认为true * @@ -213,7 +220,8 @@ var publish = { beforeInit:function(df) { df.resolve(); }, - dtAjaxCallback:function() {}, + dtAjaxCallback:function() {}, + dtDrawCallback:function() {}, tableObj:null, columnsSetting:{}, columnsJson:[], @@ -354,7 +362,7 @@ var publish = { if (p.userDefaultRender == true) { if (p.renderType == "list") { var l = p.listPage; - table = initDT(l.tableObj, l.listUrl, l.columnsSetting, l.columnsJson, l.dtOtherSetting); + table = initDT(l.tableObj, l.listUrl, l.columnsSetting, l.columnsJson, l.dtOtherSetting, l.dtDrawCallback); /***添加导入excel插件按钮**/ if (l.exportExcel) { @@ -376,8 +384,11 @@ var publish = { } e.ifUseValidate && formValidate(e.formObj, e.rules, e.messages, null, e.closeFlag, e.ajaxCallbackFun, e.beforeSubmitCallback); } - } - callback(p); + } + + //权限按钮的显示和隐藏 + controlButtonShowByPermission(); + callback(p); }, /** * 统一绑定监听事件 @@ -394,11 +405,68 @@ var publish = { } }; +/** + * 控制权限按钮的显示或者隐藏 + * @param domObj + */ +function controlButtonShowByPermission (domObj) { + //跳过超级管理员用户 + if (top.userId == SUPER_ADMIN_USER_ID) { + return; + } + if (thisPagePermissionList == null) { + //获取当前页面权限 + $.ajax({ + type:"post", + url:REQUEST_URL.OP_INTERFACE.LIST_BY_PAGE_NAME, + data:{pageName: thisPageName}, + async:false, + success:function(json) { + if (json.returnCode == RETURN_CODE.SUCCESS) { + thisPagePermissionList = json.data; + } else { + layer.alert(json.msg, {icon:5}); + } + } + }); + } + + if (thisPagePermissionList.length == 0) { + return; + } + + if (domObj == null) { + domObj = $(document); + } + + $.each(thisPagePermissionList, function(i, n) { + if (n.permissionMark == null || n.permissionMark == '') { + return true; + } + let marks = n.permissionMark.split(','); + $.each(marks, function(t, mark) { + let button; + try { + button = domObj.find(mark); + } catch(err) {} + if (button != null && button.length > 0) { + if (top.currentUserPermissionList[n.opId] == null + || n.status == '1') { + //删除按钮 + button.remove(); + } + } + }); + }); +} + //设置jQuery Ajax全局的参数 $.ajaxSetup({ - error: function (jqXHR, textStatus, errorThrown) { + error: function (jqXHR, textStatus, errorThrown) { + //关闭所有弹窗/loading等 layer.closeAll('dialog'); $(".page-container").spinModal(false); + loading(false); switch (jqXHR.status) { case(500): layer.alert("服务器系统内部错误", {icon:5}); @@ -480,7 +548,7 @@ $.fn.delegates = function(configs) { * @param columnsJson 不参与排序的列 jsonArray * @returns table 返回对应的DataTable实例 */ -function initDT (tableObj, ajaxUrl, columnsSetting, columnsJson, dtOtherSetting) { +function initDT (tableObj, ajaxUrl, columnsSetting, columnsJson, dtOtherSetting, dtDrawCallback) { var data = []; var table = $(tableObj) /*//发送ajax请求时 @@ -504,10 +572,11 @@ function initDT (tableObj, ajaxUrl, columnsSetting, columnsJson, dtOtherSetting) data = json.data; }) - /* //重绘完毕 + //重绘完毕 .on('draw.dt', function () { //初始化和刷新都会触发 - publish.renderParams.listPage.dtAjaxCallback(); - })*/ + controlButtonShowByPermission($('.table')); + typeof dtDrawCallback === 'function' && dtDrawCallback(); + }) //初始化完毕 .on( 'init.dt', function () { //刷新表格不会触发此事件 只存在一次 //添加动态拖拽改变列宽的插件 @@ -1058,25 +1127,45 @@ function layer_show (title, url, w, h, type, success, cancel, end, other) { url="/404.html"; }; if (w == null || w == '' || w >= maxWidth) { - w = maxWidth * 0.8 + w = maxWidth * 0.86 }; if (h == null || h == '' || h >= maxHeight) { - h= (maxHeight * 0.86) ; + h= (maxHeight * 0.9) ; }; + + if (w == null || w == '') { + w = '86%'; + } else { + if (w > maxWidth) { + w = '86%'; + } else { + w = w + 'px'; + } + }; + if (h == null || h == '') { + h= '90%' ; + } else { + if (h >= maxHeight) { + h= '90%' ; + } else { + h = parseInt((h / maxHeight) * 100) + '%'; + } + }; + if (type == null || type == '') { type = 2; } index = layer.open($.extend(true, { type: type, - area: [w + 'px', h + 'px'], + area: [w, h], fix: false, //不固定 - maxmin: false, - shade:0.4, - anim:5, - shadeClose:true, + maxmin: false,//禁止最大化最小化 + shade:0.4,//遮罩 + anim:5,//动画效果 + shadeClose:true,//可以通过点击遮罩关闭 title: title, content: url, - offset:'30px', + offset:'30px',//距上边距 success:function(layero, index){ $(layero).find('#layerIndex').val(index); success && success(layero, index); @@ -1677,6 +1766,73 @@ function layerMultipleChoose (options) { } +/** + * 自定义打开一个数据配置的页面 + * @param options + */ +function customDataSettingView (options) { + let defaultOptions = { + title: '配置数据', + remark: null, + layerWidth:580, + layerHeight:450, + data: {}, + saveCallback:function(data, layerIndex) { + layer.close(layerIndex); + } + }; + if (typeof options == 'object') { + $.extend(true, defaultOptions, options); + } + + layer_show(defaultOptions.title, templates['custom-data-setting-view']({remark: defaultOptions.remark, data: defaultOptions.data, title: defaultOptions.title}) + , defaultOptions.layerWidth, defaultOptions.layerHeight, 1, function(layero, index){ + //新增一堆key-value + $(layero).find('#custom-data-setting-add-variable').click(function() { + $(layero).find("#custom-data-setting-variables").append('
    ' + + '
    ' + + '
    ' + + '
    '); + }); + + //删除全部数据 + $(layero).find('#custom-data-setting-clear-all-varibale').click(function() { + layer.confirm('确认删除下列全部的数据吗?', {title:'警告'}, function(i){ + $("#custom-data-setting-variables").html(''); + layer.msg('全部删除成功!', {icon:1, time:1600}); + layer.close(i); + }); + }); + + //删除一项数据 + $(layero).delegate('#custom-data-setting-variables a', 'click', function() { + let that = this; + layer.confirm('确认删除该项数据吗?', {title:'警告'}, function(i) { + $(that).parent('.formControls').parent('.row').remove(); + layer.msg('删除成功!', {icon:1, time:1600}); + layer.close(i); + }); + }); + + //点击保存数据 + $(layero).find('#update-custom-data').click(function() { + let configObj = {}; + $("#custom-data-setting-variables").children('.row').each(function(i){ + let key = $(this).find('input').eq(0).val(); + let value = $(this).find('input').eq(1).val(); + if (strIsNotEmpty(key) && strIsNotEmpty(value)) { + configObj[key] = value; + } + }); + + typeof defaultOptions.saveCallback == 'function' && defaultOptions.saveCallback(configObj, index); + }); + }); + + +} + /** * 从form控件保存指定的值 */ @@ -1922,6 +2078,7 @@ function isJSON(str) { } } console.log('It is not a string!') + return false; } /*********************判断两个json对象是否一样*****************************/ diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index 918ab84..c173139 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -1,13 +1,17 @@ //全局常量和配置 - //返回值 var RETURN_CODE = { SUCCESS: 0, NO_LOGIN: 7 } +//超级管理员用户 +var SUPER_ADMIN_USER_ID = 1; //请求路径 var REQUEST_URL = { + WEB_SOCKET: { + PUSH_MAIL_NUM: "/push/mail", + }, //登陆相关 LOGIN: { LOGOUT: "user-logout", @@ -137,7 +141,8 @@ var REQUEST_URL = { EDIT:"validate-edit", LIST: "validate-getValidates", FULL_RULE_GET: "validate-getValidate", - RULE_UPDATE_STATUS: "validate-updateValidateStatus" + RULE_UPDATE_STATUS: "validate-updateValidateStatus", + GET_CONFIG_VALIDATE_RULES: "validate-getConfigValidates", }, //定时任务 TASK: { @@ -168,7 +173,8 @@ var REQUEST_URL = { EDIT:"op-edit", LIST: "op-listOp", GET_NODE_TREE: "op-getNodeTree", - LIST_ALL: "op-listAll" + LIST_ALL: "op-listAll", + LIST_BY_PAGE_NAME: "op-listByPageName" }, //查询数据源 QUERY_DB: { @@ -197,7 +203,8 @@ var REQUEST_URL = { GET_NODES_MENU: "role-getMenuNodes", UPDATE_POWER: "role-updateRolePower", UPDATE_MENU: "role-updateRoleMenu", - LIST_ALL: "role-listAll" + LIST_ALL: "role-listAll", + GET_USER_PERMISSION_LIST: "role-getUserPermissionList" }, //用户 USER: { @@ -264,7 +271,8 @@ var REQUEST_URL = { UPDATE_STATUS: "mock-updateStatus", UPDATE_SETTING: "mock-updateSetting", PARSE_MESSAGE_TO_CONFIG: "mock-parseMessageToConfig", - PARSE_MESSAGE_TO_NODES: "mock-parseMessageToNodes" + PARSE_MESSAGE_TO_NODES: "mock-parseMessageToNodes", + PARSE_SCENE_TO_MOCK_INFO: "mock-parseSceneToMockInfo" }, //性能测试 PERFORMANCE_TEST: { @@ -397,7 +405,7 @@ var EXPLANATION_MARK = { //接口自动化相关 -//报文处理类型参数设置 +//报文处理器参数设置 var MESSAGE_PROCESS = { "ShanXiOpenApi":{ "pemFilePath":"" @@ -410,6 +418,13 @@ var MESSAGE_PROCESS = { } } +//接口可Mock类型 +var MESSAGE_MOCK_TYPE = { + "HTTP":"HTTP", + "Socket": "Socket", + "WebSocket": "WebSocket" +} + //接口协议-调用参数配置信息 var MESSAGE_PROTOCOL = { "HTTP":{ @@ -609,3 +624,24 @@ var WEB_STEP_PARAMETER = { } } } + + +function createWebSocket (path) { + if (top.homeUrl == null || top.homeUrl == '') { + return null; + } + let url = (top.homeUrl).replace('https', 'ws').replace('http', 'ws'); + let ws; + if ('WebSocket' in window){ + ws = new WebSocket(url + path); + } + else if ('MozWebSocket' in window){ + ws = new MozWebSocket(url + path); + } + else{ + console.error("该浏览器不支持websocket"); + return null; + } + + return ws; +} \ No newline at end of file diff --git a/src/main/webapp/js/handlebarsHelpers.js b/src/main/webapp/js/handlebarsHelpers.js new file mode 100644 index 0000000..3ac2827 --- /dev/null +++ b/src/main/webapp/js/handlebarsHelpers.js @@ -0,0 +1,84 @@ +/*****************************Handlebars预定义helper***********************************/ +/**null转换空字符串**/ +Handlebars.registerHelper('inputValue', function(value, defaultValue){ + if (value == null || value.length == 0) { + value = defaultValue; + } + + return value; +}); + +/**结果标签展示**/ +Handlebars.registerHelper('resultLabelView', function(status){ + var color = ""; + var flag = ""; + if (status == "0") { + color = "success"; + flag = "SUCCESS"; + } else if (status == "1") { + color = "danger"; + flag = "FAIL"; + } else { + color = "default"; + flag = "STOP"; + } + + return '' + flag + ''; +}); + +/** + * 比对实现 + */ +Handlebars.registerHelper('if_eq', function(v1, v2, opts) { + if(v1 == v2) + return opts.fn(this); + else + return opts.inverse(this); +}); + + +/** + * 验证路径 + */ +Handlebars.registerHelper('validate_path', function(v1) { + if (v1 && !isJSON('{' + v1 + '}')) { + return v1 + "."; + } + + return ""; +}); + +/** + * 获取地址栏参数 + * @param name + * @returns + */ +function GetQueryString(name) { + var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); + var r = window.location.search.substr(1).match(reg); + if (r != null) + return decodeURIComponent(r[2]); + return null; +} + +/** + * 判断是否为json格式字符串 + * @param str + */ +function isJSON(str) { + if (typeof str == 'string') { + try { + var obj=JSON.parse(str); + if(typeof obj == 'object' && obj ){ + return true; + }else{ + return false; + } + + } catch(e) { + console.log('error:'+str+'!!!'+e); + return false; + } + } + console.log('It is not a string!') +} \ No newline at end of file diff --git a/src/main/webapp/js/json/HttpRequestHeader.json b/src/main/webapp/js/json/HttpRequestHeader.json index 90e8703..377e27f 100644 --- a/src/main/webapp/js/json/HttpRequestHeader.json +++ b/src/main/webapp/js/json/HttpRequestHeader.json @@ -1,96 +1,98 @@ { "returnCode": 0, - "error": "", - "rootPid": 1, - "data": [{ - "attributes": null, - "defaultValue": "", - "mark": "请求头", - "parameterId": 1, - "parameterIdentify": "RequestHeader", - "parameterName": "", - "parentId": 0, - "path": "TopRoot", - "type": "Map" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求头,标名请求主机器名,可为IP也可为域名,http1.1后强制使用,用此请求信息,可在服务端做WEB虚拟机,实现一机多WEB服务", - "parameterId": 2, - "parameterIdentify": "Host", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求、响应体的数据字节大小", - "parameterId": 3, - "parameterIdentify": "Content-Length", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求头,可接受的文本压缩算法,如: gzip, deflate", - "parameterId": 4, - "parameterIdentify": "Accept-Encoding", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求头,支持语言,客户端浏览器的设置,如:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3", - "parameterId": 5, - "parameterIdentify": "Accept-Language", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求头,浏览器信息,如:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0,细心会注册到IE也会用Mozilla,这是一个历史问题,早期WEB服务器貌似有问题,只支持Mozilla,微软IE做为 后起之秀只能伪装成Mozilla", - "parameterId": 6, - "parameterIdentify": "User-Agent", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求头,服务器或客户端在上次设置的COOKIE,包括作用域名(.360buy.com),过 期时间,键与值。大部分WEB服务器都会在第一次访问时在响应头上加Set-Cookie, (指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密))如:BAIDUID=49415814CDBBB4CE65EC50EE4BB65E9A:FG=1; expires=Wed, 07-Nov-42 07:03:34 GMT; path=/; domain=.baidu.com", - "parameterId": 7, - "parameterIdentify": "Cookie", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "从一个连接打开一个新页面,新页面的请求一般会加此信息,标名是从哪里跳过来的,所有的页面的打开历史链就可被挖掘出来,有利于分析用户行为与CPS分成", - "parameterId": 8, - "parameterIdentify": "Referer", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "请求的数据类型:text/html;charset=gbk", - "parameterId": 9, - "parameterIdentify": "Content-Type", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.RequestHeader", - "type": "String" - }] + "data":{ + "error": "", + "rootPid": 1, + "data": [{ + "attributes": null, + "defaultValue": "", + "mark": "请求头", + "parameterId": 1, + "parameterIdentify": "RequestHeader", + "parameterName": "", + "parentId": 0, + "path": "TopRoot", + "type": "Map" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求头,标名请求主机器名,可为IP也可为域名,http1.1后强制使用,用此请求信息,可在服务端做WEB虚拟机,实现一机多WEB服务", + "parameterId": 2, + "parameterIdentify": "Host", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求、响应体的数据字节大小", + "parameterId": 3, + "parameterIdentify": "Content-Length", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求头,可接受的文本压缩算法,如: gzip, deflate", + "parameterId": 4, + "parameterIdentify": "Accept-Encoding", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求头,支持语言,客户端浏览器的设置,如:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3", + "parameterId": 5, + "parameterIdentify": "Accept-Language", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求头,浏览器信息,如:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0,细心会注册到IE也会用Mozilla,这是一个历史问题,早期WEB服务器貌似有问题,只支持Mozilla,微软IE做为 后起之秀只能伪装成Mozilla", + "parameterId": 6, + "parameterIdentify": "User-Agent", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求头,服务器或客户端在上次设置的COOKIE,包括作用域名(.360buy.com),过 期时间,键与值。大部分WEB服务器都会在第一次访问时在响应头上加Set-Cookie, (指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密))如:BAIDUID=49415814CDBBB4CE65EC50EE4BB65E9A:FG=1; expires=Wed, 07-Nov-42 07:03:34 GMT; path=/; domain=.baidu.com", + "parameterId": 7, + "parameterIdentify": "Cookie", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "从一个连接打开一个新页面,新页面的请求一般会加此信息,标名是从哪里跳过来的,所有的页面的打开历史链就可被挖掘出来,有利于分析用户行为与CPS分成", + "parameterId": 8, + "parameterIdentify": "Referer", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "请求的数据类型:text/html;charset=gbk", + "parameterId": 9, + "parameterIdentify": "Content-Type", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.RequestHeader", + "type": "String" + }] + } } \ No newline at end of file diff --git a/src/main/webapp/js/json/HttpResponseHeader.json b/src/main/webapp/js/json/HttpResponseHeader.json index 278312f..ba5c271 100644 --- a/src/main/webapp/js/json/HttpResponseHeader.json +++ b/src/main/webapp/js/json/HttpResponseHeader.json @@ -1,76 +1,78 @@ { "returnCode": 0, - "error": "", - "rootPid": 1, - "data": [{ - "attributes": null, - "defaultValue": "", - "mark": "响应头", - "parameterId": 1, - "parameterIdentify": "ResponseHeader", - "parameterName": "", - "parentId": 0, - "path": "TopRoot", - "type": "Map" - },{ - "attributes": null, - "defaultValue": "", - "mark": "响应的数据类型:text/html;charset=gbk", - "parameterId": 2, - "parameterIdentify": "Content-Type", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "响应的数据体大小", - "parameterId": 3, - "parameterIdentify": "Content-Length", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "如果为文本、HTML信息,则使用的编码方式", - "parameterId": 4, - "parameterIdentify": "Content-Encoding", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "当前服务器日期", - "parameterId": 5, - "parameterIdentify": "Date", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "服务器名", - "parameterId": 6, - "parameterIdentify": "Server", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - },{ - "attributes": null, - "defaultValue": "", - "mark": "第一次访问或服务设置COOKIE时,响应头里会有此信息, 如,BAIDUID=49415814CDBBB4CE65EC50EE4BB65E9A:FG=1; expires=Wed, 07-Nov-42 07:03:34 GMT; path=/; domain=.baidu.com", - "parameterId": 7, - "parameterIdentify": "Set-Cookie", - "parameterName": "", - "parentId": 1, - "path": "TopRoot.ResponseHeader", - "type": "String" - }] + "data": { + "error": "", + "rootPid": 1, + "data": [{ + "attributes": null, + "defaultValue": "", + "mark": "响应头", + "parameterId": 1, + "parameterIdentify": "ResponseHeader", + "parameterName": "", + "parentId": 0, + "path": "TopRoot", + "type": "Map" + },{ + "attributes": null, + "defaultValue": "", + "mark": "响应的数据类型:text/html;charset=gbk", + "parameterId": 2, + "parameterIdentify": "Content-Type", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "响应的数据体大小", + "parameterId": 3, + "parameterIdentify": "Content-Length", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "如果为文本、HTML信息,则使用的编码方式", + "parameterId": 4, + "parameterIdentify": "Content-Encoding", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "当前服务器日期", + "parameterId": 5, + "parameterIdentify": "Date", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "服务器名", + "parameterId": 6, + "parameterIdentify": "Server", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + },{ + "attributes": null, + "defaultValue": "", + "mark": "第一次访问或服务设置COOKIE时,响应头里会有此信息, 如,BAIDUID=49415814CDBBB4CE65EC50EE4BB65E9A:FG=1; expires=Wed, 07-Nov-42 07:03:34 GMT; path=/; domain=.baidu.com", + "parameterId": 7, + "parameterIdentify": "Set-Cookie", + "parameterName": "", + "parentId": 1, + "path": "TopRoot.ResponseHeader", + "type": "String" + }] + } } \ No newline at end of file diff --git a/src/main/webapp/login.html b/src/main/webapp/login.html index 3fb1179..da1eb50 100644 --- a/src/main/webapp/login.html +++ b/src/main/webapp/login.html @@ -62,11 +62,13 @@
    - + + + - - + + diff --git a/src/main/webapp/resource/user/mail.js b/src/main/webapp/resource/user/mail.js index 394782c..bcafa14 100644 --- a/src/main/webapp/resource/user/mail.js +++ b/src/main/webapp/resource/user/mail.js @@ -67,11 +67,15 @@ var columnsSetting = [ var eventList = { "#batch-del-object":function(){ var checkboxList = $(".selectMail:checked"); - batchDelObjs(checkboxList, REQUEST_URL.MAIL.GET); + batchDelObjs(checkboxList, REQUEST_URL.MAIL.GET, null, null, function() { + (top['welcome']).getMailNum(); + }); }, "#batch-setting-read":function(){ var checkboxList = $(".selectMail:checked"); - batchOp (checkboxList, REQUEST_URL.MAIL.CHANGE_STATUS, "处理", null, "mailId", {statusName:"readStatus", status:"0"}) + batchOp(checkboxList, REQUEST_URL.MAIL.CHANGE_STATUS, "处理", null, "mailId", {statusName:"readStatus", status:"0"}, function() { + (top['welcome']).getMailNum(); + }); }, ".object-del":function(){ var data = table.row( $(this).parents('tr') ).data(); diff --git a/src/main/webapp/welcome.html b/src/main/webapp/welcome.html index 477a131..7c68ff5 100644 --- a/src/main/webapp/welcome.html +++ b/src/main/webapp/welcome.html @@ -90,131 +90,11 @@

      

    - - + + + \ No newline at end of file diff --git a/src/main/webapp/welcome.js b/src/main/webapp/welcome.js new file mode 100644 index 0000000..36cb71f --- /dev/null +++ b/src/main/webapp/welcome.js @@ -0,0 +1,165 @@ +$(document).ready(function(){ + //获取登陆之后的相关信息 + queryLoginInfo(); + + //获取权限列表 + $.get(REQUEST_URL.ROLE.GET_USER_PERMISSION_LIST, function (json) { + if (json.returnCode == RETURN_CODE.SUCCESS) { + top.currentUserPermissionList = json.data; + } else { + layer.alert('获取用户权限信息出错,请重新登陆!'); + } + }); + + //检查系统版本 + $.get(REQUEST_URL.GLOBAL_SETTING.CHECK_SYSTEM_VERSION, function(json){ + if (json.returnCode == 0) { + if (json.data.newVersion != null && json.data.newVersion != json.data.version) { + $("#version").html('有新版本可以升级'); + } + } else { + console.error("检查系统版本失败:" + json.msg); + } + }); +}); + +/** + * 获取登陆之好的相关信息:包括用户信息,全局配置,测试统计数据等 + */ +function queryLoginInfo(){ + var userInfo = {}; + var lastLoginTime = ""; + var df = $.Deferred(); + df.done(function(){ + if (!($.isEmptyObject(userInfo))) { + //加载目录信息 + parent.loadMenuFun(); + //获取配置 + getSetting(); + //获取统计信息 + getStatisticalQuantity(); + //获取未读邮件信息 + queryMailNum(); + + //填充页面基本信息 + $("#group_name").text(userInfo.role.roleGroup); + $("#real_name").text(userInfo.realName); + $("#last_login_time").text(lastLoginTime); + parent.$("#role_name").text(userInfo.role.roleName); + parent.$("#real_name").text(userInfo.realName); + if (userInfo.role.roleName != "admin") { + parent.$(".adminPower").css("display","none"); + } + + + } + }); + + //获取登陆用户信息 + $.post(REQUEST_URL.LOGIN.GET_LOGIN_USER_INFO, {token:parent.token}, function(data) { + if (data.returnCode == RETURN_CODE.SUCCESS) { + userInfo = data.data.user; + lastLoginTime = data.data.lastLoginTime; + parent.homeUrl = data.data.homeUrl; + parent.userId = userInfo.userId; + df.resolve(); + } else if (data.returnCode == RETURN_CODE.NO_LOGIN) { + var username = getCookie("username"); + var password = getCookie("password"); + if (username != null && password != null && parent.token == null) { + $.post(REQUEST_URL.LOGIN.LOGIN,{ + username:username, + password:password + }, function(data) { + if (data.returnCode == RETURN_CODE.SUCCESS) { + userInfo = data.data.user; + lastLoginTime = data.data.lastLoginTime; + parent.homeUrl = data.data.homeUrl; + parent.userId = userInfo.userId; + df.resolve(); + } else { + parent.window.location.href = parent.backUrl; + } + }); + } else { + parent.window.location.href = parent.backUrl; + } + }else{ + parent.window.location.href = parent.backUrl; + } + }); +} + +/** + * 获取全局配置并设置到页面 + */ +function getSetting() { + $.get(REQUEST_URL.GLOBAL_SETTING.GET_WEB_SETTINGS, function(data) { + if(data.returnCode == 0){ + data = data.data; + $("#notice").html(data.notice); + $("#copyright").html(data.copyright); + $("#siteName").html(data.siteName); + parent.$("#siteName").html(data.siteName); + parent.$("#version").text("V" + data.version); + } + }); +} + +/** + * ajax请求查询用户未读邮件数量 + */ +function getMailNum(){ + $.get(REQUEST_URL.MAIL.GET_NO_READ_MAIL_NUM, function(data) { + if (data.returnCode === RETURN_CODE.SUCCESS && data.data !== 0) { + parent.$(".noReadMailNum").text(data.data); + } else { + parent.$(".noReadMailNum").text(""); + } + }); +} + +/** + * 查询未读邮件数量,默认使用webSocket,否则使用ajax轮询 + */ +function queryMailNum () { + //第一次获取 + getMailNum(); + + let userId = parent.userId; + let ws = createWebSocket('/push/mail/' + userId); + + if (ws == null) { + setInterval(getMailNum, 90000); + return; + } + + ws.onmessage = function(event) { + if (event.data !== 0) { + parent.$(".noReadMailNum").text(event.data); + } + } + + parent.window.onbeforeunload = function(event) { + ws.close(); + } +} + + + +/** + * 获取测试统计数据 + */ +function getStatisticalQuantity() { + $.get(REQUEST_URL.GLOBAL_SETTING.GET_STATISTICAL_QUANTITY, function(data) { + if(data.returnCode == 0){ + $.each(data.data, function(itemName, countInfo) { + $("td[count-type='" + itemName + "']").eq(0).text(countInfo.totalCount); + $("td[count-type='" + itemName + "']").eq(1).text(countInfo.todayCount); + $("td[count-type='" + itemName + "']").eq(2).text(countInfo.yesterdayCount); + $("td[count-type='" + itemName + "']").eq(3).text(countInfo.thisWeekCount); + $("td[count-type='" + itemName + "']").eq(4).text(countInfo.thisMonthCount); + }); + } + }); +} \ No newline at end of file diff --git a/update.md b/update.md index 9c17ede..aa3fd59 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,36 @@ +~~1、增加websocket接口mock;~~ +~~2、默认不展示web自动化测试模块;~~ +3、增加初级的测试数据池功能; +4、增加历史数据报表功能。 +5、优化数据验证、数据库验证等功能; +6、支持对数组的取值,设定值; +7、增加测试集全局配置:头信息、验证规则、测试集变量等功能; +8、完善操作说明手册, +~~10、一键安装包 for linux;~~ +~~11、更加方便安全的版本更新方案;~~ +12、主页和论坛; +~~13、支持直接从接口的报文列表中新增Mock接口;~~ +~~14、测试集中可以更加方便的管理组合场景,而不是直接打开新的tab窗口;~~ +~~15、权限控制可以显示隐藏按钮。~~ +~~16、重写部分功能,使用websocket交互。~~ +9、支持从yapi/rap/postman/swagger/各种规范的日志文件中导入接口; +17、对文件上传类接口的支持。 + + + +### v0.2.2beta +#### 2019.11.28 +- 新增:更加简便安全的版本更新方案(只需要更新到最新War包即可); +- 新增:webSocket类型的接口Mock,支持选择指定的接口场景来新增接口Mock信息(支持Http/Socket/WebSocket协议); +- 新增:角色权限控制支持精确到前端按钮级别(仅支持部分主要功能的按钮); +- 新增:测试集公共变量/公共请求头/公共验证规则; +- 更新:前后端部分交互采用WebSocket技术; +- 更新:默认不显示WebUI测试相关模块(暂时废弃,不更新了); +- 修复:前端弹出窗口大小没有跟随浏览器大小动态改变而导致显示异常的问题 +- 修复:组合场景配置异常问题。 + + + ### v0.2.1beta #### 2019.11.17 - 修复:HTTP协议使用GET请求如果参数值为空的情况会导致无法正确的拼接查询参数到URL后面的问题; -- Gitee From f565d5af7168077a7e9170027ac9b3a07c81bef9 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Thu, 5 Dec 2019 18:26:10 +0800 Subject: [PATCH 03/30] setting --- src/main/resources/log4j.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index d9cfdf0..5de3f46 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -40,4 +40,4 @@ log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%l]-[%p] #other setting log4j.logger.com.opensymphony.xwork2=ERROR -#log4j.logger.yi.master.coretest.message.test.mock=DEBUG +#log4j.logger.yi.master.coretest.message.test.mock=DEBUG \ No newline at end of file -- Gitee From 04bfef27e3aeccfc60c8d4c905efecbc267541a0 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Tue, 4 Aug 2020 19:45:55 +0800 Subject: [PATCH 04/30] =?UTF-8?q?=E6=9B=B4=E6=94=B9logo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webapp/libs/h-ui.admin/images/logo.png | Bin 7465 -> 7512 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/webapp/libs/h-ui.admin/images/logo.png b/src/main/webapp/libs/h-ui.admin/images/logo.png index 1f1a505c3e68e72362af5a599b848e06c1d21925..f6e03821b6a920101e541599c5447f871e96d6fc 100644 GIT binary patch literal 7512 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 LZ=zSN1Bv}VW%1Ww -- Gitee From 1e46910521d4bb8a8f5f48b9f614e57aef90b297 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 6 Nov 2020 11:30:56 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/parse/JSONMessageParse.java | 28 +++++++-- .../java/yi/master/util/PracticalUtils.java | 58 ++++++++++++++----- src/main/resources/log4j.properties | 10 ++-- .../webapp/libs/h-ui.admin/css/H-ui.admin.css | 1 - update.md | 4 ++ 5 files changed, 76 insertions(+), 25 deletions(-) diff --git a/src/main/java/yi/master/coretest/message/parse/JSONMessageParse.java b/src/main/java/yi/master/coretest/message/parse/JSONMessageParse.java index 2907e12..1dcb46d 100644 --- a/src/main/java/yi/master/coretest/message/parse/JSONMessageParse.java +++ b/src/main/java/yi/master/coretest/message/parse/JSONMessageParse.java @@ -273,13 +273,19 @@ public class JSONMessageParse extends MessageParse { if (MessageParameterType.NUMBER.name().equals(node.getString("type").toUpperCase())) { value = (value == null || StringUtils.isBlank(value.toString())) ? 0 : new BigDecimal(value.toString()); } - createMessageNode(node.getString("path"), message).put(node.getString("parameterIdentify"), value); + JSONObject parentNode = nodes.getJSONObject(node.getString("parentId")); + String parentType = null; + if (parentNode != null) { + parentType = parentNode.getString("type").toUpperCase(); + } + + createMessageNode(node.getString("path"), message, parentType).put(node.getString("parameterIdentify"), value); } } return JSONMessageFormatBeautify(JSONObject.fromObject(message).toString()); } - private Map createMessageNode(String path, Map message) { + private Map createMessageNode(String path, Map message, String parentType) { String[] pathNames = path.split("\\."); Map nodeObj = message; for (String nodePath:pathNames) { @@ -288,9 +294,23 @@ public class JSONMessageParse extends MessageParse { } Object nodeObj_l = nodeObj.get(nodePath); if (nodeObj_l == null) { - nodeObj_l = new HashMap(); - nodeObj.put(nodePath, nodeObj_l); + if (MessageParameterType.isArrayType(parentType)) { + nodeObj_l = new ArrayList>(); + } else { + nodeObj_l = new HashMap(); + } + nodeObj.put(nodePath, nodeObj_l); } + // 如果上级为数组,则创建一个新对象 + if (nodeObj_l instanceof List || nodeObj_l instanceof ArrayList) { + List> list = (List>) nodeObj_l; + if (list.size() == 0) { + list.add(new HashMap<>()); + } + + nodeObj_l = list.get(0); + + } nodeObj = (Map) nodeObj_l; } diff --git a/src/main/java/yi/master/util/PracticalUtils.java b/src/main/java/yi/master/util/PracticalUtils.java index b81f870..451e303 100644 --- a/src/main/java/yi/master/util/PracticalUtils.java +++ b/src/main/java/yi/master/util/PracticalUtils.java @@ -2,6 +2,7 @@ package yi.master.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; @@ -263,7 +264,6 @@ public class PracticalUtils { try { return dateFormat.parse(date); } catch (Exception e) { - return null; } @@ -595,7 +595,6 @@ public class PracticalUtils { } } return randomStr.toString(); - } /** @@ -1122,8 +1121,10 @@ public class PracticalUtils { public static String getValueByRelationKeyWord(Map maps, String msg) { String getValue = ""; try { - String leftBoundary = (String) maps.get("LB"); - String rightBoundary = (String) maps.get("RB"); + String leftBoundary = escapeExprSpecialWord((String) maps.get("LB")); + String rightBoundary = escapeExprSpecialWord((String) maps.get("RB")); +// String leftBoundary = (String) maps.get("LB"); +// String rightBoundary = (String) maps.get("RB"); Integer order = Integer.valueOf((String) maps.get("ORDER")); String offset = (String) maps.get("OFFSET"); String length = (String) maps.get("LENGHT"); @@ -1133,14 +1134,8 @@ public class PracticalUtils { getValue = singleRowResponseMessage; } else { String regex = leftBoundary + "(.*?)" + rightBoundary; - Pattern pattern = Pattern.compile(regex); - List regStrs = new ArrayList(); - Matcher matcher = pattern.matcher(singleRowResponseMessage); - - while (matcher.find()) { - regStrs.add(matcher.group(1)); - } - + List regStrs = ReUtil.findAllGroup1(regex, singleRowResponseMessage); + if (regStrs.size() < order) { return null; } @@ -1156,12 +1151,32 @@ public class PracticalUtils { getValue = getValue.substring(0, Integer.valueOf(length)); } } catch (Exception e) { - return null; + LOGGER.error("边界关联出错,请检查配置", e); + return null; } return getValue; } - - /** + + + /** + * 转义正则特殊字符 ($()*+.[]?\^{},|) + * + * @param keyword + * @return + */ + public static String escapeExprSpecialWord(String keyword) { + if (StringUtils.isNotBlank(keyword)) { + String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|" }; + for (String key : fbsArr) { + if (keyword.contains(key)) { + keyword = keyword.replace(key, "\\" + key); + } + } + } + return keyword; + } + + /** * 根据质量等级获取html显示代码 * @param qualityLevel 质量等级 * @return @@ -1181,4 +1196,17 @@ public class PracticalUtils { } return ""; } + + public static void main(String[] args) { + String msg = "womendasdwww{wedaw+wioiesd我们dasdw+]"; + System.out.println(ReUtil.getGroup1("womendasdwww\\{wedaw\\+wioiesd(.*)dasdw\\+\\]", msg)); + Map map = new HashMap<>(); + map.put("LB", "womendasdwww{wedaw+wioiesd"); + map.put("RB", "dasdw+]"); + map.put("ORDER", "1"); + map.put("OFFSET", ""); + map.put("LENGHT", ""); + + System.out.println("====" + getValueByRelationKeyWord(map, msg)); + } } diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index d9cfdf0..d959ed4 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -1,6 +1,6 @@ -#log4j.rootLogger = [ level ] , appenderName, appenderName, ... +#log4j.rootLogger = [ level ] , appenderName, appenderName, ... log4j.rootLogger = INFO, console, R, E -log4j.logger.yi.master=INFO +log4j.logger.com.dcits=INFO #level=INFO,all can be output #console is set to be a ConsoleAppender log4j.appender.console = org.apache.log4j.ConsoleAppender @@ -16,7 +16,7 @@ log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%l]- log4j.appender.R = org.apache.log4j.DailyRollingFileAppender log4j.appender.R.DatePattern='.'yyyy-MM-dd #the absolute route of the log4j file -log4j.appender.R.File = /data/wwwlogs/yi/app.log +log4j.appender.R.File = logs/app.log # set this kind LV log4j.appender.R.Threshold = INFO log4j.appender.R.Append = true @@ -30,7 +30,7 @@ log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%l]-[%p] - #error log log4j.appender.E = org.apache.log4j.RollingFileAppender -log4j.appender.E.File = /data/wwwlogs/yi/error.log +log4j.appender.E.File = logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.MaxFileSize=5MB @@ -40,4 +40,4 @@ log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%l]-[%p] #other setting log4j.logger.com.opensymphony.xwork2=ERROR -#log4j.logger.yi.master.coretest.message.test.mock=DEBUG +#log4j.logger.com.dcits.coretest.message.test.mock=DEBUG \ No newline at end of file diff --git a/src/main/webapp/libs/h-ui.admin/css/H-ui.admin.css b/src/main/webapp/libs/h-ui.admin/css/H-ui.admin.css index fe6093a..19fb3a4 100644 --- a/src/main/webapp/libs/h-ui.admin/css/H-ui.admin.css +++ b/src/main/webapp/libs/h-ui.admin/css/H-ui.admin.css @@ -121,7 +121,6 @@ h4{line-height:30px} .portfolio-area li .checkbox{position: absolute; top: 10px; right: 5px; cursor:pointer} .portfolio-area li.hover .portfoliobox{ height:auto;padding-bottom:10px;box-shadow:0 1px 3px rgba(68, 68, 68,0.3);-moz-box-shadow:0 1px 3px rgba(68, 68, 68,0.3);-webkit-box-shadow:0 1px 3px rgba(68, 68, 68,0.3)} .portfolio-area li .picbox{width: 150px; height: 150px;overflow: hidden;text-align: center;vertical-align:middle;display:table-cell; line-height:150px;} -.portfolio-area li .picbox img{max-width:150px; max-height:150px;vertical-align:middle;_margin-top: expression_r(( 150 - this.height ) / 2);} .portfolio-area li .textbox{ display: none; margin-top: 5px;} .portfolio-area li.hover .textbox{ display: block;} .portfolio-area li label{ display:block; cursor:pointer} \ No newline at end of file diff --git a/update.md b/update.md index dff387c..94151bf 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,7 @@ +### v1.1.1 +#### 2020.9.4 + + ### v1.1.0 #### 2020.8.4 - 修复:测试集名称过长不显示的问题; -- Gitee From a45f6b5cf5a8e0eaefb74e7fb23c38526fe12c6a Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 6 Nov 2020 14:27:49 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E5=8D=95=E8=AF=8D=E6=8B=BC=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../action/PerformanceTestResultAction.java | 23 ++++++++----------- .../PerformanceTestAnalyzeResult.java | 4 +--- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/java/yi/master/business/advanced/action/PerformanceTestResultAction.java b/src/main/java/yi/master/business/advanced/action/PerformanceTestResultAction.java index 92d727a..adf1941 100644 --- a/src/main/java/yi/master/business/advanced/action/PerformanceTestResultAction.java +++ b/src/main/java/yi/master/business/advanced/action/PerformanceTestResultAction.java @@ -1,25 +1,16 @@ package yi.master.business.advanced.action; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - +import net.sf.json.JSONObject; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; - import yi.master.business.advanced.bean.PerformanceTestResult; import yi.master.business.advanced.service.PerformanceTestResultService; import yi.master.business.base.action.BaseAction; import yi.master.business.message.bean.TestResult; -import yi.master.constant.ReturnCodeConsts; import yi.master.constant.SystemConsts; import yi.master.exception.AppErrorCode; import yi.master.exception.YiException; @@ -27,7 +18,13 @@ import yi.master.util.FrameworkUtil; import yi.master.util.PracticalUtils; import yi.master.util.excel.ExportPerformanceTestResult; -import net.sf.json.JSONObject; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; /** * 性能测试结果查询相关接口 @@ -75,7 +72,7 @@ public class PerformanceTestResultAction extends BaseAction Date: Fri, 6 Nov 2020 19:15:52 +0800 Subject: [PATCH 07/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coretest/web/framework/BaseFrameworkExecutor.java | 10 +++++----- src/main/webapp/resource/message/messageScene.js | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/yi/master/coretest/web/framework/BaseFrameworkExecutor.java b/src/main/java/yi/master/coretest/web/framework/BaseFrameworkExecutor.java index af11e8e..a991d92 100644 --- a/src/main/java/yi/master/coretest/web/framework/BaseFrameworkExecutor.java +++ b/src/main/java/yi/master/coretest/web/framework/BaseFrameworkExecutor.java @@ -16,7 +16,7 @@ public abstract class BaseFrameworkExecutor { * 当前存在的没有结束的ui自动化测试任务 */ private static Integer runningWebScriptId; - private static Process runingWebScriptProcess; + private static Process runningWebScriptProcess; private static final WatirCucumberFrameworkExecutor wcfe = new WatirCucumberFrameworkExecutor(); @@ -37,12 +37,12 @@ public abstract class BaseFrameworkExecutor { return runningWebScriptId; } - public static void setRuningWebScriptProcess(Process runingWebScriptProcess) { - BaseFrameworkExecutor.runingWebScriptProcess = runingWebScriptProcess; + public static void setRunningWebScriptProcess(Process runingWebScriptProcess) { + BaseFrameworkExecutor.runningWebScriptProcess = runingWebScriptProcess; } - public static Process getRuningWebScriptProcess() { - return runingWebScriptProcess; + public static Process getRunningWebScriptProcess() { + return runningWebScriptProcess; } public static BaseFrameworkExecutor getExecutorInstance(String type) { diff --git a/src/main/webapp/resource/message/messageScene.js b/src/main/webapp/resource/message/messageScene.js index 922aae5..9dd273f 100644 --- a/src/main/webapp/resource/message/messageScene.js +++ b/src/main/webapp/resource/message/messageScene.js @@ -325,11 +325,11 @@ var eventList = { updateConfig["saveVariables"] = {}; $.each($("#save-variables").siblings('div').children(".edit-this-variables"), function(i, n) { var variables = $(n).text(); - updateConfig["saveVariables"][variables.substring(0, variables.indexOf("="))] = variables.substring(variables.indexOf("=") + 1); + updateConfig["saveVariables"][variables.substring(0, variables.lastIndexOf("="))] = variables.substring(variables.lastIndexOf("=") + 1); }); $.each($("#use-variables").siblings('div').children(".edit-this-variables"), function(i, n) { var variables = $(n).text(); - updateConfig["useVariables"][variables.substring(0, variables.indexOf("="))] = variables.substring(variables.indexOf("=") + 1); + updateConfig["useVariables"][variables.substring(0, variables.lastIndexOf("="))] = variables.substring(variables.lastIndexOf("=") + 1); }); if (JSON.stringify(updateConfig) != JSON.stringify(data.config)) { @@ -855,7 +855,7 @@ function editSceneConfigVariable (obj, editMode) { if (editMode == "edit") { returnContext.currentVariablesSpan = $(obj); var keyValue = $(obj).text(); - context = {"key":keyValue.substring(0, keyValue.indexOf("=")), "value":keyValue.substring(keyValue.indexOf("=") + 1)}; + context = {"key":keyValue.substring(0, keyValue.lastIndexOf("=")), "value":keyValue.substring(keyValue.lastIndexOf("=") + 1)}; name = $(obj).parents('div').siblings('label').text(); title = "修改"; } -- Gitee From 4176e3470dcf2425046828a57f471abef4013b55 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Tue, 10 Nov 2020 16:04:16 +0800 Subject: [PATCH 08/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/api/service/task/WebApiTaskService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/yi/master/business/api/service/task/WebApiTaskService.java b/src/main/java/yi/master/business/api/service/task/WebApiTaskService.java index dce5b3e..8ac21d8 100644 --- a/src/main/java/yi/master/business/api/service/task/WebApiTaskService.java +++ b/src/main/java/yi/master/business/api/service/task/WebApiTaskService.java @@ -1,14 +1,10 @@ package yi.master.business.api.service.task; -import java.util.List; - import net.sf.json.JSONArray; import net.sf.json.JSONObject; - import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - import yi.master.business.api.bean.ApiReturnInfo; import yi.master.business.localize.shanxi.bean.WebScriptModule; import yi.master.business.localize.shanxi.bean.WebScriptTask; @@ -19,6 +15,8 @@ import yi.master.coretest.web.framework.BaseFrameworkExecutor; import yi.master.util.PracticalUtils; import yi.master.util.cache.CacheUtil; +import java.util.List; + @Service public class WebApiTaskService implements ApiTaskService{ @@ -97,8 +95,8 @@ public class WebApiTaskService implements ApiTaskService{ taskService.edit(task); BaseFrameworkExecutor.setRunningWebScriptId(null); - BaseFrameworkExecutor.getRuningWebScriptProcess().destroy(); - BaseFrameworkExecutor.setRuningWebScriptProcess(null); + BaseFrameworkExecutor.getRunningWebScriptProcess().destroy(); + BaseFrameworkExecutor.setRunningWebScriptProcess(null); return new ApiReturnInfo(ApiReturnInfo.SUCCESS_CODE, "测试任务成功停止", null); } -- Gitee From 3d274f772cac51f36450501e79e4c91d0499b953 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 11 Nov 2020 09:45:32 +0800 Subject: [PATCH 09/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/update.md b/update.md index 94151bf..bab8a52 100644 --- a/update.md +++ b/update.md @@ -1,5 +1,6 @@ ### v1.1.1 -#### 2020.9.4 +#### 2020.11 +- 修复一些小问题; ### v1.1.0 -- Gitee From 07a16a374f54cfe173dd4175e61d1c6bb676e698 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 25 Nov 2020 14:55:54 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E8=BE=BD=E5=AE=81=E5=92=8C=E5=B1=B1?= =?UTF-8?q?=E4=B8=9Csocket=E5=8D=8F=E8=AE=AE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/yi/master/constant/MessageKeys.java | 8 +- .../process/LiaoNingSocketMsgProcess.java | 100 +++++++++++++++++ .../process/ShanDongSocketMsgProcess.java | 23 ++++ .../message/protocol/SocketTestClient.java | 101 ++++++++++++------ src/main/webapp/js/globalConstant.js | 8 +- 5 files changed, 204 insertions(+), 36 deletions(-) create mode 100644 src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java create mode 100644 src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java diff --git a/src/main/java/yi/master/constant/MessageKeys.java b/src/main/java/yi/master/constant/MessageKeys.java index 4af672e..3c11451 100644 --- a/src/main/java/yi/master/constant/MessageKeys.java +++ b/src/main/java/yi/master/constant/MessageKeys.java @@ -1,7 +1,9 @@ package yi.master.constant; import yi.master.coretest.message.parse.*; +import yi.master.coretest.message.process.LiaoNingSocketMsgProcess; import yi.master.coretest.message.process.MessageProcess; +import yi.master.coretest.message.process.ShanDongSocketMsgProcess; import yi.master.coretest.message.protocol.*; import java.util.regex.Pattern; @@ -233,7 +235,8 @@ public interface MessageKeys { * 报文处理类型 */ enum MessageProcessType { - ; + ShanDongSocketMsgProcess(new ShanDongSocketMsgProcess()), + LiaoNingSocketMsgProcess(new LiaoNingSocketMsgProcess()); private MessageProcess processor; @@ -268,6 +271,9 @@ public interface MessageKeys { String PUBLIC_PARAMETER_PASSWORD = "Password"; String PUBLIC_PARAMETER_METHOD = "Method"; + /**Socket协议*/ + String SOCKET_SEND_MSG_TYPE = "sendType"; + /**HTTP协议调用参数*/ String HTTP_PARAMETER_HEADER = "Headers"; diff --git a/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java new file mode 100644 index 0000000..460b8bb --- /dev/null +++ b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java @@ -0,0 +1,100 @@ +package yi.master.coretest.message.process; + +import org.apache.log4j.Logger; + +import java.util.Map; + +/** + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2020/11/25 11:15 + */ +public class LiaoNingSocketMsgProcess extends MessageProcess { + private static final Logger logger = Logger.getLogger(LiaoNingSocketMsgProcess.class); + + @Override + public String processRequestMessage(String requestMessage, Map headers, String processParameter) { + String result = requestMessage; + + try { + byte[] reqData = requestMessage.getBytes(); + int length = reqData.length; + byte[] reqLen = intToByteArray(length, 4, 0); + byte[] inPack = new byte[length + 4]; + System.arraycopy(reqLen, 0, inPack, 0, 4); + System.arraycopy(reqData, 0, inPack, 4, length); + + result = new String(inPack); + } catch (Exception e) { + logger.error("LiaoNingSocketMsgProcess 处理出错,使用原始请求报文", e); + } + + return result; + } + + @Override + public String processResponseMessage(String responseMessage, String processParameter) { + return responseMessage; + } + + private static int byteArrayToInt(byte[] data, int length, int alignment) + throws Exception + { + int value = 0; + switch (alignment) + { + case 0: + for (int i = 0; i < length; i++) + { + value <<= 8; + value += toInt(data[i]); + } + break; + case 1: + for (int i = 0; i < length; i++) + { + value <<= 8; + value += toInt(data[(length - i - 1)]); + } + break; + default: + throw new Exception("数据对齐方式非法!"); + } + return value; + } + + private static int toInt(byte b) + { + if (b >= 0) { + return b; + } + return b + 256; + } + + private byte[] intToByteArray(int value, int length, int alignment) + throws Exception + { + byte[] data = new byte[length]; + switch (alignment) + { + case 0: + for (int i = 0; i < length; i++) + { + data[(length - i - 1)] = ((byte)(value & 0xFF)); + value >>>= 8; + } + break; + case 1: + for (int i = 0; i < length; i++) + { + data[i] = ((byte)(value & 0xFF)); + value >>>= 8; + } + break; + default: + throw new Exception("数据对齐方式非法!"); + } + return data; + } +} diff --git a/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java new file mode 100644 index 0000000..a4628af --- /dev/null +++ b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java @@ -0,0 +1,23 @@ +package yi.master.coretest.message.process; + +import java.util.Map; + +/** + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2020/11/25 11:12 + */ +public class ShanDongSocketMsgProcess extends MessageProcess { + @Override + public String processRequestMessage(String requestMessage, Map headers, String processParameter) { + // 转成一行,并且前面加上长度,7位补零 + String strNoBlank = requestMessage.replaceAll("\t|\r|\n|\\s|\n\t", ""); + return String.format("%07d", strNoBlank.length()) + strNoBlank; + } + + @Override + public String processResponseMessage(String responseMessage, String processParameter) { + return responseMessage; + } +} diff --git a/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java b/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java index a8006cf..15b0b8b 100644 --- a/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java +++ b/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java @@ -1,23 +1,21 @@ package yi.master.coretest.message.protocol; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Map; - import org.apache.log4j.Logger; - import yi.master.business.testconfig.bean.TestConfig; import yi.master.constant.MessageKeys; import yi.master.coretest.message.protocol.entity.ClientTestResponseObject; import yi.master.util.PracticalUtils; +import java.io.*; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; + public class SocketTestClient extends TestClient { private static final Logger LOGGER = Logger.getLogger(SocketTestClient.class); private static SocketTestClient socketTestClient; + private String DEFAULT_ENC_CHARSET = "utf-8"; + private String DEFAULT_REC_ENC_CHARSET = "utf-8"; private SocketTestClient () {} @@ -37,6 +35,8 @@ public class SocketTestClient extends TestClient { int connectTimeOut = config.getConnectTimeOut(); int soTimeOut = config.getReadTimeOut(); + String encCharset = DEFAULT_ENC_CHARSET; + String recEncCharset = DEFAULT_REC_ENC_CHARSET; if (callParameter != null ) { if (PracticalUtils.isNumeric(callParameter.get(MessageKeys.PUBLIC_PARAMETER_CONNECT_TIMEOUT))) { @@ -46,12 +46,21 @@ public class SocketTestClient extends TestClient { if (PracticalUtils.isNumeric(callParameter.get(MessageKeys.PUBLIC_PARAMETER_READ_TIMEOUT))) { soTimeOut = Integer.parseInt((String) callParameter.get(MessageKeys.PUBLIC_PARAMETER_READ_TIMEOUT)); } + + if (callParameter.get(MessageKeys.HTTP_PARAMETER_ENC_TYPE) != null) { + encCharset = callParameter.get(MessageKeys.HTTP_PARAMETER_ENC_TYPE).toString(); + } + + if (callParameter.get(MessageKeys.HTTP_PARAMETER_REC_ENC_TYPE) != null) { + recEncCharset = callParameter.get(MessageKeys.HTTP_PARAMETER_REC_ENC_TYPE).toString(); + } } String[] ipPort = requestUrl.split(":"); long startTime = System.currentTimeMillis(); - String responseMsg = sendSocketMsg(ipPort[0], Integer.parseInt(ipPort[1]), requestMessage, connectTimeOut, soTimeOut); + String responseMsg = sendSocketMsg(ipPort[0], Integer.parseInt(ipPort[1]), requestMessage, connectTimeOut, soTimeOut, encCharset, recEncCharset); + ; long endTime = System.currentTimeMillis(); long useTime = endTime - startTime; @@ -71,38 +80,63 @@ public class SocketTestClient extends TestClient { @Override public boolean testInterface(String requestUrl) { - return false; } @Override public Object getTestClient() { - return null; } @Override public void putBackTestClient(Object procotolClient) { - - } - /************************************************************************************************/ - private String sendSocketMsg(String ip, int port, String request, int connectimeOut, int soTimeOut) { - Socket socket = new Socket(); + /************************************************************************************************/ + + /** + * 打开socket连接 + * @author xuwangcheng + * @date 2020/11/25 10:25 + * @param ip ip + * @param port port + * @param connectimeOut connectimeOut + * @param soTimeOut soTimeOut + * @return {@link Socket} + */ + private Socket open (String ip, int port, int connectimeOut, int soTimeOut) throws IOException { + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(ip, port), connectimeOut); + socket.setSoTimeout(soTimeOut); + + return socket; + } + + /** + * 已字符串的方式发送 + * @param ip + * @param port + * @param request + * @param connectTimeOut + * @param soTimeOut + * @param encCharset + * @param recEncCharset + * @return + */ + private String sendSocketMsg(String ip, int port, String request, int connectTimeOut, int soTimeOut, String encCharset, String recEncCharset) { + Socket socket = null; StringBuilder responseMsg = new StringBuilder(""); PrintWriter pw = null; BufferedReader br = null; try { - socket.connect(new InetSocketAddress(ip, port), connectimeOut); - socket.setSoTimeout(soTimeOut); - - //输出流 - pw = new PrintWriter(socket.getOutputStream()); - //输入流 - br = new BufferedReader(new InputStreamReader(socket.getInputStream())); + socket = open(ip, port, connectTimeOut, soTimeOut); + + //输出流 指定编码 + pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), encCharset)); + //输入流 指定编码 + br = new BufferedReader(new InputStreamReader(socket.getInputStream(), recEncCharset)); pw.write(request); pw.flush(); @@ -117,17 +151,16 @@ public class SocketTestClient extends TestClient { LOGGER.debug("Send Socket msg to [" + ip + ":" + port + "] Fail!", e); responseMsg = new StringBuilder("Send Socket msg to [" + ip + ":" + port + "] Fail:" + e.getMessage()); } finally { - if (br != null) - try { - br.close(); - } catch (IOException e) { - LOGGER.warn("IOException", e); - } try { - socket.close(); - } catch (IOException e) { - LOGGER.warn("IOException", e); - } + if (br != null) { + br.close(); + } + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + LOGGER.warn("IOException", e); + } } return responseMsg.toString(); } diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index 47a178b..71d4818 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -440,6 +440,10 @@ var PROJECT_STATUS = { //接口自动化相关 //报文处理器参数设置 var MESSAGE_PROCESS = { + "ShanDongSocketMsgProcess": { + }, + "LiaoNingSocketMsgProcess": { + }, "ShanXiOpenApi":{ "pemFilePath":"" }, @@ -493,7 +497,9 @@ var MESSAGE_PROTOCOL = { }, "Socket":{ "ConnectTimeOut":"", - "ReadTimeOut":"" + "ReadTimeOut":"", + "EncType":"UTF-8", + "RecEncType":"UTF-8" }, // "WebService":{ // "ConnectTimeOut":"", -- Gitee From 67f231578275b40cbea619e01d72ae0f92376e91 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 25 Nov 2020 15:08:03 +0800 Subject: [PATCH 11/30] =?UTF-8?q?Revert=20"=E6=B8=85=E9=99=A4=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E4=B8=9C=E8=A5=BF"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4751f198 --- lib/javabase64-1.3.1.jar | Bin 0 -> 4364 bytes lib/neu-cryptography.jar | Bin 0 -> 29358 bytes lib/openApiClient.jar | Bin 0 -> 42239 bytes lib/sun.misc.BASE64Decoder.jar | Bin 0 -> 7471 bytes pom.xml | 42 ++ .../AnHuiAPPEncryptMessageProcess.java | 364 ++++++++++++++++++ .../process/HeNanYsbGjjMessageProcess.java | 118 ++++++ .../process/ShanXiOpenApiMessageProcess.java | 61 +++ .../config/AnHuiAppMsgProcessParameter.java | 46 +++ .../HeNanYsbGjjMsgProcessParameter.java | 61 +++ .../ShanXiOpenApiMsgProcessParameter.java | 21 + .../message/process/util/ysb/MDFive.java | 83 ++++ .../message/process/util/ysb/YsbSM4Util.java | 54 +++ 13 files changed, 850 insertions(+) create mode 100644 lib/javabase64-1.3.1.jar create mode 100644 lib/neu-cryptography.jar create mode 100644 lib/openApiClient.jar create mode 100644 lib/sun.misc.BASE64Decoder.jar create mode 100644 src/main/java/yi/master/coretest/message/process/AnHuiAPPEncryptMessageProcess.java create mode 100644 src/main/java/yi/master/coretest/message/process/HeNanYsbGjjMessageProcess.java create mode 100644 src/main/java/yi/master/coretest/message/process/ShanXiOpenApiMessageProcess.java create mode 100644 src/main/java/yi/master/coretest/message/process/config/AnHuiAppMsgProcessParameter.java create mode 100644 src/main/java/yi/master/coretest/message/process/config/HeNanYsbGjjMsgProcessParameter.java create mode 100644 src/main/java/yi/master/coretest/message/process/config/ShanXiOpenApiMsgProcessParameter.java create mode 100644 src/main/java/yi/master/coretest/message/process/util/ysb/MDFive.java create mode 100644 src/main/java/yi/master/coretest/message/process/util/ysb/YsbSM4Util.java diff --git a/lib/javabase64-1.3.1.jar b/lib/javabase64-1.3.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..47d0553613b0d4637beac0cbd677b5835e6a4898 GIT binary patch literal 4364 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 F{{X`i8Mgoc literal 0 HcmV?d00001 diff --git a/lib/neu-cryptography.jar b/lib/neu-cryptography.jar new file mode 100644 index 0000000000000000000000000000000000000000..c78cc11cffd3458994f320236a9a8c3b5c912def GIT binary patch literal 29358 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

    YVyWC@NX0Fp$Uvdn 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 KHjg;WfBy#@E5UsL literal 0 HcmV?d00001 diff --git a/lib/sun.misc.BASE64Decoder.jar b/lib/sun.misc.BASE64Decoder.jar new file mode 100644 index 0000000000000000000000000000000000000000..9811c130389b95328a689e9f9466d42624445500 GIT binary patch literal 7471 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 6254bd2..1165c96 100644 --- a/pom.xml +++ b/pom.xml @@ -362,6 +362,23 @@ + + + com.openApiClient + openApiClient + 1.0 + system + ${project.basedir}/lib/openApiClient.jar + + + + it.sauronsoftware + Base64 + 1.3.1 + system + ${project.basedir}/lib/javabase64-1.3.1.jar + + @@ -459,6 +476,31 @@ 1.11.3 + + + + + org.bouncycastle + bcprov-jdk15on + 1.58 + + + + com.cryptography.neu + sm + 1.0 + system + ${project.basedir}/lib/neu-cryptography.jar + + + + com.cryptography.neu + BASE64Decoder + 1.0 + system + ${project.basedir}/lib/sun.misc.BASE64Decoder.jar + + + org.bouncycastle diff --git a/src/main/java/yi/master/coretest/message/process/HeNanYsbGjjMessageProcess.java b/src/main/java/yi/master/coretest/message/process/HeNanYsbGjjMessageProcess.java index cb42275..5fb1c26 100644 --- a/src/main/java/yi/master/coretest/message/process/HeNanYsbGjjMessageProcess.java +++ b/src/main/java/yi/master/coretest/message/process/HeNanYsbGjjMessageProcess.java @@ -18,7 +18,7 @@ import java.util.Map; /** * - * 河南豫事办公积金加解密 + * ysb加解密 * @author xuwangcheng * @version 1.0.0 * @description @@ -63,7 +63,7 @@ public class HeNanYsbGjjMessageProcess extends MessageProcess { private String encrypt(HeNanYsbGjjMsgProcessParameter parameter, String requestMessage) { if (StringUtils.isBlank(parameter.getPriKey()) || StringUtils.isBlank(parameter.getPubKey())) { - LOGGER.error("河南豫事办公积金接口加密失败:私钥和公钥均不能为空!"); + LOGGER.error("ysb接口加密失败:私钥和公钥均不能为空!"); return requestMessage; } JSONObject jsonObject = new JSONObject(); @@ -78,7 +78,7 @@ public class HeNanYsbGjjMessageProcess extends MessageProcess { jsonObject.put("sign_r", sm2Result.str_r); jsonObject.put("sign_s", sm2Result.str_s); } catch (Exception e) { - LOGGER.error("河南豫事办公积金接口加密失败", e); + LOGGER.error("ysb接口加密失败", e); return requestMessage; } @@ -87,7 +87,7 @@ public class HeNanYsbGjjMessageProcess extends MessageProcess { private String decode(HeNanYsbGjjMsgProcessParameter parameter, String responseMessage) { if (StringUtils.isBlank(parameter.getPriKey()) || StringUtils.isBlank(parameter.getPubKey())) { - LOGGER.error("河南豫事办公积金接口解密失败:私钥和公钥均不能为空!"); + LOGGER.error("ysb接口解密失败:私钥和公钥均不能为空!"); return responseMessage; } @@ -110,7 +110,7 @@ public class HeNanYsbGjjMessageProcess extends MessageProcess { return jsonObject.toJSONString(); } catch (Exception e) { - LOGGER.error("河南豫事办公积金接口解密失败", e); + LOGGER.error("ysb接口解密失败", e); return responseMessage; } diff --git a/src/main/java/yi/master/coretest/message/process/config/HeNanYsbGjjMsgProcessParameter.java b/src/main/java/yi/master/coretest/message/process/config/HeNanYsbGjjMsgProcessParameter.java index 10eda45..94649ea 100644 --- a/src/main/java/yi/master/coretest/message/process/config/HeNanYsbGjjMsgProcessParameter.java +++ b/src/main/java/yi/master/coretest/message/process/config/HeNanYsbGjjMsgProcessParameter.java @@ -1,7 +1,7 @@ package yi.master.coretest.message.process.config; /** - * 河南豫事办报文处理器参数 + * ysb报文处理器参数 * @author xuwangcheng * @version 1.0.0 * @description -- Gitee From 15953ad9e4ba40bd4b3c0efa1a94e98d2d02ab7f Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 25 Nov 2020 15:20:35 +0800 Subject: [PATCH 13/30] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/yi/master/constant/MessageKeys.java | 11 ++++++----- .../process/LiaoNingSocketMsgProcess.java | 11 +++++++++++ .../process/ShanDongSocketMsgProcess.java | 16 ++++++++++++++++ src/main/webapp/js/globalConstant.js | 4 ++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/java/yi/master/constant/MessageKeys.java b/src/main/java/yi/master/constant/MessageKeys.java index 3c11451..0199fcc 100644 --- a/src/main/java/yi/master/constant/MessageKeys.java +++ b/src/main/java/yi/master/constant/MessageKeys.java @@ -1,9 +1,7 @@ package yi.master.constant; import yi.master.coretest.message.parse.*; -import yi.master.coretest.message.process.LiaoNingSocketMsgProcess; -import yi.master.coretest.message.process.MessageProcess; -import yi.master.coretest.message.process.ShanDongSocketMsgProcess; +import yi.master.coretest.message.process.*; import yi.master.coretest.message.protocol.*; import java.util.regex.Pattern; @@ -235,8 +233,11 @@ public interface MessageKeys { * 报文处理类型 */ enum MessageProcessType { - ShanDongSocketMsgProcess(new ShanDongSocketMsgProcess()), - LiaoNingSocketMsgProcess(new LiaoNingSocketMsgProcess()); + AnhuiApp(AnHuiAPPEncryptMessageProcess.getInstance()), + HeNanYsb(HeNanYsbGjjMessageProcess.getInstance()), + ShanXiOpenApi(ShanXiOpenApiMessageProcess.getInstance()), + ShanDongSocket(ShanDongSocketMsgProcess.getInstance()), + LiaoNingSocket(LiaoNingSocketMsgProcess.getInstance()); private MessageProcess processor; diff --git a/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java index 460b8bb..c295206 100644 --- a/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java +++ b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java @@ -12,6 +12,17 @@ import java.util.Map; */ public class LiaoNingSocketMsgProcess extends MessageProcess { private static final Logger logger = Logger.getLogger(LiaoNingSocketMsgProcess.class); + private static LiaoNingSocketMsgProcess liaoNingSocketMsgProcess; + + private LiaoNingSocketMsgProcess (){} + + public static LiaoNingSocketMsgProcess getInstance() { + if (liaoNingSocketMsgProcess == null) { + liaoNingSocketMsgProcess = new LiaoNingSocketMsgProcess(); + } + + return liaoNingSocketMsgProcess; + } @Override public String processRequestMessage(String requestMessage, Map headers, String processParameter) { diff --git a/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java index a4628af..830489e 100644 --- a/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java +++ b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java @@ -1,5 +1,7 @@ package yi.master.coretest.message.process; +import org.apache.log4j.Logger; + import java.util.Map; /** @@ -9,6 +11,20 @@ import java.util.Map; * @date 2020/11/25 11:12 */ public class ShanDongSocketMsgProcess extends MessageProcess { + + private static final Logger logger = Logger.getLogger(ShanDongSocketMsgProcess.class); + private static ShanDongSocketMsgProcess shanDongSocketMsgProcess; + + private ShanDongSocketMsgProcess (){} + + public static ShanDongSocketMsgProcess getInstance() { + if (shanDongSocketMsgProcess == null) { + shanDongSocketMsgProcess = new ShanDongSocketMsgProcess(); + } + + return shanDongSocketMsgProcess; + } + @Override public String processRequestMessage(String requestMessage, Map headers, String processParameter) { // 转成一行,并且前面加上长度,7位补零 diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index 71d4818..c81ffb6 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -440,9 +440,9 @@ var PROJECT_STATUS = { //接口自动化相关 //报文处理器参数设置 var MESSAGE_PROCESS = { - "ShanDongSocketMsgProcess": { + "ShanDongSocket": { }, - "LiaoNingSocketMsgProcess": { + "LiaoNingSocket": { }, "ShanXiOpenApi":{ "pemFilePath":"" -- Gitee From 751f1c506ec4a31cb6237756cd5d91b028749bd1 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 25 Nov 2020 21:36:38 +0800 Subject: [PATCH 14/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B1=B1=E4=B8=9Csokce?= =?UTF-8?q?t=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coretest/message/process/ShanDongSocketMsgProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java index 830489e..5327830 100644 --- a/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java +++ b/src/main/java/yi/master/coretest/message/process/ShanDongSocketMsgProcess.java @@ -28,7 +28,7 @@ public class ShanDongSocketMsgProcess extends MessageProcess { @Override public String processRequestMessage(String requestMessage, Map headers, String processParameter) { // 转成一行,并且前面加上长度,7位补零 - String strNoBlank = requestMessage.replaceAll("\t|\r|\n|\\s|\n\t", ""); + String strNoBlank = requestMessage.replaceAll("\t|\r|\n|\n\t", ""); return String.format("%07d", strNoBlank.length()) + strNoBlank; } -- Gitee From 0f998a557f198f0faaf183335898be2dc1251039 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 27 Nov 2020 13:55:42 +0800 Subject: [PATCH 15/30] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/process/AnHuiAPPEncryptMessageProcess.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/yi/master/coretest/message/process/AnHuiAPPEncryptMessageProcess.java b/src/main/java/yi/master/coretest/message/process/AnHuiAPPEncryptMessageProcess.java index e2be719..5689d21 100644 --- a/src/main/java/yi/master/coretest/message/process/AnHuiAPPEncryptMessageProcess.java +++ b/src/main/java/yi/master/coretest/message/process/AnHuiAPPEncryptMessageProcess.java @@ -48,15 +48,7 @@ public class AnHuiAPPEncryptMessageProcess extends MessageProcess { /** * 默认公钥 */ - /*public static final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTzkDgp27ZJ66BlR3tC1CarLVXrj14Ca05hzvG3aIxA+em3BCmMaWe7FurDP6nDD5u2EZRT9gmVEe3khXrHODLKVFOGdY9y6DBrO6Eix5aKLh4C3eCwW+5duJdKJT2SZrs3h8xvdQrgyDLM52P73guyWUhoNlSEmDLo6MM6bRHzwIDAQAB\r" - + "ip5/HiCVaYmzep/D1FupbGGVhV3ejjseNMC0pNYdVbmNN7OZyeSXQK1jtKl1pkkI0A+GpEMo4wW/\r" - + "BTqxI8jUb8VfANQDD42MF4OaT5nDl2/ei3PNEpOi0dMDEMBpVJuAAZX+R5trjD3oeST4+/PIVMLm\r" - + "J3vAxpSRkNpeqEN/bO0=";*/ - - public static final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfRTdcPIH10gT9f31rQuIInLwe" - + "\r" + "7fl2dtEJ93gTmjE9c2H+kLVENWgECiJVQ5sonQNfwToMKdO0b3Olf4pgBKeLThra" + "\r" - + "z/L3nYJYlbqjHC3jTjUnZc0luumpXGsox62+PuSGBlfb8zJO6hix4GV/vhyQVCpG" + "\r" - + "9aYqgE7zyTRZYX9byQIDAQAB" + "\r"; + public static final String DEFAULT_PUBLIC_KEY = ""; @Override public String processRequestMessage(String requestMessage, Map headers, String processParameter) { -- Gitee From 82c2f46db3c66d8b727da6dc3502f947eeec36df Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 27 Nov 2020 15:22:14 +0800 Subject: [PATCH 16/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/yi/master/coretest/message/test/mock/MockServer.java | 2 +- .../message/test/performance/PerformanceTestObject.java | 1 - update.md | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/yi/master/coretest/message/test/mock/MockServer.java b/src/main/java/yi/master/coretest/message/test/mock/MockServer.java index fc0170d..e5271b9 100644 --- a/src/main/java/yi/master/coretest/message/test/mock/MockServer.java +++ b/src/main/java/yi/master/coretest/message/test/mock/MockServer.java @@ -156,7 +156,7 @@ public abstract class MockServer { String ip = ""; try { InetAddress addr = InetAddress.getLocalHost(); - ip = addr.getHostAddress().toString(); + ip = addr.getHostAddress(); } catch (Exception e) { logger.error("获取服务器本地地址失败,使用配置选项!", e); String homeUrl = CacheUtil.getSettingValue(SystemConsts.GLOBAL_SETTING_HOME); diff --git a/src/main/java/yi/master/coretest/message/test/performance/PerformanceTestObject.java b/src/main/java/yi/master/coretest/message/test/performance/PerformanceTestObject.java index ff8b50a..5c16a6c 100644 --- a/src/main/java/yi/master/coretest/message/test/performance/PerformanceTestObject.java +++ b/src/main/java/yi/master/coretest/message/test/performance/PerformanceTestObject.java @@ -708,7 +708,6 @@ public class PerformanceTestObject { @Override public void run() { - infoMsg.add(timeTag() + Thread.currentThread().getName() + " - 开始进行测试..."); //复制一份测试对象,注意此时操作是浅复制 TestMessageScene threadTestScene = (TestMessageScene) testScene.clone(); diff --git a/update.md b/update.md index bab8a52..70ff367 100644 --- a/update.md +++ b/update.md @@ -1,6 +1,7 @@ ### v1.1.1 #### 2020.11 - 修复一些小问题; +- 增加shangdong和liaoning的Socket协议报文处理器; ### v1.1.0 -- Gitee From 5ccf0aa055ebb430fa8278c4a7427d26b3435673 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Fri, 27 Nov 2020 15:50:38 +0800 Subject: [PATCH 17/30] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coretest/task/time/TimeTaskJobAction.java | 27 ++-- .../task/time/TimeTaskJobListener.java | 148 +++++++++--------- 2 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/main/java/yi/master/coretest/task/time/TimeTaskJobAction.java b/src/main/java/yi/master/coretest/task/time/TimeTaskJobAction.java index b56d4c6..2698a8c 100644 --- a/src/main/java/yi/master/coretest/task/time/TimeTaskJobAction.java +++ b/src/main/java/yi/master/coretest/task/time/TimeTaskJobAction.java @@ -27,21 +27,20 @@ public class TimeTaskJobAction implements Job { @SuppressWarnings("rawtypes") @Override public void execute(JobExecutionContext context) { - - JobDataMap dataMap = context.getJobDetail().getJobDataMap(); - - AutoTask task = (AutoTask)dataMap.get(context.getJobDetail().getKey().getName()); - - String[] result = new String[2]; - //获取请求地址 - String testUrl = CacheUtil.getHomeUrl() + "/" + SystemConsts.AUTO_TASK_TEST_RMI_URL - + "?setId=" + task.getRelatedId() + "&autoTestFlag=true" + "&token=" + SystemConsts.REQUEST_ALLOW_TOKEN + "&userId=" + task.getUser().getUserId(); - LOGGER.info("[自动化定时任务]执行自动化测试任务:url=" + testUrl); - - String returnJson = PracticalUtils.doGetHttpRequest(testUrl); - - LOGGER.info("[自动化定时任务]请求返回内容:" + returnJson); + String[] result = new String[2]; + String returnJson = ""; try { + JobDataMap dataMap = context.getJobDetail().getJobDataMap(); + + AutoTask task = (AutoTask)dataMap.get(context.getJobDetail().getKey().getName()); + //获取请求地址 + String testUrl = CacheUtil.getHomeUrl() + "/" + SystemConsts.AUTO_TASK_TEST_RMI_URL + + "?setId=" + task.getRelatedId() + "&autoTestFlag=true" + "&token=" + SystemConsts.REQUEST_ALLOW_TOKEN + "&userId=" + task.getUser().getUserId(); + LOGGER.info("[自动化定时任务]执行自动化测试任务:url=" + testUrl); + + returnJson = PracticalUtils.doGetHttpRequest(testUrl); + + LOGGER.info("[自动化定时任务]请求返回内容:" + returnJson); Map maps = new ObjectMapper().readValue(returnJson, Map.class); if (String.valueOf(ReturnCodeConsts.SUCCESS_CODE).equals(maps.get("returnCode").toString())) { result[0] = String.valueOf(((List)maps.get("data")).get(0)); diff --git a/src/main/java/yi/master/coretest/task/time/TimeTaskJobListener.java b/src/main/java/yi/master/coretest/task/time/TimeTaskJobListener.java index 8987f04..68a56d4 100644 --- a/src/main/java/yi/master/coretest/task/time/TimeTaskJobListener.java +++ b/src/main/java/yi/master/coretest/task/time/TimeTaskJobListener.java @@ -55,7 +55,6 @@ public class TimeTaskJobListener implements JobListener { @Override public String getName() { - return LISTENER_NAME; } @@ -72,78 +71,81 @@ public class TimeTaskJobListener implements JobListener { @Override public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { - - JobDataMap dataMap = context.getJobDetail().getJobDataMap(); - AutoTask task = (AutoTask)dataMap.get(context.getJobDetail().getKey().getName()); - - String[] result = (String[]) context.getResult(); - StringBuilder tip = new StringBuilder(); - if (StringUtils.isEmpty(result[0])) { - tip.append("接口自动化测试定时任务
    [任务Id] = ") - .append(task.getTaskId() + "
    [任务名称] = ") - .append(task.getTaskName() + "
    [任务类型] = ") - .append(getTaskType(task.getTaskType()) + "
    [任务状态] = 失败

    ") 
    -				.append(result[1] + "
    "); - mailService.sendSystemMail("接口自动化定时任务失败提醒", tip.toString(), task.getUser().getUserId()); - return; - } - - if (TestType.INTERFACE.getType().equals(task.getTaskType())) { - String finishFlag = SystemConsts.FinishedFlag.N.name(); - while (SystemConsts.FinishedFlag.N.name().equalsIgnoreCase(finishFlag)) { - finishFlag = reportService.isFinished(Integer.parseInt(result[0])); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - LOGGER.warn("InterruptedException", e); - } - } - - tip.append("接口自动化测试定时任务
    [任务Id] = ") - .append(task.getTaskId() + "
    [任务名称] = ") - .append(task.getTaskName() + "
    [任务类型] = ") - .append(getTaskType(task.getTaskType()) + "
    [测试报告ID] = ") - .append(result[0] + "
    详情请查看本次测试报告!"); - } - - task.setRunCount(task.getRunCount() + 1); - task.setLastFinishTime(new Timestamp(System.currentTimeMillis())); - taskService.edit(task); - - //发送推送邮件 - if (CommonStatus.ENABLED.getStatus().equals(CacheUtil.getSettingValue(SystemConsts.GLOBAL_SETTING_IF_SEND_REPORT_MAIL)) - && SystemConsts.DefaultBooleanIdentify.TRUE.getNumber().equals(task.getMailNotify())) { - String createReportUrl = CacheUtil.getHomeUrl() + "/" - + SystemConsts.CREATE_STATIC_REPORT_HTML_RMI_URL + "?reportId=" + result[0] - + "&token=" + SystemConsts.REQUEST_ALLOW_TOKEN; - String returnJson = PracticalUtils.doGetHttpRequest(createReportUrl); - try { - Map maps = new ObjectMapper().readValue(returnJson, Map.class); - if (!ReturnCodeConsts.SUCCESS_CODE.toString().equals(maps.get("returnCode").toString())) { - throw new Exception(returnJson); - } - - TestReport report = reportService.get(Integer.valueOf(result[0])); - report.setTrs(new HashSet(resultService.listByReportId(Integer.valueOf(result[0])))); - - TestConfig config = testSetService.get(task.getRelatedId()).getConfig(); - String sendMailSuccessFlag = NotifyMail.sendEmail(new ReportEmailCreator(report), config.getMailReceiveAddress(), config.getMailCopyAddress()); - - if (SystemConsts.DefaultBooleanIdentify.TRUE.getString().equalsIgnoreCase(sendMailSuccessFlag)) { - tip.append("

    本次测试结果及报告已通过邮件推送!

    "); - } else { - tip.append("

    发送推送邮件失败,原因:

    " + sendMailSuccessFlag + "

    "); - } - - - } catch (Exception e) { - tip.append("

    发送推送邮件失败,原因:" + e.getMessage() + "。ReportId=" + result[0] + "

    "); - } - } else { - tip.append("

    !!!没有开启测试报告邮件推送或者全局配置中的推送开关被关闭!!!

    "); - } - - mailService.sendSystemMail("接口自动化定时任务完成提醒", tip.toString(), task.getUser().getUserId()); + try { + JobDataMap dataMap = context.getJobDetail().getJobDataMap(); + AutoTask task = (AutoTask)dataMap.get(context.getJobDetail().getKey().getName()); + + String[] result = (String[]) context.getResult(); + StringBuilder tip = new StringBuilder(); + if (StringUtils.isEmpty(result[0])) { + tip.append("接口自动化测试定时任务
    [任务Id] = ") + .append(task.getTaskId() + "
    [任务名称] = ") + .append(task.getTaskName() + "
    [任务类型] = ") + .append(getTaskType(task.getTaskType()) + "
    [任务状态] = 失败
    ")
    +                        .append(result[1] + "
    "); + mailService.sendSystemMail("接口自动化定时任务失败提醒", tip.toString(), task.getUser().getUserId()); + return; + } + + if (TestType.INTERFACE.getType().equals(task.getTaskType())) { + String finishFlag = SystemConsts.FinishedFlag.N.name(); + while (SystemConsts.FinishedFlag.N.name().equalsIgnoreCase(finishFlag)) { + finishFlag = reportService.isFinished(Integer.parseInt(result[0])); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + LOGGER.warn("InterruptedException", e); + } + } + + tip.append("接口自动化测试定时任务
    [任务Id] = ") + .append(task.getTaskId() + "
    [任务名称] = ") + .append(task.getTaskName() + "
    [任务类型] = ") + .append(getTaskType(task.getTaskType()) + "
    [测试报告ID] = ") + .append(result[0] + "
    详情请查看本次测试报告!"); + } + + task.setRunCount(task.getRunCount() + 1); + task.setLastFinishTime(new Timestamp(System.currentTimeMillis())); + taskService.edit(task); + + //发送推送邮件 + if (CommonStatus.ENABLED.getStatus().equals(CacheUtil.getSettingValue(SystemConsts.GLOBAL_SETTING_IF_SEND_REPORT_MAIL)) + && SystemConsts.DefaultBooleanIdentify.TRUE.getNumber().equals(task.getMailNotify())) { + String createReportUrl = CacheUtil.getHomeUrl() + "/" + + SystemConsts.CREATE_STATIC_REPORT_HTML_RMI_URL + "?reportId=" + result[0] + + "&token=" + SystemConsts.REQUEST_ALLOW_TOKEN; + String returnJson = PracticalUtils.doGetHttpRequest(createReportUrl); + try { + Map maps = new ObjectMapper().readValue(returnJson, Map.class); + if (!ReturnCodeConsts.SUCCESS_CODE.toString().equals(maps.get("returnCode").toString())) { + throw new Exception(returnJson); + } + + TestReport report = reportService.get(Integer.valueOf(result[0])); + report.setTrs(new HashSet(resultService.listByReportId(Integer.valueOf(result[0])))); + + TestConfig config = testSetService.get(task.getRelatedId()).getConfig(); + String sendMailSuccessFlag = NotifyMail.sendEmail(new ReportEmailCreator(report), config.getMailReceiveAddress(), config.getMailCopyAddress()); + + if (SystemConsts.DefaultBooleanIdentify.TRUE.getString().equalsIgnoreCase(sendMailSuccessFlag)) { + tip.append("

    本次测试结果及报告已通过邮件推送!

    "); + } else { + tip.append("

    发送推送邮件失败,原因:

    " + sendMailSuccessFlag + "

    "); + } + + + } catch (Exception e) { + tip.append("

    发送推送邮件失败,原因:" + e.getMessage() + "。ReportId=" + result[0] + "

    "); + } + } else { + tip.append("

    !!!没有开启测试报告邮件推送或者全局配置中的推送开关被关闭!!!

    "); + } + + mailService.sendSystemMail("接口自动化定时任务完成提醒", tip.toString(), task.getUser().getUserId()); + } catch (Exception e) { + LOGGER.error("TimeTaskJobListener exec error!", e); + } } -- Gitee From 39612c379d11e3c37e822a411b68643405681cdb Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 2 Dec 2020 16:00:31 +0800 Subject: [PATCH 18/30] =?UTF-8?q?liaoning=20Socket=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process/LiaoNingSocketMsgProcess.java | 77 +---------- .../message/protocol/SocketTestClient.java | 126 ++++++++++++++++-- 2 files changed, 117 insertions(+), 86 deletions(-) diff --git a/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java index c295206..23292ea 100644 --- a/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java +++ b/src/main/java/yi/master/coretest/message/process/LiaoNingSocketMsgProcess.java @@ -11,6 +11,8 @@ import java.util.Map; * @date 2020/11/25 11:15 */ public class LiaoNingSocketMsgProcess extends MessageProcess { + public static final String SOCKET_MSG_TAG = "[LN_SOCKET]"; + private static final Logger logger = Logger.getLogger(LiaoNingSocketMsgProcess.class); private static LiaoNingSocketMsgProcess liaoNingSocketMsgProcess; @@ -26,22 +28,7 @@ public class LiaoNingSocketMsgProcess extends MessageProcess { @Override public String processRequestMessage(String requestMessage, Map headers, String processParameter) { - String result = requestMessage; - - try { - byte[] reqData = requestMessage.getBytes(); - int length = reqData.length; - byte[] reqLen = intToByteArray(length, 4, 0); - byte[] inPack = new byte[length + 4]; - System.arraycopy(reqLen, 0, inPack, 0, 4); - System.arraycopy(reqData, 0, inPack, 4, length); - - result = new String(inPack); - } catch (Exception e) { - logger.error("LiaoNingSocketMsgProcess 处理出错,使用原始请求报文", e); - } - - return result; + return SOCKET_MSG_TAG + requestMessage; } @Override @@ -49,63 +36,5 @@ public class LiaoNingSocketMsgProcess extends MessageProcess { return responseMessage; } - private static int byteArrayToInt(byte[] data, int length, int alignment) - throws Exception - { - int value = 0; - switch (alignment) - { - case 0: - for (int i = 0; i < length; i++) - { - value <<= 8; - value += toInt(data[i]); - } - break; - case 1: - for (int i = 0; i < length; i++) - { - value <<= 8; - value += toInt(data[(length - i - 1)]); - } - break; - default: - throw new Exception("数据对齐方式非法!"); - } - return value; - } - - private static int toInt(byte b) - { - if (b >= 0) { - return b; - } - return b + 256; - } - private byte[] intToByteArray(int value, int length, int alignment) - throws Exception - { - byte[] data = new byte[length]; - switch (alignment) - { - case 0: - for (int i = 0; i < length; i++) - { - data[(length - i - 1)] = ((byte)(value & 0xFF)); - value >>>= 8; - } - break; - case 1: - for (int i = 0; i < length; i++) - { - data[i] = ((byte)(value & 0xFF)); - value >>>= 8; - } - break; - default: - throw new Exception("数据对齐方式非法!"); - } - return data; - } } diff --git a/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java b/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java index 15b0b8b..e2ab65c 100644 --- a/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java +++ b/src/main/java/yi/master/coretest/message/protocol/SocketTestClient.java @@ -3,6 +3,7 @@ package yi.master.coretest.message.protocol; import org.apache.log4j.Logger; import yi.master.business.testconfig.bean.TestConfig; import yi.master.constant.MessageKeys; +import yi.master.coretest.message.process.LiaoNingSocketMsgProcess; import yi.master.coretest.message.protocol.entity.ClientTestResponseObject; import yi.master.util.PracticalUtils; @@ -132,21 +133,61 @@ public class SocketTestClient extends TestClient { try { socket = open(ip, port, connectTimeOut, soTimeOut); - + OutputStream os = socket.getOutputStream(); + InputStream is = socket.getInputStream(); //输出流 指定编码 - pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), encCharset)); + pw = new PrintWriter(new OutputStreamWriter(os, encCharset)); //输入流 指定编码 - br = new BufferedReader(new InputStreamReader(socket.getInputStream(), recEncCharset)); - - pw.write(request); - pw.flush(); + br = new BufferedReader(new InputStreamReader(is, recEncCharset)); + + // 处理liaoningSocket特殊处理 + boolean LNFlag = request.startsWith(LiaoNingSocketMsgProcess.SOCKET_MSG_TAG); + + if (LNFlag) { + request = request.replace(LiaoNingSocketMsgProcess.SOCKET_MSG_TAG, ""); + byte[] reqData = request.getBytes(encCharset); + int length = reqData.length; + byte[] reqLen = intToByteArray(length, 4, 0); + byte[] inPack = new byte[length + 4]; + System.arraycopy(reqLen, 0, inPack, 0, 4); + System.arraycopy(reqData, 0, inPack, 4, length); + + os.write(inPack); + os.flush(); + } else { + pw.write(request); + pw.flush(); + } + socket.shutdownOutput(); - - String reply = null; - - while (((reply = br.readLine()) != null)) { - responseMsg.append(reply); - } + + if (LNFlag) { + byte[] buffer = new byte[4]; + int size = is.read(buffer, 0, 4); + if (size <= 0) { + throw new IOException("Socket receive no data!"); + } + int length = byteArrayToInt(buffer, size, 0); + byte[] data = new byte[length]; + byte[] tmp = new byte[2048]; + int readedLen = 0; + while (readedLen < length) + { + int tmpLen = is.read(tmp); + if (tmpLen > 0) + { + System.arraycopy(tmp, 0, data, readedLen, tmpLen); + readedLen += tmpLen; + } + } + + responseMsg.append(new String(data, recEncCharset)); + } else { + String reply; + while (((reply = br.readLine()) != null)) { + responseMsg.append(reply); + } + } } catch (Exception e) { LOGGER.debug("Send Socket msg to [" + ip + ":" + port + "] Fail!", e); responseMsg = new StringBuilder("Send Socket msg to [" + ip + ":" + port + "] Fail:" + e.getMessage()); @@ -165,4 +206,65 @@ public class SocketTestClient extends TestClient { return responseMsg.toString(); } + + + private static int byteArrayToInt(byte[] data, int length, int alignment) + throws Exception + { + int value = 0; + switch (alignment) + { + case 0: + for (int i = 0; i < length; i++) + { + value <<= 8; + value += toInt(data[i]); + } + break; + case 1: + for (int i = 0; i < length; i++) + { + value <<= 8; + value += toInt(data[(length - i - 1)]); + } + break; + default: + throw new Exception("数据对齐方式非法!"); + } + return value; + } + + private static int toInt(byte b) + { + if (b >= 0) { + return b; + } + return b + 256; + } + + private byte[] intToByteArray(int value, int length, int alignment) + throws Exception + { + byte[] data = new byte[length]; + switch (alignment) + { + case 0: + for (int i = 0; i < length; i++) + { + data[(length - i - 1)] = ((byte)(value & 0xFF)); + value >>>= 8; + } + break; + case 1: + for (int i = 0; i < length; i++) + { + data[i] = ((byte)(value & 0xFF)); + value >>>= 8; + } + break; + default: + throw new Exception("数据对齐方式非法!"); + } + return data; + } } -- Gitee From af1f73d156f11d70670cdf74dd1aa01048dc3655 Mon Sep 17 00:00:00 2001 From: SHENGYIN Date: Sat, 12 Dec 2020 10:43:27 +0800 Subject: [PATCH 19/30] =?UTF-8?q?=E5=A2=9E=E5=8A=A0dcits=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/webapp/dcits.ico | Bin 0 -> 4286 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/webapp/dcits.ico diff --git a/src/main/webapp/dcits.ico b/src/main/webapp/dcits.ico new file mode 100644 index 0000000000000000000000000000000000000000..7d26ff0170f642dc6690804becdb052234d78e5d GIT binary patch literal 4286 zcmdT{dr(v96^|sjj}RjA3=$wbTu>#&K!;hhrb&D!nSRhQ!iImsm5=OJA4y% zv^4A7D9VKNn(gSJ#RpEJ1rV(_0iQto{0Ejbik<|aa6d#xC;XwavvbQ@ZD?xNy3q8( zlkYYIk8gy4z|rZNJ$I_lyl;}6?tS3g&@dmLlEl0gvY8#HC?h&!LU9=dZ|^kY?yB8~ zu3x|Q+-BUl`-tP=X_#{0V*g`5_riB~6;>=Iu=1su5AB7gXqJi7L_LXp|q+S(F%;w0-59-%vL z@db4me0`%BwfdE(cw+u-jXeDC7L zi#*J$Ec{{%7x~zV&nFnM*kS@lx(|Y1h`smP!G_qvqWf~O7duVRcad!hb7^tOk~#EM zHof=0P9PTRKjWg@rs#5bF*mOUpF0* zTCLPaqPr~=ega#!K6F=Y@X@q>2bqnqhz|HxGv)O zV4~?^h=`c_P~vNt<`D=7)Zf9)EphRsib_>e6DuexWIZ}M7DP+wS#CWdoP8V1r0Gsb zOi1jR6sV|B<>LLq!uz4FZUzSXflnAfAgF|_?Cg^_KfcLHP0{Xj6dFt< zbqBSTMFt9@?om=pW>Xz!Br-@togICJ2@0ZSZ9%QVT(8;mT*Dxc7yI=ll4 z3JVWm`QOQ5U!esCRKGq(bumoS($ez6YW3QmFIH-$DDNg|!6-=m!lv5VTEp>v?u)az z0-?c-^N~+}2^-cYn9It_EIx{f)wb|a>;!^eLP&7vUoTv^Ahegc+UKHTO_+y=UW09r zNMe}1YIVWAFaN=jN3%UPJdo5lZ1f7%G&KA`g6m>+9=%m(z#$UakMMAS2_AtI5e_S8Ho)lvP!;A%0S30?#BAJ%#9Vq}Mht zSbL_(DGAhSbrj~`nKu(Fa5NxX{u#w?>-100ePF>c-do94T&hWP_s}yGg=<-+xwuIA z{ddnSh-5OR$H~bWduuKD&%8pCCm=dX)?||(vROC8#r2eG!Z?20w!YH4s#Fu{DW0Du zP>&TkDIqf>yZ3j)BZRV06B!hw8*&oOn=P{%@&oP*j*fj$kY7}7ldmdc<$U4+V18GZ zFyrCFho!c?mEP;>n1H}Q{R9uik`^?AOcr(U!HZagJ=qqkuK$B87nAU;0+)Ki-)e0l4H-uYW$x*d!dfUPa8JID#s>?E$gG~Ew@foYneqM}0=FOB?HujzYlLFn!|KWWWV zJlFjgllZ)H*qbqq;;Og{>StBrcDPXPoM5xHea5VztZ=i zp@&3z>P#`JIisjxU=bBoTkHB4ejDO?xlY(>t|JtW!@2NS z><=Ij19VGT;hIPRpA(3I>j$T}Z$THg6UMmL;9p;iSp=9BV@SbA0Ni$f53v?RW)kbg G*S`V$Sf^nC literal 0 HcmV?d00001 -- Gitee From 1e8b92107497d91d44fcda764b556c77cd261377 Mon Sep 17 00:00:00 2001 From: SHENGYIN Date: Sat, 12 Dec 2020 10:43:40 +0800 Subject: [PATCH 20/30] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E5=92=8C=E9=A6=96=E9=A1=B5dcits=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/webapp/index.html | 4 ++-- src/main/webapp/login.html | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index b4916b9..9124854 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -6,8 +6,8 @@ - - + + false - true + false none diff --git a/src/main/resources/struts.xml b/src/main/resources/struts.xml index c2516f0..1722b6e 100644 --- a/src/main/resources/struts.xml +++ b/src/main/resources/struts.xml @@ -255,6 +255,16 @@ checkNameFlag + + + + + + + jsonObject + false + + diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index 19691aa..ab31a56 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -98,6 +98,13 @@ var REQUEST_URL = { CHANGE_STATUS: "data-changeStatus", UPDATE_PARAMS_DATA: "data-updateParamsData" }, + // 数据池 + DATA_POOL: { + DEL: "pool-del", + GET: "pool-get", + EDIT: "pool-edit", + LIST: "pool-list" + }, //测试报告 REPORT: { DEL: "report-del", diff --git a/src/main/webapp/resource/setting/dataPool.html b/src/main/webapp/resource/setting/dataPool.html index e69de29..57dcfae 100644 --- a/src/main/webapp/resource/setting/dataPool.html +++ b/src/main/webapp/resource/setting/dataPool.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + 数据池 + + +
    + +
    +
    +
    + + + + + + + + + +
    ID
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/resource/setting/dataPool.js b/src/main/webapp/resource/setting/dataPool.js index e69de29..1722193 100644 --- a/src/main/webapp/resource/setting/dataPool.js +++ b/src/main/webapp/resource/setting/dataPool.js @@ -0,0 +1,178 @@ +var templateParams = { + tableTheads:["池名称", "池变量", "数据类别","创建时间", "创建用户", "备注", "操作"], + btnTools:[{ + type:"success", + id:"add-object", + iconFont:"", + name:"添加数据池" + }, { + type:"danger", + size:"M", + markClass:"batch-del-object", + iconFont:"", + name:"批量删除" + }], + formControls:[ + { + edit:true, + required:false, + label:"  ID", + objText:"poolIdText", + input:[{ + hidden:true, + name:"poolId" + }] + }, + { + edit:false, + required:true, + label:"池名称", + input:[{ + name:"name" + }] + }, + { + name:"createTime", + value:new Date().Format("yyyy-MM-dd hh:mm:ss") + }, + { + name:"user.userId" + }, + { + edit:false, + label:"  备注", + textarea:[{ + name:"mark" + }] + }, + { + name:"projectInfo.projectId", + value: top.currentProjectId + } + ] + +}; + +var columnsSetting = [ + { + "data":null, + "render":function(data, type, full, meta){ + return checkboxHmtl(data.name, data.poolId, "selectDataPool"); + }}, + {"data":"poolId"},{"data":"name"}, + { + "data":"nameCount", + "render":function(data, type, full, meta){ + var context = + [{ + type:"default", + size:"M", + markClass:"show-name-count", + name:data + }]; + return btnTextTemplate(context); + } + }, + { + "data":"itemCount", + "render":function(data, type, full, meta){ + var context = + [{ + type:"default", + size:"M", + markClass:"show-item-count", + name:data + }]; + return btnTextTemplate(context); + } + }, + ellipsisData("createTime"),ellipsisData("user.realName"), + { + "data":"mark", + "className":"ellipsis", + "render":function(data, type, full, meta ){ + if (data != "" && data != null) { + return '' + data + ''; + } + return ""; + } + } + ,{ + "data":null, + "render":function (data) { + var context = [{ + title:"编辑", + markClass:"object-edit", + iconFont:"" + },{ + title:"删除", + markClass:"object-del", + iconFont:"" + }]; + return btnIconTemplate(context); + } + } +]; + +var eventList = { + ".object-edit": function () { + var data = table.row( $(this).parents('tr') ).data(); + publish.renderParams.editPage.modeFlag = 1; + publish.renderParams.editPage.objId = data.poolId; + layer_show("编辑数据池信息", editHtml, editPageWidth, editPageHeight.edit, 1); + publish.init(); + }, + ".object-del": function () { + var data = table.row( $(this).parents('tr') ).data(); + delObj("警告:确认要删除此数据池吗(可能会导致相关测试集无法正常测试)?", REQUEST_URL.DATA_POOL.DEL, data.poolId, this); + }, + "#add-object": function() { + console.log(editPageHeight) + publish.renderParams.editPage.modeFlag = 0; + layer_show("添加数据池信息", editHtml, editPageWidth, editPageHeight.add, 1); + publish.init(); + }, + ".batch-del-object": function() { + var checkboxList = $(".selectDataPool:checked"); + batchDelObjs(checkboxList, REQUEST_URL.DATA_POOL.DEL); + }, + ".show-name-count": function () { + var data = table.row($(this).parents('tr')).data(); + // currIndex = layer_show(data.projectName + "-成员管理", "projectUser.html?projectId=" + data.projectId, null, null, 2, null, function() { + // refreshTable(); + // }); + }, + ".show-item-count": function () { + var data = table.row($(this).parents('tr')).data(); + // currIndex = layer_show(data.projectName + "-成员管理", "projectUser.html?projectId=" + data.projectId, null, null, 2, null, function() { + // refreshTable(); + // }); + } +}; + +var mySetting = { + eventList:eventList, + editPage:{ + editUrl:REQUEST_URL.DATA_POOL.EDIT, + getUrl:REQUEST_URL.DATA_POOL.GET, + rules:{ + name:{ + required:true, + minlength:2, + maxlength:100 + } + } + }, + listPage:{ + listUrl:REQUEST_URL.DATA_POOL.LIST, + tableObj:".table-sort", + columnsSetting:columnsSetting, + columnsJson:[0, 8] + }, + templateParams:templateParams +}; + +$(function(){ + publish.renderParams = $.extend(true, publish.renderParams, mySetting); + publish.init(); +}); \ No newline at end of file diff --git a/update.md b/update.md index 70ff367..85c5f34 100644 --- a/update.md +++ b/update.md @@ -1,7 +1,7 @@ ### v1.1.1 #### 2020.11 -- 修复一些小问题; -- 增加shangdong和liaoning的Socket协议报文处理器; +- 修改logo和ico图表; +- 增加几个定制化的报文处理器; ### v1.1.0 -- Gitee From 8ee42d5b99c0d1d33332ba6ecbb1cc63e8e071ba Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Mon, 4 Jan 2021 14:19:22 +0800 Subject: [PATCH 26/30] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testconfig/action/DataPoolAction.java | 22 +++ .../testconfig/action/PoolDataNameAction.java | 78 ++++++++ .../testconfig/bean/PoolDataName.hbm.xml | 4 +- .../testconfig/dao/PoolDataNameDao.java | 21 +++ .../dao/impl/PoolDataNameDaoImpl.java | 18 ++ .../service/PoolDataNameService.java | 21 +++ .../service/impl/PoolDataNameServiceImpl.java | 12 ++ src/main/resources/struts.xml | 15 +- src/main/webapp/js/globalConstant.js | 10 +- src/main/webapp/resource/setting/dataPool.js | 7 +- .../webapp/resource/setting/poolDataName.html | 64 +++++++ .../webapp/resource/setting/poolDataName.js | 170 ++++++++++++++++++ 12 files changed, 434 insertions(+), 8 deletions(-) create mode 100644 src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java create mode 100644 src/main/webapp/resource/setting/poolDataName.html create mode 100644 src/main/webapp/resource/setting/poolDataName.js diff --git a/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java b/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java index 8382f4f..4b290fd 100644 --- a/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java +++ b/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java @@ -9,6 +9,8 @@ import yi.master.business.testconfig.service.DataPoolService; import yi.master.business.testconfig.service.PoolDataItemService; import yi.master.business.testconfig.service.PoolDataNameService; import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.exception.AppErrorCode; +import yi.master.exception.YiException; import yi.master.util.FrameworkUtil; import java.sql.Timestamp; @@ -64,4 +66,24 @@ public class DataPoolAction extends BaseAction { } return super.edit(); } + + /** + * 获取指定数据池的变量名称列表 + * @author xuwangcheng + * @date 2021/1/3 14:57 + * @param + * @return {@link String} + */ + public String listDataName () { + if (model.getPoolId() == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + + setData(poolDataNameService.listDataName(model.getPoolId())); + + return SUCCESS; + } + + + //////////////////////////////////////////////////////////////////////////////////////////////// } diff --git a/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java b/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java new file mode 100644 index 0000000..35a307c --- /dev/null +++ b/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java @@ -0,0 +1,78 @@ +package yi.master.business.testconfig.action; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; +import yi.master.business.base.action.BaseAction; +import yi.master.business.testconfig.bean.PoolDataName; +import yi.master.business.testconfig.service.PoolDataNameService; +import yi.master.util.FrameworkUtil; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +/** + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2020/12/30 17:58 + */ +@Controller("poolDataNameAction") +@Scope("prototype") +public class PoolDataNameAction extends BaseAction { + /** + * + */ + private static final long serialVersionUID = 1L; + + private PoolDataNameService poolDataNameService; + + private Integer poolId; + + @Autowired + public void setPoolDataNameService(PoolDataNameService poolDataNameService) { + super.setBaseService(poolDataNameService); + this.poolDataNameService = poolDataNameService; + } + + @Override + public String[] prepareList() { + List conditions = new ArrayList(); + if (this.poolId != null) { + conditions.add("t.dataPool.poolId=" + this.poolId); + } + + this.filterCondition = conditions.toArray(new String[0]); + return this.filterCondition; + } + + @Override + public String edit() { + if (this.model.getId() == null) { + model.setCreateTime(new Timestamp(System.currentTimeMillis())); + model.setUser(FrameworkUtil.getLoginUser()); + } + return super.edit(); + } + + /** + * 判断接口名重复性 + * 新增或者修改状态下均可用 + */ + @Override + public void checkObjectName() { + PoolDataName info = poolDataNameService.findByName(model.getName(), poolId); + checkNameFlag = (info != null && !info.getId().equals(model.getId())) ? "重复的接口名" : "true"; + + if (model.getId() == null) { + checkNameFlag = (info == null) ? "true" : "重复的接口名"; + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + + public void setPoolId(Integer poolId) { + this.poolId = poolId; + } +} diff --git a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml index 0a41921..1541ea8 100644 --- a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml +++ b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml @@ -10,13 +10,13 @@ - + - + diff --git a/src/main/java/yi/master/business/testconfig/dao/PoolDataNameDao.java b/src/main/java/yi/master/business/testconfig/dao/PoolDataNameDao.java index 3512034..feb0025 100644 --- a/src/main/java/yi/master/business/testconfig/dao/PoolDataNameDao.java +++ b/src/main/java/yi/master/business/testconfig/dao/PoolDataNameDao.java @@ -3,6 +3,8 @@ package yi.master.business.testconfig.dao; import yi.master.business.base.dao.BaseDao; import yi.master.business.testconfig.bean.PoolDataName; +import java.util.List; + /** * @author xuwangcheng * @version 1.0.0 @@ -10,4 +12,23 @@ import yi.master.business.testconfig.bean.PoolDataName; * @date 2020/12/30 14:14 */ public interface PoolDataNameDao extends BaseDao { + + /** + * 获取指定资源池的数据变量名 + * @author xuwangcheng + * @date 2021/1/3 14:50 + * @param poolId poolId + * @return {@link List} + */ + List listDataName (Integer poolId); + + /** + * 根据名称查询池变量 + * @author xuwangcheng + * @date 2021/1/3 15:28 + * @param name name + * @param poolId poolId + * @return {@link PoolDataName} + */ + PoolDataName findByName (String name, Integer poolId); } diff --git a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataNameDaoImpl.java b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataNameDaoImpl.java index 013fe6e..2948a37 100644 --- a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataNameDaoImpl.java +++ b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataNameDaoImpl.java @@ -5,6 +5,8 @@ import yi.master.business.base.dao.impl.BaseDaoImpl; import yi.master.business.testconfig.bean.PoolDataName; import yi.master.business.testconfig.dao.PoolDataNameDao; +import java.util.List; + /** * @author xuwangcheng * @version 1.0.0 @@ -13,4 +15,20 @@ import yi.master.business.testconfig.dao.PoolDataNameDao; */ @Repository("poolDataNameDao") public class PoolDataNameDaoImpl extends BaseDaoImpl implements PoolDataNameDao { + @Override + public List listDataName(Integer poolId) { + String hql = "From PoolDataName t where t.dataPool.poolId=:poolId"; + return getSession().createQuery(hql) + .setInteger("poolId", poolId) + .setCacheable(true) + .list(); + } + + @Override + public PoolDataName findByName(String name, Integer poolId) { + String hql = "From PoolDataName t where t.name=:name and t.dataPool.poolId=:poolId"; + return (PoolDataName) getSession().createQuery(hql) + .setString("name", name).setInteger("poolId", poolId) + .setCacheable(true).uniqueResult(); + } } diff --git a/src/main/java/yi/master/business/testconfig/service/PoolDataNameService.java b/src/main/java/yi/master/business/testconfig/service/PoolDataNameService.java index 3f20ae2..8f9fed8 100644 --- a/src/main/java/yi/master/business/testconfig/service/PoolDataNameService.java +++ b/src/main/java/yi/master/business/testconfig/service/PoolDataNameService.java @@ -3,6 +3,8 @@ package yi.master.business.testconfig.service; import yi.master.business.base.service.BaseService; import yi.master.business.testconfig.bean.PoolDataName; +import java.util.List; + /** * @author xuwangcheng * @version 1.0.0 @@ -10,4 +12,23 @@ import yi.master.business.testconfig.bean.PoolDataName; * @date 2020/12/30 16:55 */ public interface PoolDataNameService extends BaseService { + + /** + * 获取指定资源池的数据变量名 + * @author xuwangcheng + * @date 2021/1/3 14:50 + * @param poolId poolId + * @return {@link List} + */ + List listDataName (Integer poolId); + + /** + * 根据名称查询池变量 + * @author xuwangcheng + * @date 2021/1/3 15:28 + * @param name name + * @param poolId poolId + * @return {@link PoolDataName} + */ + PoolDataName findByName (String name, Integer poolId); } diff --git a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataNameServiceImpl.java b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataNameServiceImpl.java index aa55217..e64984a 100644 --- a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataNameServiceImpl.java +++ b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataNameServiceImpl.java @@ -7,6 +7,8 @@ import yi.master.business.testconfig.bean.PoolDataName; import yi.master.business.testconfig.dao.PoolDataNameDao; import yi.master.business.testconfig.service.PoolDataNameService; +import java.util.List; + /** * @author xuwangcheng * @version 1.0.0 @@ -23,4 +25,14 @@ public class PoolDataNameServiceImpl extends BaseServiceImpl imple super.setBaseDao(poolDataNameDao); this.poolDataNameDao = poolDataNameDao; } + + @Override + public List listDataName(Integer poolId) { + return poolDataNameDao.listDataName(poolId); + } + + @Override + public PoolDataName findByName(String name, Integer poolId) { + return poolDataNameDao.findByName(name, poolId); + } } diff --git a/src/main/resources/struts.xml b/src/main/resources/struts.xml index 1722b6e..394e36e 100644 --- a/src/main/resources/struts.xml +++ b/src/main/resources/struts.xml @@ -265,7 +265,20 @@ false
    - + + + + + + + jsonObject + false + + + checkNameFlag + + + diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index ab31a56..bfd2157 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -98,13 +98,21 @@ var REQUEST_URL = { CHANGE_STATUS: "data-changeStatus", UPDATE_PARAMS_DATA: "data-updateParamsData" }, - // 数据池 + //数据池 DATA_POOL: { DEL: "pool-del", GET: "pool-get", EDIT: "pool-edit", LIST: "pool-list" }, + //数据池变量 + POOL_DATA_NAME: { + DEL: "poolDataName-del", + GET: "poolDataName-get", + EDIT: "poolDataName-edit", + LIST_ALL: "poolDataName-listAll", + CHECK_NAME: "poolDataName-checkName" + }, //测试报告 REPORT: { DEL: "report-del", diff --git a/src/main/webapp/resource/setting/dataPool.js b/src/main/webapp/resource/setting/dataPool.js index 1722193..7a13788 100644 --- a/src/main/webapp/resource/setting/dataPool.js +++ b/src/main/webapp/resource/setting/dataPool.js @@ -127,7 +127,6 @@ var eventList = { delObj("警告:确认要删除此数据池吗(可能会导致相关测试集无法正常测试)?", REQUEST_URL.DATA_POOL.DEL, data.poolId, this); }, "#add-object": function() { - console.log(editPageHeight) publish.renderParams.editPage.modeFlag = 0; layer_show("添加数据池信息", editHtml, editPageWidth, editPageHeight.add, 1); publish.init(); @@ -138,9 +137,9 @@ var eventList = { }, ".show-name-count": function () { var data = table.row($(this).parents('tr')).data(); - // currIndex = layer_show(data.projectName + "-成员管理", "projectUser.html?projectId=" + data.projectId, null, null, 2, null, function() { - // refreshTable(); - // }); + currIndex = layer_show(data.name + "-池变量管理", "poolDataName.html?poolId=" + data.poolId, null, null, 2, null, function() { + refreshTable(); + }); }, ".show-item-count": function () { var data = table.row($(this).parents('tr')).data(); diff --git a/src/main/webapp/resource/setting/poolDataName.html b/src/main/webapp/resource/setting/poolDataName.html new file mode 100644 index 0000000..c27257f --- /dev/null +++ b/src/main/webapp/resource/setting/poolDataName.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + 数据池变量管理 + + +
    + +
    +
    +
    + + + + + + + + + +
    ID
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/resource/setting/poolDataName.js b/src/main/webapp/resource/setting/poolDataName.js new file mode 100644 index 0000000..703dd86 --- /dev/null +++ b/src/main/webapp/resource/setting/poolDataName.js @@ -0,0 +1,170 @@ +var poolId; + +var templateParams = { + tableTheads:["池名称", "池变量名称", "创建时间", "创建用户", "备注", "操作"], + btnTools:[{ + type:"success", + id:"add-object", + iconFont:"", + name:"添加池变量" + }, { + type:"danger", + size:"M", + markClass:"batch-del-object", + iconFont:"", + name:"批量删除" + }], + formControls:[ + { + edit:true, + required:false, + label:"  ID", + objText:"idText", + input:[{ + hidden:true, + name:"id" + }] + }, + { + edit:false, + required:true, + label:"池变量名称", + input:[{ + name:"name" + }] + }, + { + name:"dataPool.poolId" + }, + { + name:"createTime", + value:new Date().Format("yyyy-MM-dd hh:mm:ss") + }, + { + name:"user.userId" + }, + { + edit:false, + label:"  备注", + textarea:[{ + name:"mark" + }] + } + ] + +}; + +var columnsSetting = [ + { + "data":null, + "render":function(data, type, full, meta){ + return checkboxHmtl(data.name, data.id, "selectDataPoolName"); + }}, + {"data":"id"}, + ellipsisData("dataPool.name"), + ellipsisData("name"), + ellipsisData("createTime"),ellipsisData("user.realName"), + { + "data":"mark", + "className":"ellipsis", + "render":function(data, type, full, meta ){ + if (data != "" && data != null) { + return '' + data + ''; + } + return ""; + } + } + ,{ + "data":null, + "render":function (data) { + var context = [{ + title:"编辑", + markClass:"object-edit", + iconFont:"" + },{ + title:"删除", + markClass:"object-del", + iconFont:"" + }]; + return btnIconTemplate(context); + } + } +]; + +var eventList = { + ".object-edit": function () { + var data = table.row( $(this).parents('tr') ).data(); + publish.renderParams.editPage.modeFlag = 1; + publish.renderParams.editPage.objId = data.id; + layer_show("编辑池变量信息", editHtml, editPageWidth, editPageHeight.edit, 1); + publish.init(); + }, + ".object-del": function () { + var data = table.row( $(this).parents('tr') ).data(); + delObj("警告:确认要删除此池变量吗(会同时删除数据池下不同数据类别中的该变量值)?", REQUEST_URL.POOL_DATA_NAME.DEL, data.id, this); + }, + "#add-object": function() { + publish.renderParams.editPage.modeFlag = 0; + layer_show("添加池变量信息", editHtml, editPageWidth, editPageHeight.add, 1); + publish.init(); + }, + ".batch-del-object": function() { + var checkboxList = $(".selectDataPoolName:checked"); + batchDelObjs(checkboxList, REQUEST_URL.POOL_DATA_NAME.DEL); + } +}; + +var mySetting = { + eventList:eventList, + templateCallBack:function(df){ + poolId = GetQueryString("poolId"); + publish.renderParams.listPage.listUrl = REQUEST_URL.POOL_DATA_NAME.LIST_ALL + "?poolId=" + poolId; + df.resolve(); + }, + editPage:{ + editUrl:REQUEST_URL.POOL_DATA_NAME.EDIT, + getUrl:REQUEST_URL.POOL_DATA_NAME.GET, + beforeInit:function(df){ + $("#dataPool\\.poolId").val(poolId); + + df.resolve(); + }, + rules:{ + name:{ + required:true, + minlength:2, + maxlength:100, + remote:{ + url:REQUEST_URL.POOL_DATA_NAME.CHECK_NAME, + type:"post", + dataType: "json", + data: { + name: function() { + return $("#name").val(); + }, + poolId:function(){ + return poolId; + }, + id:function () { + return $("#id").val() + } + }} + } + } + }, + listPage:{ + listUrl:REQUEST_URL.POOL_DATA_NAME.LIST, + tableObj:".table-sort", + columnsSetting:columnsSetting, + columnsJson:[7], + dtOtherSetting:{ + serverSide:false + } + }, + templateParams:templateParams +}; + +$(function(){ + publish.renderParams = $.extend(true, publish.renderParams, mySetting); + publish.init(); +}); \ No newline at end of file -- Gitee From 8765a50a4a9329ab1c158bc23aa1b7a793adfbc2 Mon Sep 17 00:00:00 2001 From: xuwangcheng Date: Wed, 13 Jan 2021 17:33:53 +0800 Subject: [PATCH 27/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=ACv1.1.?= =?UTF-8?q?1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/action/AutoTestAction.java | 10 +- .../business/message/bean/ComplexScene.java | 10 +- .../business/message/bean/TestResult.hbm.xml | 3 + .../business/message/bean/TestResult.java | 38 +- .../testconfig/action/DataPoolAction.java | 25 + .../testconfig/action/PoolDataItemAction.java | 260 +++++++++ .../testconfig/action/PoolDataNameAction.java | 59 +- .../business/testconfig/bean/DataPool.java | 6 + .../testconfig/bean/GlobalVariable.java | 14 +- .../testconfig/bean/PoolDataItem.hbm.xml | 20 +- .../testconfig/bean/PoolDataItem.java | 101 ++++ .../testconfig/bean/PoolDataName.hbm.xml | 9 + .../testconfig/bean/PoolDataName.java | 53 ++ .../testconfig/bean/TestConfig.hbm.xml | 9 +- .../business/testconfig/bean/TestConfig.java | 41 +- .../testconfig/dao/PoolDataItemDao.java | 31 + .../testconfig/dao/PoolDataValueDao.java | 21 + .../dao/impl/PoolDataItemDaoImpl.java | 33 ++ .../dao/impl/PoolDataValueDaoImpl.java | 18 + .../testconfig/dto/ItemNameValueDto.java | 60 ++ .../service/PoolDataItemService.java | 40 ++ .../service/PoolDataValueService.java | 11 + .../service/impl/PoolDataItemServiceImpl.java | 128 +++++ .../impl/PoolDataValueServiceImpl.java | 21 + .../service/impl/TestConfigServiceImpl.java | 10 +- .../java/yi/master/constant/SystemConsts.java | 2 +- .../message/protocol/HTTPTestClient.java | 3 + .../message/test/MessageAutoTest.java | 255 ++++++--- .../message/test/TestMessageScene.java | 34 +- .../yi/master/exception/AppErrorCode.java | 3 +- .../java/yi/master/exception/YiException.java | 6 + .../yi/master/listener/VersionUpdateUtil.java | 1 + .../java/yi/master/util/PracticalUtils.java | 61 +- .../java/yi/master/util/cache/CacheUtil.java | 7 +- .../util/excel/ExcelPoolDataTemplate.java | 259 +++++++++ .../java/yi/master/util/message/JsonUtil.java | 7 +- src/main/resources/struts.xml | 13 + src/main/resources/update/1.1.1 | 19 + src/main/webapp/index.js | 1 + src/main/webapp/js/dcits.js | 1 + src/main/webapp/js/globalConstant.js | 24 +- src/main/webapp/libs/h-ui/css/H-ui.min.css | 2 +- .../reportHtml/offlineReportTemplateNew.xml | 29 +- .../resource/advanced/interfaceProbe.js | 30 +- src/main/webapp/resource/advanced/mockTest.js | 28 +- src/main/webapp/resource/message/autoTask.js | 26 +- src/main/webapp/resource/message/interface.js | 19 +- .../webapp/resource/message/reportView.html | 8 +- .../webapp/resource/message/reportView.js | 15 +- src/main/webapp/resource/message/setScene.js | 80 ++- src/main/webapp/resource/message/testData.js | 41 +- src/main/webapp/resource/setting/dataPool.js | 15 +- .../webapp/resource/setting/poolDataItem.html | 67 +++ .../webapp/resource/setting/poolDataItem.js | 528 ++++++++++++++++++ .../webapp/resource/setting/poolDataName.js | 63 ++- .../resource/template/customTemplate.htm | 275 +++++---- .../template/showDataPoolUseSample.htm | 24 + update.md | 5 +- 58 files changed, 2717 insertions(+), 265 deletions(-) create mode 100644 src/main/java/yi/master/business/testconfig/action/PoolDataItemAction.java create mode 100644 src/main/java/yi/master/business/testconfig/dto/ItemNameValueDto.java create mode 100644 src/main/java/yi/master/util/excel/ExcelPoolDataTemplate.java create mode 100644 src/main/resources/update/1.1.1 create mode 100644 src/main/webapp/resource/setting/poolDataItem.html create mode 100644 src/main/webapp/resource/setting/poolDataItem.js create mode 100644 src/main/webapp/resource/template/showDataPoolUseSample.htm diff --git a/src/main/java/yi/master/business/message/action/AutoTestAction.java b/src/main/java/yi/master/business/message/action/AutoTestAction.java index f0c0831..3e17db6 100644 --- a/src/main/java/yi/master/business/message/action/AutoTestAction.java +++ b/src/main/java/yi/master/business/message/action/AutoTestAction.java @@ -121,7 +121,7 @@ public class AutoTestAction extends ActionSupport implements ModelDriven testObjects = autoTest.packageRequestObject(task.getScene(), config, task.getSystem()); + Set testObjects = autoTest.packageRequestObject(task.getScene(), config, task.getSystem(), null); if (testObjects.size() == 0) { throw new YiException(AppErrorCode.AUTO_TEST_BUSINESS_SYSTEM_NOT_EXIST, task.getSystem().getSystemName()); @@ -256,9 +256,13 @@ public class AutoTestAction extends ActionSupport implements ModelDriven scenes = new ArrayList(); + /** + * 是否已经解析了测试场景? + */ + private boolean hasPackageScenes; public ComplexScene() { super(); @@ -108,7 +112,6 @@ public class ComplexScene implements Serializable { try { complexSceneConfigs = PracticalUtils.getComplexSceneConfigs(configInfo); } catch (Exception e) { - LOGGER.error("无法转换该组合场景的配置信息:" + configInfo, e); } } else { @@ -185,7 +188,9 @@ public class ComplexScene implements Serializable { @SuppressWarnings({ "unchecked", "rawtypes" }) public List setScenes(MessageSceneService service) { - + if (this.hasPackageScenes) { + return scenes; + } Map configs = PracticalUtils.getComplexSceneConfigs(this.configInfo); if (configs != null && configs.size() != 0) { @@ -208,6 +213,7 @@ public class ComplexScene implements Serializable { return aId - bId; } }); + this.hasPackageScenes = true; return scenes; } diff --git a/src/main/java/yi/master/business/message/bean/TestResult.hbm.xml b/src/main/java/yi/master/business/message/bean/TestResult.hbm.xml index ea696f6..51e3b81 100644 --- a/src/main/java/yi/master/business/message/bean/TestResult.hbm.xml +++ b/src/main/java/yi/master/business/message/bean/TestResult.hbm.xml @@ -16,6 +16,9 @@ + + + diff --git a/src/main/java/yi/master/business/message/bean/TestResult.java b/src/main/java/yi/master/business/message/bean/TestResult.java index 92e3821..78cebdf 100644 --- a/src/main/java/yi/master/business/message/bean/TestResult.java +++ b/src/main/java/yi/master/business/message/bean/TestResult.java @@ -4,6 +4,7 @@ import org.apache.struts2.json.annotations.JSON; import yi.master.annotation.FieldNameMapper; import yi.master.business.advanced.bean.InterfaceProbe; import yi.master.business.advanced.bean.config.probe.ProbeConfig; +import yi.master.business.testconfig.bean.PoolDataItem; import java.io.Serializable; import java.sql.Timestamp; @@ -141,6 +142,14 @@ public class TestResult implements Serializable, Comparable { * 格式类型 */ private String messageType; + + /** + * 对应数据池类别 + */ + private PoolDataItem poolDataItem; + + private String poolName; + private String poolItemName; private String threadName; @@ -175,8 +184,33 @@ public class TestResult implements Serializable, Comparable { public String getThreadName() { return threadName; } - - public void setHeaders(String headers) { + + public void setPoolItemName(String poolItemName) { + this.poolItemName = poolItemName; + } + + public void setPoolName(String poolName) { + this.poolName = poolName; + } + + public String getPoolItemName() { + return (this.poolDataItem == null || this.poolDataItem.getDataPool() == null) ? "" : this.poolDataItem.getName(); + } + + public String getPoolName() { + return (this.poolDataItem == null || this.poolDataItem.getDataPool() == null) ? "" : this.poolDataItem.getDataPool().getName(); + } + + public void setPoolDataItem(PoolDataItem poolDataItem) { + this.poolDataItem = poolDataItem; + } + + @JSON(serialize = false) + public PoolDataItem getPoolDataItem() { + return poolDataItem; + } + + public void setHeaders(String headers) { this.headers = headers; } diff --git a/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java b/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java index 4b290fd..e64bb17 100644 --- a/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java +++ b/src/main/java/yi/master/business/testconfig/action/DataPoolAction.java @@ -1,14 +1,17 @@ package yi.master.business.testconfig.action; +import net.sf.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import yi.master.business.base.action.BaseAction; import yi.master.business.testconfig.bean.DataPool; +import yi.master.business.testconfig.bean.PoolDataName; import yi.master.business.testconfig.service.DataPoolService; import yi.master.business.testconfig.service.PoolDataItemService; import yi.master.business.testconfig.service.PoolDataNameService; import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.coretest.message.parse.JSONMessageParse; import yi.master.exception.AppErrorCode; import yi.master.exception.YiException; import yi.master.util.FrameworkUtil; @@ -84,6 +87,28 @@ public class DataPoolAction extends BaseAction { return SUCCESS; } + /** + * json数据示例 + * @author xuwangcheng + * @date 2021/1/7 12:16 + * @param + * @return {@link String} + */ + public String showJsonData () { + DataPool dataPool = dataPoolService.get(model.getPoolId()); + if (dataPool == null) { + throw new YiException("信息不存在!"); + } + + JSONObject jsonObject = new JSONObject(); + for (PoolDataName name:dataPool.getDataNames()) { + jsonObject.put(name.getName(), name.getDefaultValue() == null ? "" : name.getDefaultValue()); + } + + setData(JSONMessageParse.getInstance().messageFormatBeautify(jsonObject.toString())); + return SUCCESS; + } + //////////////////////////////////////////////////////////////////////////////////////////////// } diff --git a/src/main/java/yi/master/business/testconfig/action/PoolDataItemAction.java b/src/main/java/yi/master/business/testconfig/action/PoolDataItemAction.java new file mode 100644 index 0000000..f56ae13 --- /dev/null +++ b/src/main/java/yi/master/business/testconfig/action/PoolDataItemAction.java @@ -0,0 +1,260 @@ +package yi.master.business.testconfig.action; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import net.sf.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; +import yi.master.business.base.action.BaseAction; +import yi.master.business.testconfig.bean.DataPool; +import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.service.DataPoolService; +import yi.master.business.testconfig.service.PoolDataItemService; +import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.constant.SystemConsts; +import yi.master.exception.AppErrorCode; +import yi.master.exception.YiException; +import yi.master.util.FrameworkUtil; +import yi.master.util.excel.ExcelPoolDataTemplate; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2020/12/30 17:58 + */ +@Controller("poolDataItemAction") +@Scope("prototype") +public class PoolDataItemAction extends BaseAction { + /** + * + */ + private static final long serialVersionUID = 1L; + + private PoolDataItemService poolDataItemService; + + @Autowired + private PoolDataValueService poolDataValueService; + @Autowired + private DataPoolService dataPoolService; + + private Integer poolId; + + private String exportItemIds; + + private String path; + + @Autowired + public void setPoolDataItemService(PoolDataItemService poolDataItemService) { + super.setBaseService(poolDataItemService); + this.poolDataItemService = poolDataItemService; + } + + @Override + public String[] prepareList() { + List conditions = new ArrayList(); + if (this.poolId != null) { + conditions.add("t.dataPool.poolId=" + this.poolId); + } + + this.filterCondition = conditions.toArray(new String[0]); + return this.filterCondition; + } + + @Override + public String edit() { + //判断接口名是否重复 + this.poolId = this.model.getDataPool().getPoolId(); + checkObjectName(); + if (!checkNameFlag.equals(SystemConsts.DefaultBooleanIdentify.TRUE.getString())) { + throw new YiException(AppErrorCode.NAME_EXIST); + } + if (this.model.getItemId() == null) { + model.setCreateTime(new Timestamp(System.currentTimeMillis())); + model.setUser(FrameworkUtil.getLoginUser()); + } + if (this.model.getMessageScene().getMessageSceneId() == null) { + this.model.setMessageScene(null); + } + if (this.model.getSceneSystem().getSystemId() == null) { + this.model.setSceneSystem(null); + } + + return super.edit(); + } + + + /** + * 获取该类别的值 + * @author xuwangcheng + * @date 2021/1/4 19:18 + * @param + * @return {@link String} + */ + public String listNameValue () { + if (this.poolId == null || this.model.getItemId() == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + setData(poolDataItemService.queryItemNameValue(poolId, this.model.getItemId())); + return SUCCESS; + } + + /** + * 保存该类别的值 + * @author xuwangcheng + * @date 2021/1/4 20:15 + * @param + * @return {@link String} + */ + public String saveNameValue () { + Map params = FrameworkUtil.getParametersMap(); + for (String key:params.keySet()) { + if ("itemId".equals(key) || !NumberUtil.isInteger(key)) { + continue; + } + + poolDataValueService.updateItemValue(model.getItemId(), Integer.valueOf(key), ((String[])params.get(key))[0].toString()); + } + return SUCCESS; + } + + /** + * 导出导入模板 + * @author xuwangcheng + * @date 2021/1/6 11:56 + * @param + * @return {@link String} + */ + public String exportValueTemplate () { + if (poolId == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + + DataPool dataPool = dataPoolService.get(poolId); + if (dataPool == null) { + throw new YiException("数据池信息不存在"); + } + if (dataPool.getItemCount() == 0 || dataPool.getNameCount() == 0) { + throw new YiException("请先添加数据池变量和数据池类别"); + } + + String path = ExcelPoolDataTemplate.exportDocument(dataPool, CollUtil.newArrayList(dataPool.getDataNames()) + , CollUtil.newArrayList(dataPool.getDataItems())); + if (StrUtil.isBlank(path)) { + throw new YiException("导出失败"); + } + + setData(path); + + return SUCCESS; + } + + + /** + * 导入文件设置数据值 + * @author xuwangcheng + * @date 2021/1/6 14:25 + * @param + * @return {@link String} + */ + public String importItemValue () { + ExcelPoolDataTemplate.importItemValues(poolId, path); + + return SUCCESS; + } + + + /** + * 批量新增 + * @author xuwangcheng + * @date 2021/1/6 18:04 + * @param + * @return {@link String} + */ + public String batchAdd () { + if (StrUtil.isBlank(model.getName()) || poolId == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + + List names = CollUtil.newArrayList(model.getName().split("\\n+")); + List existNames = CollUtil.newArrayList(); + int successCount = 0; + for (String name:names) { + if (StrUtil.isBlank(name)) { + continue; + } + if (poolDataItemService.findByName(name, poolId) == null) { + PoolDataItem poolDataItem = new PoolDataItem(); + poolDataItem.setUser(FrameworkUtil.getLoginUser()); + poolDataItem.setCreateTime(new Timestamp(System.currentTimeMillis())); + poolDataItem.setDataPool(new DataPool(poolId)); + poolDataItem.setName(name); + poolDataItem.setMark(name); + poolDataItemService.save(poolDataItem); + successCount++; + } else { + existNames.add(name); + } + } + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("existNames", existNames); + jsonObject.put("successCount", successCount); + setData(jsonObject); + + return SUCCESS; + } + + + /** + * 判断名称重复性 + * 新增或者修改状态下均可用 + */ + @Override + public void checkObjectName() { + PoolDataItem info = poolDataItemService.findByName(model.getName(), poolId); + checkNameFlag = (info != null && !info.getItemId().equals(model.getItemId())) ? "重复的名称" : "true"; + + if (model.getItemId() == null) { + checkNameFlag = (info == null) ? "true" : "重复的名称"; + } + } + + /** + * 通过请求更新数据池值 + * @author xuwangcheng + * @date 2021/1/7 15:56 + * @param + * @return {@link String} + */ + public String updateValueByRequest () { + if (model.getItemId() == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + + poolDataItemService.updateItemValueByRequest(model.getItemId()); + + return SUCCESS; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + + public void setPoolId(Integer poolId) { + this.poolId = poolId; + } + + public void setExportItemIds(String exportItemIds) { + this.exportItemIds = exportItemIds; + } + + public void setPath(String path) { + this.path = path; + } +} diff --git a/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java b/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java index 35a307c..ec36b5b 100644 --- a/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java +++ b/src/main/java/yi/master/business/testconfig/action/PoolDataNameAction.java @@ -1,11 +1,18 @@ package yi.master.business.testconfig.action; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import net.sf.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import yi.master.business.base.action.BaseAction; +import yi.master.business.testconfig.bean.DataPool; import yi.master.business.testconfig.bean.PoolDataName; import yi.master.business.testconfig.service.PoolDataNameService; +import yi.master.constant.SystemConsts; +import yi.master.exception.AppErrorCode; +import yi.master.exception.YiException; import yi.master.util.FrameworkUtil; import java.sql.Timestamp; @@ -49,6 +56,12 @@ public class PoolDataNameAction extends BaseAction { @Override public String edit() { + //判断接口名是否重复 + this.poolId = this.model.getDataPool().getPoolId(); + checkObjectName(); + if (!checkNameFlag.equals(SystemConsts.DefaultBooleanIdentify.TRUE.getString())) { + throw new YiException(AppErrorCode.NAME_EXIST); + } if (this.model.getId() == null) { model.setCreateTime(new Timestamp(System.currentTimeMillis())); model.setUser(FrameworkUtil.getLoginUser()); @@ -63,13 +76,55 @@ public class PoolDataNameAction extends BaseAction { @Override public void checkObjectName() { PoolDataName info = poolDataNameService.findByName(model.getName(), poolId); - checkNameFlag = (info != null && !info.getId().equals(model.getId())) ? "重复的接口名" : "true"; + checkNameFlag = (info != null && !info.getId().equals(model.getId())) ? "重复的名称" : "true"; if (model.getId() == null) { - checkNameFlag = (info == null) ? "true" : "重复的接口名"; + checkNameFlag = (info == null) ? "true" : "重复的名称"; } } + + /** + * 批量新增 + * @author xuwangcheng + * @date 2021/1/6 18:04 + * @param + * @return {@link String} + */ + public String batchAdd () { + if (StrUtil.isBlank(model.getName()) || poolId == null) { + throw new YiException(AppErrorCode.MISS_PARAM); + } + + List names = CollUtil.newArrayList(model.getName().split("\\n+")); + List existNames = CollUtil.newArrayList(); + int successCount = 0; + for (String name:names) { + if (StrUtil.isBlank(name)) { + continue; + } + if (poolDataNameService.findByName(name, poolId) == null) { + PoolDataName poolDataName = new PoolDataName(); + poolDataName.setUser(FrameworkUtil.getLoginUser()); + poolDataName.setCreateTime(new Timestamp(System.currentTimeMillis())); + poolDataName.setDataPool(new DataPool(poolId)); + poolDataName.setName(name); + poolDataName.setMark(name); + poolDataNameService.save(poolDataName); + successCount++; + } else { + existNames.add(name); + } + } + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("existNames", existNames); + jsonObject.put("successCount", successCount); + setData(jsonObject); + + return SUCCESS; + } + //////////////////////////////////////////////////////////////////////////////////////////////// public void setPoolId(Integer poolId) { diff --git a/src/main/java/yi/master/business/testconfig/bean/DataPool.java b/src/main/java/yi/master/business/testconfig/bean/DataPool.java index cc420f8..9e2b988 100644 --- a/src/main/java/yi/master/business/testconfig/bean/DataPool.java +++ b/src/main/java/yi/master/business/testconfig/bean/DataPool.java @@ -60,6 +60,12 @@ public class DataPool implements Serializable { @FieldNameMapper(fieldPath = "size(dataItems)", ifSearch = false) private Integer itemCount; + public DataPool(Integer poolId) { + this.poolId = poolId; + } + + public DataPool() { + } public Integer getNameCount() { return this.dataNames.size(); diff --git a/src/main/java/yi/master/business/testconfig/bean/GlobalVariable.java b/src/main/java/yi/master/business/testconfig/bean/GlobalVariable.java index 19002c9..8e3a7ef 100644 --- a/src/main/java/yi/master/business/testconfig/bean/GlobalVariable.java +++ b/src/main/java/yi/master/business/testconfig/bean/GlobalVariable.java @@ -311,7 +311,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.currentTimestamp.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -327,7 +327,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.datetime.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -344,7 +344,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.randomNum.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -358,7 +358,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.randomString.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -371,7 +371,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.uuid.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -383,7 +383,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.dynamicInterface.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; @@ -397,7 +397,7 @@ public class GlobalVariable implements Serializable { } if (GlobalVariableType.dbSql.name().equalsIgnoreCase(this.variableType)) { - if (this.expiryDate.getTime() > System.currentTimeMillis() + if (this.expiryDate != null && this.expiryDate.getTime() > System.currentTimeMillis() && StringUtils.isNotBlank(this.lastCreateValue) && !forceCreate) { return this.lastCreateValue; diff --git a/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.hbm.xml b/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.hbm.xml index a49943c..c58e8c7 100644 --- a/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.hbm.xml +++ b/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.hbm.xml @@ -16,13 +16,31 @@ + + + + + + + + + + + + + + + + + + - + diff --git a/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.java b/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.java index 922d8f9..78f4cfb 100644 --- a/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.java +++ b/src/main/java/yi/master/business/testconfig/bean/PoolDataItem.java @@ -1,6 +1,8 @@ package yi.master.business.testconfig.bean; import org.apache.struts2.json.annotations.JSON; +import yi.master.annotation.FieldNameMapper; +import yi.master.business.message.bean.MessageScene; import yi.master.business.user.bean.User; import java.io.Serializable; @@ -42,11 +44,110 @@ public class PoolDataItem implements Serializable { * 创建时间 */ private Timestamp createTime; + + /** + * 通过接口获取,接口必须为get请求,且返回json + */ + private String requestUrl; + + /** + * 关联测试场景 + */ + private MessageScene messageScene; + + /** + * 关联测试场景使用的测试环境 + */ + private BusinessSystem sceneSystem; + + /** + * 优先使用测试场景获取数据 + */ + private String useMessageScene; + /** * 类别对应数据值 */ private Set dataValues = new HashSet<>(); + /** + * 已设置的值数量 + */ + @FieldNameMapper(fieldPath = "size(dataValues)", ifSearch = false) + private Integer valueCount; + + /** + * 使用前自动更新数据,前提是必须配置了requestUrl或者messageScene + */ + private String beforeUseAutoUpdate; + + /** + * 请求返回数据的指定JSON_PATH + */ + private String responseDataJsonPath; + + public PoolDataItem() { + } + + public PoolDataItem(Integer itemId) { + this.itemId = itemId; + } + + public void setResponseDataJsonPath(String responseDataJsonPath) { + this.responseDataJsonPath = responseDataJsonPath; + } + + public String getResponseDataJsonPath() { + return responseDataJsonPath; + } + + public void setBeforeUseAutoUpdate(String beforeUseAutoUpdate) { + this.beforeUseAutoUpdate = beforeUseAutoUpdate; + } + + public String getBeforeUseAutoUpdate() { + return beforeUseAutoUpdate; + } + + public void setSceneSystem(BusinessSystem sceneSystem) { + this.sceneSystem = sceneSystem; + } + + public BusinessSystem getSceneSystem() { + return sceneSystem; + } + + public void setMessageScene(MessageScene messageScene) { + this.messageScene = messageScene; + } + + public MessageScene getMessageScene() { + return messageScene; + } + + public String getUseMessageScene() { + return useMessageScene; + } + + public void setUseMessageScene(String useMessageScene) { + this.useMessageScene = useMessageScene; + } + + public void setRequestUrl(String requestUrl) { + this.requestUrl = requestUrl; + } + + public String getRequestUrl() { + return requestUrl; + } + + public void setValueCount(Integer valueCount) { + this.valueCount = valueCount; + } + + public Integer getValueCount() { + return this.dataValues.size(); + } public Integer getItemId() { return itemId; diff --git a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml index 1541ea8..6a61bd7 100644 --- a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml +++ b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.hbm.xml @@ -13,6 +13,9 @@ + + + @@ -22,5 +25,11 @@ + + + + + + diff --git a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.java b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.java index c0bf35a..f0869fa 100644 --- a/src/main/java/yi/master/business/testconfig/bean/PoolDataName.java +++ b/src/main/java/yi/master/business/testconfig/bean/PoolDataName.java @@ -5,6 +5,11 @@ import yi.master.business.user.bean.User; import java.io.Serializable; import java.sql.Timestamp; +import java.util.HashSet; +import java.util.Set; + +import static yi.master.constant.GlobalVariableConstant.USE_VARIABLE_LEFT_BOUNDARY; +import static yi.master.constant.GlobalVariableConstant.USE_VARIABLE_RIGHT_BOUNDARY; /** * 数据池数据name @@ -27,6 +32,12 @@ public class PoolDataName implements Serializable { * 名称 */ private String name; + + /** + * 使用时的key + */ + private String useKey; + /** * 备注 */ @@ -40,6 +51,48 @@ public class PoolDataName implements Serializable { */ private Timestamp createTime; + /** + * 默认值 + */ + private String defaultValue; + + /** + * 类别对应数据值 + */ + private Set dataValues = new HashSet<>(); + + public PoolDataName() { + } + + public PoolDataName(Integer id) { + this.id = id; + } + + + public void setUseKey(String useKey) { + this.useKey = useKey; + } + + public String getUseKey() { + return USE_VARIABLE_LEFT_BOUNDARY + this.name + USE_VARIABLE_RIGHT_BOUNDARY; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDataValues(Set dataValues) { + this.dataValues = dataValues; + } + + @JSON(serialize = false) + public Set getDataValues() { + return dataValues; + } public Integer getId() { return id; diff --git a/src/main/java/yi/master/business/testconfig/bean/TestConfig.hbm.xml b/src/main/java/yi/master/business/testconfig/bean/TestConfig.hbm.xml index 3231f09..f459606 100644 --- a/src/main/java/yi/master/business/testconfig/bean/TestConfig.hbm.xml +++ b/src/main/java/yi/master/business/testconfig/bean/TestConfig.hbm.xml @@ -42,7 +42,7 @@ - + @@ -59,7 +59,12 @@ - + + + + + + diff --git a/src/main/java/yi/master/business/testconfig/bean/TestConfig.java b/src/main/java/yi/master/business/testconfig/bean/TestConfig.java index a8135c1..ab76805 100644 --- a/src/main/java/yi/master/business/testconfig/bean/TestConfig.java +++ b/src/main/java/yi/master/business/testconfig/bean/TestConfig.java @@ -6,10 +6,7 @@ import yi.master.business.message.bean.SceneValidateRule; import yi.master.util.PracticalUtils; import java.io.Serializable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 接口自动化测试配置 @@ -122,10 +119,24 @@ public class TestConfig implements Serializable, Cloneable { */ private Set businessSystems; + /** + * 使用哪个数据池? + */ + private DataPool dataPool; + /** + * 使用数据池下的类别,不选择默认使用全部 + */ + private String poolItemIds; + /** * 关联的测试配置 */ private Set rules = new HashSet<>(); + + /** + * 所用数据池类别 + */ + private List poolDataItems; public TestConfig(Integer userId, String requestUrlFlag, Integer connectTimeOut, Integer readTimeOut, String httpMethodFlag, @@ -168,7 +179,27 @@ public class TestConfig implements Serializable, Cloneable { return maps; } - public void setTopScenes(String topScenes) { + public List getPoolDataItems() { + return PracticalUtils.getPoolDataItems(this.poolItemIds); + } + + public void setDataPool(DataPool dataPool) { + this.dataPool = dataPool; + } + + public DataPool getDataPool() { + return dataPool; + } + + public void setPoolItemIds(String poolItemIds) { + this.poolItemIds = poolItemIds; + } + + public String getPoolItemIds() { + return poolItemIds; + } + + public void setTopScenes(String topScenes) { this.topScenes = topScenes; } diff --git a/src/main/java/yi/master/business/testconfig/dao/PoolDataItemDao.java b/src/main/java/yi/master/business/testconfig/dao/PoolDataItemDao.java index 372fd60..81b848d 100644 --- a/src/main/java/yi/master/business/testconfig/dao/PoolDataItemDao.java +++ b/src/main/java/yi/master/business/testconfig/dao/PoolDataItemDao.java @@ -2,6 +2,9 @@ package yi.master.business.testconfig.dao; import yi.master.business.base.dao.BaseDao; import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.dto.ItemNameValueDto; + +import java.util.List; /** * @author xuwangcheng @@ -10,4 +13,32 @@ import yi.master.business.testconfig.bean.PoolDataItem; * @date 2020/12/30 14:14 */ public interface PoolDataItemDao extends BaseDao { + /** + * 查询类别数据 + * @author xuwangcheng + * @date 2021/1/4 19:06 + * @param poolId poolId + * @param itemId itemId + * @return {@link List} + */ + List queryItemNameValue(Integer poolId, Integer itemId); + + /** + * 根据名称查询 + * @author xuwangcheng + * @date 2021/1/6 13:44 + * @param name name + * @param poolId poolId + * @return {@link PoolDataItem} + */ + PoolDataItem findByName (String name, Integer poolId); + + /** + * 查询指定池下面的类别 + * @author xuwangcheng + * @date 2021/1/12 13:41 + * @param poolId poolId + * @return {@link List} + */ + List listByPoolId (Integer poolId); } diff --git a/src/main/java/yi/master/business/testconfig/dao/PoolDataValueDao.java b/src/main/java/yi/master/business/testconfig/dao/PoolDataValueDao.java index ce3e293..0bb3079 100644 --- a/src/main/java/yi/master/business/testconfig/dao/PoolDataValueDao.java +++ b/src/main/java/yi/master/business/testconfig/dao/PoolDataValueDao.java @@ -10,4 +10,25 @@ import yi.master.business.testconfig.bean.PoolDataValue; * @date 2020/12/30 14:14 */ public interface PoolDataValueDao extends BaseDao { + + /** + * 更新值 + * @author xuwangcheng + * @date 2021/1/6 9:06 + * @param nameId nameId + * @param itemId itemId + * @param value value + * @return {@link int} + */ + int updateNameValue (Integer nameId, Integer itemId, String value); + + /** + * 获取指定的value + * @author xuwangcheng + * @date 2021/1/6 10:06 + * @param nameId nameId + * @param itemId itemId + * @return {@link PoolDataValue} + */ + PoolDataValue get (Integer nameId, Integer itemId); } diff --git a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataItemDaoImpl.java b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataItemDaoImpl.java index 52f1647..b5aeeed 100644 --- a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataItemDaoImpl.java +++ b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataItemDaoImpl.java @@ -1,9 +1,14 @@ package yi.master.business.testconfig.dao.impl; +import cn.hutool.core.util.StrUtil; +import org.hibernate.transform.Transformers; import org.springframework.stereotype.Repository; import yi.master.business.base.dao.impl.BaseDaoImpl; import yi.master.business.testconfig.bean.PoolDataItem; import yi.master.business.testconfig.dao.PoolDataItemDao; +import yi.master.business.testconfig.dto.ItemNameValueDto; + +import java.util.List; /** * @author xuwangcheng @@ -13,4 +18,32 @@ import yi.master.business.testconfig.dao.PoolDataItemDao; */ @Repository("poolDataItemDao") public class PoolDataItemDaoImpl extends BaseDaoImpl implements PoolDataItemDao { + @Override + public List queryItemNameValue(Integer poolId, Integer itemId) { + String sql = "SELECT p.id as nameId,p.name, v.value,p.default_value as defaultValue FROM at_pool_data_name p LEFT JOIN at_pool_data_value v ON v.name_id = p.id and v.item_id=:itemId WHERE p.pool_id=:poolId order by p.id desc"; + + return getSession().createSQLQuery(sql) + .setResultTransformer(Transformers.aliasToBean(ItemNameValueDto.class)) + .setInteger("poolId", poolId) + .setInteger("itemId", itemId) + .list(); + } + + @Override + public PoolDataItem findByName(String name, Integer poolId) { + String hql = "From PoolDataItem p where p.name=:name and p.dataPool.poolId=:poolId"; + + return (PoolDataItem) getSession().createQuery(hql) + .setCacheable(true) + .setString("name", StrUtil.trim(name)) + .setInteger("poolId", poolId) + .uniqueResult(); + } + + @Override + public List listByPoolId(Integer poolId) { + String hql = "From PoolDataItem p where p.dataPool.poolId=:poolId"; + return getSession().createQuery(hql).setCacheable(true) + .setInteger("poolId", poolId).list(); + } } diff --git a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataValueDaoImpl.java b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataValueDaoImpl.java index 5158306..b01a6ad 100644 --- a/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataValueDaoImpl.java +++ b/src/main/java/yi/master/business/testconfig/dao/impl/PoolDataValueDaoImpl.java @@ -13,4 +13,22 @@ import yi.master.business.testconfig.dao.PoolDataValueDao; */ @Repository("poolDataValueDao") public class PoolDataValueDaoImpl extends BaseDaoImpl implements PoolDataValueDao { + @Override + public int updateNameValue(Integer nameId, Integer itemId, String value) { + String hql = "update PoolDataValue p set p.value=:value where p.poolDataItem.itemId=:itemId and p.poolDataName.id=:nameId"; + return getSession().createQuery(hql) + .setInteger("itemId", itemId) + .setInteger("nameId", nameId) + .setString("value", value) + .executeUpdate(); + } + + @Override + public PoolDataValue get(Integer nameId, Integer itemId) { + String hql = "From PoolDataValue p where p.poolDataItem.itemId=:itemId and p.poolDataName.id=:nameId"; + return (PoolDataValue) getSession().createQuery(hql) + .setInteger("itemId", itemId) + .setInteger("nameId", nameId) + .setCacheable(true).uniqueResult(); + } } diff --git a/src/main/java/yi/master/business/testconfig/dto/ItemNameValueDto.java b/src/main/java/yi/master/business/testconfig/dto/ItemNameValueDto.java new file mode 100644 index 0000000..ffad845 --- /dev/null +++ b/src/main/java/yi/master/business/testconfig/dto/ItemNameValueDto.java @@ -0,0 +1,60 @@ +package yi.master.business.testconfig.dto; + +import static yi.master.constant.GlobalVariableConstant.USE_VARIABLE_LEFT_BOUNDARY; +import static yi.master.constant.GlobalVariableConstant.USE_VARIABLE_RIGHT_BOUNDARY; + +/** + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2021/1/4 19:04 + */ +public class ItemNameValueDto { + + private Integer nameId; + private String useKey; + private String name; + private String value; + private String defaultValue; + + + public String getUseKey() { + return USE_VARIABLE_LEFT_BOUNDARY + this.name + USE_VARIABLE_RIGHT_BOUNDARY; + } + + public void setUseKey(String useKey) { + this.useKey = useKey; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getDefaultValue() { + return defaultValue; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Integer getNameId() { + return nameId; + } + + public void setNameId(Integer nameId) { + this.nameId = nameId; + } +} diff --git a/src/main/java/yi/master/business/testconfig/service/PoolDataItemService.java b/src/main/java/yi/master/business/testconfig/service/PoolDataItemService.java index 18f952c..68fdaae 100644 --- a/src/main/java/yi/master/business/testconfig/service/PoolDataItemService.java +++ b/src/main/java/yi/master/business/testconfig/service/PoolDataItemService.java @@ -2,6 +2,9 @@ package yi.master.business.testconfig.service; import yi.master.business.base.service.BaseService; import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.dto.ItemNameValueDto; + +import java.util.List; /** * @author xuwangcheng @@ -10,4 +13,41 @@ import yi.master.business.testconfig.bean.PoolDataItem; * @date 2020/12/30 16:54 */ public interface PoolDataItemService extends BaseService { + /** + * 查询类别数据 + * @author xuwangcheng + * @date 2021/1/4 19:06 + * @param poolId poolId + * @param itemId itemId + * @return {@link List} + */ + List queryItemNameValue(Integer poolId, Integer itemId); + + /** + * 根据名称查询 + * @author xuwangcheng + * @date 2021/1/6 13:44 + * @param name name + * @param poolId poolId + * @return {@link PoolDataItem} + */ + PoolDataItem findByName (String name, Integer poolId); + + /** + * 请求URL来更新item下的数据 + * @author xuwangcheng + * @date 2021/1/7 15:32 + * @param itemId itemId + * @return + */ + void updateItemValueByRequest (Integer itemId); + + /** + * 查询指定池下面的类别 + * @author xuwangcheng + * @date 2021/1/12 13:41 + * @param poolId poolId + * @return {@link List} + */ + List listByPoolId (Integer poolId); } diff --git a/src/main/java/yi/master/business/testconfig/service/PoolDataValueService.java b/src/main/java/yi/master/business/testconfig/service/PoolDataValueService.java index 47a2f8d..4b174ba 100644 --- a/src/main/java/yi/master/business/testconfig/service/PoolDataValueService.java +++ b/src/main/java/yi/master/business/testconfig/service/PoolDataValueService.java @@ -10,4 +10,15 @@ import yi.master.business.testconfig.bean.PoolDataValue; * @date 2020/12/30 16:56 */ public interface PoolDataValueService extends BaseService { + + /** + * 更新类别数据值 + * @author xuwangcheng + * @date 2021/1/6 10:24 + * @param itemId itemId + * @param nameId nameId + * @param value value + * @return + */ + void updateItemValue (Integer itemId, Integer nameId, String value); } diff --git a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataItemServiceImpl.java b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataItemServiceImpl.java index 8975061..6abb2f3 100644 --- a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataItemServiceImpl.java +++ b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataItemServiceImpl.java @@ -1,11 +1,36 @@ package yi.master.business.testconfig.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import yi.master.business.base.service.impl.BaseServiceImpl; +import yi.master.business.message.bean.TestResult; import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.bean.PoolDataName; +import yi.master.business.testconfig.bean.TestConfig; import yi.master.business.testconfig.dao.PoolDataItemDao; +import yi.master.business.testconfig.dto.ItemNameValueDto; import yi.master.business.testconfig.service.PoolDataItemService; +import yi.master.business.testconfig.service.PoolDataNameService; +import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.business.testconfig.service.TestConfigService; +import yi.master.constant.MessageKeys; +import yi.master.constant.SystemConsts; +import yi.master.coretest.message.parse.JSONMessageParse; +import yi.master.coretest.message.test.MessageAutoTest; +import yi.master.coretest.message.test.TestMessageScene; +import yi.master.exception.YiException; +import yi.master.util.FrameworkUtil; +import yi.master.util.PracticalUtils; +import yi.master.util.message.JsonUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; /** * @author xuwangcheng @@ -16,11 +41,114 @@ import yi.master.business.testconfig.service.PoolDataItemService; @Service("poolDataItemService") public class PoolDataItemServiceImpl extends BaseServiceImpl implements PoolDataItemService { + private static final Logger logger = LoggerFactory.getLogger(PoolDataItemServiceImpl.class); + private PoolDataItemDao poolDataItemDao; + @Autowired + private PoolDataValueService poolDataValueService; + @Autowired + private PoolDataNameService poolDataNameService; + @Autowired + private MessageAutoTest messageAutoTest; + @Autowired + private TestConfigService testConfigService; @Autowired public void setPoolDataItemDao(PoolDataItemDao poolDataItemDao) { super.setBaseDao(poolDataItemDao); this.poolDataItemDao = poolDataItemDao; } + + @Override + public List queryItemNameValue(Integer poolId, Integer itemId) { + return poolDataItemDao.queryItemNameValue(poolId, itemId); + } + + @Override + public PoolDataItem findByName(String name, Integer poolId) { + return poolDataItemDao.findByName(name, poolId); + } + + @Override + public void updateItemValueByRequest(Integer itemId) { + PoolDataItem poolDataItem = poolDataItemDao.get(itemId); + if (poolDataItem == null) { + throw new YiException("该池类别不存在"); + } + + boolean useMessageScene = SystemConsts.DefaultBooleanIdentify.TRUE.getString().equals(poolDataItem.getUseMessageScene()); + boolean requestUrlIsNotBlank = StrUtil.isNotBlank(poolDataItem.getRequestUrl()); + boolean messageSceneNotNull = poolDataItem.getMessageScene() != null; + + if (!requestUrlIsNotBlank && !messageSceneNotNull) { + throw new YiException("未配置数据请求地址和接口场景"); + } + + String result = ""; + + try { + // 使用messageScene + if ((useMessageScene && messageSceneNotNull) || (!useMessageScene && !requestUrlIsNotBlank)) { + if (poolDataItem.getSceneSystem() == null) { + throw new YiException("数据池[{}]自动获取数据出错:你必须为接口场景选择一个可用的测试环境", poolDataItem.getDataPool().getName()); + } + TestConfig testConfig = testConfigService.getConfigByUserId(FrameworkUtil.getLoginUser().getUserId()); + Set testMessageScenes = messageAutoTest.packageRequestObject(poolDataItem.getMessageScene(), testConfig, poolDataItem.getSceneSystem(), null); + if (CollUtil.isEmpty(testMessageScenes)) { + throw new YiException("数据池[{}]自动获取数据出错:通过接口获取数据出错:无法解析要使用的接口场景", poolDataItem.getDataPool().getName()); + } + + TestResult result1 = messageAutoTest.singleTest(new ArrayList<>(testMessageScenes).get(0), null); + if (!MessageKeys.TestRunStatus.SUCCESS.getCode().equals(result1.getRunStatus())) { + throw new YiException("数据池[{}]自动获取数据出错:{}", poolDataItem.getDataPool().getName(), result1.getMark()); + } + + result = result1.getResponseMessage(); + } + + // 使用requestUrl + if ((!useMessageScene && requestUrlIsNotBlank) || (useMessageScene && !messageSceneNotNull)) { + result = PracticalUtils.doGetHttpRequest(poolDataItem.getRequestUrl()); + } + } catch (Exception e) { + if (e instanceof YiException) { + throw e; + } else { + throw new YiException("数据池[{}]接口请求出错:{}", poolDataItem.getDataPool().getName(), e.getMessage()); + } + } + + if (StrUtil.isBlank(result) || !JSONMessageParse.getInstance().messageFormatValidation(result)) { + throw new YiException("数据池[{}]接口请求出错:返回数据格式不正确,必须为JSON格式!", poolDataItem.getDataPool().getName()); + } + + logger.info(StrUtil.format("通过接口获取数据池[{}]数据,接口返回内容为:{}", poolDataItem.getDataPool().getName(), result)); + + // 是否配置了指定的JSONPATH? + if (StrUtil.isNotBlank(poolDataItem.getResponseDataJsonPath())) { + result = JsonUtil.getObjectByJson(result, poolDataItem.getResponseDataJsonPath(), JsonUtil.TypeEnum.map); + } + if (StrUtil.isBlank(result)) { + throw new YiException("数据池[{}]接口请求出错:JSON_PATH配置有误,无法获取指定节点[{}]下的数据", poolDataItem.getDataPool().getName() + , poolDataItem.getResponseDataJsonPath()); + } + + JSONObject jsonObject = JSONObject.parseObject(result); + + for (String key:jsonObject.keySet()) { + if (jsonObject.get(key) == null) { + continue; + } + + PoolDataName dataName = poolDataNameService.findByName(key, poolDataItem.getDataPool().getPoolId()); + if (dataName != null) { + poolDataValueService.updateItemValue(itemId, dataName.getId(), jsonObject.getString(key)); + } + } + } + + @Override + public List listByPoolId(Integer poolId) { + return poolDataItemDao.listByPoolId(poolId); + } } diff --git a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataValueServiceImpl.java b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataValueServiceImpl.java index 2a475e2..0f613b4 100644 --- a/src/main/java/yi/master/business/testconfig/service/impl/PoolDataValueServiceImpl.java +++ b/src/main/java/yi/master/business/testconfig/service/impl/PoolDataValueServiceImpl.java @@ -3,9 +3,14 @@ package yi.master.business.testconfig.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import yi.master.business.base.service.impl.BaseServiceImpl; +import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.bean.PoolDataName; import yi.master.business.testconfig.bean.PoolDataValue; import yi.master.business.testconfig.dao.PoolDataValueDao; import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.util.FrameworkUtil; + +import java.sql.Timestamp; /** * @author xuwangcheng @@ -23,4 +28,20 @@ public class PoolDataValueServiceImpl extends BaseServiceImpl imp super.setBaseDao(poolDataValueDao); this.poolDataValueDao = poolDataValueDao; } + + @Override + public void updateItemValue(Integer itemId, Integer nameId, String value) { + if (poolDataValueDao.get(nameId, itemId) == null) { + PoolDataValue poolDataValue = new PoolDataValue(); + poolDataValue.setCreateTime(new Timestamp(System.currentTimeMillis())); + poolDataValue.setUser(FrameworkUtil.getLoginUser()); + poolDataValue.setValue(value); + poolDataValue.setPoolDataItem(new PoolDataItem(itemId)); + poolDataValue.setPoolDataName(new PoolDataName(nameId)); + + poolDataValueDao.save(poolDataValue); + } else { + poolDataValueDao.updateNameValue(nameId, itemId, value); + } + } } diff --git a/src/main/java/yi/master/business/testconfig/service/impl/TestConfigServiceImpl.java b/src/main/java/yi/master/business/testconfig/service/impl/TestConfigServiceImpl.java index 59ea864..2956453 100644 --- a/src/main/java/yi/master/business/testconfig/service/impl/TestConfigServiceImpl.java +++ b/src/main/java/yi/master/business/testconfig/service/impl/TestConfigServiceImpl.java @@ -21,8 +21,14 @@ public class TestConfigServiceImpl extends BaseServiceImpl implement @Override public TestConfig getConfigByUserId(Integer userId) { - - return testConfigDao.getConfigByUserId(userId); + TestConfig config = testConfigDao.getConfigByUserId(userId); + if (config == null) { + config = (TestConfig) getConfigByUserId(0).clone(); + config.setConfigId(null); + config.setUserId(userId); + config.setConfigId(save(config)); + } + return config; } } diff --git a/src/main/java/yi/master/constant/SystemConsts.java b/src/main/java/yi/master/constant/SystemConsts.java index c49f2b1..f03cf24 100644 --- a/src/main/java/yi/master/constant/SystemConsts.java +++ b/src/main/java/yi/master/constant/SystemConsts.java @@ -13,7 +13,7 @@ public interface SystemConsts { /** * 当前版本号 */ - String VERSION = "1.1.0"; + String VERSION = "1.1.1"; /** diff --git a/src/main/java/yi/master/coretest/message/protocol/HTTPTestClient.java b/src/main/java/yi/master/coretest/message/protocol/HTTPTestClient.java index 9ded415..a40eda4 100644 --- a/src/main/java/yi/master/coretest/message/protocol/HTTPTestClient.java +++ b/src/main/java/yi/master/coretest/message/protocol/HTTPTestClient.java @@ -242,6 +242,9 @@ public class HTTPTestClient extends TestClient { //失败重试 boolean requestSuccessFlag = false; int retryCount = 0; + if (config.getRetryCount() == null) { + config.setRetryCount(3); + } while (!requestSuccessFlag && config.getRetryCount() > retryCount) { try { if (HttpMethod.GET.name().equalsIgnoreCase(method)) { diff --git a/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java b/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java index 7d980df..e66a5f9 100644 --- a/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java +++ b/src/main/java/yi/master/coretest/message/test/MessageAutoTest.java @@ -2,6 +2,7 @@ package yi.master.coretest.message.test; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; import net.sf.json.JSONObject; import org.apache.commons.lang3.StringUtils; import org.apache.http.impl.client.DefaultHttpClient; @@ -14,10 +15,13 @@ import yi.master.business.message.enums.ComplexSceneTestClientType; import yi.master.business.message.service.*; import yi.master.business.system.bean.ProjectInfo; import yi.master.business.testconfig.bean.BusinessSystem; +import yi.master.business.testconfig.bean.PoolDataItem; import yi.master.business.testconfig.bean.TestConfig; +import yi.master.business.testconfig.dto.ItemNameValueDto; import yi.master.business.testconfig.enums.TestRunType; import yi.master.business.testconfig.service.BusinessSystemService; import yi.master.business.testconfig.service.GlobalVariableService; +import yi.master.business.testconfig.service.PoolDataItemService; import yi.master.business.testconfig.service.TestConfigService; import yi.master.business.user.bean.User; import yi.master.constant.MessageKeys; @@ -70,6 +74,8 @@ public class MessageAutoTest { private GlobalVariableService globalVariableService; @Autowired private BusinessSystemService businessSystemService; + @Autowired + private PoolDataItemService poolDataItemService; /** * 通过接口场景动态获取指定的值 @@ -102,7 +108,7 @@ public class MessageAutoTest { throw new Exception("指定的测试环境不存在或者已被删除,请检查!"); } - Set testObjects = packageRequestObject(scene, config, system); + Set testObjects = packageRequestObject(scene, config, system, null); if (testObjects.size() == 0) { throw new Exception("测试环境[" + system.getSystemName() + "]被禁用,请检查!"); @@ -141,7 +147,11 @@ public class MessageAutoTest { InterfaceInfo info = messageSceneService.getInterfaceOfScene(scene.getMessageSceneId()); String messageInfo = info.getInterfaceName() + "," + msg.getMessageName() + "," + scene.getSceneName(); - + + if (testScene.getPoolDataItemId() != null) { + result.setPoolDataItem(new PoolDataItem(testScene.getPoolDataItemId())); + } + result.setMessageInfo(messageInfo); result.setOpTime(new Timestamp(System.currentTimeMillis())); result.setMessageScene(scene); @@ -362,6 +372,9 @@ public class MessageAutoTest { TestResult complexResult = new TestResult(); complexResult.setMessageInfo(testScene.getComplexScene().getComplexSceneName() + ",组合场景,组合场景"); complexResult.setTestReport(report); + if (testScene.getPoolDataItemId() != null) { + complexResult.setPoolDataItem(new PoolDataItem(testScene.getPoolDataItemId())); + } complexResult.setOpTime(new Timestamp(System.currentTimeMillis())); complexResult.setMark(complexMark.toString()); complexResult.setUseTime(0); @@ -399,6 +412,16 @@ public class MessageAutoTest { } + /** + * 测试组合场景 + * @param scene + * @param saveVariables + * @param procotolClient + * @param complexSceneName + * @param results + * @param async + * @return + */ private boolean testSceneOfComplex(TestMessageScene scene, Map saveVariables, DefaultHttpClient procotolClient , String complexSceneName, List results, boolean async) { //替换上下文变量 @@ -455,6 +478,9 @@ public class MessageAutoTest { } } result.setMark("组合场景名 [" + complexSceneName + "] , " + (async ? "该场景为异步执行方式。" : "执行序号 [" + scene.getScene().getSequenceNum() + "]") + " \n\n" + result.getMark()); + if (scene.getPoolDataItemId() != null) { + result.setPoolDataItem(new PoolDataItem(scene.getPoolDataItemId())); + } results.add(result); //测试成功要获取保存变量并设置数据状态 if (successFlag) { @@ -530,6 +556,17 @@ public class MessageAutoTest { final TestConfig config = config1; + + // 先处理好数据池数据 + Map> poolData = new HashMap<>(); + // 配置数据池 + if (config.getDataPool() != null) { + for (PoolDataItem pdi:(config.getPoolDataItems().size() < 1 ? config.getDataPool().getDataItems() : config.getPoolDataItems())) { + poolData.put(pdi.getItemId(), queryPoolItemData(pdi.getItemId(), pdi.getDataPool().getPoolId())); + } + } else { + poolData.put(null, null); + } //测试报告 final TestReport report = new TestReport(); @@ -555,22 +592,26 @@ public class MessageAutoTest { //组装单独的测试场景元素对象 for (MessageScene scene:scenes) { - testObjects.addAll(packageRequestObject(scene, config, null)); + testObjects.addAll(packageRequestObject(scene, config, null, poolData)); } //场景数量 分别为finishCount和totalCount final int[] count = new int[]{0, testObjects.size()}; //检查场景数量,包含单场景和组合场景中的场景 boolean noSceneFlag = testObjects.size() > 0 ? false : true; - //组装组合场景中的测试场景 + //组装组合场景中的测试场景 + + // 组合场景也要区分数据池 for (ComplexScene s:complexScenes) { - TestMessageScene testScene = packageComplexRequestObject(s, config); - count[1] = count[1] + testScene.getTestCount(); - testObjects.add(testScene); + for (Integer poolItemId:poolData.keySet()) { + TestMessageScene testScene = packageComplexRequestObject(s, config, poolData.get(poolItemId), poolItemId); + count[1] = count[1] + testScene.getTestCount(); + testObjects.add(testScene); - if (noSceneFlag && testScene.getScenes().size() > 0) { - noSceneFlag = false; - } + if (noSceneFlag && testScene.getScenes().size() > 0) { + noSceneFlag = false; + } + } } if (noSceneFlag) { @@ -661,20 +702,25 @@ public class MessageAutoTest { * @param config 对应测试配置 * @return */ - public TestMessageScene packageComplexRequestObject(ComplexScene complexScene, TestConfig config){ + public TestMessageScene packageComplexRequestObject(ComplexScene complexScene, TestConfig config, Map poolData, Integer poolItemId){ complexScene.setComplexSceneConfigs(); TestMessageScene testScene = new TestMessageScene(); testScene.setComplexFlag(true); + testScene.setPoolDataItemId(poolItemId); testScene.setComplexScene(complexScene); testScene.setNewClient(ComplexSceneTestClientType.NEW_CLIENT.getClientType().equals(complexScene.getNewClient())); int sceneCount = 0; + + Map> poolDatas = new HashMap<>(); + poolDatas.put(poolItemId, poolData); + for (MessageScene scene:complexScene.setScenes(messageSceneService)) { BusinessSystem system = null; if (StringUtils.isNotBlank(scene.getConfig().getSystemId()) && NumberUtil.isInteger(scene.getConfig().getSystemId())) { system = businessSystemService.get(Integer.valueOf(scene.getConfig().getSystemId())); } - Set tss = packageRequestObject(scene, config, system); + Set tss = packageRequestObject(scene, config, system, poolDatas); if (tss.size() >= 1) { testScene.getScenes().add(new ArrayList<>(tss).get(0)); if (ComplexSceneSuccessFlag.SEPARATE_STATISTICS_RESULT.getFlag().equals(complexScene.getSuccessFlag())) { @@ -704,7 +750,7 @@ public class MessageAutoTest { * @return */ @SuppressWarnings("static-access") - public Set packageRequestObject (MessageScene scene, TestConfig config, BusinessSystem singleSystem) { + public Set packageRequestObject (MessageScene scene, TestConfig config, BusinessSystem singleSystem, Map> poolData) { InterfaceInfo info = messageSceneService.getInterfaceOfScene(scene.getMessageSceneId()); Message msg = messageSceneService.getMessageOfScene(scene.getMessageSceneId()); @@ -714,6 +760,12 @@ public class MessageAutoTest { //配置为空时默认测试全部的 Set enableTestSystems = config.getBusinessSystems(); + + // 防止无法循环 + if (poolData == null || poolData.size() < 1) { + poolData = new HashMap<>(1); + poolData.put(null, null); + } boolean allSystemsTestFlag = false; if (StringUtils.isBlank(config.getSystems())) { @@ -729,79 +781,101 @@ public class MessageAutoTest { continue; } if (singleSystem == null || system.getSystemId().equals(singleSystem.getSystemId())) { - TestMessageScene testScene = new TestMessageScene(); - - //获取测试地址 - String requestUrl = ""; - if (StringUtils.isNotBlank(scene.getRequestUrl())) { - requestUrl = scene.getRequestUrl(); - } - if (StringUtils.isBlank(requestUrl) && StringUtils.isNotBlank(msg.getRequestUrl())) { - requestUrl = msg.getRequestUrl(); - } - if (StringUtils.isBlank(requestUrl)) { - requestUrl = info.getRequestUrlReal(); - } - - requestUrl = system.getReuqestUrl(requestUrl, system.getDefaultPath(), info.getInterfaceName()); - - //获取测试数据 - MessageParse parseUtil = MessageParse.getParseInstance(msg.getMessageType()); - String requestMessage = ""; - List datas= scene.getEnabledTestDatas(1, String.valueOf(system.getSystemId())); - TestData d = null; - if (datas.size() != 0) { - d = datas.get(0); - } - if (d != null && !CacheUtil.checkLockedTestData(d.getDataId())) { - if (info.getInterfaceType().equalsIgnoreCase(MessageKeys.InterfaceBusiType.SL.name()) && d.getStatus().equals("0")) { - //预占测试数据 - CacheUtil.addLockedTestData(d.getDataId()); - testScene.setDataId(d.getDataId()); - } - - JSONObject paramsData = JSONObject.fromObject(StringUtils.isNotBlank(d.getParamsData()) ? d.getParamsData() : "{}"); - //有单独的测试配置说明是组合场景下的场景 - if (scene.getConfig() != null) { - for (Map.Entry entry:scene.getConfig().getUseVariables().entrySet()) { - String replaceVariable = entry.getValue(); - if (!Pattern.matches("\\$\\{__(.*?)\\}", replaceVariable)) { - //如果不是全局变量说明是常量或者上下文保存的测试结果变量 - replaceVariable = MessageKeys.CUSTOM_PARAMETER_BOUNDARY_SYMBOL_LEFT + replaceVariable + MessageKeys.CUSTOM_PARAMETER_BOUNDARY_SYMBOL_RIGHT; - } - paramsData.put(MessageKeys.MESSAGE_PARAMETER_DEFAULT_ROOT_PATH + "." + entry.getKey(), replaceVariable); - } - } - //替换测试集公共变量 - requestMessage = PracticalUtils.replaceSetPublicVariable(parseUtil.depacketizeMessageToString(msg.getComplexParameter() - , paramsData.toString()), config.getPublicDataObject()); - } - //替换入参报文中的全局变量 - requestMessage = PracticalUtils.replaceGlobalVariable(requestMessage, globalVariableService); - - //处理请求URL中的全局变量 - requestUrl = PracticalUtils.replaceGlobalVariable(requestUrl, globalVariableService); - //处理路径参数:在请求URL中出现 #路径path# - requestUrl = PracticalUtils.replacePathVariableParameter(requestUrl, requestMessage, parseUtil); - - testScene.setTestClient(TestClient.getTestClientInstance(info.getInterfaceProtocol())); - testScene.setRequestMessage(requestMessage); - testScene.setComplexFlag(false); - testScene.setScene(scene); - testScene.setRequestUrl(requestUrl); - testScene.setParseUtil(parseUtil); - testScene.setBusinessSystem(system); - testScene.setConfig(config); - //提前在此处替换调用参数中的全局变量,防止在异步线程中调用时出现一些不可预期的错误 - testScene.setCallParameter(PracticalUtils.jsonToMap(PracticalUtils.replaceGlobalVariable(msg.getCallParameter(), null))); - testObjects.add(testScene); + for (Integer itemId:poolData.keySet()) { + + TestMessageScene testScene = new TestMessageScene(); + + //获取测试地址 + String requestUrl = ""; + if (StringUtils.isNotBlank(scene.getRequestUrl())) { + requestUrl = scene.getRequestUrl(); + } + if (StringUtils.isBlank(requestUrl) && StringUtils.isNotBlank(msg.getRequestUrl())) { + requestUrl = msg.getRequestUrl(); + } + if (StringUtils.isBlank(requestUrl)) { + requestUrl = info.getRequestUrlReal(); + } + + requestUrl = system.getReuqestUrl(requestUrl, system.getDefaultPath(), info.getInterfaceName()); + + //获取测试数据 + MessageParse parseUtil = MessageParse.getParseInstance(msg.getMessageType()); + String requestMessage = ""; + List datas= scene.getEnabledTestDatas(1, String.valueOf(system.getSystemId())); + TestData d = null; + if (datas.size() != 0) { + d = datas.get(0); + } + if (d != null && !CacheUtil.checkLockedTestData(d.getDataId())) { + if (info.getInterfaceType().equalsIgnoreCase(MessageKeys.InterfaceBusiType.SL.name()) && d.getStatus().equals("0")) { + //预占测试数据 + CacheUtil.addLockedTestData(d.getDataId()); + testScene.setDataId(d.getDataId()); + } + + JSONObject paramsData = JSONObject.fromObject(StringUtils.isNotBlank(d.getParamsData()) ? d.getParamsData() : "{}"); + //有单独的测试配置说明是组合场景下的场景 + if (scene.getConfig() != null) { + for (Map.Entry entry:scene.getConfig().getUseVariables().entrySet()) { + String replaceVariable = entry.getValue(); + if (!Pattern.matches("\\$\\{__(.*?)\\}", replaceVariable)) { + //如果不是全局变量说明是常量或者上下文保存的测试结果变量 + replaceVariable = MessageKeys.CUSTOM_PARAMETER_BOUNDARY_SYMBOL_LEFT + replaceVariable + MessageKeys.CUSTOM_PARAMETER_BOUNDARY_SYMBOL_RIGHT; + } + paramsData.put(MessageKeys.MESSAGE_PARAMETER_DEFAULT_ROOT_PATH + "." + entry.getKey(), replaceVariable); + } + } + //替换入参报文中的测试集公共变量 + requestMessage = PracticalUtils.replaceSetPublicVariable(parseUtil.depacketizeMessageToString(msg.getComplexParameter() + , paramsData.toString()), config.getPublicDataObject()); + } + + // 处理数据池 + if (itemId != null) { + testScene.setPoolDataItemId(itemId); + testScene.setPoolData(poolData.get(itemId)); + + // 替换数据池里的数据 + requestMessage = PracticalUtils.replacePoolData(requestMessage, testScene.getPoolData()); + } + + //替换入参报文中的全局变量 + requestMessage = PracticalUtils.replaceGlobalVariable(requestMessage, globalVariableService); + + //处理请求URL中的全局变量 + requestUrl = PracticalUtils.replaceGlobalVariable(requestUrl, globalVariableService); + //处理路径参数:在请求URL中出现 #路径path# + requestUrl = PracticalUtils.replacePathVariableParameter(requestUrl, requestMessage, parseUtil); + + testScene.setTestClient(TestClient.getTestClientInstance(info.getInterfaceProtocol())); + testScene.setRequestMessage(requestMessage); + testScene.setComplexFlag(false); + testScene.setScene(scene); + testScene.setRequestUrl(requestUrl); + testScene.setParseUtil(parseUtil); + testScene.setBusinessSystem(system); + testScene.setConfig(config); + //提前在此处替换调用参数中的全局变量,防止在异步线程中调用时出现一些不可预期的错误 + testScene.setCallParameter(PracticalUtils.jsonToMap(PracticalUtils.replaceGlobalVariable(msg.getCallParameter(), null))); + testObjects.add(testScene); + } } } return testObjects; } - + + /** + * 查找指定的测试场景通过messageSceneId + * @author xuwangcheng + * @date 2021/1/12 11:16 + * @param sceneId sceneId + * @param testObjects testObjects + * @param priority priority + * @return {@link int} + */ private int findTestObjectBySceneId(Integer sceneId, List testObjects, int priority) { for (TestMessageScene scene:testObjects) { if (!scene.getComplexFlag() && sceneId.equals(scene.getScene().getMessageSceneId())) { @@ -812,4 +886,25 @@ public class MessageAutoTest { return priority; } + private Map queryPoolItemData (Integer poolItemId, Integer poolId) { + // 更新数据 + PoolDataItem poolDataItem = poolDataItemService.get(poolItemId); + if (SystemConsts.DefaultBooleanIdentify.TRUE.getNumber().equals(poolDataItem.getBeforeUseAutoUpdate()) + && (StrUtil.isNotBlank(poolDataItem.getRequestUrl()) || poolDataItem.getMessageScene() != null)) { + poolDataItemService.updateItemValueByRequest(poolItemId); + } + + List values = poolDataItemService.queryItemNameValue(poolId, poolItemId); + Map results = new HashMap<>(values.size()); + + for (ItemNameValueDto dto:values) { + String value = StrUtil.isBlank(dto.getValue()) ? dto.getDefaultValue() : dto.getValue(); + // 替换可能使用的全局变量 + value = PracticalUtils.replaceGlobalVariable(value, globalVariableService); + results.put(dto.getName(), value); + } + + return results; + } + } diff --git a/src/main/java/yi/master/coretest/message/test/TestMessageScene.java b/src/main/java/yi/master/coretest/message/test/TestMessageScene.java index fbdacc9..2688ee5 100644 --- a/src/main/java/yi/master/coretest/message/test/TestMessageScene.java +++ b/src/main/java/yi/master/coretest/message/test/TestMessageScene.java @@ -62,8 +62,14 @@ public class TestMessageScene implements Cloneable { * 所属测试环境 */ private BusinessSystem businessSystem; - + + /** + * 指定的报文格式处理工具 + */ private MessageParse parseUtil; + /** + * 指定的协议客户端 + */ private TestClient testClient; /** @@ -90,8 +96,17 @@ public class TestMessageScene implements Cloneable { */ private Integer priority = 0; + /** + * 使用数据池类别:可以包含全局变量,全局变量要在使用之前先处理 + */ + private Map poolData; + /** + * 当前数据池poolDataItemId,只有设置了该值才会启用数据池 + */ + private Integer poolDataItemId; - public TestMessageScene(MessageScene scene, String requestUrl, + + public TestMessageScene(MessageScene scene,String requestUrl, String requestMessage, Integer dataId, Boolean complexFlag) { super(); this.scene = scene; @@ -123,6 +138,21 @@ public class TestMessageScene implements Cloneable { } + public void setPoolDataItemId(Integer poolDataItemId) { + this.poolDataItemId = poolDataItemId; + } + + public Integer getPoolDataItemId() { + return poolDataItemId; + } + + public Map getPoolData() { + return poolData; + } + + public void setPoolData(Map poolData) { + this.poolData = poolData; + } public void setTestClient(TestClient testClient) { this.testClient = testClient; diff --git a/src/main/java/yi/master/exception/AppErrorCode.java b/src/main/java/yi/master/exception/AppErrorCode.java index a27a5fa..ad4cf10 100644 --- a/src/main/java/yi/master/exception/AppErrorCode.java +++ b/src/main/java/yi/master/exception/AppErrorCode.java @@ -28,7 +28,8 @@ public enum AppErrorCode { MOCK_ERROR(9995, "接口mock出错,请联系接口自动化测试平台"), SYSTEM_IS_UPDATING(9994, "系统正在系统,请稍后刷新访问..."), SYSTEM_IS_NEED_RESTART(9993, "系统刚刚升级完成,请联系管理员重启服务器..."), - + EXPORT_FILE_ERROR(9992, "导出文件出错,请重试"), + TEMPLATE_FILE_ERROR(9991, "模板格式不正确,请检查"), //自动化测试 AUTO_TEST_COMPLEX_SCENE_LACK_BUSINESS_SYSTEM(100001, "测试场景没有配置独立的环境,请打开组合场景中的配置管理添加"), diff --git a/src/main/java/yi/master/exception/YiException.java b/src/main/java/yi/master/exception/YiException.java index b44c964..31bd543 100644 --- a/src/main/java/yi/master/exception/YiException.java +++ b/src/main/java/yi/master/exception/YiException.java @@ -49,6 +49,12 @@ public class YiException extends RuntimeException { this.msg = msg; } + public YiException(String format, String ... var) { + super(StrUtil.format(format, var)); + this.code = AppErrorCode.INTERNAL_SERVER_ERROR.getCode(); + this.msg = StrUtil.format(format, var); + } + public YiException(String msg, Throwable e) { super(msg, e); this.code = AppErrorCode.INTERNAL_SERVER_ERROR.getCode(); diff --git a/src/main/java/yi/master/listener/VersionUpdateUtil.java b/src/main/java/yi/master/listener/VersionUpdateUtil.java index 18878d9..78a8e3b 100644 --- a/src/main/java/yi/master/listener/VersionUpdateUtil.java +++ b/src/main/java/yi/master/listener/VersionUpdateUtil.java @@ -52,6 +52,7 @@ public class VersionUpdateUtil { ALL_VERSION_LIST.add("1.0.4"); ALL_VERSION_LIST.add("1.0.5"); ALL_VERSION_LIST.add("1.1.0"); + ALL_VERSION_LIST.add("1.1.1"); } /** diff --git a/src/main/java/yi/master/util/PracticalUtils.java b/src/main/java/yi/master/util/PracticalUtils.java index 451e303..8c6afd9 100644 --- a/src/main/java/yi/master/util/PracticalUtils.java +++ b/src/main/java/yi/master/util/PracticalUtils.java @@ -21,8 +21,10 @@ import yi.master.business.message.service.TestSetService; import yi.master.business.testconfig.bean.BusinessSystem; import yi.master.business.testconfig.bean.DataDB; import yi.master.business.testconfig.bean.GlobalVariable; +import yi.master.business.testconfig.bean.PoolDataItem; import yi.master.business.testconfig.service.BusinessSystemService; import yi.master.business.testconfig.service.GlobalVariableService; +import yi.master.business.testconfig.service.PoolDataItemService; import yi.master.constant.GlobalVariableConstant; import yi.master.constant.SystemConsts; import yi.master.coretest.message.parse.MessageParse; @@ -473,7 +475,8 @@ public class PracticalUtils { jsonMap.put("data", resultService.findAll("testReport.reportId=" + report.getReportId())); JsonConfig jsonConfig = new JsonConfig(); - jsonConfig.setExcludes(new String[]{"testReport", "messageScene", "complexResult"}); + // 设置排除的数据 + jsonConfig.setExcludes(new String[]{"testReport", "messageScene", "complexResult", "poolDataItem"}); jsonConfig.registerJsonValueProcessor(java.sql.Timestamp.class, new JsonDateValueProcessor("yyyy-MM-dd HH:mm:ss")); return JSONObject.fromObject(jsonMap, jsonConfig).toString(); @@ -649,6 +652,39 @@ public class PracticalUtils { return msg; } + /** + * 替换数据池数据 + * @author xuwangcheng + * @date 2021/1/12 16:01 + * @param msg msg + * @param values values + * @return {@link String} + */ + public static String replacePoolData (String msg, Map values) { + if (StringUtils.isBlank(msg)) { + return msg; + } + + String regex = "\\$\\{__(.*?)\\}"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(msg); + + String value = null; + String useVariable = null; + while (matcher.find()) { + useVariable = "${__" + matcher.group(1) + "}"; + if (!msg.contains(useVariable)) { + continue; + } + value = values.get(matcher.group(1)); + if (value == null) { + continue; + } + msg = msg.replace(useVariable, value); + } + return msg; + } + /** * 处理请求URL中可能存在的路径参数
    * @author xuwangcheng @@ -902,6 +938,29 @@ public class PracticalUtils { } return systems; } + + /** + * 根据ID集合获取数据池类别ID + * @author xuwangcheng + * @date 2021/1/11 14:32 + * @param ids ids + * @return {@link List} + */ + public static List getPoolDataItems (String ids) { + List poolDataItems = new ArrayList<>(); + if (StringUtils.isNotBlank(ids)) { + PoolDataItemService poolDataItemService = (PoolDataItemService) FrameworkUtil.getSpringBean(PoolDataItemService.class); + for (String id:ids.split(",")) { + PoolDataItem poolDataItem = poolDataItemService.get(Integer.valueOf(id)); + if (poolDataItem != null) { + poolDataItems.add(poolDataItem); + } + } + } + + return poolDataItems; + } + /** * 从request中获取body内容 * @param request diff --git a/src/main/java/yi/master/util/cache/CacheUtil.java b/src/main/java/yi/master/util/cache/CacheUtil.java index 7ed94d2..75f33e6 100644 --- a/src/main/java/yi/master/util/cache/CacheUtil.java +++ b/src/main/java/yi/master/util/cache/CacheUtil.java @@ -77,7 +77,12 @@ public class CacheUtil { public static void removeLockedTestData(Integer dataId) { CacheUtil.lockedTestDatas.remove(dataId); } - + + /** + * 检查该测试数据是不是已经被预占了 + * @param dataId + * @return + */ public static boolean checkLockedTestData(Integer dataId) { return CacheUtil.lockedTestDatas.contains(dataId); } diff --git a/src/main/java/yi/master/util/excel/ExcelPoolDataTemplate.java b/src/main/java/yi/master/util/excel/ExcelPoolDataTemplate.java new file mode 100644 index 0000000..d550404 --- /dev/null +++ b/src/main/java/yi/master/util/excel/ExcelPoolDataTemplate.java @@ -0,0 +1,259 @@ +package yi.master.util.excel; + + +import cn.hutool.core.util.StrUtil; +import org.apache.log4j.Logger; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import yi.master.business.testconfig.bean.DataPool; +import yi.master.business.testconfig.bean.PoolDataItem; +import yi.master.business.testconfig.bean.PoolDataName; +import yi.master.business.testconfig.service.DataPoolService; +import yi.master.business.testconfig.service.PoolDataItemService; +import yi.master.business.testconfig.service.PoolDataNameService; +import yi.master.business.testconfig.service.PoolDataValueService; +import yi.master.constant.SystemConsts; +import yi.master.exception.AppErrorCode; +import yi.master.exception.YiException; +import yi.master.util.FrameworkUtil; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * excel导入导出数据池相关文件 + * @author xuwangcheng + * @version 1.0.0 + * @description + * @date 2021/1/6 11:12 + */ +public class ExcelPoolDataTemplate { + private static final Logger logger = Logger.getLogger(ExcelPoolDataTemplate.class); + + /** + * 下载数据池导入模板 + * @author xuwangcheng + * @date 2021/1/6 16:45 + * @param dataPool dataPool + * @param names names + * @param items items + * @return {@link String} + */ + public static String exportDocument (DataPool dataPool, List names, List items) { + String path = null; + OutputStream outputStream = null; + String fileName = "dataPoolTemplate_" + System.currentTimeMillis() + ".xlsx"; + try { + //创建excel + Workbook wb = PoiExcelUtil.createWorkBook(PoiExcelUtil.XLSX); + Sheet sheet = PoiExcelUtil.createSheet(wb, dataPool.getName() + "_数据导入模板"); + // 创建变量名行 + // 空出第一行 + Row itemRow = sheet.createRow(0); + for (int i = 1;i <= names.size();i++) { + Row nameRow = sheet.createRow(i); + Cell cell = nameRow.createCell(0); + cell.setCellValue(names.get(i - 1).getName()); + } + // 创建池类别列 + CellStyle headerStyle = PoiExcelUtil.createHeadCellStyle(wb); + Cell titleCell = itemRow.createCell(0); + titleCell.setCellValue("变量名"); + titleCell.setCellStyle(headerStyle); + for (int i = 1;i <= items.size();i++) { + PoolDataItem item = items.get(i - 1); + Cell cell = itemRow.createCell(i); + cell.setCellValue(item.getName()); + cell.setCellStyle(headerStyle); + } + + path = SystemConsts.EXCEL_FILE_FOLDER + File.separator + fileName; + outputStream = new FileOutputStream(new File(FrameworkUtil.getProjectPath() + File.separator + path)); + + wb.write(outputStream); + } catch (Exception e) { + logger.error("导出数据池变量模板文件失败!", e); + throw new YiException(AppErrorCode.EXPORT_FILE_ERROR); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return path; + } + + /** + * excel导入数据池数据 + * @author xuwangcheng + * @date 2021/1/6 16:45 + * @param poolId poolId + * @param filePath filePath + * @return + */ + public static void importItemValues (Integer poolId, String filePath) { + DataPoolService dataPoolService = (DataPoolService) FrameworkUtil.getSpringBean(DataPoolService.class); + + DataPool dataPool = dataPoolService.get(poolId); + if (dataPool == null) { + throw new YiException("数据池信息不存在"); + } + + PoolDataValueService poolDataValueService = (PoolDataValueService) FrameworkUtil.getSpringBean(PoolDataValueService.class); + + try { + Map> infos = parseExcelInfo(filePath, poolId); + + // 保存到数据库 + for (Integer itemId:infos.keySet()) { + Map info = infos.get(itemId); + for (Integer nameId:info.keySet()) { + if (itemId != null && nameId != null) { + poolDataValueService.updateItemValue(itemId, nameId, info.get(nameId)); + } + } + } + } catch (Exception e) { + logger.error("导入出错", e); + throw new YiException("导入出错"); + } + + } + + /** + * 根据文件路径解析类别->变量->值 + * @author xuwangcheng + * @date 2021/1/6 16:46 + * @param filePath filePath + * @param poolId poolId + * @return {@link Map} + */ + private static Map> parseExcelInfo (String filePath, Integer poolId) { + Map> infos = new HashMap<>(); + if (StrUtil.isBlank(filePath)) { + return infos; + } + XSSFWorkbook xssfWorkbook = null; + try { + InputStream is = new FileInputStream(filePath); + xssfWorkbook = new XSSFWorkbook(is); + is.close(); + } catch (IOException e) { + logger.error(e); + } + + if (xssfWorkbook != null) { + XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0); + List itemNames = parseItems(xssfSheet, poolId); + if (itemNames.size() == 0) { + throw new YiException(AppErrorCode.TEMPLATE_FILE_ERROR); + } + List valueNames = parseNames(xssfSheet, poolId); + if (valueNames.size() == 0) { + throw new YiException(AppErrorCode.TEMPLATE_FILE_ERROR); + } + + + for (int i = 1;i <= itemNames.size();i++) { + infos.put(itemNames.get(i - 1), parseValues(valueNames, xssfSheet, i)); + } + + } + + return infos; + } + + /** + * 解析值value + * @author xuwangcheng + * @date 2021/1/6 16:46 + * @param valueNames valueNames + * @param xssfSheet xssfSheet + * @param colIndex colIndex + * @return {@link Map} + */ + private static Map parseValues (List valueNames, XSSFSheet xssfSheet, int colIndex) { + Map values = new HashMap<>(valueNames.size()); + for (int i = 1;i <= valueNames.size();i++) { + XSSFRow row = xssfSheet.getRow(i); + XSSFCell cell = row.getCell(colIndex); + values.put(valueNames.get(i - 1), PoiExcelUtil.getValue(cell)); + } + + return values; + } + + /** + * 解析类别 + * @author xuwangcheng + * @date 2021/1/6 16:47 + * @param xssfSheet xssfSheet + * @param poolId poolId + * @return {@link List} + */ + private static List parseItems (XSSFSheet xssfSheet, Integer poolId) { + // 第一行从第二列开始是类别 + XSSFRow xssfRow = xssfSheet.getRow(0); + PoolDataItemService poolDataItemService = (PoolDataItemService) FrameworkUtil.getSpringBean(PoolDataItemService.class); + List itemNames = new ArrayList<>(); + boolean flag = true; + + int i = 1; + while (flag) { + XSSFCell cell = xssfRow.getCell(i); + String name = PoiExcelUtil.getValue(cell); + if (StrUtil.isBlank(name)) { + flag = false; + } else { + PoolDataItem poolDataItem = poolDataItemService.findByName(name, poolId); + itemNames.add(poolDataItem == null ? null : poolDataItem.getItemId()); + } + i ++; + } + + return itemNames; + } + + /** + * 解析变量名称 + * @author xuwangcheng + * @date 2021/1/6 16:47 + * @param xssfSheet xssfSheet + * @param poolId poolId + * @return {@link List} + */ + private static List parseNames (XSSFSheet xssfSheet, Integer poolId) { + List names = new ArrayList<>(); + PoolDataNameService poolDataNameService = (PoolDataNameService) FrameworkUtil.getSpringBean(PoolDataNameService.class); + boolean flag = true; + int i = 1; + while (flag) { + XSSFRow xssfRow = xssfSheet.getRow(i); + if (xssfRow == null) { + flag = false; + continue; + } + XSSFCell cell = xssfRow.getCell(0); + String name = PoiExcelUtil.getValue(cell); + if (StrUtil.isBlank(name)) { + flag = false; + } else { + PoolDataName poolDataName = poolDataNameService.findByName(name, poolId); + names.add(poolDataName == null ? null : poolDataName.getId()); + } + i ++; + } + + return names; + } +} diff --git a/src/main/java/yi/master/util/message/JsonUtil.java b/src/main/java/yi/master/util/message/JsonUtil.java index 07d7ccd..b3ebe34 100644 --- a/src/main/java/yi/master/util/message/JsonUtil.java +++ b/src/main/java/yi/master/util/message/JsonUtil.java @@ -2,6 +2,7 @@ package yi.master.util.message; import cn.hutool.core.util.ReUtil; import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; import yi.master.constant.MessageKeys; @@ -17,6 +18,7 @@ import java.util.*; */ @SuppressWarnings("rawtypes") public class JsonUtil { + private static final Logger logger = Logger.getLogger(JsonUtil.class); // private static String jsonStr = // "{\"ROOT\":{\"PHONE_NO\": \"18755189818\",\"LOGIN_NO\":\"A0AAA0021\",\"CHANNEL_TYPE\": \"1000\",\"ROUTE_NO\": \"18755189818\"}}"; @@ -171,7 +173,7 @@ public class JsonUtil { } catch (Exception e) { // System.out.println("###[Error] viewJsonTree() "+e.getMessage()); - e.printStackTrace(); + logger.error(e); throw new Exception(); } } @@ -213,7 +215,7 @@ public class JsonUtil { } } } catch (Exception e) { - e.printStackTrace(); + logger.error(e); // System.out.println("###[Error] getObjectByJson() "+e.getMessage()); return null; } @@ -331,6 +333,7 @@ public class JsonUtil { } } } catch (Exception e) { + logger.error(e); } return o; diff --git a/src/main/resources/struts.xml b/src/main/resources/struts.xml index 394e36e..124705f 100644 --- a/src/main/resources/struts.xml +++ b/src/main/resources/struts.xml @@ -279,6 +279,19 @@
    + + + + + + jsonObject + false + + + checkNameFlag + + + diff --git a/src/main/resources/update/1.1.1 b/src/main/resources/update/1.1.1 new file mode 100644 index 0000000..ce40439 --- /dev/null +++ b/src/main/resources/update/1.1.1 @@ -0,0 +1,19 @@ +SET FOREIGN_KEY_CHECKS=0; +CREATE TABLE `at_data_pool` ( `pool_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '数据池ID', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据池名称', `mark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '备注信息', `user_id` int(11) NULL DEFAULT NULL COMMENT '创建用户', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `project_id` int(11) NULL DEFAULT NULL COMMENT '所属项目', PRIMARY KEY (`pool_id`) USING BTREE, INDEX `at_data_pool_fk_user_id`(`user_id`) USING BTREE, INDEX `at_data_pool_fk_project_id`(`project_id`) USING BTREE, CONSTRAINT `at_data_pool_fk_project_id` FOREIGN KEY (`project_id`) REFERENCES `at_project_info` (`project_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `at_data_pool_fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `at_user` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +CREATE TABLE `at_pool_data_item` ( `item_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '数据池类别ID', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据名称', `pool_id` int(11) NULL DEFAULT NULL COMMENT '所属池ID', `message_scene_id` int(11) NULL DEFAULT NULL COMMENT '通过关联测试场景去获取数据', `scene_system_id` int(11) NULL DEFAULT NULL COMMENT '接口场景的测试环境', `use_message_scene` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '1' COMMENT '优先使用测试场景去请求数据,否则优先使用request_url', `request_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '通过接口获取,接口必须为get请求,且返回json', `mark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '备注信息', `user_id` int(11) NULL DEFAULT NULL COMMENT '创建用户', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `before_use_auto_update` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '0' COMMENT '使用前自动更新数据,前提是必须配置了requestUrl或者messageScene', `response_data_json_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '通过请求获取的结果中,需要的测试数据所在的JSON_PATH,例如ROOT.OUT_DATA.DATA', PRIMARY KEY (`item_id`) USING BTREE, INDEX `at_pool_data_item_fk_message_scene_id`(`message_scene_id`) USING BTREE, INDEX `at_pool_data_item_fk_scene_system_id`(`scene_system_id`) USING BTREE, CONSTRAINT `at_pool_data_item_fk_message_scene_id` FOREIGN KEY (`message_scene_id`) REFERENCES `at_message_scene` (`message_scene_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `at_pool_data_item_fk_scene_system_id` FOREIGN KEY (`scene_system_id`) REFERENCES `at_business_system` (`system_id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +CREATE TABLE `at_pool_data_name` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '数据ID', `pool_id` int(11) NULL DEFAULT NULL COMMENT '数据池ID', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据name值', `default_value` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '默认值', `mark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '备注信息', `user_id` int(11) NULL DEFAULT NULL COMMENT '创建用户', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE, INDEX `at_pool_data_fk_user_id`(`user_id`) USING BTREE, INDEX `at_pool_data_fk_pool_id`(`pool_id`) USING BTREE, CONSTRAINT `at_pool_data_fk_pool_id` FOREIGN KEY (`pool_id`) REFERENCES `at_data_pool` (`pool_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `at_pool_data_fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `at_user` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +CREATE TABLE `at_pool_data_value` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据值,可填写全局的变量模版', `name_id` int(11) NULL DEFAULT NULL COMMENT '对应的name', `user_id` int(11) NULL DEFAULT NULL COMMENT '创建用户', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `item_id` int(11) NULL DEFAULT NULL COMMENT '所属的池的数据类别ID', `mark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +ALTER TABLE `at_test_config` ADD COLUMN `pool_id` int(11) NULL DEFAULT NULL COMMENT '数据池' AFTER `public_header`; +ALTER TABLE `at_test_config` ADD COLUMN `pool_item_ids` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '数据池下的类别,默认测试所有,否则只测试选中的' AFTER `pool_id`; +ALTER TABLE `at_test_config` MODIFY COLUMN `config_id` int(11) NOT NULL COMMENT '配置ID' FIRST; +ALTER TABLE `at_test_config` MODIFY COLUMN `user_id` int(11) NULL DEFAULT NULL COMMENT '所属用户' AFTER `config_id`; +ALTER TABLE `at_test_config` MODIFY COLUMN `run_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '运行模式,并行或者串行' AFTER `check_Data_flag`; +ALTER TABLE `at_test_config` MODIFY COLUMN `systems` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT ' ' COMMENT '测试环境,不配置默认取第一个,否则测试所有可用环境' AFTER `retry_count`; +ALTER TABLE `at_test_config` MODIFY COLUMN `top_scenes` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT ' ' COMMENT '指定测试场景的ID' AFTER `systems`; +ALTER TABLE `at_test_config` MODIFY COLUMN `config_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '配置ID' FIRST; +ALTER TABLE `at_test_config` ADD CONSTRAINT `at_test_config_fk_pool_id` FOREIGN KEY (`pool_id`) REFERENCES `at_data_pool` (`pool_id`) ON DELETE RESTRICT ON UPDATE RESTRICT; +ALTER TABLE `at_test_config` ADD INDEX `at_test_config_fk_pool_id`(`pool_id`) USING BTREE; +ALTER TABLE `at_test_result` ADD COLUMN `pool_item_id` int(11) NULL DEFAULT NULL COMMENT '测试数据所属数据池类别' AFTER `message_type`; +ALTER TABLE `at_test_result` ADD CONSTRAINT `at_test_result_fk_pool_item_id` FOREIGN KEY (`pool_item_id`) REFERENCES `at_pool_data_item` (`item_id`) ON DELETE RESTRICT ON UPDATE RESTRICT; +ALTER TABLE `at_test_result` ADD INDEX `at_test_result_fk_pool_item_id`(`pool_item_id`) USING BTREE; +SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file diff --git a/src/main/webapp/index.js b/src/main/webapp/index.js index 32b248a..8b517f9 100644 --- a/src/main/webapp/index.js +++ b/src/main/webapp/index.js @@ -56,6 +56,7 @@ $(document).ready(function() { "messageScene-validateFullJson", "messageScene-validateKeyword", "role-power", + "showDataPoolUseSample", "viewWindow"]); /*****************************************************/ }); diff --git a/src/main/webapp/js/dcits.js b/src/main/webapp/js/dcits.js index dbc474f..97d2c44 100644 --- a/src/main/webapp/js/dcits.js +++ b/src/main/webapp/js/dcits.js @@ -1985,6 +1985,7 @@ function renderResultViewPage(result, messageSceneId) { businessSystemName:result.businessSystemName, color:color, flag:flag, + poolItemName: result.poolName ? (result.poolName + '-' + result.poolItemName) : '', useTime:result.useTime, statusCode:result.statusCode, responseMessage:(result.responseMessage == "null") ? "" : result.responseMessage, diff --git a/src/main/webapp/js/globalConstant.js b/src/main/webapp/js/globalConstant.js index bfd2157..99f4f91 100644 --- a/src/main/webapp/js/globalConstant.js +++ b/src/main/webapp/js/globalConstant.js @@ -103,15 +103,33 @@ var REQUEST_URL = { DEL: "pool-del", GET: "pool-get", EDIT: "pool-edit", - LIST: "pool-list" + LIST: "pool-list", + LIST_ALL: "pool-listAll", + SHOW_JSON_DATA: "pool-showJsonData" }, //数据池变量 POOL_DATA_NAME: { DEL: "poolDataName-del", GET: "poolDataName-get", EDIT: "poolDataName-edit", - LIST_ALL: "poolDataName-listAll", - CHECK_NAME: "poolDataName-checkName" + LIST: "poolDataName-list", + CHECK_NAME: "poolDataName-checkName", + BATCH_ADD: "poolDataName-batchAdd" + }, + // 数据池类别 + POOL_DATA_ITEM: { + DEL: "poolDataItem-del", + GET: "poolDataItem-get", + EDIT: "poolDataItem-edit", + LIST: "poolDataItem-list", + LIST_ALL: "poolDataItem-listAll", + BATCH_ADD: "poolDataItem-batchAdd", + LIST_NAME_VALUE: "poolDataItem-listNameValue", + SAVE_NAME_VALUE: "poolDataItem-saveNameValue", + EXPORT_VALUE_TEMPLATE: "poolDataItem-exportValueTemplate", + CHECK_NAME: "poolDataItem-checkName", + IMPORT_ITEM_VALUE: "poolDataItem-importItemValue", + UPDATE_VALUE_BY_REQUEST: "poolDataItem-updateValueByRequest" }, //测试报告 REPORT: { diff --git a/src/main/webapp/libs/h-ui/css/H-ui.min.css b/src/main/webapp/libs/h-ui/css/H-ui.min.css index 7a318fe..7c565ad 100644 --- a/src/main/webapp/libs/h-ui/css/H-ui.min.css +++ b/src/main/webapp/libs/h-ui/css/H-ui.min.css @@ -9,4 +9,4 @@ * http://opensource.org/licenses/MIT * */ -@charset "utf-8";*{word-wrap:break-word}html,body,h1,h2,h3,h4,h5,h6,hr,p,iframe,dl,dt,dd,ul,ol,li,pre,form,button,input,textarea,th,td,fieldset{margin:0;padding:0}ul,ol,dl{list-style-type:none}html,body{*position:static}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}input,button{overflow:visible;vertical-align:middle;outline:0}input[type="submit"],input[type="reset"],input[type="button"],input[type="text"],input[type="password"]{-webkit-appearance:none;outline:0}body,th,td,button,input,select,textarea{font-family:"Microsoft Yahei","Hiragino Sans GB","Helvetica Neue",Helvetica,tahoma,arial,"WenQuanYi Micro Hei",Verdana,sans-serif,"\5B8B\4F53";font-size:12px;color:#333;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media(max-width :767px){html{overflow-y:auto}body,th,td,button,input,select,textarea{font-size:14px}}body{line-height:1.6}h1,h2,h3,h4,h5,h6{font-size:100%}a,area{outline:0;blr:expression(this.onFocus=this.blur())}a{text-decoration:none;cursor:pointer}a:hover{text-decoration:underline;outline:0}a.ie6:hover{zoom:1}a:focus{outline:0}a:hover,a:active{outline:0}:focus{outline:0}sub,sup{vertical-align:baseline}button,input[type="button"],input[type="submit"]{line-height:normal!important}img{border:0;vertical-align:middle}a img,img{-ms-interpolation-mode:bicubic}*html{overflow:-moz-scrollbars-vertical;zoom:expression(function(ele){ele.style.zoom = "1";document.execCommand("BackgroundImageCache",false,true)}(this))}header,footer,section,aside,details,menu,article,section,nav,address,hgroup,figure,figcaption,legend{display:block;margin:0;padding:0}time{display:inline}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}legend{width:100%;margin-bottom:20px;font-size:21px;line-height:40px;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}svg:not(:root){overflow:hidden}fieldset{border-width:0;padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}.cl:after,.clearfix:after{content:"\20";display:block;height:0;clear:both;visibility:hidden}.cl,.clearfix{zoom:1}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width :992px){.container{width:960px}}@media(min-width :1200px){.container{width:1170px}}@media(min-width :1300px){.container{width:1270px}}@media print{.container{width:auto}}.row{box-sizing:border-box;margin-left:-15px;margin-right:-15px}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{min-height:1px;position:relative;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;-o-transition:all .3s ease-in;transition:all .3s ease-in}.col-1{width:8.33333%}.col-2{width:16.66667%}.col-3{width:25%}.col-4{width:33.33333%}.col-5{width:41.66667%}.col-6{width:50%}.col-7{width:58.33333%}.col-8{width:66.66667%}.col-9{width:75%}.col-10{width:83.33333%}.col-11{width:91.66667%}.col-12{width:100%}.col-offset-0{margin-left:0}.col-offset-1{margin-left:8.33333%}.col-offset-2{margin-left:16.66667%}.col-offset-3{margin-left:25%}.col-offset-4{margin-left:33.33333%}.col-offset-5{margin-left:41.66667%}.col-offset-6{margin-left:50%}.col-offset-7{margin-left:58.33333%}.col-offset-8{margin-left:66.66667%}.col-offset-9{margin-left:75%}.col-offset-10{margin-left:83.33333%}.col-offset-11{margin-left:91.66667%}.col-push-0{position:relative;left:0;right:auto}.col-pull-0{right:0;left:auto}.col-push-1{left:8.33333%;right:auto}.col-pull-1{right:8.33333%;left:auto}.col-push-2{left:16.66667%;right:auto}.col-pull-2{right:16.66667%;left:auto}.col-push-3{left:25%;right:auto}.col-pull-3{right:25%;left:auto}.col-push-4{left:33.33333%;right:auto}.col-pull-4{right:33.33333%;left:auto}.col-push-5{left:41.66667%;right:auto}.col-pull-5{right:41.66667%;left:auto}.col-push-6{left:50%;right:auto}.col-pull-6{right:50%;left:auto}.col-push-7{left:58.33333%;right:auto}.col-pull-7{right:58.33333%;left:auto}.col-push-8{left:66.66667%;right:auto}.col-pull-8{right:66.66667%;left:auto}.col-push-9{left:75%;right:auto}.col-pull-9{right:75%;left:auto}.col-push-10{left:83.33333%;right:auto}.col-pull-10{right:83.33333%;left:auto}.col-push-11{left:91.66667%;right:auto}.col-pull-11{right:91.66667%;left:auto}.col-1-1{width:100%}.col-2-1{width:50%}.col-3-1{width:33.333333%}.col-3-2{width:66.666667%}.col-4-1{width:25%}.col-4-3{width:75%}.col-5-1{width:20%}.col-5-2{width:40%}.col-5-3{width:60%}.col-5-4{width:80%}.col-6-1{width:16.666667%}.col-6-5{width:83.333333%}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media(max-width:767px){.responsive [class^="col-"],.responsive [class*=" col-"]{float:none!important;width:auto!important}.responsive [class^="col-offset-"],.responsive [class*=" col-offset-"]{margin-left:0!important}}@media(min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.visible-xs,.visible-sm,.visible-md,.visible-lg,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media(max-width :767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}.hidden-xs{display:none!important}.visible-xs-block{display:block!important}.visible-xs-inline{display:inline!important}.visible-xs-inline-block{display:inline-block!important}}@media(min-width :768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}.hidden-sm{display:none!important}.visible-sm-block{display:block!important}.visible-sm-inline{display:inline!important}.visible-sm-inline-block{display:inline-block!important}}@media(min-width :992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}.hidden-md{display:none!important}.visible-md-block{display:block!important}.visible-md-inline{display:inline!important}.visible-md-inline-block{display:inline-block!important}}@media(min-width :1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}.hidden-lg{display:none!important}.visible-lg-block{display:block!important}.visible-lg-inline{display:inline!important}.visible-lg-inline-block{display:inline-block!important}}.visible-print{display:none!important}.visible-print-block{display:none!important}.visible-print-inline{display:none!important}.visible-print-inline-block{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.visible-print-block{display:block!important}.visible-print-inline{display:inline!important}.visible-print-inline-block{display:inline-block!important}.hidden-print{display:none!important}}.Hui-wraper,.wp{margin-left:auto;margin-right:auto;text-align:left}.sd{float:right}.ct2 .mn{float:left}.ct2 .sd{float:right}.ct2_r .leftmenu{float:left}.ct2_r .mn{float:right}.ct3 .app{float:left;margin-right:20px}.ct3 .mn{float:left;border-left:solid 1px #ddd}.ct3 .sd{float:right}.w-1000{width:1000px}.w-980{width:980px}.w-300{width:300px}.w-200{width:200px}@media(max-width:1000px){.Hui-wraper,.wp,{width:auto!important;padding:0 15px!important}}@media print{.Hui-wraper{width:auto}}h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small{font-weight:400;line-height:1;color:#999}h1,h2,h3{padding-top:20px;padding-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:18px}h5{font-size:14px}h6{font-size:12px}p{margin-bottom:10px}small{font-size:85%}b,strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}mark{color:#000;background:#ff0}dfn{font-style:italic}del{font-family:Simsun}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.en{font-family:Arial!important}.text-l{text-align:left}.text-r{text-align:right}.text-c{text-align:center}.va *{vertical-align:sub!important;*vertical-align:middle!important;_vertical-align:middle!important}.va-t{vertical-align:top!important}.va-m{vertical-align:middle!important}.va-b{vertical-align:bottom!important}.pos-r{position:relative}.pos-a{position:absolute}.pos-f{position:fixed}.l,.f-l{float:left!important;_display:inline}.r,.f-r{float:right!important;_display:inline}[class*="span"].r,[class*="span"].f-r{float:right}.left{left:0;right:auto}.right{right:0;left:auto}.top{top:auto;bottom:0}.bottom{top:0;bottom:auto}.text-overflow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.line{font-size:0;line-height:0;border-top:solid 1px #eee;float:none}.mt-5{margin-top:5px}.mt-10{margin-top:10px}.mt-15{margin-top:15px}.mt-20{margin-top:20px}.mt-25{margin-top:25px}.mt-30{margin-top:30px}.mt-35{margin-top:35px}.mt-40{margin-top:40px}.mt-50{margin-top:50px}.mb-5{margin-bottom:5px}.mb-10{margin-bottom:10px}.mb-15{margin-bottom:15px}.mb-20{margin-bottom:20px}.mb-30{margin-bottom:30px}.mb-40{margin-bottom:40px}.mb-50{margin-bottom:50px}.ml-5{margin-left:5px}.ml-10{margin-left:10px}.ml-15{margin-left:15px}.ml-20{margin-left:20px}.ml-30{margin-left:30px}.ml-40{margin-left:40px}.ml-50{margin-left:50px}.mr-5{margin-right:5px}.mr-10{margin-right:10px}.mr-15{margin-right:15px}.mr-20{margin-right:20px}.mr-30{margin-right:30px}.mr-40{margin-right:40px}.mr-50{margin-right:50px}.pt-5{padding-top:5px}.pt-10{padding-top:10px}.pt-20{padding-top:20px}.pb-5{padding-bottom:5px}.pb-10{padding-bottom:10px}.pb-20{padding-bottom:20px}.pb-30{padding-bottom:30px}.pl-5{padding-left:5px}.pl-10{padding-left:10px}.pl-20{padding-left:20px}.pl-30{padding-left:30px}.pr-5{padding-right:5px}.pr-10{padding-right:10px}.pr-20{padding-right:20px}.pd-5{padding:5px}.pd-10{padding:10px}.pd-15{padding:15px}.pd-20{padding:20px}.pd-30{padding:30px}.pd-40{padding:40px}.bk-gray{border:solid 1px #eee}.radius{border-radius:4px}.size-MINI.radius{border-radius:3px}.size-L.radius{border-radius:5px}.size-XL.radius{border-radius:6px}.round{border-radius:50%;overflow:hidden}.box-shadow{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.1);box-shadow:0 1px 2px rgba(0,0,0,0.1)}.text-shadow{-webkit-text-shadow:0 0 2px rgba(0,0,0,0.2);text-shadow:0 0 2px rgba(0,0,0,0.2)}.pipe{margin:0 5px;color:#CCC;font-size:10px!important}.f-12{font-size:12px}.f-14{font-size:14px}.f-16{font-size:16px}.f-18{font-size:18px}.f-20{font-size:20px}.f-24{font-size:24px}.f-26{font-size:26px}.f-28{font-size:28px}.f-30{font-size:30px}.lh-16{line-height:16px}.lh-18{line-height:18px}.lh-20{line-height:20px}.lh-22{line-height:22px}.lh-24{line-height:24px}.lh-26{line-height:26px}.lh-28{line-height:28px}.lh-30{line-height:30px}.l16{line-height:16px}.l18{line-height:18px}.l20{line-height:20px}.l22{line-height:22px}.l-24{line-height:24px}.l-26{line-height:26px}.l-28{line-height:28px}.l-30{line-height:30px}body{background-color:#fff;color:#333}.bg-fff{background-color:#fff}a{color:#333}a:hover,.active a{color:#06c}.c-primary,.c-primary a,a.c-primary{color:#5a98de}.c-primary a:hover,a.c-primary:hover{color:#5a98de}.c-secondary,.c-secondary a,a.c-secondary{color:#555}.c-secondary a:hover,a.c-secondary:hover{color:#555}.c-success,.c-success a,a.c-success{color:#5eb95e}.c-success a:hover,a.c-success:hover{color:#5eb95e}.c-danger,.c-danger a,a.c-danger{color:#dd514c}.c-danger a:hover,a.c-danger:hover{color:#dd514c}.c-warning,.c-warning a,a.c-warning{color:#f37b1d}.c-warning a:hover,a.c-warning:hover{color:#f37b1d}.c-error,.c-error a,a.c-error{color:#c00}.c-error a:hover,a.c-error:hover{color:#c00}.c-333,.c-333 a,a.c-333{color:#333}.c-333 a:hover,a.c-333:hover{color:#333}.c-666,.c-666 a,a.c-666{color:#666}.c-666 a:hover,a.c-666:hover{color:#666}.c-999,.c-999 a,a.c-999{color:#999}.c-999 a:hover,a.c-999:hover{color:#999}.c-red,.c-red a,a.c-red{color:red}.c-red a:hover,a.c-red:hover{color:red}.c-green,.c-green a,a.c-green{color:green}.c-red a:hover,a.c-red:hover{color:green}.c-blue,.c-blue a,a.c-blue{color:blue}.c-blue a:hover,a.c-blue:hover{color:blue}.c-white,.c-white a,a.c-white{color:white}.c-white a:hover,a.c-white:hover{color:white}.c-black,.c-black a{color:black}.c-black a:hover,a.c-black:hover{color:black}.c-orange,.c-orange a,a.c-orange{color:orange}.c-orange a:hover,a.c-orange:hover{color:orange}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.text-r{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.text-r p,blockquote.text-r small{text-align:right}blockquote.text-r small:before{content:''}blockquote.text-r small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}.content{position:relative;font-size:17px;line-height:1.8;overflow:hidden;text-align:left;word-break:break-all;word-wrap:break-word}.content h3{font-size:18px}.content h4{font-size:16px}.content p{margin-bottom:1.5rem;text-align:justify;word-break:break-all}.content p.text-c{text-align:center}.indent{text-indent:2em}.content img{max-width:100%}.content ul{text-indent:2em}@media(max-width:767px){.content{font-size:16px}}@media(max-width:480px){.content img{max-width:100%!important;height:auto!important;width:expression(this.width>320 ? "320px":this.width)!important}*html .content img{width:expression(this.width>320&&this.width>this.height?320:auto)}}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}.list-view>.item{padding:10px;position:relative;overflow:hidden}.list-view>.item .date{font-size:12px;font-family:Arial;color:#999}@media(max-width:767px){.list-view>.item{font-size:18px;padding:11px 15px;border-bottom:1px solid #eee}.list-view>.item>a{display:block;margin:-11px -15px}.night .list-view>.item{border-bottom:1px solid #1f1f1f}.list-view>.item .date{display:none}.list-view>.item .Hui-iconfont{background-size:9px auto;margin-top:-7px;position:absolute;right:15px;top:50%}}.list-top>.item{padding-left:30px}.list-top>.item .num{position:absolute;top:11px;display:block;width:20px;height:20px;color:#fff;background-color:#5a98de;text-align:center}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.hide{display:none}[hidden]{display:none}.hidden{display:none!important;visibility:hidden!important}.f-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}.show{display:block}.invisible{visibility:hidden}.input-text,.btn,.input-text.size-M,.btn.size-M{font-size:14px;height:31px;*height:auto;line-height:1.42857;padding:4px}a.btn,a.btn.size-M,span.btn,span.btn.size-M{line-height:21px}.btn,.btn.size-M{padding:4px 12px}.input-text.size-MINI,.btn.size-MINI{font-size:12px;height:23px;padding:1px 2px;line-height:1.42857}a.btn.size-MINI,span.btn.size-MINI{line-height:21px}.btn.size-MINI{padding:1px 4px}.input-text.size-S,.btn.size-S{font-size:12px;height:27px;padding:3px;line-height:1.42857}a.btn.size-S,span.btn.size-S{line-height:19px}.btn.size-S{padding:3px 8px}.input-text.size-L,.btn.size-L{font-size:16px;height:41px;padding:8px}a.btn.size-L,span.btn.size-L{line-height:23px}.btn.size-L{padding:8px 16px}.input-text.size-XL,.btn.size-XL{font-size:18px;height:48px;padding:10px}a.btn.size-XL,span.btn.size-XL{line-height:26px}.btn.size-XL{padding:10px 24px}@media(max-width:767px){.responsive .input-text.size-MINI,.responsive .btn.size-MINI{height:24px}.responsive .input-text.size-S,.responsive .btn.size-S{font-size:14px;height:30px}.responsive .input-text,.btn,.responsive .input-text.size-M,.responsive .btn.size-M{font-size:16px;height:36px}.responsive .input-text.size-L,.responsive .btn.size-L{font-size:18px;height:42px}.responsive .input-text.size-XL,.responsive .btn.size-XL{font-size:20px;height:48px}}code{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace}pre .title,pre .keyword,pre .body,pre .des{color:#333}pre{display:block;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;padding:9.5px;margin-bottom:10px;font-size:12px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px;color:#333}.prettyprint{margin-bottom:20px;padding:8px;background-color:#f7f7f9;border:1px solid #e1e1e8}.prettyprint .com{color:#998;font-style:italic}.prettyprint .tag{color:#007}.prettyprint .lit{color:#195f91}.prettyprint .pun,.prettyprint .opn,.prettyprint .clo{color:#93a1a1}.prettyprint .fun{color:#dc322f}.prettyprint .str,.prettyprint .atv{color:#D14}.prettyprint .kwd,.prettyprint .prettyprint .tag{color:#1e347b}.prettyprint .typ,.prettyprint .atn,.prettyprint .dec,.prettyprint .var{color:teal}.prettyprint .pln{color:#48484c}.prettyprint.linenums{box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0}.pre-scrollable{max-height:340px;overflow-y:scroll}ol.linenums{list-style:decimal outside none;margin-left:20px}ol.linenums li{line-height:28px;padding-left:10px}pre ol.linenums{margin:0 0 0 33px}pre ol.linenums li{padding-left:12px;color:#bbb;line-height:18px;text-shadow:0 1px 0 #fff}@media(max-width:767px){pre ol.linenums{margin-left:0;list-style:none}ol.linenums li{padding-left:0}.prettyprint.linenums{box-shadow:inset 0 0 0 #fbfbfc,inset 0 0 0 #ececf0}}table{width:100%;empty-cells:show;background-color:transparent;border-collapse:collapse;border-spacing:0}table th{text-align:left;font-weight:400}.table th{font-weight:bold}.table th,.table td{padding:8px;line-height:20px;word-break:break-all}.table td{text-align:left}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-border{border-top:1px solid #ddd}.table-border th,.table-border td{border-bottom:1px solid #ddd}.table-bg thead th{background-color:#f5fafe}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-border.table-bordered{border-bottom:0}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-condensed th,.table-condensed td{padding:4px 5px}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}.table tbody tr.selected td{background-color:#f3f3f3}.table tbody tr.active,.table tbody tr.active>td,.table tbody tr.active>th,.table tbody tr .active{background-color:#f5f5f5!important}.table tbody tr.success,.table tbody tr.success>td,.table tbody tr.success>th,.table tbody tr .success{background-color:#dff0d8!important}.table tbody tr.warning,.table tbody tr.warning>td,.table tbody tr.warning>th,.table tbody tr .warning{background-color:#fcf8e3!important}.table tbody tr.danger,.table tbody tr.danger>td,.table tbody tr.danger>th,.table tbody tr .danger{background-color:#f2dede!important}.table .text-c th,.table .text-c td{text-align:center}.table .text-r th,.table .text-r td{text-align:right}.table th.text-l,.table td.text-l{text-align:left!important}.table th.text-c,.table td.text-c{text-align:center!important}.table th.text-r,.table td.text-r{text-align:right!important}table.dataTable{border-collapse:separate;border-spacing:0;clear:both}table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting{cursor:pointer;background-repeat:no-repeat;background-position:right center}table.dataTable thead .sorting{background-image:url(../images/dataTable/sort_both.png)}table.dataTable thead .sorting_asc{background-image:url(../images/dataTable/sort_asc.png)}table.dataTable thead .sorting_desc{background-image:url(../images/dataTable/sort_desc.png)}.dataTable td.sorting_1{background-color:#f5fafe}.dataTables_wrapper .dataTables_length{float:left;padding-bottom:20px}.dataTables_wrapper .dataTables_length .select{width:50px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter .input-text{width:auto}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:10px;font-size:14px;color:#666}.dataTables_wrapper .dataTables_paginate{float:right;padding-top:10px;text-align:right}.dataTables_wrapper .dataTables_paginate .paginate_button{border:1px solid #ccc;cursor:pointer;display:inline-block;margin-left:2px;text-align:center;text-decoration:none;color:#666;height:26px;line-height:26px;text-decoration:none;margin:0 0 6px 6px;padding:0 10px;font-size:14px}.dataTables_wrapper .dataTables_paginate .paginate_button:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{background:#5a98de;color:#fff}@media(max-width:767px){table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}table-responsive>.table{margin-bottom:0}table-responsive>.table>thead>tr>th,table-responsive>.table>tbody>tr>th,table-responsive>.table>tfoot>tr>th,table-responsive>.table>thead>tr>td,table-responsive>.table>tbody>tr>td,table-responsive>.table>tfoot>tr>td{white-space:nowrap}table-responsive>.table-bordered{border:0}table-responsive>.table-bordered>thead>tr>th:first-child,table-responsive>.table-bordered>tbody>tr>th:first-child,table-responsive>.table-bordered>tfoot>tr>th:first-child,table-responsive>.table-bordered>thead>tr>td:first-child,table-responsive>.table-bordered>tbody>tr>td:first-child,table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}table-responsive>.table-bordered>thead>tr>th:last-child,table-responsive>.table-bordered>tbody>tr>th:last-child,table-responsive>.table-bordered>tfoot>tr>th:last-child,table-responsive>.table-bordered>thead>tr>td:last-child,table-responsive>.table-bordered>tbody>tr>td:last-child,table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}table-responsive>.table-bordered>tbody>tr:last-child>th,table-responsive>.table-bordered>tfoot>tr:last-child>th,table-responsive>.table-bordered>tbody>tr:last-child>td,table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}.input-text,.textarea{box-sizing:border-box;border:solid 1px #ddd;width:100%;-webkit-transition:all .2s linear 0s;-moz-transition:all .2s linear 0s;-o-transition:all .2s linear 0s;transition:all .2s linear 0s}.textarea{height:100px;resize:none;font-size:14px;padding:4px}.textarea-numberbar{position:absolute;right:20px;bottom:5px;z-index:1;margin-bottom:0}.textarea-length{font-style:normal}.input-text:hover,.textarea:hover{border:solid 1px #3bb4f2}.input-text.focus,.textarea.focus{border:solid 1px #0f9ae0 \9;border-color:rgba(82,168,236,0.8);box-shadow:0 1px 1px rgba(0,0,0,0.075) inset,0 0 8px rgba(102,175,233,0.6)}.input-text.disabled,.textarea.disabled,.input-text.disabled.focus,.textarea.disabled.focus{background-color:#ededed;cursor:default;border-color:#ddd;-webkit-box-shadow:inset 0 2px 2px #e8e7e7;-moz-box-shadow:inset 0 2px 2px #e8e7e7;box-shadow:inset 0 2px 2px #e8e7e7}.input-text.disabled,.textarea.disabled{background-color:#e6e6e6;cursor:default}.input-text.box-shadow,.textarea.box-shadow{-ms-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.input-text.inline{display:inline-block;width:auto}input[type="radio"],input[type="checkbox"]{line-height:normal;margin-top:-4px}.check-box,.radio-box{display:inline-block;box-sizing:border-box;cursor:pointer;position:relative;padding-left:30px;padding-right:20px}.icheckbox,.icheckbox-red,.icheckbox-green,.icheckbox-blue,.icheckbox-aero,.icheckbox-grey,.icheckbox-orange,.icheckbox-yellow,.icheckbox-pink,.icheckbox-purple,.iradio,.iradio-red,.iradio-green,.iradio-blue,.iradio-aero,.iradio-grey,.iradio-orange,.iradio-yellow,.iradio-pink,.iradio-purple{position:absolute;top:4px;left:0}@media(max-width:767px){.responsive .check-box,.responsive .radio-box{display:block}}.select-box{border:solid 1px #ddd;box-sizing:border-box;vertical-align:middle;width:100%;display:inline-block}.select{border:solid 1px #ddd;box-sizing:border-box;cursor:pointer;line-height:normal;font-weight:normal;width:100%;white-space:nowrap}.select-box .select{border:0}.select-box.inline,.select-box.inline .select{width:auto}.select-box,.select-box.size-M{padding:4px 5px}.select,.size-M .select{font-size:14px}.select-box.size-MINI{padding:0 5px}.size-MINI .select{font-size:12px}.select-box.size-S{padding:3px 5px}.size-S .select{font-size:12px}.select-box.size-L{padding:8px 5px}.size-L .select{font-size:16px}.select-box.size-XL{padding:10px 5px}.size-XL .select{font-size:18px}@media(max-width:767px){.responsive .select-box{border:0}.responsive .select-box .select,.responsive .select{border:solid 1px #ddd;padding:10px;font-size:16px}.responsive .select-box,.responsive .select-box.size-M,.responsive .select-box.size-MINI,.responsive .select-box.size-S,.responsive .select-box.size-L,.responsive .select-box.size-XL{height:auto;padding:0}}.select-wrapper{position:relative;display:inline-block;font-size:14px;cursor:default}.select-default{zoom:1;display:block;padding-left:10px;padding-right:30px;background-color:#fff;border:solid 1px #d0d0d0;height:34px;line-height:34px}.jsselect.radius{overflow:visible}.jsselect.radius .select-default{border-radius:4px}.jsselect.radius .select-list{border-radius:4px;border-top-left-radius:0;border-top-right-radius:0}.select-icon{position:absolute;height:8px;width:12px;right:10px;top:50%;margin-top:-4px;background:url(../images/jselect/iconpic-arrow-down2.png) no-repeat center}.unselectable{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.select-list{position:absolute;left:0;right:0;top:100%;z-index:1;line-height:34px;max-height:320px;overflow:auto;background-color:#fff;background-clip:padding-box;_height:expression(this.scrollHeight>319 ? "320px":"auto");-moz-box-shadow:0 1px 2px rgba(0,1,1,0.2);-webkit-box-shadow:0 1px 2px rgba(0,1,1,0.2);box-shadow:0 1px 2px rgba(0,1,1,0.2);box-sizing:border-box;border:solid 1px #d0d0d0;behavior:url(ie-css3.htc)}.select-item{margin:0;padding:0}.select-option{background:#fff;line-height:34px;text-align:left;white-space:nowrap;cursor:pointer;border-bottom:1px solid #f2f2f2;padding:0 10px}.select-item .selected{background-color:#148cf1;color:#fff}.btn-upload{position:relative;display:inline-block;height:31px;*display:inline;overflow:hidden;vertical-align:middle;cursor:pointer}.upload-url{cursor:pointer;width:300px}.input-file{position:absolute;right:0;top:0;cursor:pointer;z-index:1;font-size:30em;opacity:0;filter:alpha(opacity=0)}.form-group .upload-btn{margin-left:-1px}.btn-upload .icon-add,.btn-upload .icon-minus{cursor:pointer;display:inline-block;font-family:Arial;font-size:30px;height:31px;line-height:31px;text-align:center;vertical-align:middle;width:36px}@media(max-width:767px){.upload-btn{display:none}.upload-url{display:none}}.numberControlBox{display:inline-block;overflow:hidden;vertical-align:middle}.ncb-up,.ncb-down{font-size:0;display:block;height:10px;background-color:#f4f4f4;background:-moz-linear-gradient(top,#fff 0,#e6e6e6 50%,#fff 100%);width:24px;border:1px solid #d1d1d1;cursor:pointer}.ncb-up{margin-bottom:1px}.numberControlBox .ncb_ico{display:block;height:10px;background-image:url(../images/iconpic-arrow.png);background-repeat:no-repeat}.ncb-up .ncb_ico{background-position:-22px center}.ncb-down .ncb_ico{background-position:1px center}.ncb_btn_hover{border:1px solid #9dc7e7;background-color:#dff2fc;background:-moz-linear-gradient(top,#fff 0,#d2edfa 50%,#fff 100%)}.ncb_btn_selected{border:1px solid #6198c2;background-color:#aee1fb;background:-moz-linear-gradient(top,#fff 0,#aee1fb 50%,#fff 100%)}.input-text[type="number"]{width:80px}label,.placeholder{font-size:14px}.form legend{font-size:20px}.form .row{margin-top:15px}.form-label{display:block;color:#555}.formControls{position:relative}.formControls>*{vertical-align:middle}.placeholder{position:absolute;left:4px;top:4px;color:#c6c6c6;cursor:text}.form-horizontal .form-label{margin-top:3px;cursor:text;text-align:right}.form-horizontal .Validform_checktip{margin-top:5px}::-webkit-input-placeholder{color:#b3b3b3}:-moz-placeholder{color:#b3b3b3}::-moz-placeholder{color:#b3b3b3}:-ms-input-placeholder{color:#b3b3b3}.placeholder{color:#adb0be;position:absolute;z-index:9}@media(max-width:767px){.form-horizontal .form-label{text-align:left}}.Validform_error,input.error,select.error{background-color:#fbe2e2;border-color:#c66161;color:#c00}.Validform_wrong,.Validform_right,.Validform_warning{display:inline-block;height:20px;font-size:12px;vertical-align:middle;padding-left:25px}.Validform_wrong{background:url(../images/validform/iconpic-error.png) no-repeat 0 center;color:#ef392b}.Validform_right{background:url(../images/validform/iconpic-right.png) no-repeat 0 center}.Validform_warning{background:url(../images/validform/iconpic-warning.png) no-repeat 0 center;color:#777}label.error{position:absolute;right:18px;top:5px;color:#ef392b;font-size:12px}.passwordStrength b{font-weight:400}.passwordStrength b,.passwordStrength span{display:inline-block;vertical-align:middle;line-height:16px;line-height:18px\9;height:16px}.passwordStrength span{width:57px;text-align:center;background-color:#d0d0d0;border-right:1px solid #fff}.passwordStrength .last{border-right:0}.passwordStrength .bgStrength{color:#fff;background-color:#fcc900}#Validform_msg{font-size:14px;width:300px;-webkit-box-shadow:2px 2px 3px #aaa;-moz-box-shadow:2px 2px 3px #aaa;background:#fff;position:absolute;top:0;right:50px;z-index:99999;display:none;filter:progid:DXImageTransform.Microsoft.Shadow(Strength=3,Direction=135,Color='#999999');box-shadow:2px 2px 0 rgba(0,0,0,0.1)}#Validform_msg .iframe{position:absolute;left:0;top:-1px;z-index:-1}#Validform_msg .Validform_title{font-size:20px;padding:10px;text-align:left;color:#fff;position:relative;background-color:#fcc900}#Validform_msg a.Validform_close:link,#Validform_msg a.Validform_close:visited{position:absolute;right:8px;top:6px;color:#fff;text-decoration:none;font-family:Verdana}#Validform_msg a.Validform_close:hover{color:#fff}#Validform_msg .Validform_info{padding:10px;border:1px solid #bbb;border-top:0;text-align:left}@media(max-width:767px){.responsive .Validform_checktip{margin-top:10px}}.close{font-size:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;box-sizing:border-box;cursor:pointer;text-align:center;font-weight:400;white-space:nowrap;vertical-align:middle;-moz-padding-start:npx;-moz-padding-end:npx;border:solid 1px #ddd;background-color:#fff;width:auto;*zoom:1;*overflow:visible;-webkit-transition:background-color .1s linear;-moz-transition:background-color .1s linear;-o-transition:background-color .1s linear;transition:background-color .1s linear}a.btn:hover,a.btn:focus,a.btn:active,a.btn.active,a.btn.disabled,a.btn[disabled]{text-decoration:none}.btn:active,.btn.active{background-color:#ccc}.btn:first-child{*margin-left:0}.btn.active,.btn:active{-moz-box-shadow:0 1px 8px rgba(0,0,0,0.125) inset;-webkit-box-shadow:0 1px 8px rgba(0,0,0,0.125) inset;box-shadow:0 1px 8px rgba(0,0,0,0.125) inset}.btn-default{background-color:#e6e6e6;border-color:#e6e6e6}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active{color:#333;background-color:#c7c7c7;border-color:#c7c7c7}.btn-primary{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active{color:#fff;background-color:#0a6999;border-color:#0a6999}.btn-secondary{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary:hover,.btn-secondary:focus,.btn-secondary:active,.btn-secondary.active{color:#fff;background-color:#0f9ae0;border-color:#0f9ae0}.btn-success{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active{color:#fff;background-color:#429842;border-color:#429842}.btn-warning{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active{color:#fff;background-color:#c85e0b;border-color:#c85e0b}.btn-danger{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active{color:#fff;background-color:#c62b26;border-color:#c62b26}.btn-link{color:#0e90d2;cursor:pointer;border-color:transparent;background-color:transparent}.btn-link:hover,.btn-link:focus,.btn-link:active,.btn-link.active{color:#095f8a;text-decoration:underline;background-color:transparent}.btn.disabled{cursor:not-allowed;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none;pointer-events:none}.btn-block{-moz-box-sizing:border-box;display:block;padding-left:0;padding-right:0;width:100%}.btn-primary-outline{color:#5a98de;background-color:transparent;background-image:none;border-color:#5a98de}.btn-primary-outline.active,.btn-primary-outline.focus,.btn-primary-outline:active,.btn-primary-outline:focus,.open>.btn-primary-outline.dropdown-toggle{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary-outline:hover{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary-outline.disabled.focus,.btn-primary-outline.disabled:focus,.btn-primary-outline:disabled.focus,.btn-primary-outline:disabled:focus,fieldset[disabled] .btn-primary-outline.focus,fieldset[disabled] .btn-primary-outline:focus{border-color:#0a6999}.btn-primary-outline.disabled:hover,.btn-primary-outline:disabled:hover,fieldset[disabled] .btn-primary-outline:hover{border-color:#0a6999}.btn-secondary-outline{color:#3bb4f2;background-color:transparent;background-image:none;border-color:#3bb4f2}.btn-secondary-outline.active,.btn-secondary-outline.focus,.btn-secondary-outline:active,.btn-secondary-outline:focus,.open>.btn-secondary-outline.dropdown-toggle{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary-outline:hover{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary-outline.disabled.focus,.btn-secondary-outline.disabled:focus,.btn-secondary-outline:disabled.focus,.btn-secondary-outline:disabled:focus,fieldset[disabled] .btn-secondary-outline.focus,fieldset[disabled] .btn-secondary-outline:focus{border-color:#0f9ae0}.btn-secondary-outline.disabled:hover,.btn-secondary-outline:disabled:hover,fieldset[disabled] .btn-secondary-outline:hover{border-color:#0f9ae0}.btn-success-outline{color:#5eb95e;background-color:transparent;background-image:none;border-color:#5eb95e}.btn-success-outline.active,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline:focus,.open>.btn-success-outline.dropdown-toggle{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success-outline:hover{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success-outline.disabled.focus,.btn-success-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-success-outline:disabled:focus,fieldset[disabled] .btn-success-outline.focus,fieldset[disabled] .btn-success-outline:focus{border-color:#429842}.btn-success-outline.disabled:hover,.btn-success-outline:disabled:hover,fieldset[disabled] .btn-success-outline:hover{border-color:#429842}.btn-warning-outline{color:#f37b1d;background-color:transparent;background-image:none;border-color:#f37b1d}.btn-warning-outline.active,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline:focus,.open>.btn-warning-outline.dropdown-toggle{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning-outline:hover{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning-outline.disabled.focus,.btn-warning-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-warning-outline:disabled:focus,fieldset[disabled] .btn-warning-outline.focus,fieldset[disabled] .btn-warning-outline:focus{border-color:#c85e0b}.btn-warning-outline.disabled:hover,.btn-warning-outline:disabled:hover,fieldset[disabled] .btn-warning-outline:hover{border-color:#c85e0b}.btn-danger-outline{color:#dd514c;background-color:transparent;background-image:none;border-color:#dd514c}.btn-danger-outline.active,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline:focus,.open>.btn-danger-outline.dropdown-toggle{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger-outline:hover{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger-outline.disabled.focus,.btn-danger-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-danger-outline:disabled:focus,fieldset[disabled] .btn-danger-outline.focus,fieldset[disabled] .btn-danger-outline:focus{border-color:#c62b26}.btn-danger-outline.disabled:hover,.btn-danger-outline:disabled:hover,fieldset[disabled] .btn-danger-outline:hover{border-color:#c62b26}.form-group{display:inline-block;vertical-align:middle}.form-group .input-text{position:relative;vertical-align:top}.form-group.radius{overflow:hidden}.form-group.radius .input-text{border-radius:4px 0 0 4px}.form-group.round .input-text{border-radius:1000px 0 0 1000px}.form-group .btn{position:relative;margin-left:-1px}.form-group.radius .btn{border-radius:0 4px 4px 0}.form-group.round .btn{border-radius:0 1000px 1000px 0}.img-responsive{display:inline-block;max-width:100%;height:auto}.thumbnail{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}@media(max-width:767px){.img-responsive{width:100%}}.duang-opacity img{-webkit-transition:opacity .1s linear;-moz-transition:opacity .1s linear;-o-transition:opacity .1s linear;transition:opacity .1s linear}.duang-opacity a:hover img,a:hover .opacity img{opacity:.85;filter:alpha(opacity=85)}.album-img{border:1px solid #e0e0e0}.album-img img{display:block;width:100%}.album-title{display:block;text-align:left;padding:7px 5px;line-height:18px;color:#555;text-decoration:none;font-size:12px;border:solid 1px #e0e0e0;border-top:0}.album-bg-Fir,.album-bg-Sec{border:1px solid #e6e6e6;border-top:1px solid #f5f5f5;height:1px;margin:0 auto;overflow:hidden}.album-bg-Fir{margin:0 3px}.album-bg-Sec{margin:0 6px}.avatar{display:inline-block;position:relative;overflow:hidden}.avatar img{display:block}.avatar.radius,.avatar.radius img{border-radius:50%}.avatar,.avatar img{width:32px;height:32px}.avatar.size-MINI{width:16px;height:16px}.avatar.size-S,.avatar.size-S img{width:24px;height:24px}.avatar.size-M,.avatar.size-M img{width:32px;height:32px}.avatar.size-L,.avatar.size-L img{width:40px;height:40px}.avatar.size-XL,.avatar.size-XL img{width:64px;height:64px}.avatar.size-XXL,.avatar.size-XXL img{width:100px;height:100px}.avatar.size-XXXL,.avatar.size-XXXL img{width:128px;height:128px}.iconpic{display:inline-block;vertical-align:sub;*vertical-align:middle;_vertical-align:middle;width:16px;height:16px;background-position:center;background-repeat:no-repeat}.hui-bounce,.hui-flip,.hui-flash,.hui-shake,.hui-swing,.hui-wobble,.hui-ring{-webkit-animation:1s ease;-moz-animation:1s ease;-ms-animation:1s ease;animation:1s ease}.hui-fadein,.hui-fadeinT,.hui-fadeinR,.hui-fadeinB,.hui-fadeinL,.hui-bouncein,.hui-bounceinT,.hui-bounceinR,.hui-bounceinB,.hui-bounceinL,.hui-rotatein,.hui-rotateinLT,.hui-rotateinLB,.hui-rotateinRT,.hui-rotateinRB,.hui-flipin,.hui-flipinX,.hui-flipinY{-webkit-animation:1s ease-out backwards;-moz-animation:1s ease-out backwards;-ms-animation:1s ease-out backwards;animation:1s ease-out backwards}.hui-fadeout,.hui-fadeoutT,.hui-fadeoutR,.hui-fadeoutB,.hui-fadeoutL,.hui-bounceout,.hui-bounceoutT,.hui-bounceoutR,.hui-bounceoutB,.hui-bounceoutL,.hui-rotateout,.hui-rotateoutLT,.hui-rotateoutLB,.hui-rotateoutRT,.hui-rotateoutRB,.hui-flipout,.hui-flipoutX,.hui-flipoutY{-webkit-animation:1s ease-in forwards;-moz-animation:1s ease-in forwards;-ms-animation:1s ease-in forwards;animation:1s ease-in forwards}.hui-fadein{-webkit-animation-name:fadein;-moz-animation-name:fadein;-ms-animation-name:fadein;animation-name:fadein}.hui-fadeinT{-webkit-animation-name:fadeinT;-moz-animation-name:fadeinT;-ms-animation-name:fadeinT;animation-name:fadeinT}.hui-fadeinR{-webkit-animation-name:fadeinR;-moz-animation-name:fadeinR;-ms-animation-name:fadeinR;animation-name:fadeinR}.hui-fadeinB{-webkit-animation-name:fadeinB;-moz-animation-name:fadeinB;-ms-animation-name:fadeinB;animation-name:fadeinB}.hui-fadeinL{-webkit-animation-name:fadeinL;-moz-animation-name:fadeinL;-ms-animation-name:fadeinL;animation-name:fadeinL}.hui-fadeout{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-ms-animation-name:fadeout;animation-name:fadeout}.hui-fadeoutT{-webkit-animation-name:fadeoutT;-moz-animation-name:fadeoutT;-ms-animation-name:fadeoutT;animation-name:fadeoutT}.hui-fadeoutR{-webkit-animation-name:fadeoutR;-moz-animation-name:fadeoutR;-ms-animation-name:fadeoutR;animation-name:fadeoutR}.hui-fadeoutB{-webkit-animation-name:fadeoutB;-moz-animation-name:fadeoutB;-ms-animation-name:fadeoutB;animation-name:fadeoutB}.hui-fadeoutL{-webkit-animation-name:fadeoutL;-moz-animation-name:fadeoutL;-ms-animation-name:fadeoutL;animation-name:fadeoutL}.hui-bounce{-webkit-animation-name:bounce;-moz-animation-name:bounce;-ms-animation-name:bounce;animation-name:bounce}.hui-bouncein{-webkit-animation-name:bouncein;-moz-animation-name:bouncein;-ms-animation-name:bouncein;animation-name:bouncein}.hui-bounceinT{-webkit-animation-name:bounceinT;-moz-animation-name:bounceinT;-ms-animation-name:bounceinT;animation-name:bounceinT}.hui-bounceinR{-webkit-animation-name:bounceinR;-moz-animation-name:bounceinR;-ms-animation-name:bounceinR;animation-name:bounceinR}.hui-bounceinB{-webkit-animation-name:bounceinB;-moz-animation-name:bounceinB;-ms-animation-name:bounceinB;animation-name:bounceinB}.hui-bounceinL{-webkit-animation-name:bounceinL;-moz-animation-name:bounceinL;-ms-animation-name:bounceinL;animation-name:bounceinL}.hui-bounceout{-webkit-animation-name:bounceout;-moz-animation-name:bounceout;-ms-animation-name:bounceout;animation-name:bounceout}.hui-bounceoutT{-webkit-animation-name:bounceoutT;-moz-animation-name:bounceoutT;-ms-animation-name:bounceoutT;animation-name:bounceoutT}.hui-bounceoutR{-webkit-animation-name:bounceoutR;-moz-animation-name:bounceoutR;-ms-animation-name:bounceoutR;animation-name:bounceoutR}.hui-bounceoutB{-webkit-animation-name:bounceoutB;-moz-animation-name:bounceoutB;-ms-animation-name:bounceoutB;animation-name:bounceoutB}.hui-bounceoutL{-webkit-animation-name:bounceoutL;-moz-animation-name:bounceoutL;-ms-animation-name:bounceoutL;animation-name:bounceoutL}.hui-rotatein{-webkit-animation-name:rotatein;-moz-animation-name:rotatein;-ms-animation-name:rotatein;animation-name:rotatein}.hui-rotateinLT{-webkit-animation-name:rotateinLT;-moz-animation-name:rotateinLT;-ms-animation-name:rotateinLT;animation-name:rotateinLT}.hui-rotateinLB{-webkit-animation-name:rotateinLB;-moz-animation-name:rotateinLB;-ms-animation-name:rotateinLB;animation-name:rotateinLB}.hui-rotateinRT{-webkit-animation-name:rotateinRT;-moz-animation-name:rotateinRT;-ms-animation-name:rotateinRT;animation-name:rotateinRT}.hui-rotateinRB{-webkit-animation-name:rotateinRB;-moz-animation-name:rotateinRB;-ms-animation-name:rotateinRB;animation-name:rotateinRB}.hui-rotateout{-webkit-animation-name:rotateout;-moz-animation-name:rotateout;-ms-animation-name:rotateout;animation-name:rotateout}.hui-rotateoutLT{-webkit-animation-name:rotateoutLT;-moz-animation-name:rotateoutLT;-ms-animation-name:rotateoutLT;animation-name:rotateoutLT}.hui-rotateoutLB{-webkit-animation-name:rotateoutLB;-moz-animation-name:rotateoutLB;-ms-animation-name:rotateoutLB;animation-name:rotateoutLB}.hui-rotateoutRT{-webkit-animation-name:rotateoutRT;-moz-animation-name:rotateoutRT;-ms-animation-name:rotateoutRT;animation-name:rotateoutRT}.hui-rotateoutRB{-webkit-animation-name:rotateoutRB;-moz-animation-name:rotateoutRB;-ms-animation-name:rotateoutRB;animation-name:rotateoutRB}.hui-flip{-webkit-animation-name:flip;-moz-animation-name:flip;-ms-animation-name:flip;animation-name:flip}.hui-flipinX{-webkit-animation-name:flipinX;-moz-animation-name:flipinX;-ms-animation-name:flipinX;animation-name:flipinX}.hui-flipin,.hui-flipinY{-webkit-animation-name:flipinY;-moz-animation-name:flipinY;-ms-animation-name:flipinY;animation-name:flipinY}.hui-flipoutX{-webkit-animation-name:flipoutX;-moz-animation-name:flipoutX;-ms-animation-name:flipoutX;animation-name:flipoutX}.hui-flipout,.hui-flipoutY{-webkit-animation-name:flipoutY;-moz-animation-name:flipoutY;-ms-animation-name:flipoutY;animation-name:flipoutY}.hui-flash{-webkit-animation-name:flash;-moz-animation-name:flash;-ms-animation-name:flash;animation-name:flash}.hui-shake{-webkit-animation-name:shake;-moz-animation-name:shake;-ms-animation-name:shake;animation-name:shake}.hui-swing{-webkit-animation-name:swing;-moz-animation-name:swing;-ms-animation-name:swing;animation-name:swing}.hui-wobble{-webkit-animation-name:wobble;-moz-animation-name:wobble;-ms-animation-name:wobble;animation-name:wobble}.hui-ring{-webkit-animation-name:ring;-moz-animation-name:ring;-ms-animation-name:ring;animation-name:ring}@-webkit-keyframes fadein{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadein{0%{opacity:0}100%{opacity:1}}@-ms-keyframes fadein{0%{opacity:0}100%{opacity:1}}@keyframes fadein{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeinT{0%{opacity:0;-webkit-transform:translateY(-100px)}100%{opacity:1;-webkit-transform:translateY(0)}}@-moz-keyframes fadeinT{0%{opacity:0;-moz-transform:translateY(-100px)}100%{opacity:1;-moz-transform:translateY(0)}}@-ms-keyframes fadeinT{0%{opacity:0;-ms-transform:translateY(-100px)}100%{opacity:1;-ms-transform:translateY(0)}}@keyframes fadeinT{0%{opacity:0;transform:translateY(-100px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes fadeinR{0%{opacity:0;-webkit-transform:translateX(100px)}100%{opacity:1;-webkit-transform:translateX(0)}}@-moz-keyframes fadeinR{0%{opacity:0;-moz-transform:translateX(100px)}100%{opacity:1;-moz-transform:translateX(0)}}@-ms-keyframes fadeinR{0%{opacity:0;-ms-transform:translateX(100px)}100%{opacity:1;-ms-transform:translateX(0)}}@keyframes fadeinR{0%{opacity:0;transform:translateX(100px)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes fadeinB{0%{opacity:0;-webkit-transform:translateY(100px)}100%{opacity:1;-webkit-transform:translateY(0)}}@-moz-keyframes fadeinB{0%{opacity:0;-moz-transform:translateY(100px)}100%{opacity:1;-moz-transform:translateY(0)}}@-ms-keyframes fadeinB{0%{opacity:0;-ms-transform:translateY(100px)}100%{opacity:1;-ms-transform:translateY(0)}}@keyframes fadeinB{0%{opacity:0;transform:translateY(100px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes fadeinL{0%{opacity:0;-webkit-transform:translateX(-100px)}100%{opacity:1;-webkit-transform:translateX(0)}}@-moz-keyframes fadeinL{0%{opacity:0;-moz-transform:translateX(-100px)}100%{opacity:1;-moz-transform:translateX(0)}}@-ms-keyframes fadeinL{0%{opacity:0;-ms-transform:translateX(-100px)}100%{opacity:1;-ms-transform:translateX(0)}}@keyframes fadeinL{0%{opacity:0;transform:translateX(-100px)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-ms-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes fadeoutT{0%{opacity:1;-webkit-transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-100px)}}@-moz-keyframes fadeoutT{0%{opacity:1;-moz-transform:translateY(0)}100%{opacity:0;-moz-transform:translateY(-100px)}}@-ms-keyframes fadeoutT{0%{opacity:1;-ms-transform:translateY(0)}100%{opacity:0;-ms-transform:translateY(-100px)}}@keyframes fadeoutT{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-100px)}}@-webkit-keyframes fadeoutR{0%{opacity:1;-webkit-transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(100px)}}@-moz-keyframes fadeoutR{0%{opacity:1;-moz-transform:translateX(0)}100%{opacity:0;-moz-transform:translateX(100px)}}@-ms-keyframes fadeoutR{0%{opacity:1;-ms-transform:translateX(0)}100%{opacity:0;-ms-transform:translateX(100px)}}@keyframes fadeoutR{0%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(100px)}}@-webkit-keyframes fadeoutB{0%{opacity:1;-webkit-transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(100px)}}@-moz-keyframes fadeoutB{0%{opacity:1;-moz-transform:translateY(0)}100%{opacity:0;-moz-transform:translateY(100px)}}@-ms-keyframes fadeoutB{0%{opacity:1;-ms-transform:translateY(0)}100%{opacity:0;-ms-transform:translateY(100px)}}@keyframes fadeoutB{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(100px)}}@-webkit-keyframes fadeoutL{0%{opacity:1;-webkit-transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-100px)}}@-moz-keyframes fadeoutL{0%{opacity:1;-moz-transform:translateX(0)}100%{opacity:0;-moz-transform:translateX(-100px)}}@-ms-keyframes fadeoutL{0%{opacity:1;-ms-transform:translateX(0)}100%{opacity:0;-ms-transform:translateX(-100px)}}@keyframes fadeoutL{0%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(-100px)}}@-webkit-keyframes bounce{0%,20%,50%,80%,100%{-webkit-transform:translateY(0)}40%{-webkit-transform:translateY(-30px)}60%{-webkit-transform:translateY(-15px)}}@-moz-keyframes bounce{0%,20%,50%,80%,100%{-moz-transform:translateY(0)}40%{-moz-transform:translateY(-30px)}60%{-moz-transform:translateY(-15px)}}@-ms-keyframes bounce{0%,20%,50%,80%,100%{-ms-transform:translateY(0)}40%{-ms-transform:translateY(-30px)}60%{-ms-transform:translateY(-15px)}}@keyframes bounce{0%,20%,50%,80%,100%{transform:translateY(0)}40%{transform:translateY(-30px)}60%{transform:translateY(-15px)}}@-webkit-keyframes bouncein{0%{opacity:0;-webkit-transform:scale(0.3)}50%{opacity:1;-webkit-transform:scale(1.05)}70%{-webkit-transform:scale(0.9)}100%{-webkit-transform:scale(1)}}@-moz-keyframes bouncein{0%{opacity:0;-moz-transform:scale(0.3)}50%{opacity:1;-moz-transform:scale(1.05)}70%{-moz-transform:scale(0.9)}100%{-moz-transform:scale(1)}}@-ms-keyframes bouncein{0%{opacity:0;-ms-transform:scale(0.3)}50%{opacity:1;-ms-transform:scale(1.05)}70%{-ms-transform:scale(0.9)}100%{-ms-transform:scale(1)}}@keyframes bouncein{0%{opacity:0;transform:scale(0.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(0.9)}100%{transform:scale(1)}}@-webkit-keyframes bounceinT{0%{opacity:0;-webkit-transform:translateY(-100px)}60%{opacity:1;-webkit-transform:translateY(30px)}80%{-webkit-transform:translateY(-10px)}100%{-webkit-transform:translateY(0)}}@-moz-keyframes bounceinT{0%{opacity:0;-moz-transform:translateY(-100px)}60%{opacity:1;-moz-transform:translateY(30px)}80%{-moz-transform:translateY(-10px)}100%{-moz-transform:translateY(0)}}@-ms-keyframes bounceinT{0%{opacity:0;-ms-transform:translateY(-100px)}60%{opacity:1;-ms-transform:translateY(30px)}80%{-ms-transform:translateY(-10px)}100%{-ms-transform:translateY(0)}}@keyframes bounceinT{0%{opacity:0;transform:translateY(-100px)}60%{opacity:1;transform:translateY(30px)}80%{transform:translateY(-10px)}100%{transform:translateY(0)}}@-webkit-keyframes bounceinR{0%{opacity:0;-webkit-transform:translateX(100px)}60%{opacity:1;-webkit-transform:translateX(-30px)}80%{-webkit-transform:translateX(10px)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes bounceinR{0%{opacity:0;-moz-transform:translateX(100px)}60%{opacity:1;-moz-transform:translateX(-30px)}80%{-moz-transform:translateX(10px)}100%{-moz-transform:translateX(0)}}@-ms-keyframes bounceinR{0%{opacity:0;-ms-transform:translateX(100px)}60%{opacity:1;-ms-transform:translateX(-30px)}80%{-ms-transform:translateX(10px)}100%{-ms-transform:translateX(0)}}@keyframes bounceinR{0%{opacity:0;transform:translateX(100px)}60%{opacity:1;transform:translateX(-30px)}80%{transform:translateX(10px)}100%{transform:translateX(0)}}@-webkit-keyframes bounceinB{0%{opacity:0;-webkit-transform:translateY(100px)}60%{opacity:1;-webkit-transform:translateY(-30px)}80%{-webkit-transform:translateY(10px)}100%{-webkit-transform:translateY(0)}}@-moz-keyframes bounceinB{0%{opacity:0;-moz-transform:translateY(100px)}60%{opacity:1;-moz-transform:translateY(-30px)}80%{-moz-transform:translateY(10px)}100%{-moz-transform:translateY(0)}}@-ms-keyframes bounceinB{0%{opacity:0;-ms-transform:translateY(100px)}60%{opacity:1;-ms-transform:translateY(-30px)}80%{-ms-transform:translateY(10px)}100%{-ms-transform:translateY(0)}}@keyframes bounceinB{0%{opacity:0;transform:translateY(100px)}60%{opacity:1;transform:translateY(-30px)}80%{transform:translateY(10px)}100%{transform:translateY(0)}}@-webkit-keyframes bounceinL{0%{opacity:0;-webkit-transform:translateX(-100px)}60%{opacity:1;-webkit-transform:translateX(30px)}80%{-webkit-transform:translateX(-10px)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes bounceinL{0%{opacity:0;-moz-transform:translateX(-100px)}60%{opacity:1;-moz-transform:translateX(30px)}80%{-moz-transform:translateX(-10px)}100%{-moz-transform:translateX(0)}}@-ms-keyframes bounceinL{0%{opacity:0;-ms-transform:translateX(-100px)}60%{opacity:1;-ms-transform:translateX(30px)}80%{-ms-transform:translateX(-10px)}100%{-ms-transform:translateX(0)}}@keyframes bounceinL{0%{opacity:0;transform:translateX(-100px)}60%{opacity:1;transform:translateX(30px)}80%{transform:translateX(-10px)}100%{transform:translateX(0)}}@-webkit-keyframes bounceout{0%{-webkit-transform:scale(1)}25%{-webkit-transform:scale(0.95)}50%{opacity:1;-webkit-transform:scale(1.1)}100%{opacity:0;-webkit-transform:scale(0.3)}}@-moz-keyframes bounceout{0%{-moz-transform:scale(1)}25%{-moz-transform:scale(0.95)}50%{opacity:1;-moz-transform:scale(1.1)}100%{opacity:0;-moz-transform:scale(0.3)}}@-ms-keyframes bounceout{0%{-ms-transform:scale(1)}25%{-ms-transform:scale(0.95)}50%{opacity:1;-ms-transform:scale(1.1)}100%{opacity:0;-ms-transform:scale(0.3)}}@keyframes bounceout{0%{transform:scale(1)}25%{transform:scale(0.95)}50%{opacity:1;transform:scale(1.1)}100%{opacity:0;transform:scale(0.3)}}@-webkit-keyframes bounceoutT{0%{-webkit-transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(20px)}100%{opacity:0;-webkit-transform:translateY(-100px)}}@-moz-keyframes bounceoutT{0%{-moz-transform:translateY(0)}20%{opacity:1;-moz-transform:translateY(20px)}100%{opacity:0;-moz-transform:translateY(-100px)}}@-ms-keyframes bounceoutT{0%{-ms-transform:translateY(0)}20%{opacity:1;-ms-transform:translateY(20px)}100%{opacity:0;-ms-transform:translateY(-100px)}}@keyframes bounceoutT{0%{transform:translateY(0)}20%{opacity:1;transform:translateY(20px)}100%{opacity:0;transform:translateY(-100px)}}@-webkit-keyframes bounceoutR{0%{-webkit-transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(-20px)}100%{opacity:0;-webkit-transform:translateX(100px)}}@-moz-keyframes bounceoutR{0%{-moz-transform:translateX(0)}20%{opacity:1;-moz-transform:translateX(-20px)}100%{opacity:0;-moz-transform:translateX(100px)}}@-ms-keyframes bounceoutR{0%{-ms-transform:translateX(0)}20%{opacity:1;-ms-transform:translateX(-20px)}100%{opacity:0;-ms-transform:translateX(100px)}}@keyframes bounceoutR{0%{transform:translateX(0)}20%{opacity:1;transform:translateX(-20px)}100%{opacity:0;transform:translateX(100px)}}@-webkit-keyframes bounceoutB{0%{-webkit-transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(-20px)}100%{opacity:0;-webkit-transform:translateY(100px)}}@-moz-keyframes bounceoutB{0%{-moz-transform:translateY(0)}20%{opacity:1;-moz-transform:translateY(-20px)}100%{opacity:0;-moz-transform:translateY(100px)}}@-ms-keyframes bounceoutB{0%{-ms-transform:translateY(0)}20%{opacity:1;-ms-transform:translateY(-20px)}100%{opacity:0;-ms-transform:translateY(100px)}}@keyframes bounceoutB{0%{transform:translateY(0)}20%{opacity:1;transform:translateY(-20px)}100%{opacity:0;transform:translateY(100px)}}@-webkit-keyframes bounceoutL{0%{-webkit-transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(20px)}100%{opacity:0;-webkit-transform:translateX(-100px)}}@-moz-keyframes bounceoutL{0%{-moz-transform:translateX(0)}20%{opacity:1;-moz-transform:translateX(20px)}100%{opacity:0;-moz-transform:translateX(-100px)}}@-ms-keyframes bounceoutL{0%{-ms-transform:translateX(0)}20%{opacity:1;-ms-transform:translateX(20px)}100%{opacity:0;-ms-transform:translateX(-100px)}}@keyframes bounceoutL{0%{transform:translateX(0)}20%{opacity:1;transform:translateX(20px)}100%{opacity:0;transform:translateX(-200px)}}@-webkit-keyframes rotatein{0%{opacity:0;-webkit-transform:rotate(-200deg)}100%{opacity:1;-webkit-transform:rotate(0)}}@-moz-keyframes rotatein{0%{opacity:0;-moz-transform:rotate(-200deg)}100%{opacity:1;-moz-transform:rotate(0)}}@-ms-keyframes rotatein{0%{opacity:0;-ms-transform:rotate(-200deg)}100%{opacity:1;-ms-transform:rotate(0)}}@keyframes rotatein{0%{opacity:0;transform:rotate(-200deg)}100%{opacity:1;transform:rotate(0)}}@-webkit-keyframes rotateinLT{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinLT{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinLT{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinLT{0%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}100%{transform-origin:left bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateineftB{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateineftB{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateineftB{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateineftB{0%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}100%{transform-origin:left bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateinRT{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinRT{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinRT{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinRT{0%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}100%{transform-origin:right bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateinRB{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinRB{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinRB{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinRB{0%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}100%{transform-origin:right bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateout{0%{-webkit-transform-origin:center center;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:center center;-webkit-transform:rotate(200deg);opacity:0}}@-moz-keyframes rotateout{0%{-moz-transform-origin:center center;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:center center;-moz-transform:rotate(200deg);opacity:0}}@-ms-keyframes rotateout{0%{-ms-transform-origin:center center;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:center center;-ms-transform:rotate(200deg);opacity:0}}@keyframes rotateout{0%{transform-origin:center center;transform:rotate(0);opacity:1}100%{transform-origin:center center;transform:rotate(200deg);opacity:0}}@-webkit-keyframes rotateoutLT{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}}@-moz-keyframes rotateoutLT{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}}@-ms-keyframes rotateoutLT{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}}@keyframes rotateoutLT{0%{transform-origin:left bottom;transform:rotate(0);opacity:1}100%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}}@-webkit-keyframes rotateoutLB{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}}@-moz-keyframes rotateoutLB{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}}@-ms-keyframes rotateoutLB{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}}@keyframes rotateoutLB{0%{transform-origin:left bottom;transform:rotate(0);opacity:1}100%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}}@-webkit-keyframes rotateoutRT{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}}@-moz-keyframes rotateoutRT{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}}@-ms-keyframes rotateoutRT{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}}@keyframes rotateoutRT{0%{transform-origin:right bottom;transform:rotate(0);opacity:1}100%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}}@-webkit-keyframes rotateoutBR{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}}@-moz-keyframes rotateoutBR{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}}@-ms-keyframes rotateoutBR{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}}@keyframes rotateoutBR{0%{transform-origin:right bottom;transform:rotate(0);opacity:1}100%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotateY(0);-webkit-animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(170deg);-webkit-animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-webkit-animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) rotateY(360deg) scale(0.95);-webkit-animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px) scale(1);-webkit-animation-timing-function:ease-in}}@-moz-keyframes flip{0%{-moz-transform:perspective(400px) rotateY(0);-moz-animation-timing-function:ease-out}40%{-moz-transform:perspective(400px) translateZ(150px) rotateY(170deg);-moz-animation-timing-function:ease-out}50%{-moz-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-moz-animation-timing-function:ease-in}80%{-moz-transform:perspective(400px) rotateY(360deg) scale(0.95);-moz-animation-timing-function:ease-in}100%{-moz-transform:perspective(400px) scale(1);-moz-animation-timing-function:ease-in}}@-ms-keyframes flip{0%{-ms-transform:perspective(400px) rotateY(0);-ms-animation-timing-function:ease-out}40%{-ms-transform:perspective(400px) translateZ(150px) rotateY(170deg);-ms-animation-timing-function:ease-out}50%{-ms-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-ms-animation-timing-function:ease-in}80%{-ms-transform:perspective(400px) rotateY(360deg) scale(0.95);-ms-animation-timing-function:ease-in}100%{-ms-transform:perspective(400px) scale(1);-ms-animation-timing-function:ease-in}}@keyframes flip{0%{transform:perspective(400px) rotateY(0);animation-timing-function:ease-out}40%{transform:perspective(400px) translateZ(150px) rotateY(170deg);animation-timing-function:ease-out}50%{transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);animation-timing-function:ease-in}80%{transform:perspective(400px) rotateY(360deg) scale(0.95);animation-timing-function:ease-in}100%{transform:perspective(400px) scale(1);animation-timing-function:ease-in}}@-webkit-keyframes flipinX{0%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg)}100%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}}@-moz-keyframes flipinX{0%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-moz-transform:perspective(400px) rotateX(-10deg)}70%{-moz-transform:perspective(400px) rotateX(10deg)}100%{-moz-transform:perspective(400px) rotateX(0);opacity:1}}@-ms-keyframes flipinX{0%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-ms-transform:perspective(400px) rotateX(-10deg)}70%{-ms-transform:perspective(400px) rotateX(10deg)}100%{-ms-transform:perspective(400px) rotateX(0);opacity:1}}@keyframes flipinX{0%{transform:perspective(400px) rotateX(90deg);opacity:0}40%{transform:perspective(400px) rotateX(-10deg)}70%{transform:perspective(400px) rotateX(10deg)}100%{transform:perspective(400px) rotateX(0);opacity:1}}@-webkit-keyframes flipinY{0%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-10deg)}70%{-webkit-transform:perspective(400px) rotateY(10deg)}100%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}}@-moz-keyframes flipinY{0%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-moz-transform:perspective(400px) rotateY(-10deg)}70%{-moz-transform:perspective(400px) rotateY(10deg)}100%{-moz-transform:perspective(400px) rotateY(0);opacity:1}}@-ms-keyframes flipinY{0%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-ms-transform:perspective(400px) rotateY(-10deg)}70%{-ms-transform:perspective(400px) rotateY(10deg)}100%{-ms-transform:perspective(400px) rotateY(0);opacity:1}}@keyframes flipinY{0%{transform:perspective(400px) rotateY(90deg);opacity:0}40%{transform:perspective(400px) rotateY(-10deg)}70%{transform:perspective(400px) rotateY(10deg)}100%{transform:perspective(400px) rotateY(0);opacity:1}}@-webkit-keyframes flipoutX{0%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}100%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}}@-moz-keyframes flipoutX{0%{-moz-transform:perspective(400px) rotateX(0);opacity:1}100%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}}@-ms-keyframes flipoutX{0%{-ms-transform:perspective(400px) rotateX(0);opacity:1}100%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}}@keyframes flipoutX{0%{transform:perspective(400px) rotateX(0);opacity:1}100%{transform:perspective(400px) rotateX(90deg);opacity:0}}@-webkit-keyframes flipoutY{0%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}100%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}}@-moz-keyframes flipoutY{0%{-moz-transform:perspective(400px) rotateY(0);opacity:1}100%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}}@-ms-keyframes flipoutY{0%{-ms-transform:perspective(400px) rotateY(0);opacity:1}100%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}}@keyframes flipoutY{0%{transform:perspective(400px) rotateY(0);opacity:1}100%{transform:perspective(400px) rotateY(90deg);opacity:0}}@-webkit-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-moz-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-ms-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px)}}@-moz-keyframes shake{0%,100%{-moz-transform:translateX(0)}10%,30%,50%,70%,90%{-moz-transform:translateX(-10px)}20%,40%,60%,80%{-moz-transform:translateX(10px)}}@-ms-keyframes shake{0%,100%{-ms-transform:translateX(0)}10%,30%,50%,70%,90%{-ms-transform:translateX(-10px)}20%,40%,60%,80%{-ms-transform:translateX(10px)}}@keyframes shake{0%,100%{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-10px)}20%,40%,60%,80%{transform:translateX(10px)}}@-webkit-keyframes swing{20%{-webkit-transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg)}100%{-webkit-transform:rotate(0)}}@-moz-keyframes swing{20%{-moz-transform:rotate(15deg)}40%{-moz-transform:rotate(-10deg)}60%{-moz-transform:rotate(5deg)}80%{-moz-transform:rotate(-5deg)}100%{-moz-transform:rotate(0)}}@-ms-keyframes swing{20%{-ms-transform:rotate(15deg)}40%{-ms-transform:rotate(-10deg)}60%{-ms-transform:rotate(5deg)}80%{-ms-transform:rotate(-5deg)}100%{-ms-transform:rotate(0)}}@keyframes swing{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}100%{transform:rotate(0)}}@-webkit-keyframes wobble{0%{-webkit-transform:translateX(0)}15%{-webkit-transform:translateX(-100px) rotate(-5deg)}30%{-webkit-transform:translateX(80px) rotate(3deg)}45%{-webkit-transform:translateX(-65px) rotate(-3deg)}60%{-webkit-transform:translateX(40px) rotate(2deg)}75%{-webkit-transform:translateX(-20px) rotate(-1deg)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes wobble{0%{-moz-transform:translateX(0)}15%{-moz-transform:translateX(-100px) rotate(-5deg)}30%{-moz-transform:translateX(80px) rotate(3deg)}45%{-moz-transform:translateX(-65px) rotate(-3deg)}60%{-moz-transform:translateX(40px) rotate(2deg)}75%{-moz-transform:translateX(-20px) rotate(-1deg)}100%{-moz-transform:translateX(0)}}@-ms-keyframes wobble{0%{-ms-transform:translateX(0)}15%{-ms-transform:translateX(-100px) rotate(-5deg)}30%{-ms-transform:translateX(80px) rotate(3deg)}45%{-ms-transform:translateX(-65px) rotate(-3deg)}60%{-ms-transform:translateX(40px) rotate(2deg)}75%{-ms-transform:translateX(-20px) rotate(-1deg)}100%{-ms-transform:translateX(0)}}@keyframes wobble{0%{transform:translateX(0)}15%{transform:translateX(-100px) rotate(-5deg)}30%{transform:translateX(80px) rotate(3deg)}45%{transform:translateX(-65px) rotate(-3deg)}60%{transform:translateX(40px) rotate(2deg)}75%{transform:translateX(-20px) rotate(-1deg)}100%{transform:translateX(0)}}@-webkit-keyframes ring{0%{-webkit-transform:scale(1)}10%,20%{-webkit-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg)}100%{-webkit-transform:scale(1) rotate(0)}}@-moz-keyframes ring{0%{-moz-transform:scale(1)}10%,20%{-moz-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-moz-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-moz-transform:scale(1.1) rotate(-3deg)}100%{-moz-transform:scale(1) rotate(0)}}@-ms-keyframes ring{0%{-ms-transform:scale(1)}10%,20%{-ms-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-ms-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-ms-transform:scale(1.1) rotate(-3deg)}100%{-ms-transform:scale(1) rotate(0)}}@keyframes ring{0%{transform:scale(1)}10%,20%{transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale(1.1) rotate(3deg)}40%,60%,80%{transform:scale(1.1) rotate(-3deg)}100%{transform:scale(1) rotate(0)}}.btn-group{font-size:0}.btn-group .btn{margin-left:-1px}.btn-group .btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.navbar-wrapper{height:45px}.navbar{position:relative;z-index:1030;background-color:#fff}.navbar-black{background-color:#222}.navbar-fixed-top{position:fixed;top:0;left:0;right:0;z-index:1030}.logo{display:inline-block;text-decoration:none;cursor:pointer;background-repeat:no-repeat;background-position:left center;background-size:auto 100%}a.logo:hover{text-decoration:none}.navbar .logo{height:44px;line-height:44px;margin-right:10px;float:left}.navbar-logo,.navbar-logo-m{font-size:16px}.navbar-slogan{font-size:12px;cursor:default}.navbar .container{position:relative}.navbar-userbar{position:absolute;top:0;right:15px}.navbar .container .navbar-userbar{right:0}.nav{z-index:1}.nav>ul{font-size:0;line-height:0}.nav>ul>li{position:relative;float:left}.nav>ul>li,.nav>ul>li>a{display:inline-block;text-align:center}.nav>ul>li>a{padding:0 20px}.nav>ul>li>a:hover,.nav>ul>li.current>a{background-color:rgba(255,255,255,0.2);text-decoration:none;-webkit-transition:background-color .3s ease 0s;-moz-transition:background-color .3s ease 0s;-o-transition:background-color .3s ease 0s;-ms-transition:background-color .3s ease 0s;transition:background-color .3s ease 0s}.navbar-nav>ul>li,.navbar-nav>ul>li>a{line-height:44px;font-size:14px}@media(max-width:767px){.navbar-wrapper{height:45px!important}.logo{margin-right:0}.navbar .logo{height:44px!important;line-height:44px!important}.navbar-nav{display:none;float:none!important}.navbar-nav>ul>li{width:100%;text-align:left;border-bottom:solid 1px #eee}.navbar-nav>ul>li>a{display:block;padding:0 15px;text-align:left}.navbar-nav>ul>li.dropDown.open>.dropDown-menu{display:none}.navbar-nav>ul>li.dropDown>.dropDown_A>.Hui-iconfont{display:none}.navbar-nav>ul>li,.navbar-nav>ul>li>a{height:44px!important;line-height:44px!important}.nav-collapse>ul,.nav-collapse>ul>li{width:100%;display:block}.js .nav-collapse{position:absolute;display:block;float:none;clear:both;max-height:0;clip:rect(0 0 0 0);margin-left:-15px;margin-right:-15px;overflow:hidden;-webkt-transition:max-height 284ms ease 0s;-moz-transition:max-height 284ms ease 0s;-o-transition:max-height 284ms ease 0s;-ms-transition:max-height 284ms ease 0s;transition:max-height 284ms ease 0s}.js-nav-active .nav-collapse.closed{max-height:none}.nav-collapse.opened{max-height:9999px}}.navbar-black{background-color:#222;border-bottom:#080808 1px solid;-moz-box-shadow:0 0 4px #333;-webkit-box-shadow:0 0 4px #333;box-shadow:0 0 4px #333}.navbar-black .logo{color:#fff}.navbar-black .navbar-logo-m{color:#eee}.navbar-black .navbar-nav>ul>li,.navbar-black .navbar-nav>ul>li>a{color:#fff}.navbar-black .navbar-nav>ul>li>a:hover,.navbar-black .navbar-nav>ul>li.current>a{color:#fff}.navbar-black .navbar-userbar{color:#fff}@media(max-width:767px){.navbar-black .navbar-nav>ul>li{border-bottom:solid 1px #222}.navbar-black .navbar-nav>ul>li>a:hover,.navbar-black .navbar-nav>ul>li.current>a{background:#777}}.nav-toggle,a.nav-toggle{position:absolute;top:0;right:15px;font-size:20px;color:#999;padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.nav-toggle:hover,a.nav-toggle:hover{text-decoration:none;color:#fff}.mainnav{z-index:1;background-color:#222}.mainnav>ul{font-size:0;line-height:0}.mainnav>ul>li,.mainnav>ul>li>a{height:40px;line-height:40px}.mainnav>ul>li{display:inline-block;color:#fff;font-size:14px;font-weight:bold}.mainnav>ul>li>a{display:inline-block;padding:0 20px;color:#fff;text-align:center}.mainnav>ul>li>a:hover,.mainnav>ul>li.current>a{color:#fff;text-decoration:none;background-color:#000;-webkit-transition:background-color .3s ease 0s;-moz-transition:background-color .3s ease 0s;-o-transition:background-color .3s ease 0s;-ms-transition:background-color .3s ease 0s;transition:background-color .3s ease 0s}.Hui-nav-toggle,a.Hui-nav-toggle{position:absolute;top:0;right:15px;font-size:20px;color:#999;padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff}.Hui-nav-toggle:hover,a.Hui-nav-toggle:hover{text-decoration:none;color:#fff}@media(max-width:767px){.mainnav>ul>li{font-size:1.125em}}@media(max-width:480px){.mainnav>ul>li{text-align:center}.mainnav>ul>li{width:20%}.mainnav>ul>li>a{padding:0;padding:0;display:block}}.breadcrumb{border-bottom:1px solid #e5e5e5;line-height:39px;height:39px;overflow:hidden}.breadcrumb span{padding:0 5px}@media(max-width:767px){.breadcrumb>.container{padding:0}}.pageNav{float:none;clear:both;font-size:0;font-family:Arial,Helvetica,sans-serif;padding:18px 0;text-align:center}.pageNav span,.pageNav a,.pageNav b{font-size:14px;margin-right:5px;overflow:hidden;padding:3px 8px}.pageNav a{border:1px solid #ccdbe4;cursor:pointer}.pageNav b{color:#000}.pageNav .mor{padding:3px;font-weight:bold}.topnav{height:30px;line-height:30px;background-color;#f7f7f7;border-bottom:1px solid #ebebeb;font-size:12px}.topbar{background-color:#ececec;border-bottom:1px solid #ddd}.topbar a{margin-right:5px}.r_nav{display:inline-block;color:#999}.steps,.step{display:inline-block;position:relative;padding:1em 2em 1em 3em;vertical-align:top;background-color:#FFF;color:#888;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.step:after,.steps .step:after{position:absolute;z-index:2;content:'';top:0;right:-1.45em;border-bottom:1.5em solid transparent;border-left:1.5em solid #FFF;border-top:1.5em solid transparent;width:0;height:0}.step,.steps .step,.steps .step:after{-webkit-transition:opacity .1s ease,color .1s ease,-webkit-box-shadow .1s ease;transition:opacity .1s ease,color .1s ease,box-shadow .1s ease}.steps{cursor:pointer;display:inline-block;font-size:0;box-shadow:0 0 0 1px rgba(0,0,0,.1);border-radius:.3125rem;line-height:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.steps .step:first-child{padding-left:1.35em;border-radius:.3125em 0 0 .3125em}.steps .step:last-child{border-radius:0 .3125em .3125em 0}.steps .step:only-child{border-radius:.3125em}.steps .step:last-child{margin-right:0}.steps .step:last-child:after{display:none}.step:hover,.step.hover{background-color:#f7f7f7;color:rgba(0,0,0,.8)}.steps .step.hover:after,.steps .step:hover:after,.step:hover,.step.hover::after{border-left-color:#f7f7f7}.steps .step.down,.steps .step:active,.step.down,.step:active{background-color:#f0f0f0}.steps .step.down:after,.steps .step:active:after,.steps.down::after,.steps:active::after{border-left-color:#f0f0f0}.steps .step.active,.active.step{cursor:auto;background-color:#428bca;color:#FFF;font-weight:700}.steps .step.active:after,.active.steps:after{border-left-color:#428bca}.steps .disabled.step,.disabled.step{cursor:auto;background-color:#FFF;color:#cbcbcb}.disabled.step:after{border:0;background-color:#FFF;top:.42em;right:-1em;width:2.15em;height:2.15em;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);box-shadow:-1px -1px 0 0 rgba(0,0,0,.1) inset}.attached.steps{margin:0;border-radius:.3125em .3125em 0 0}.attached.steps .step:first-child{border-radius:.3125em 0 0}.attached.steps .step:last-child{border-radius:0 .3125em 0 0}.bottom.attached.steps{margin-top:-1px;border-radius:0 0 .3125em .3125em}.bottom.attached.steps .step:first-child{border-radius:0 0 0 .3125em}.bottom.attached.steps .step:last-child{border-radius:0 0 .3125em}.one.steps,.two.steps,.three.steps,.four.steps,.five.steps,.six.steps,.seven.steps,.eight.steps{display:block}.one.steps>.step{width:100%}.two.steps>.step{width:50%}.three.steps>.step{width:33.333%}.four.steps>.step{width:25%}.five.steps>.step{width:20%}.six.steps>.step{width:16.666%}.seven.steps>.step{width:14.285%}.eight.steps>.step{width:12.5%}.small.step,.small.steps .step{font-size:.8rem}.step,.steps .step{font-size:1rem}.large.step,.large.steps .step{font-size:1.25rem}.steps-ie,.step-ie,.step-ie .arrow{height:44px;line-height:44px}.steps-ie{background-color:#eaf4fd;border:solid 1px #afcfcc}.step-ie{position:relative;display:inline-block;float:left;cursor:pointer;padding:0 20px 0 40px;background:url(../images/steps/step_bg.png) repeat-x 0 center}.step-ie .arrow{position:absolute;right:-21px;top:0;width:21px;height:44px;display:block;cursor:pointer;background:url(../images/steps/step_arrow.png) no-repeat 0 center;z-index:50}.step-ie.active{background-image:url(../images/steps/step_bg-active.png);color:#fff;z-index:100}.step-ie.active .arrow{background-image:url(../images/steps/step_arrow-active.png)}.verticalTab{background:#fff url(../images/verticalTab/tab_bg.png) repeat-y 0 0;width:38px}.verticalTab a{position:relative;display:block;width:18px;height:auto;text-align:center;position:relative;padding:26px 10px 6px 10px;background:url(../images/verticalTab/tabNav.png) no-repeat 0 0}.verticalTab a em{position:absolute;left:0;bottom:-20px;width:38px;height:20px;background:url(../images/tabNav_right.png) no-repeat 0 0;z-index:50}.verticalTab a.active{background-image:url(../images/verticalTab/tabNav-active.png);color:#fff;z-index:99}.verticalTab a.active em{background-image:url(../images/verticalTab/tabNav_right-active.png)}.acrossTab,.acrossTab li,.acrossTab li em{background-image:url(../images/acrossTab/acrossTab-bg.png)}.acrossTab{height:29px;background-repeat:repeat-x;background-position:0 0;padding-top:1px}.acrossTab li,.acrossTab li em{background-repeat:no-repeat;background-position:0 0}.acrossTab li{position:relative;float:left;display:inline-block;height:29px;line-height:29px;font-size:12px;cursor:pointer;padding:0 30px;white-space:nowrap;color:#282828;background-position:0 0}.acrossTab li em{position:absolute;width:23px;height:29px;right:-20px;top:0;z-index:50;background-position:right -30px}.acrossTab li:hover{background-position:0 -60px}.acrossTab li:hover em{background-position:right -90px}.acrossTab li.active{background-position:0 -120px;z-index:99}.acrossTab li.active em{background-position:right -150px}.acrossTab li i{position:absolute;display:block;width:13px;height:13px;top:50%;margin-top:-6px;right:5px;font-size:0;line-height:0;cursor:pointer;background-image:url(../images/acrossTab/acrossTab-close.png);background-repeat:no-repeat;background-position:0 0}.acrossTab li i:hover{background-position:0 bottom}.dropDown{display:inline-block}.dropDown_A{display:inline-block}.dropDown-menu{display:none;transition:all .3s ease 0s}.dropDown:focus,.dropDown-menu:focus{outline:0}.dropDown-menu li.arrow{position:absolute;display:block;width:12px;height:8px;margin-top:-13px;margin-left:20%;line-height:0;background:url(../images/dropDown/icon-jt.png) no-repeat 0 0}.dropDown.hover .dropDown_A,.dropDown.open .dropDown_A{text-decoration:none;background-color:rgba(255,255,255,0.2)}.dropDown.open .dropDown_A .menu_dropdown-arrow{transition-duration:.3s;transition-property:all;_background-position:0 0;transform:rotate(180deg)}.menu{background-color:#fff;border:solid 1px #f2f2f2;display:inline-block}.menu.radius{border-top-left-radius:0;border-top-right-radius:0}.menu.box-shadow{border-top:0}.menu>li{position:relative;clear:both;* float:left}.menu>li>a{display:block;border-bottom:solid 1px #f2f2f2;padding:5px 20px;line-height:1.8;text-align:left;font-weight:normal;white-space:nowrap;vertical-align:top}.menu>li:last-child>a{border-bottom:0}.menu>li>a:hover,.menu>li>a:focus,.menu>li.open>a{text-decoration:none;background-color:#fafafa}.menu>li>a .arrow{position:absolute;top:50%;margin-top:-10px;right:5px;line-height:20px;height:20px;color:#999}.menu>li>.menu{display:none}.menu>li.open>.menu{display:inline-block;position:absolute;left:100%;top:-1px;min-width:100%}.menu>li.disabled>a{color:#999;text-decoration:none;cursor:no-drop;background-color:transparent}.menu>li.divider{display:block;height:0;line-height:0;margin:9px 0;overflow:hidden;border-top:solid 1px #eee}.dropDown>.dropDown-menu{display:none}.dropDown.open{position:relative;z-index:990}.dropDown.open>.dropDown-menu{position:absolute;z-index:1000;display:inline-block;top:100%;left:-1px;min-width:100%;background-color:#fff;border:solid 1px #f2f2f2}.dropDown.open.right>.dropDown-menu{right:-1px!important;left:auto!important}.slider{position:relative;text-align:center;margin:0 auto;z-index:1}.slider .bd,.slider .bd li,.slider .bd img{width:100%;height:100%}.slider .bd{z-index:2;overflow:hidden}.slider .bd li{float:left;width:100%;overflow:hidden;background-position:center;background-repeat:no-repeat}.slider .bd li a{display:block;width:100%;height:100%}.slider .bd li img{display:block}.slider .hd{position:absolute;z-index:3;left:0;right:0;bottom:10px;padding:0 10px;text-align:center}.slider .hd li{display:inline-block;text-align:center;margin-right:10px;cursor:pointer;background-color:#c2c2c2}.slider .hd li.active{background-color:#222}.dots li{width:10px;height:10px;font-size:0;line-height:0;border-radius:50%}.numbox li{width:20px;height:20px;line-height:20px;font-size:13px;font-family:Arial;font-weight:bold;text-indent:inherit}.numbox li.active{color:#fff}.rectangle li{width:40px;height:10px;font-size:0;line-height:0}.slider-arrow{display:block;position:absolute;top:50%;margin-top:-25px;height:50px;width:50px;line-height:50px;text-align:center;z-index:3;opacity:.7;filter:alpha(opacity=70)}.slider-arrow:hover{opacity:1;filter:alpha(opacity=100)}.slider-arrow.prev{left:0}.slider-arrow.next{right:0}.tabBar{border-bottom:2px solid #222}.tabBar span{background-color:#e8e8e8;cursor:pointer;display:inline-block;float:left;font-weight:bold;height:30px;line-height:30px;padding:0 15px}.tabBar span.current{background-color:#222;color:#fff}.tabCon{display:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;white-space:nowrap;vertical-align:middle;background-color:#999;overflow:hidden}.label.radius{border-radius:3px}.badge{padding-right:9px;padding-left:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-default,.badge-default{background-color:#e6e6e6;color:#333}.label-default[href],.badge-default[href]{background-color:#e6e6e6;color:#333}.label-primary,.badge-primary{background-color:#5a98de}.label-primary[href],.badge-primary[href]{background-color:#5a98de}.label-secondary,.badge-secondary{background-color:#3bb4f2}.label-secondary[href],.badge-secondary[href]{background-color:#3bb4f2}.label-success,.badge-success{background-color:#5eb95e}.label-success[href],.badge-success[href]{background-color:#5eb95e}.label-warning,.badge-warning{background-color:#f37b1d}.label-warning[href],.badge-warning[href]{background-color:#f37b1d}.label-danger,.badge-danger{background-color:#dd514c}.label-danger[href],.badge-danger[href]{background-color:#dd514c}.Huialert{position:relative;padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5}.Huialert,.Huialert h4{color:#c09853}.Huialert h4{margin:0}.Huialert .Hui-iconfont{position:absolute;top:9px;right:10px;line-height:20px;cursor:pointer;color:#000;opacity:.2;_color:#666}.Huialert .Hui-iconfont.hover{color:#000;opacity:.8}.Huialert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.Huialert-success h4{color:#468847}.Huialert-danger{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.Huialert-danger h4{color:#b94a48}.Huialert-error{color:#fff;background-color:#f37b1d;border-color:#e56c0c}.Huialert-error h4{color:#fff}.Huialert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.Huialert-info h4{color:#31708f}.Huialert-block{padding-top:14px;padding-bottom:14px}.Huialert-block>p,.Huialert-block>ul{margin-bottom:0}.Huialert-block p+p{margin-top:5px}.progress,.progress-bar,.sr-only{height:10px;font-size:0;line-height:0}.progress{overflow:hidden;width:400px}.progress-bar{width:100%;background-color:#efefef}.sr-only{display:inline-block;background-color:#58b957}.loading{height:50px;background:url(../images/loading-b.gif) no-repeat center}.mask{position:fixed;top:0;left:0;z-index:999;width:100%;height:100%;background-color:rgba(0,0,0,0.7);-moz-transition:all .3s ease-in;-webkit-transition:all .3s ease-in;-o-transition:all .3s ease-in;transition:all .3s ease-in}* html .mask{position:absolute;left:expression(documentElement.scrollLeft+documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop+documentElement.clientHeight - this.offsetHeight)}.modal-open{overflow:hidden}.page-overflow{margin-right:16px}.modal-scrollable{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto}.modal-overflow .modal-scrollable{overflow-y:scroll}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:1040;background-color:#000}* html .modal-backdrop{position:absolute;left:expression(documentElement.scrollLeft+documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop+documentElement.clientHeight - this.offsetHeight)}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop,.modal-backdrop.fade.in{opacity:.7;filter:alpha(opacity=70)}.modal{position:absolute;top:50%;left:50%;width:500px;margin-left:-250px;z-index:1050;overflow:visible;background-color:#fff;background-clip:padding-box;box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-khtml-background-clip:padding-box;-moz-background-clip:padding-box;-ms-background-clip:padding-box;-o-background-clip:padding-box;background-clip:padding-box;border-radius:6px;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999}.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.fade.in{opacity:1;filter:alpha(opacity=100)}.modal.fade{top:-100%}.modal.fade.in{top:50%}.modal.modal-overflow.fade.in{top:0}.loading-spinner{position:absolute;top:50%;left:50%;margin:-12px 0 0 -12px}.modal-header{padding:9px 15px;border-bottom:1px solid #eee;position:relative}.modal-header .close{position:absolute;right:10px;top:10px}.modal-header h3{margin:0}.modal-body{overflow-y:visible;padding:15px;word-break:break-all}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;*zoom:1;border-radius:0 0 6px 6px;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-alert{position:fixed;width:300px;margin-left:-150px;margin-top:-30px;z-index:9999}.modal-alert-info{padding:30px;text-align:center;font-size:14px;background-color:#fff}.mask_box{background-image:none;display:none;z-index:99}.hover .mask_box{position:absolute;bottom:0;left:0;display:block;background-color:rgba(0,0,0,0.3);text-align:left}.easyDialog_wrapper{width:320px;color:#444;border:3px solid rgba(0,0,0,0);border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.4);display:none}.easyDialog_wrapper .easyDialog_content{border-radius:4px;background:#fff;border:1px solid #e5e5e5}.easyDialog_wrapper .easyDialog_title{height:30px;line-height:30px;overflow:hidden;color:#666;padding:0 10px;font-size:14px;border-bottom:1px solid #e5e5e5;background:#f7f7f7;border-radius:4px 4px 0 0;margin:0}.easyDialog_wrapper .close_btn{font-family:arial;font-size:18px;_font-size:12px;font-weight:700;color:#999;text-decoration:none;float:right}.easyDialog_wrapper .close_btn:hover{color:#333}.easyDialog_wrapper .easyDialog_text{padding:25px 10px;font-size:13px;line-height:22px}.easyDialog_wrapper .easyDialog_footer{padding:10px;text-align:right;*zoom:1}.easyDialog_wrapper .easyDialog_footer:after{content:'';display:block;height:0;overflow:hidden;visibility:hidden;clear:both}.easyDialog_wrapper .btn_highlight,.easyDialog_wrapper .btn_normal{border:1px solid;border-radius:2px;cursor:pointer;float:right;font-size:12px;padding:0 12px;height:24px;line-height:24px;margin-bottom:10px}.easyDialog_wrapper .btn_highlight{background:#4787ed;background:-webkit-gradient(linear,center bottom,center top,from(#4787ed),to(#4d90fe));background:-moz-linear-gradient(90deg,#4787ed,#4d90fe);border-color:#3079ed;color:#fff}.easyDialog_wrapper .btn_normal{margin-left:10px;border-color:#c3c3c3;background:#ececec;color:#333;background:-webkit-gradient(linear,center bottom,center top,from(#ececec),to(#f4f4f4));background:-moz-linear-gradient(90deg,#ececec,#f4f4f4)}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2070}.toTop{position:fixed;bottom:60px;right:15px;z-index:999;display:none;cursor:pointer;overflow:hidden;visibility:visible;background-color:#fff;border:1px solid #d9d9d9;color:#9c9c9c;font-size:16px;width:38px;height:38px;line-height:38px;text-align:center;text-decoration:none;_position:absolute;_top:expression(documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight)}.toTop:hover{color:#fff;text-decoration:none;background-color:#999;border-color:#999}.bdsharebuttonbox.Hui-share a.bds_more,.bdsharebuttonbox.Hui-share a.bds_weixin,.bdsharebuttonbox.Hui-share a.bds_qzone,.bdsharebuttonbox.Hui-share a.bds_sqq,.bdsharebuttonbox.Hui-share a.bds_tsina,.bdsharebuttonbox.Hui-share a.bds_tqq,.bdsharebuttonbox.Hui-share a.bds_douban{display:inline-block;background:0;padding-left:0;text-decoration:none;margin:0;margin-right:6px;height:auto;line-height:auto}.bdsharebuttonbox.Hui-share a:hover{text-decoration:none}.bdsharebuttonbox.Hui-share .share-text{display:inline-block;margin-right:6px;color:#999;cursor:default;float:left}.bdsharebuttonbox.bdshare-button-style0-16.Hui-share a,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{line-height:16px}.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{font-size:16px}.bdsharebuttonbox.bdshare-button-style0-24.Hui-share a,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{line-height:24px}.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{font-size:24px}.Hui-share.jiathis_style_24x24 .jtico{background:0;padding-left:0!important}.Hui-share.jiathis_style_24x24 .jiathis_separator{margin-left:0;margin-right:6px}.panel{background-color:#fff;border:solid 1px transparent}.panel-header{border-bottom:solid 1px transparent;padding:8px 15px;font-size:14px;font-weight:700}.panel-body{padding:15px}.panel-footer{background-color:#f5f5f5;border-top:1px solid #ddd;padding:5px 20px}.panel-default{border-color:#ddd}.panel-default>.panel-header{border-color:#ddd;background-color:#f5f5f5;color:#444}.panel-primary{border-color:#5a98de}.panel-primary>.panel-header{border-color:#5a98de;background-color:#5a98de;color:#fff}.panel-secondary{border-color:#3bb4f2}.panel-secondary>.panel-header{border-color:#3bb4f2;background-color:#3bb4f2;color:#fff}.panel-success{border-color:#5eb95e}.panel-success>.panel-header{border-color:#5eb95e;background-color:#5eb95e;color:#fff}.panel-warning{border-color:#f37b1d}.panel-warning>.panel-header{border-color:#f37b1d;background-color:#f37b1d;color:#fff}.panel-danger{border-color:#dd514c}.panel-danger>.panel-header{border-color:#dd514c;background-color:#dd514c;color:#fff}.docs-example{position:relative;*position:static;*padding-top:19px;margin:15px 0;padding:39px 19px 14px;background-color:#fff;border:1px solid #ddd;border-radius:4px}.docs-example:after{content:"Example";position:absolute;top:-1px;left:-1px;*position:static;padding:3px 7px;font-size:12px;font-weight:bold;background-color:#f5f5f5;border:1px solid #ddd;color:#9da0a4;border-radius:4px 0 4px 0}.marquee{height:22px;overflow:hidden;line-height:22px}.rollpic .prev,.rollpic .next{display:block;height:38px;width:38px;cursor:pointer;float:left;background:url(../images/unslider-arrow2.png) no-repeat 0 0;margin-top:70px}.rollpic .prev{background-position:0 0;margin-right:5px}.rollpic .prev:hover{background-position:0 -38px}.rollpic .next{background-position:0 -76px;margin-left:5px}.rollpic .next:hover{background-position:0 -114px}.rollpicshow{float:left;border:solid 1px #ddd}.rollpicshow li{padding:10px}.ac_results{position:absolute;border:solid 1px #ddd;background-color:#fff;padding:3px;display:none;margin-top:-1px;z-index:999}.ac_results ul{width:100%;list-style-position:outside;list-style:none;padding:0;margin:0}.ac_results li{padding-left:5px;padding-right:5px;display:block;height:24px;line-height:24px;cursor:pointer}.ac_results li p{float:left;margin:0;padding:0;overflow:hidden}.ac_results li p tt{color:#666}.ac_results li span{margin:0;padding:0;display:inline;float:right;color:#f93;width:90px;text-align:right;overflow:hidden}.ac_results li.ac_over{background-color:#f0f1f2}.ac_loading{background:#fff url(../images/loading-s.gif) right center no-repeat}.AD{text-align:center}.dual{top:260px;position:absolute;width:102px;overflow:hidden;display:none;z-index:100}.dual_l{left:6px}.dual_r{right:6px}.dual_con{border:#CCC solid 1px;width:100px;height:300px;overflow:hidden;background-color:#0C9}.dual_close{width:100%;height:24px;line-height:24px;text-align:center;display:block;font-size:13px;color:#555;text-decoration:none}.Hui-tags{border:solid 1px #dedede;padding:0 10px}.Hui-tags-editor{position:relative;padding:10px 0 10px 24px}.Hui-tags-editor .Hui-tags-icon{position:absolute;left:0;top:11px;font-size:14px;color:#666}.Hui-tags-token{color:#aaa;float:left;font-size:12px;height:20px;line-height:20px;margin-right:8px;padding:0 1px;white-space:nowrap;cursor:pointer}.Hui-tags-token:before{content:"#"}.Hui-tags-token:hover{text-decoration:line-through}.Hui-tags-iptwrap{position:relative;float:left}.Hui-tags-input{position:relative;height:20px;min-width:60px;border:0 none;vertical-align:top;line-height:20px;color:#333;z-index:2;background:url(../images/Hui-tags/empty.png) repeat scroll 0 0;display:inline-block;width:100%}.Hui-tags-label{position:absolute;top:0;left:2px;width:240px;height:20px;line-height:20px;font-size:14px;overflow:hidden;z-index:1;color:#ccc}.Hui-tags-list{padding:0 0 10px 0;display:none}.Hui-notag{font-size:12px}.Hui-tags-has span{cursor:pointer;font-size:12px;white-space:nowrap;margin-right:10px}.tags a{height:26px;line-height:26px;padding-right:6px}.tags1{color:#C00;font-size:24px}.tags2{color:#030;font-size:16px}.tags3{color:#00F}.tags4{font-size:16px}.tags5{color:#C00;font-size:20px}.tags6{color:#F06 font-size:20px}.tags7{color:#030;font-weight:bold;font-size:18px}.tags8{color:#F06;font-weight:bold}.tags9{color:#C00;font-weight:bold;font-size:16px}.tags a:hover{color:#F00;text-decoration:underline}#tagyun{position:relative}#tagyun a{position:absolute;top:0;left:0;font-weight:bold;text-decoration:none;padding:3px 6px}.Huifold .item{position:relative}.Huifold .item h4{margin:0;font-weight:bold;position:relative;border-top:1px solid #fff;font-size:15px;line-height:22px;padding:7px 10px;background-color:#eee;cursor:pointer;padding-right:30px}.Huifold .item h4 b{position:absolute;display:block;cursor:pointer;right:10px;top:7px;width:16px;height:16px;text-align:center;color:#666}.Huifold .item .info{display:none;padding:10px}.maskBar{position:absolute;height:auto;left:0;bottom:-100%;right:0;padding:10px;background-color:rgba(0,0,0,0.6);z-index:2;color:#fff!important}.maskWraper{position:relative;overflow:hidden}.maskWraper.hover .maskBar{bottom:0;transition:bottom 200ms;-moz-transition:bottom 200ms;-webkit-transition:bottom 200ms;-o-transition:bottom 200ms}.maskBox{position:absolute;width:100%;height:100%;top:0;left:0;bottom:0;right:0;z-index:2;color:#fff!important}.maskWraper.hover .maskBox{background-color:rgba(0,0,0,0.6);transition:all 500ms;-moz-transition:all 500ms;-webkit-transition:all 500ms;-o-transition:all 500ms}.commentList .item{list-style:none outside none;margin:1.6rem 0 0}.commentList .avatar{border:1px solid transparent;float:left}.comment-main{position:relative;margin-left:64px;border:1px solid #dedede;border-radius:2px}.comment-main:before,.comment-main:after{position:absolute;top:11px;left:-16px;right:100%;width:0;height:0;display:block;content:" ";border-color:transparent;border-style:solid solid outset;pointer-events:none}.comment-main:before{border-right-color:#dedede;border-width:8px}.comment-main:after{border-width:7px;border-right-color:#f8f8f8;margin-top:1px;margin-left:2px}.comment-header{padding:10px 15px;background:#f8f8f8;border-bottom:1px solid #eee}.comment-title{margin:0 0 8px 0;font-size:1.6rem;line-height:1.2}.comment-meta{font-size:13px;color:#999;line-height:1.2}.comment-meta a{color:#999}.comment-author{font-weight:700;color:#999}.comment-body{padding:15px;overflow:hidden}.comment-body>:last-child{margin-bottom:0}.commentList .comment-flip .avatar{float:right}.comment-flip .comment-main{margin-left:0;margin-right:64px}.comment-flip .comment-main:before{border-left-color:#dedede;border-right-color:transparent}.comment-flip .comment-main:before,.comment-flip .comment-main:after{left:100%;position:absolute;right:-16px}.comment-flip .comment-main:after{border-left-color:#f8f8f8;border-right-color:transparent;margin-left:auto;margin-right:2px}.footer{border-top:1px solid #e8e8e8;padding:15px 0;font-family:tahoma,Arial;font-size:12px;color:#999;line-height:22px;text-align:center}.footer a,.footer a:hover{color:#999}.page-404{color:#afb5bf;padding-top:60px;padding-bottom:90px}.page-404 .error-title{font-size:80px}.page-404 .error-title .iconfont{font-size:80px}.page-404 .error-description{font-size:24px}.page-404 .error-info{font-size:14px} \ No newline at end of file +@charset "utf-8";*{word-wrap:break-word}html,body,h1,h2,h3,h4,h5,h6,hr,p,iframe,dl,dt,dd,ul,ol,li,pre,form,button,input,textarea,th,td,fieldset{margin:0;padding:0}ul,ol,dl{list-style-type:none}html,body{*position:static}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}input,button{overflow:visible;vertical-align:middle;outline:0}input[type="submit"],input[type="reset"],input[type="button"],input[type="text"],input[type="password"]{-webkit-appearance:none;outline:0}body,th,td,button,input,select,textarea{font-family:"Microsoft Yahei","Hiragino Sans GB","Helvetica Neue",Helvetica,tahoma,arial,"WenQuanYi Micro Hei",Verdana,sans-serif,"\5B8B\4F53";font-size:12px;color:#333;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media(max-width :767px){html{overflow-y:auto}body,th,td,button,input,select,textarea{font-size:14px}}body{line-height:1.6}h1,h2,h3,h4,h5,h6{font-size:100%}a,area{outline:0;blr:expression(this.onFocus=this.blur())}a{text-decoration:none;cursor:pointer}a:hover{text-decoration:underline;outline:0}a.ie6:hover{zoom:1}a:focus{outline:0}a:hover,a:active{outline:0}:focus{outline:0}sub,sup{vertical-align:baseline}button,input[type="button"],input[type="submit"]{line-height:normal!important}img{border:0;vertical-align:middle}a img,img{-ms-interpolation-mode:bicubic}*html{overflow:-moz-scrollbars-vertical;zoom:expression(function(ele){ele.style.zoom = "1";document.execCommand("BackgroundImageCache",false,true)}(this))}header,footer,section,aside,details,menu,article,section,nav,address,hgroup,figure,figcaption,legend{display:block;margin:0;padding:0}time{display:inline}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}legend{width:100%;margin-bottom:20px;font-size:21px;line-height:40px;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}svg:not(:root){overflow:hidden}fieldset{border-width:0;padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}.cl:after,.clearfix:after{content:"\20";display:block;height:0;clear:both;visibility:hidden}.cl,.clearfix{zoom:1}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width :992px){.container{width:960px}}@media(min-width :1200px){.container{width:1170px}}@media(min-width :1300px){.container{width:1270px}}@media print{.container{width:auto}}.row{box-sizing:border-box;margin-left:-15px;margin-right:-15px}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{min-height:1px;position:relative;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;-o-transition:all .3s ease-in;transition:all .3s ease-in}.col-1{width:8.33333%}.col-2{width:16.66667%}.col-3{width:25%}.col-4{width:33.33333%}.col-5{width:41.66667%}.col-6{width:50%}.col-7{width:58.33333%}.col-8{width:66.66667%}.col-9{width:75%}.col-10{width:83.33333%}.col-11{width:91.66667%}.col-12{width:100%}.col-offset-0{margin-left:0}.col-offset-1{margin-left:8.33333%}.col-offset-2{margin-left:16.66667%}.col-offset-3{margin-left:25%}.col-offset-4{margin-left:33.33333%}.col-offset-5{margin-left:41.66667%}.col-offset-6{margin-left:50%}.col-offset-7{margin-left:58.33333%}.col-offset-8{margin-left:66.66667%}.col-offset-9{margin-left:75%}.col-offset-10{margin-left:83.33333%}.col-offset-11{margin-left:91.66667%}.col-push-0{position:relative;left:0;right:auto}.col-pull-0{right:0;left:auto}.col-push-1{left:8.33333%;right:auto}.col-pull-1{right:8.33333%;left:auto}.col-push-2{left:16.66667%;right:auto}.col-pull-2{right:16.66667%;left:auto}.col-push-3{left:25%;right:auto}.col-pull-3{right:25%;left:auto}.col-push-4{left:33.33333%;right:auto}.col-pull-4{right:33.33333%;left:auto}.col-push-5{left:41.66667%;right:auto}.col-pull-5{right:41.66667%;left:auto}.col-push-6{left:50%;right:auto}.col-pull-6{right:50%;left:auto}.col-push-7{left:58.33333%;right:auto}.col-pull-7{right:58.33333%;left:auto}.col-push-8{left:66.66667%;right:auto}.col-pull-8{right:66.66667%;left:auto}.col-push-9{left:75%;right:auto}.col-pull-9{right:75%;left:auto}.col-push-10{left:83.33333%;right:auto}.col-pull-10{right:83.33333%;left:auto}.col-push-11{left:91.66667%;right:auto}.col-pull-11{right:91.66667%;left:auto}.col-1-1{width:100%}.col-2-1{width:50%}.col-3-1{width:33.333333%}.col-3-2{width:66.666667%}.col-4-1{width:25%}.col-4-3{width:75%}.col-5-1{width:20%}.col-5-2{width:40%}.col-5-3{width:60%}.col-5-4{width:80%}.col-6-1{width:16.666667%}.col-6-5{width:83.333333%}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media(max-width:767px){.responsive [class^="col-"],.responsive [class*=" col-"]{float:none!important;width:auto!important}.responsive [class^="col-offset-"],.responsive [class*=" col-offset-"]{margin-left:0!important}}@media(min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.visible-xs,.visible-sm,.visible-md,.visible-lg,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media(max-width :767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}.hidden-xs{display:none!important}.visible-xs-block{display:block!important}.visible-xs-inline{display:inline!important}.visible-xs-inline-block{display:inline-block!important}}@media(min-width :768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}.hidden-sm{display:none!important}.visible-sm-block{display:block!important}.visible-sm-inline{display:inline!important}.visible-sm-inline-block{display:inline-block!important}}@media(min-width :992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}.hidden-md{display:none!important}.visible-md-block{display:block!important}.visible-md-inline{display:inline!important}.visible-md-inline-block{display:inline-block!important}}@media(min-width :1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}.hidden-lg{display:none!important}.visible-lg-block{display:block!important}.visible-lg-inline{display:inline!important}.visible-lg-inline-block{display:inline-block!important}}.visible-print{display:none!important}.visible-print-block{display:none!important}.visible-print-inline{display:none!important}.visible-print-inline-block{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.visible-print-block{display:block!important}.visible-print-inline{display:inline!important}.visible-print-inline-block{display:inline-block!important}.hidden-print{display:none!important}}.Hui-wraper,.wp{margin-left:auto;margin-right:auto;text-align:left}.sd{float:right}.ct2 .mn{float:left}.ct2 .sd{float:right}.ct2_r .leftmenu{float:left}.ct2_r .mn{float:right}.ct3 .app{float:left;margin-right:20px}.ct3 .mn{float:left;border-left:solid 1px #ddd}.ct3 .sd{float:right}.w-1000{width:1000px}.w-980{width:980px}.w-300{width:300px}.w-200{width:200px}@media(max-width:1000px){.Hui-wraper,.wp,{width:auto!important;padding:0 15px!important}}@media print{.Hui-wraper{width:auto}}h1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small{font-weight:400;line-height:1;color:#999}h1,h2,h3{padding-top:20px;padding-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:18px}h5{font-size:14px}h6{font-size:12px}p{margin-bottom:10px}small{font-size:85%}b,strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}mark{color:#000;background:#ff0}dfn{font-style:italic}del{font-family:Simsun}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.en{font-family:Arial!important}.text-l{text-align:left}.text-r{text-align:right}.text-c{text-align:center}.va *{vertical-align:sub!important;*vertical-align:middle!important;_vertical-align:middle!important}.va-t{vertical-align:top!important}.va-m{vertical-align:middle!important}.va-b{vertical-align:bottom!important}.pos-r{position:relative}.pos-a{position:absolute}.pos-f{position:fixed}.l,.f-l{float:left!important;_display:inline}.r,.f-r{float:right!important;_display:inline}[class*="span"].r,[class*="span"].f-r{float:right}.left{left:0;right:auto}.right{right:0;left:auto}.top{top:auto;bottom:0}.bottom{top:0;bottom:auto}.text-overflow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.line{font-size:0;line-height:0;border-top:solid 1px #eee;float:none}.mt-5{margin-top:5px}.mt-10{margin-top:10px}.mt-15{margin-top:15px}.mt-20{margin-top:20px}.mt-25{margin-top:25px}.mt-30{margin-top:30px}.mt-35{margin-top:35px}.mt-40{margin-top:40px}.mt-50{margin-top:50px}.mb-5{margin-bottom:5px}.mb-10{margin-bottom:10px}.mb-15{margin-bottom:15px}.mb-20{margin-bottom:20px}.mb-30{margin-bottom:30px}.mb-40{margin-bottom:40px}.mb-50{margin-bottom:50px}.ml-5{margin-left:5px}.ml-10{margin-left:10px}.ml-15{margin-left:15px}.ml-20{margin-left:20px}.ml-30{margin-left:30px}.ml-40{margin-left:40px}.ml-50{margin-left:50px}.mr-5{margin-right:5px}.mr-10{margin-right:10px}.mr-15{margin-right:15px}.mr-20{margin-right:20px}.mr-30{margin-right:30px}.mr-40{margin-right:40px}.mr-50{margin-right:50px}.pt-5{padding-top:5px}.pt-10{padding-top:10px}.pt-20{padding-top:20px}.pb-5{padding-bottom:5px}.pb-10{padding-bottom:10px}.pb-20{padding-bottom:20px}.pb-30{padding-bottom:30px}.pl-5{padding-left:5px}.pl-10{padding-left:10px}.pl-20{padding-left:20px}.pl-30{padding-left:30px}.pr-5{padding-right:5px}.pr-10{padding-right:10px}.pr-20{padding-right:20px}.pd-5{padding:5px}.pd-10{padding:10px}.pd-15{padding:15px}.pd-20{padding:20px}.pd-30{padding:30px}.pd-40{padding:40px}.bk-gray{border:solid 1px #eee}.radius{border-radius:4px}.size-MINI.radius{border-radius:3px}.size-L.radius{border-radius:5px}.size-XL.radius{border-radius:6px}.round{border-radius:50%;overflow:hidden}.box-shadow{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.1);box-shadow:0 1px 2px rgba(0,0,0,0.1)}.text-shadow{-webkit-text-shadow:0 0 2px rgba(0,0,0,0.2);text-shadow:0 0 2px rgba(0,0,0,0.2)}.pipe{margin:0 5px;color:#CCC;font-size:10px!important}.f-12{font-size:12px}.f-14{font-size:14px}.f-16{font-size:16px}.f-18{font-size:18px}.f-20{font-size:20px}.f-24{font-size:24px}.f-26{font-size:26px}.f-28{font-size:28px}.f-30{font-size:30px}.lh-16{line-height:16px}.lh-18{line-height:18px}.lh-20{line-height:20px}.lh-22{line-height:22px}.lh-24{line-height:24px}.lh-26{line-height:26px}.lh-28{line-height:28px}.lh-30{line-height:30px}.l16{line-height:16px}.l18{line-height:18px}.l20{line-height:20px}.l22{line-height:22px}.l-24{line-height:24px}.l-26{line-height:26px}.l-28{line-height:28px}.l-30{line-height:30px}body{background-color:#fff;color:#333}.bg-fff{background-color:#fff}a{color:#333}a:hover,.active a{color:#06c}.c-primary,.c-primary a,a.c-primary{color:#5a98de}.c-primary a:hover,a.c-primary:hover{color:#5a98de}.c-secondary,.c-secondary a,a.c-secondary{color:#555}.c-secondary a:hover,a.c-secondary:hover{color:#555}.c-success,.c-success a,a.c-success{color:#5eb95e}.c-success a:hover,a.c-success:hover{color:#5eb95e}.c-danger,.c-danger a,a.c-danger{color:#dd514c}.c-danger a:hover,a.c-danger:hover{color:#dd514c}.c-warning,.c-warning a,a.c-warning{color:#f37b1d}.c-warning a:hover,a.c-warning:hover{color:#f37b1d}.c-error,.c-error a,a.c-error{color:#c00}.c-error a:hover,a.c-error:hover{color:#c00}.c-333,.c-333 a,a.c-333{color:#333}.c-333 a:hover,a.c-333:hover{color:#333}.c-666,.c-666 a,a.c-666{color:#666}.c-666 a:hover,a.c-666:hover{color:#666}.c-999,.c-999 a,a.c-999{color:#999}.c-999 a:hover,a.c-999:hover{color:#999}.c-red,.c-red a,a.c-red{color:red}.c-red a:hover,a.c-red:hover{color:red}.c-green,.c-green a,a.c-green{color:green}.c-red a:hover,a.c-red:hover{color:green}.c-blue,.c-blue a,a.c-blue{color:blue}.c-blue a:hover,a.c-blue:hover{color:blue}.c-white,.c-white a,a.c-white{color:white}.c-white a:hover,a.c-white:hover{color:white}.c-black,.c-black a{color:black}.c-black a:hover,a.c-black:hover{color:black}.c-orange,.c-orange a,a.c-orange{color:orange}.c-orange a:hover,a.c-orange:hover{color:orange}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.text-r{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.text-r p,blockquote.text-r small{text-align:right}blockquote.text-r small:before{content:''}blockquote.text-r small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}.content{position:relative;font-size:17px;line-height:1.8;overflow:hidden;text-align:left;word-break:break-all;word-wrap:break-word}.content h3{font-size:18px}.content h4{font-size:16px}.content p{margin-bottom:1.5rem;text-align:justify;word-break:break-all}.content p.text-c{text-align:center}.indent{text-indent:2em}.content img{max-width:100%}.content ul{text-indent:2em}@media(max-width:767px){.content{font-size:16px}}@media(max-width:480px){.content img{max-width:100%!important;height:auto!important;width:expression(this.width>320 ? "320px":this.width)!important}*html .content img{width:expression(this.width>320&&this.width>this.height?320:auto)}}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}.list-view>.item{padding:10px;position:relative;overflow:hidden}.list-view>.item .date{font-size:12px;font-family:Arial;color:#999}@media(max-width:767px){.list-view>.item{font-size:18px;padding:11px 15px;border-bottom:1px solid #eee}.list-view>.item>a{display:block;margin:-11px -15px}.night .list-view>.item{border-bottom:1px solid #1f1f1f}.list-view>.item .date{display:none}.list-view>.item .Hui-iconfont{background-size:9px auto;margin-top:-7px;position:absolute;right:15px;top:50%}}.list-top>.item{padding-left:30px}.list-top>.item .num{position:absolute;top:11px;display:block;width:20px;height:20px;color:#fff;background-color:#5a98de;text-align:center}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.hide{display:none}[hidden]{display:none}.hidden{display:none!important;visibility:hidden!important}.f-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}.show{display:block}.invisible{visibility:hidden}.input-text,.btn,.input-text.size-M,.btn.size-M{font-size:14px;height:31px;*height:auto;line-height:1.42857;padding:4px}a.btn,a.btn.size-M,span.btn,span.btn.size-M{line-height:21px}.btn,.btn.size-M{padding:4px 12px}.input-text.size-MINI,.btn.size-MINI{font-size:12px;height:23px;padding:1px 2px;line-height:1.42857}a.btn.size-MINI,span.btn.size-MINI{line-height:21px}.btn.size-MINI{padding:1px 4px}.input-text.size-S,.btn.size-S{font-size:12px;height:27px;padding:3px;line-height:1.42857}a.btn.size-S,span.btn.size-S{line-height:19px}.btn.size-S{padding:3px 8px}.input-text.size-L,.btn.size-L{font-size:16px;height:41px;padding:8px}a.btn.size-L,span.btn.size-L{line-height:23px}.btn.size-L{padding:8px 16px}.input-text.size-XL,.btn.size-XL{font-size:18px;height:48px;padding:10px}a.btn.size-XL,span.btn.size-XL{line-height:26px}.btn.size-XL{padding:10px 24px}@media(max-width:767px){.responsive .input-text.size-MINI,.responsive .btn.size-MINI{height:24px}.responsive .input-text.size-S,.responsive .btn.size-S{font-size:14px;height:30px}.responsive .input-text,.btn,.responsive .input-text.size-M,.responsive .btn.size-M{font-size:16px;height:36px}.responsive .input-text.size-L,.responsive .btn.size-L{font-size:18px;height:42px}.responsive .input-text.size-XL,.responsive .btn.size-XL{font-size:20px;height:48px}}code{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace}pre .title,pre .keyword,pre .body,pre .des{color:#333}pre{display:block;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;padding:9.5px;margin-bottom:10px;font-size:12px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px;color:#333}.prettyprint{margin-bottom:20px;padding:8px;background-color:#f7f7f9;border:1px solid #e1e1e8}.prettyprint .com{color:#998;font-style:italic}.prettyprint .tag{color:#007}.prettyprint .lit{color:#195f91}.prettyprint .pun,.prettyprint .opn,.prettyprint .clo{color:#93a1a1}.prettyprint .fun{color:#dc322f}.prettyprint .str,.prettyprint .atv{color:#D14}.prettyprint .kwd,.prettyprint .prettyprint .tag{color:#1e347b}.prettyprint .typ,.prettyprint .atn,.prettyprint .dec,.prettyprint .var{color:teal}.prettyprint .pln{color:#48484c}.prettyprint.linenums{box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0}.pre-scrollable{max-height:340px;overflow-y:scroll}ol.linenums{list-style:decimal outside none;margin-left:20px}ol.linenums li{line-height:28px;padding-left:10px}pre ol.linenums{margin:0 0 0 33px}pre ol.linenums li{padding-left:12px;color:#bbb;line-height:18px;text-shadow:0 1px 0 #fff}@media(max-width:767px){pre ol.linenums{margin-left:0;list-style:none}ol.linenums li{padding-left:0}.prettyprint.linenums{box-shadow:inset 0 0 0 #fbfbfc,inset 0 0 0 #ececf0}}table{width:100%;empty-cells:show;background-color:transparent;border-collapse:collapse;border-spacing:0}table th{text-align:left;font-weight:400}.table th{font-weight:bold}.table th,.table td{padding:8px;line-height:20px;word-break:break-all}.table td{text-align:left}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-border{border-top:1px solid #ddd}.table-border th,.table-border td{border-bottom:1px solid #ddd}.table-bg thead th{background-color:#f5fafe}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-border.table-bordered{border-bottom:0}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-condensed th,.table-condensed td{padding:4px 5px}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}.table tbody tr.selected td{background-color:#f3f3f3}.table tbody tr.active,.table tbody tr.active>td,.table tbody tr.active>th,.table tbody tr .active{background-color:#f5f5f5!important}.table tbody tr.success,.table tbody tr.success>td,.table tbody tr.success>th,.table tbody tr .success{background-color:#dff0d8!important}.table tbody tr.warning,.table tbody tr.warning>td,.table tbody tr.warning>th,.table tbody tr .warning{background-color:#fcf8e3!important}.table tbody tr.danger,.table tbody tr.danger>td,.table tbody tr.danger>th,.table tbody tr .danger{background-color:#f2dede!important}.table .text-c th,.table .text-c td{text-align:center}.table .text-r th,.table .text-r td{text-align:right}.table th.text-l,.table td.text-l{text-align:left!important}.table th.text-c,.table td.text-c{text-align:center!important}.table th.text-r,.table td.text-r{text-align:right!important}table.dataTable{border-collapse:separate;border-spacing:0;clear:both}table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting{cursor:pointer;background-repeat:no-repeat;background-position:right center}table.dataTable thead .sorting{background-image:url(../images/dataTable/sort_both.png)}table.dataTable thead .sorting_asc{background-image:url(../images/dataTable/sort_asc.png)}table.dataTable thead .sorting_desc{background-image:url(../images/dataTable/sort_desc.png)}.dataTable td.sorting_1{background-color:#f5fafe}.dataTables_wrapper .dataTables_length{float:left;padding-bottom:20px}.dataTables_wrapper .dataTables_length .select{width:50px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter .input-text{width:auto}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:10px;font-size:14px;color:#666}.dataTables_wrapper .dataTables_paginate{float:right;padding-top:10px;text-align:right}.dataTables_wrapper .dataTables_paginate .paginate_button{border:1px solid #ccc;cursor:pointer;display:inline-block;margin-left:2px;text-align:center;text-decoration:none;color:#666;height:26px;line-height:26px;text-decoration:none;margin:0 0 6px 6px;padding:0 10px;font-size:14px}.dataTables_wrapper .dataTables_paginate .paginate_button:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{background:#5a98de;color:#fff}@media(max-width:767px){table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}table-responsive>.table{margin-bottom:0}table-responsive>.table>thead>tr>th,table-responsive>.table>tbody>tr>th,table-responsive>.table>tfoot>tr>th,table-responsive>.table>thead>tr>td,table-responsive>.table>tbody>tr>td,table-responsive>.table>tfoot>tr>td{white-space:nowrap}table-responsive>.table-bordered{border:0}table-responsive>.table-bordered>thead>tr>th:first-child,table-responsive>.table-bordered>tbody>tr>th:first-child,table-responsive>.table-bordered>tfoot>tr>th:first-child,table-responsive>.table-bordered>thead>tr>td:first-child,table-responsive>.table-bordered>tbody>tr>td:first-child,table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}table-responsive>.table-bordered>thead>tr>th:last-child,table-responsive>.table-bordered>tbody>tr>th:last-child,table-responsive>.table-bordered>tfoot>tr>th:last-child,table-responsive>.table-bordered>thead>tr>td:last-child,table-responsive>.table-bordered>tbody>tr>td:last-child,table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}table-responsive>.table-bordered>tbody>tr:last-child>th,table-responsive>.table-bordered>tfoot>tr:last-child>th,table-responsive>.table-bordered>tbody>tr:last-child>td,table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}.input-text,.textarea{box-sizing:border-box;border:solid 1px #ddd;width:100%;-webkit-transition:all .2s linear 0s;-moz-transition:all .2s linear 0s;-o-transition:all .2s linear 0s;transition:all .2s linear 0s}.textarea{height:100px;resize:none;font-size:14px;padding:4px}.textarea-numberbar{position:absolute;right:20px;bottom:5px;z-index:1;margin-bottom:0}.textarea-length{font-style:normal}.input-text:hover,.textarea:hover{border:solid 1px #3bb4f2}.input-text.focus,.textarea.focus{border:solid 1px #0f9ae0 \9;border-color:rgba(82,168,236,0.8);box-shadow:0 1px 1px rgba(0,0,0,0.075) inset,0 0 8px rgba(102,175,233,0.6)}.input-text.disabled,.textarea.disabled,.input-text.disabled.focus,.textarea.disabled.focus{background-color:#ededed;cursor:default;border-color:#ddd;-webkit-box-shadow:inset 0 2px 2px #e8e7e7;-moz-box-shadow:inset 0 2px 2px #e8e7e7;box-shadow:inset 0 2px 2px #e8e7e7}.input-text.disabled,.textarea.disabled{background-color:#e6e6e6;cursor:default}.input-text.box-shadow,.textarea.box-shadow{-ms-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.input-text.inline{display:inline-block;width:auto}input[type="radio"],input[type="checkbox"]{line-height:normal;margin-top:-4px}.check-box,.radio-box{display:inline-block;box-sizing:border-box;cursor:pointer;position:relative;padding-left:30px;padding-right:20px}.icheckbox,.icheckbox-red,.icheckbox-green,.icheckbox-blue,.icheckbox-aero,.icheckbox-grey,.icheckbox-orange,.icheckbox-yellow,.icheckbox-pink,.icheckbox-purple,.iradio,.iradio-red,.iradio-green,.iradio-blue,.iradio-aero,.iradio-grey,.iradio-orange,.iradio-yellow,.iradio-pink,.iradio-purple{position:absolute;top:4px;left:0}@media(max-width:767px){.responsive .check-box,.responsive .radio-box{display:block}}.select-box{border:solid 1px #ddd;box-sizing:border-box;vertical-align:middle;width:100%;display:inline-block}.select{border:solid 1px #ddd;box-sizing:border-box;cursor:pointer;line-height:normal;font-weight:normal;width:100%;white-space:nowrap}.select-box .select{border:0}.select-box.inline,.select-box.inline .select{width:auto}.select-box,.select-box.size-M{padding:4px 5px}.select,.size-M .select{font-size:14px}.select-box.size-MINI{padding:0 5px}.size-MINI .select{font-size:12px}.select-box.size-S{padding:3px 5px}.size-S .select{font-size:12px}.select-box.size-L{padding:8px 5px}.size-L .select{font-size:16px}.select-box.size-XL{padding:10px 5px}.size-XL .select{font-size:18px}@media(max-width:767px){.responsive .select-box{border:0}.responsive .select-box .select,.responsive .select{border:solid 1px #ddd;padding:10px;font-size:16px}.responsive .select-box,.responsive .select-box.size-M,.responsive .select-box.size-MINI,.responsive .select-box.size-S,.responsive .select-box.size-L,.responsive .select-box.size-XL{height:auto;padding:0}}.select-wrapper{position:relative;display:inline-block;font-size:14px;cursor:default}.select-default{zoom:1;display:block;padding-left:10px;padding-right:30px;background-color:#fff;border:solid 1px #d0d0d0;height:34px;line-height:34px}.jsselect.radius{overflow:visible}.jsselect.radius .select-default{border-radius:4px}.jsselect.radius .select-list{border-radius:4px;border-top-left-radius:0;border-top-right-radius:0}.select-icon{position:absolute;height:8px;width:12px;right:10px;top:50%;margin-top:-4px;background:url(../images/jselect/iconpic-arrow-down2.png) no-repeat center}.unselectable{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.select-list{position:absolute;left:0;right:0;top:100%;z-index:1;line-height:34px;max-height:320px;overflow:auto;background-color:#fff;background-clip:padding-box;_height:expression(this.scrollHeight>319 ? "320px":"auto");-moz-box-shadow:0 1px 2px rgba(0,1,1,0.2);-webkit-box-shadow:0 1px 2px rgba(0,1,1,0.2);box-shadow:0 1px 2px rgba(0,1,1,0.2);box-sizing:border-box;border:solid 1px #d0d0d0;behavior:url(ie-css3.htc)}.select-item{margin:0;padding:0}.select-option{background:#fff;line-height:34px;text-align:left;white-space:nowrap;cursor:pointer;border-bottom:1px solid #f2f2f2;padding:0 10px}.select-item .selected{background-color:#148cf1;color:#fff}.btn-upload{position:relative;display:inline-block;height:31px;*display:inline;overflow:hidden;vertical-align:middle;cursor:pointer}.upload-url{cursor:pointer;width:300px}.input-file{position:absolute;right:0;top:0;cursor:pointer;z-index:1;font-size:30em;opacity:0;filter:alpha(opacity=0)}.form-group .upload-btn{margin-left:-1px}.btn-upload .icon-add,.btn-upload .icon-minus{cursor:pointer;display:inline-block;font-family:Arial;font-size:30px;height:31px;line-height:31px;text-align:center;vertical-align:middle;width:36px}@media(max-width:767px){.upload-btn{display:none}.upload-url{display:none}}.numberControlBox{display:inline-block;overflow:hidden;vertical-align:middle}.ncb-up,.ncb-down{font-size:0;display:block;height:10px;background-color:#f4f4f4;background:-moz-linear-gradient(top,#fff 0,#e6e6e6 50%,#fff 100%);width:24px;border:1px solid #d1d1d1;cursor:pointer}.ncb-up{margin-bottom:1px}.numberControlBox .ncb_ico{display:block;height:10px;background-image:url(../images/iconpic-arrow.png);background-repeat:no-repeat}.ncb-up .ncb_ico{background-position:-22px center}.ncb-down .ncb_ico{background-position:1px center}.ncb_btn_hover{border:1px solid #9dc7e7;background-color:#dff2fc;background:-moz-linear-gradient(top,#fff 0,#d2edfa 50%,#fff 100%)}.ncb_btn_selected{border:1px solid #6198c2;background-color:#aee1fb;background:-moz-linear-gradient(top,#fff 0,#aee1fb 50%,#fff 100%)}.input-text[type="number"]{width:80px}label,.placeholder{font-size:14px}.form legend{font-size:20px}.form .row{margin-top:15px}.form-label{display:block;color:#555}.formControls{position:relative}.formControls>*{vertical-align:middle}.placeholder{position:absolute;left:4px;top:4px;color:#c6c6c6;cursor:text}.form-horizontal .form-label{margin-top:3px;cursor:text;text-align:right}.form-horizontal .Validform_checktip{margin-top:5px}::-webkit-input-placeholder{color:#b3b3b3}:-moz-placeholder{color:#b3b3b3}::-moz-placeholder{color:#b3b3b3}:-ms-input-placeholder{color:#b3b3b3}.placeholder{color:#adb0be;position:absolute;z-index:9}@media(max-width:767px){.form-horizontal .form-label{text-align:left}}.Validform_error,input.error,select.error{background-color:#fbe2e2;border-color:#c66161;color:#c00}.Validform_wrong,.Validform_right,.Validform_warning{display:inline-block;height:20px;font-size:12px;vertical-align:middle;padding-left:25px}.Validform_wrong{background:url(../images/validform/iconpic-error.png) no-repeat 0 center;color:#ef392b}.Validform_right{background:url(../images/validform/iconpic-right.png) no-repeat 0 center}.Validform_warning{background:url(../images/validform/iconpic-warning.png) no-repeat 0 center;color:#777}label.error{position:absolute;right:18px;top:5px;color:#ef392b;font-size:12px}.passwordStrength b{font-weight:400}.passwordStrength b,.passwordStrength span{display:inline-block;vertical-align:middle;line-height:16px;line-height:18px\9;height:16px}.passwordStrength span{width:57px;text-align:center;background-color:#d0d0d0;border-right:1px solid #fff}.passwordStrength .last{border-right:0}.passwordStrength .bgStrength{color:#fff;background-color:#fcc900}#Validform_msg{font-size:14px;width:300px;-webkit-box-shadow:2px 2px 3px #aaa;-moz-box-shadow:2px 2px 3px #aaa;background:#fff;position:absolute;top:0;right:50px;z-index:99999;display:none;filter:progid:DXImageTransform.Microsoft.Shadow(Strength=3,Direction=135,Color='#999999');box-shadow:2px 2px 0 rgba(0,0,0,0.1)}#Validform_msg .iframe{position:absolute;left:0;top:-1px;z-index:-1}#Validform_msg .Validform_title{font-size:20px;padding:10px;text-align:left;color:#fff;position:relative;background-color:#fcc900}#Validform_msg a.Validform_close:link,#Validform_msg a.Validform_close:visited{position:absolute;right:8px;top:6px;color:#fff;text-decoration:none;font-family:Verdana}#Validform_msg a.Validform_close:hover{color:#fff}#Validform_msg .Validform_info{padding:10px;border:1px solid #bbb;border-top:0;text-align:left}@media(max-width:767px){.responsive .Validform_checktip{margin-top:10px}}.close{font-size:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;box-sizing:border-box;cursor:pointer;text-align:center;font-weight:400;white-space:nowrap;vertical-align:middle;-moz-padding-start:npx;-moz-padding-end:npx;border:solid 1px #ddd;background-color:#fff;width:auto;*zoom:1;*overflow:visible;-webkit-transition:background-color .1s linear;-moz-transition:background-color .1s linear;-o-transition:background-color .1s linear;transition:background-color .1s linear}a.btn:hover,a.btn:focus,a.btn:active,a.btn.active,a.btn.disabled,a.btn[disabled]{text-decoration:none}.btn:active,.btn.active{background-color:#ccc}.btn:first-child{*margin-left:0}.btn.active,.btn:active{-moz-box-shadow:0 1px 8px rgba(0,0,0,0.125) inset;-webkit-box-shadow:0 1px 8px rgba(0,0,0,0.125) inset;box-shadow:0 1px 8px rgba(0,0,0,0.125) inset}.btn-default{background-color:#e6e6e6;border-color:#e6e6e6}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active{color:#333;background-color:#c7c7c7;border-color:#c7c7c7}.btn-primary{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active{color:#fff;background-color:#0a6999;border-color:#0a6999}.btn-secondary{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary:hover,.btn-secondary:focus,.btn-secondary:active,.btn-secondary.active{color:#fff;background-color:#0f9ae0;border-color:#0f9ae0}.btn-success{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active{color:#fff;background-color:#429842;border-color:#429842}.btn-warning{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active{color:#fff;background-color:#c85e0b;border-color:#c85e0b}.btn-danger{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active{color:#fff;background-color:#c62b26;border-color:#c62b26}.btn-link{color:#0e90d2;cursor:pointer;border-color:transparent;background-color:transparent}.btn-link:hover,.btn-link:focus,.btn-link:active,.btn-link.active{color:#095f8a;text-decoration:underline;background-color:transparent}.btn.disabled{cursor:not-allowed;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none;pointer-events:none}.btn-block{-moz-box-sizing:border-box;display:block;padding-left:0;padding-right:0;width:100%}.btn-primary-outline{color:#5a98de;background-color:transparent;background-image:none;border-color:#5a98de}.btn-primary-outline.active,.btn-primary-outline.focus,.btn-primary-outline:active,.btn-primary-outline:focus,.open>.btn-primary-outline.dropdown-toggle{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary-outline:hover{color:#fff;background-color:#5a98de;border-color:#5a98de}.btn-primary-outline.disabled.focus,.btn-primary-outline.disabled:focus,.btn-primary-outline:disabled.focus,.btn-primary-outline:disabled:focus,fieldset[disabled] .btn-primary-outline.focus,fieldset[disabled] .btn-primary-outline:focus{border-color:#0a6999}.btn-primary-outline.disabled:hover,.btn-primary-outline:disabled:hover,fieldset[disabled] .btn-primary-outline:hover{border-color:#0a6999}.btn-secondary-outline{color:#3bb4f2;background-color:transparent;background-image:none;border-color:#3bb4f2}.btn-secondary-outline.active,.btn-secondary-outline.focus,.btn-secondary-outline:active,.btn-secondary-outline:focus,.open>.btn-secondary-outline.dropdown-toggle{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary-outline:hover{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}.btn-secondary-outline.disabled.focus,.btn-secondary-outline.disabled:focus,.btn-secondary-outline:disabled.focus,.btn-secondary-outline:disabled:focus,fieldset[disabled] .btn-secondary-outline.focus,fieldset[disabled] .btn-secondary-outline:focus{border-color:#0f9ae0}.btn-secondary-outline.disabled:hover,.btn-secondary-outline:disabled:hover,fieldset[disabled] .btn-secondary-outline:hover{border-color:#0f9ae0}.btn-success-outline{color:#5eb95e;background-color:transparent;background-image:none;border-color:#5eb95e}.btn-success-outline.active,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline:focus,.open>.btn-success-outline.dropdown-toggle{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success-outline:hover{color:#fff;background-color:#5eb95e;border-color:#5eb95e}.btn-success-outline.disabled.focus,.btn-success-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-success-outline:disabled:focus,fieldset[disabled] .btn-success-outline.focus,fieldset[disabled] .btn-success-outline:focus{border-color:#429842}.btn-success-outline.disabled:hover,.btn-success-outline:disabled:hover,fieldset[disabled] .btn-success-outline:hover{border-color:#429842}.btn-warning-outline{color:#f37b1d;background-color:transparent;background-image:none;border-color:#f37b1d}.btn-warning-outline.active,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline:focus,.open>.btn-warning-outline.dropdown-toggle{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning-outline:hover{color:#fff;background-color:#f37b1d;border-color:#f37b1d}.btn-warning-outline.disabled.focus,.btn-warning-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-warning-outline:disabled:focus,fieldset[disabled] .btn-warning-outline.focus,fieldset[disabled] .btn-warning-outline:focus{border-color:#c85e0b}.btn-warning-outline.disabled:hover,.btn-warning-outline:disabled:hover,fieldset[disabled] .btn-warning-outline:hover{border-color:#c85e0b}.btn-danger-outline{color:#dd514c;background-color:transparent;background-image:none;border-color:#dd514c}.btn-danger-outline.active,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline:focus,.open>.btn-danger-outline.dropdown-toggle{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger-outline:hover{color:#fff;background-color:#dd514c;border-color:#dd514c}.btn-danger-outline.disabled.focus,.btn-danger-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-danger-outline:disabled:focus,fieldset[disabled] .btn-danger-outline.focus,fieldset[disabled] .btn-danger-outline:focus{border-color:#c62b26}.btn-danger-outline.disabled:hover,.btn-danger-outline:disabled:hover,fieldset[disabled] .btn-danger-outline:hover{border-color:#c62b26}.form-group{display:inline-block;vertical-align:middle}.form-group .input-text{position:relative;vertical-align:top}.form-group.radius{overflow:hidden}.form-group.radius .input-text{border-radius:4px 0 0 4px}.form-group.round .input-text{border-radius:1000px 0 0 1000px}.form-group .btn{position:relative;margin-left:-1px}.form-group.radius .btn{border-radius:0 4px 4px 0}.form-group.round .btn{border-radius:0 1000px 1000px 0}.img-responsive{display:inline-block;max-width:100%;height:auto}.thumbnail{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}@media(max-width:767px){.img-responsive{width:100%}}.duang-opacity img{-webkit-transition:opacity .1s linear;-moz-transition:opacity .1s linear;-o-transition:opacity .1s linear;transition:opacity .1s linear}.duang-opacity a:hover img,a:hover .opacity img{opacity:.85;filter:alpha(opacity=85)}.album-img{border:1px solid #e0e0e0}.album-img img{display:block;width:100%}.album-title{display:block;text-align:left;padding:7px 5px;line-height:18px;color:#555;text-decoration:none;font-size:12px;border:solid 1px #e0e0e0;border-top:0}.album-bg-Fir,.album-bg-Sec{border:1px solid #e6e6e6;border-top:1px solid #f5f5f5;height:1px;margin:0 auto;overflow:hidden}.album-bg-Fir{margin:0 3px}.album-bg-Sec{margin:0 6px}.avatar{display:inline-block;position:relative;overflow:hidden}.avatar img{display:block}.avatar.radius,.avatar.radius img{border-radius:50%}.avatar,.avatar img{width:32px;height:32px}.avatar.size-MINI{width:16px;height:16px}.avatar.size-S,.avatar.size-S img{width:24px;height:24px}.avatar.size-M,.avatar.size-M img{width:32px;height:32px}.avatar.size-L,.avatar.size-L img{width:40px;height:40px}.avatar.size-XL,.avatar.size-XL img{width:64px;height:64px}.avatar.size-XXL,.avatar.size-XXL img{width:100px;height:100px}.avatar.size-XXXL,.avatar.size-XXXL img{width:128px;height:128px}.iconpic{display:inline-block;vertical-align:sub;*vertical-align:middle;_vertical-align:middle;width:16px;height:16px;background-position:center;background-repeat:no-repeat}.hui-bounce,.hui-flip,.hui-flash,.hui-shake,.hui-swing,.hui-wobble,.hui-ring{-webkit-animation:1s ease;-moz-animation:1s ease;-ms-animation:1s ease;animation:1s ease}.hui-fadein,.hui-fadeinT,.hui-fadeinR,.hui-fadeinB,.hui-fadeinL,.hui-bouncein,.hui-bounceinT,.hui-bounceinR,.hui-bounceinB,.hui-bounceinL,.hui-rotatein,.hui-rotateinLT,.hui-rotateinLB,.hui-rotateinRT,.hui-rotateinRB,.hui-flipin,.hui-flipinX,.hui-flipinY{-webkit-animation:1s ease-out backwards;-moz-animation:1s ease-out backwards;-ms-animation:1s ease-out backwards;animation:1s ease-out backwards}.hui-fadeout,.hui-fadeoutT,.hui-fadeoutR,.hui-fadeoutB,.hui-fadeoutL,.hui-bounceout,.hui-bounceoutT,.hui-bounceoutR,.hui-bounceoutB,.hui-bounceoutL,.hui-rotateout,.hui-rotateoutLT,.hui-rotateoutLB,.hui-rotateoutRT,.hui-rotateoutRB,.hui-flipout,.hui-flipoutX,.hui-flipoutY{-webkit-animation:1s ease-in forwards;-moz-animation:1s ease-in forwards;-ms-animation:1s ease-in forwards;animation:1s ease-in forwards}.hui-fadein{-webkit-animation-name:fadein;-moz-animation-name:fadein;-ms-animation-name:fadein;animation-name:fadein}.hui-fadeinT{-webkit-animation-name:fadeinT;-moz-animation-name:fadeinT;-ms-animation-name:fadeinT;animation-name:fadeinT}.hui-fadeinR{-webkit-animation-name:fadeinR;-moz-animation-name:fadeinR;-ms-animation-name:fadeinR;animation-name:fadeinR}.hui-fadeinB{-webkit-animation-name:fadeinB;-moz-animation-name:fadeinB;-ms-animation-name:fadeinB;animation-name:fadeinB}.hui-fadeinL{-webkit-animation-name:fadeinL;-moz-animation-name:fadeinL;-ms-animation-name:fadeinL;animation-name:fadeinL}.hui-fadeout{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-ms-animation-name:fadeout;animation-name:fadeout}.hui-fadeoutT{-webkit-animation-name:fadeoutT;-moz-animation-name:fadeoutT;-ms-animation-name:fadeoutT;animation-name:fadeoutT}.hui-fadeoutR{-webkit-animation-name:fadeoutR;-moz-animation-name:fadeoutR;-ms-animation-name:fadeoutR;animation-name:fadeoutR}.hui-fadeoutB{-webkit-animation-name:fadeoutB;-moz-animation-name:fadeoutB;-ms-animation-name:fadeoutB;animation-name:fadeoutB}.hui-fadeoutL{-webkit-animation-name:fadeoutL;-moz-animation-name:fadeoutL;-ms-animation-name:fadeoutL;animation-name:fadeoutL}.hui-bounce{-webkit-animation-name:bounce;-moz-animation-name:bounce;-ms-animation-name:bounce;animation-name:bounce}.hui-bouncein{-webkit-animation-name:bouncein;-moz-animation-name:bouncein;-ms-animation-name:bouncein;animation-name:bouncein}.hui-bounceinT{-webkit-animation-name:bounceinT;-moz-animation-name:bounceinT;-ms-animation-name:bounceinT;animation-name:bounceinT}.hui-bounceinR{-webkit-animation-name:bounceinR;-moz-animation-name:bounceinR;-ms-animation-name:bounceinR;animation-name:bounceinR}.hui-bounceinB{-webkit-animation-name:bounceinB;-moz-animation-name:bounceinB;-ms-animation-name:bounceinB;animation-name:bounceinB}.hui-bounceinL{-webkit-animation-name:bounceinL;-moz-animation-name:bounceinL;-ms-animation-name:bounceinL;animation-name:bounceinL}.hui-bounceout{-webkit-animation-name:bounceout;-moz-animation-name:bounceout;-ms-animation-name:bounceout;animation-name:bounceout}.hui-bounceoutT{-webkit-animation-name:bounceoutT;-moz-animation-name:bounceoutT;-ms-animation-name:bounceoutT;animation-name:bounceoutT}.hui-bounceoutR{-webkit-animation-name:bounceoutR;-moz-animation-name:bounceoutR;-ms-animation-name:bounceoutR;animation-name:bounceoutR}.hui-bounceoutB{-webkit-animation-name:bounceoutB;-moz-animation-name:bounceoutB;-ms-animation-name:bounceoutB;animation-name:bounceoutB}.hui-bounceoutL{-webkit-animation-name:bounceoutL;-moz-animation-name:bounceoutL;-ms-animation-name:bounceoutL;animation-name:bounceoutL}.hui-rotatein{-webkit-animation-name:rotatein;-moz-animation-name:rotatein;-ms-animation-name:rotatein;animation-name:rotatein}.hui-rotateinLT{-webkit-animation-name:rotateinLT;-moz-animation-name:rotateinLT;-ms-animation-name:rotateinLT;animation-name:rotateinLT}.hui-rotateinLB{-webkit-animation-name:rotateinLB;-moz-animation-name:rotateinLB;-ms-animation-name:rotateinLB;animation-name:rotateinLB}.hui-rotateinRT{-webkit-animation-name:rotateinRT;-moz-animation-name:rotateinRT;-ms-animation-name:rotateinRT;animation-name:rotateinRT}.hui-rotateinRB{-webkit-animation-name:rotateinRB;-moz-animation-name:rotateinRB;-ms-animation-name:rotateinRB;animation-name:rotateinRB}.hui-rotateout{-webkit-animation-name:rotateout;-moz-animation-name:rotateout;-ms-animation-name:rotateout;animation-name:rotateout}.hui-rotateoutLT{-webkit-animation-name:rotateoutLT;-moz-animation-name:rotateoutLT;-ms-animation-name:rotateoutLT;animation-name:rotateoutLT}.hui-rotateoutLB{-webkit-animation-name:rotateoutLB;-moz-animation-name:rotateoutLB;-ms-animation-name:rotateoutLB;animation-name:rotateoutLB}.hui-rotateoutRT{-webkit-animation-name:rotateoutRT;-moz-animation-name:rotateoutRT;-ms-animation-name:rotateoutRT;animation-name:rotateoutRT}.hui-rotateoutRB{-webkit-animation-name:rotateoutRB;-moz-animation-name:rotateoutRB;-ms-animation-name:rotateoutRB;animation-name:rotateoutRB}.hui-flip{-webkit-animation-name:flip;-moz-animation-name:flip;-ms-animation-name:flip;animation-name:flip}.hui-flipinX{-webkit-animation-name:flipinX;-moz-animation-name:flipinX;-ms-animation-name:flipinX;animation-name:flipinX}.hui-flipin,.hui-flipinY{-webkit-animation-name:flipinY;-moz-animation-name:flipinY;-ms-animation-name:flipinY;animation-name:flipinY}.hui-flipoutX{-webkit-animation-name:flipoutX;-moz-animation-name:flipoutX;-ms-animation-name:flipoutX;animation-name:flipoutX}.hui-flipout,.hui-flipoutY{-webkit-animation-name:flipoutY;-moz-animation-name:flipoutY;-ms-animation-name:flipoutY;animation-name:flipoutY}.hui-flash{-webkit-animation-name:flash;-moz-animation-name:flash;-ms-animation-name:flash;animation-name:flash}.hui-shake{-webkit-animation-name:shake;-moz-animation-name:shake;-ms-animation-name:shake;animation-name:shake}.hui-swing{-webkit-animation-name:swing;-moz-animation-name:swing;-ms-animation-name:swing;animation-name:swing}.hui-wobble{-webkit-animation-name:wobble;-moz-animation-name:wobble;-ms-animation-name:wobble;animation-name:wobble}.hui-ring{-webkit-animation-name:ring;-moz-animation-name:ring;-ms-animation-name:ring;animation-name:ring}@-webkit-keyframes fadein{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadein{0%{opacity:0}100%{opacity:1}}@-ms-keyframes fadein{0%{opacity:0}100%{opacity:1}}@keyframes fadein{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeinT{0%{opacity:0;-webkit-transform:translateY(-100px)}100%{opacity:1;-webkit-transform:translateY(0)}}@-moz-keyframes fadeinT{0%{opacity:0;-moz-transform:translateY(-100px)}100%{opacity:1;-moz-transform:translateY(0)}}@-ms-keyframes fadeinT{0%{opacity:0;-ms-transform:translateY(-100px)}100%{opacity:1;-ms-transform:translateY(0)}}@keyframes fadeinT{0%{opacity:0;transform:translateY(-100px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes fadeinR{0%{opacity:0;-webkit-transform:translateX(100px)}100%{opacity:1;-webkit-transform:translateX(0)}}@-moz-keyframes fadeinR{0%{opacity:0;-moz-transform:translateX(100px)}100%{opacity:1;-moz-transform:translateX(0)}}@-ms-keyframes fadeinR{0%{opacity:0;-ms-transform:translateX(100px)}100%{opacity:1;-ms-transform:translateX(0)}}@keyframes fadeinR{0%{opacity:0;transform:translateX(100px)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes fadeinB{0%{opacity:0;-webkit-transform:translateY(100px)}100%{opacity:1;-webkit-transform:translateY(0)}}@-moz-keyframes fadeinB{0%{opacity:0;-moz-transform:translateY(100px)}100%{opacity:1;-moz-transform:translateY(0)}}@-ms-keyframes fadeinB{0%{opacity:0;-ms-transform:translateY(100px)}100%{opacity:1;-ms-transform:translateY(0)}}@keyframes fadeinB{0%{opacity:0;transform:translateY(100px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes fadeinL{0%{opacity:0;-webkit-transform:translateX(-100px)}100%{opacity:1;-webkit-transform:translateX(0)}}@-moz-keyframes fadeinL{0%{opacity:0;-moz-transform:translateX(-100px)}100%{opacity:1;-moz-transform:translateX(0)}}@-ms-keyframes fadeinL{0%{opacity:0;-ms-transform:translateX(-100px)}100%{opacity:1;-ms-transform:translateX(0)}}@keyframes fadeinL{0%{opacity:0;transform:translateX(-100px)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-ms-keyframes fadeout{0%{opacity:1}100%{opacity:0}}@keyframes fadeout{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes fadeoutT{0%{opacity:1;-webkit-transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-100px)}}@-moz-keyframes fadeoutT{0%{opacity:1;-moz-transform:translateY(0)}100%{opacity:0;-moz-transform:translateY(-100px)}}@-ms-keyframes fadeoutT{0%{opacity:1;-ms-transform:translateY(0)}100%{opacity:0;-ms-transform:translateY(-100px)}}@keyframes fadeoutT{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-100px)}}@-webkit-keyframes fadeoutR{0%{opacity:1;-webkit-transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(100px)}}@-moz-keyframes fadeoutR{0%{opacity:1;-moz-transform:translateX(0)}100%{opacity:0;-moz-transform:translateX(100px)}}@-ms-keyframes fadeoutR{0%{opacity:1;-ms-transform:translateX(0)}100%{opacity:0;-ms-transform:translateX(100px)}}@keyframes fadeoutR{0%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(100px)}}@-webkit-keyframes fadeoutB{0%{opacity:1;-webkit-transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(100px)}}@-moz-keyframes fadeoutB{0%{opacity:1;-moz-transform:translateY(0)}100%{opacity:0;-moz-transform:translateY(100px)}}@-ms-keyframes fadeoutB{0%{opacity:1;-ms-transform:translateY(0)}100%{opacity:0;-ms-transform:translateY(100px)}}@keyframes fadeoutB{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(100px)}}@-webkit-keyframes fadeoutL{0%{opacity:1;-webkit-transform:translateX(0)}100%{opacity:0;-webkit-transform:translateX(-100px)}}@-moz-keyframes fadeoutL{0%{opacity:1;-moz-transform:translateX(0)}100%{opacity:0;-moz-transform:translateX(-100px)}}@-ms-keyframes fadeoutL{0%{opacity:1;-ms-transform:translateX(0)}100%{opacity:0;-ms-transform:translateX(-100px)}}@keyframes fadeoutL{0%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(-100px)}}@-webkit-keyframes bounce{0%,20%,50%,80%,100%{-webkit-transform:translateY(0)}40%{-webkit-transform:translateY(-30px)}60%{-webkit-transform:translateY(-15px)}}@-moz-keyframes bounce{0%,20%,50%,80%,100%{-moz-transform:translateY(0)}40%{-moz-transform:translateY(-30px)}60%{-moz-transform:translateY(-15px)}}@-ms-keyframes bounce{0%,20%,50%,80%,100%{-ms-transform:translateY(0)}40%{-ms-transform:translateY(-30px)}60%{-ms-transform:translateY(-15px)}}@keyframes bounce{0%,20%,50%,80%,100%{transform:translateY(0)}40%{transform:translateY(-30px)}60%{transform:translateY(-15px)}}@-webkit-keyframes bouncein{0%{opacity:0;-webkit-transform:scale(0.3)}50%{opacity:1;-webkit-transform:scale(1.05)}70%{-webkit-transform:scale(0.9)}100%{-webkit-transform:scale(1)}}@-moz-keyframes bouncein{0%{opacity:0;-moz-transform:scale(0.3)}50%{opacity:1;-moz-transform:scale(1.05)}70%{-moz-transform:scale(0.9)}100%{-moz-transform:scale(1)}}@-ms-keyframes bouncein{0%{opacity:0;-ms-transform:scale(0.3)}50%{opacity:1;-ms-transform:scale(1.05)}70%{-ms-transform:scale(0.9)}100%{-ms-transform:scale(1)}}@keyframes bouncein{0%{opacity:0;transform:scale(0.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(0.9)}100%{transform:scale(1)}}@-webkit-keyframes bounceinT{0%{opacity:0;-webkit-transform:translateY(-100px)}60%{opacity:1;-webkit-transform:translateY(30px)}80%{-webkit-transform:translateY(-10px)}100%{-webkit-transform:translateY(0)}}@-moz-keyframes bounceinT{0%{opacity:0;-moz-transform:translateY(-100px)}60%{opacity:1;-moz-transform:translateY(30px)}80%{-moz-transform:translateY(-10px)}100%{-moz-transform:translateY(0)}}@-ms-keyframes bounceinT{0%{opacity:0;-ms-transform:translateY(-100px)}60%{opacity:1;-ms-transform:translateY(30px)}80%{-ms-transform:translateY(-10px)}100%{-ms-transform:translateY(0)}}@keyframes bounceinT{0%{opacity:0;transform:translateY(-100px)}60%{opacity:1;transform:translateY(30px)}80%{transform:translateY(-10px)}100%{transform:translateY(0)}}@-webkit-keyframes bounceinR{0%{opacity:0;-webkit-transform:translateX(100px)}60%{opacity:1;-webkit-transform:translateX(-30px)}80%{-webkit-transform:translateX(10px)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes bounceinR{0%{opacity:0;-moz-transform:translateX(100px)}60%{opacity:1;-moz-transform:translateX(-30px)}80%{-moz-transform:translateX(10px)}100%{-moz-transform:translateX(0)}}@-ms-keyframes bounceinR{0%{opacity:0;-ms-transform:translateX(100px)}60%{opacity:1;-ms-transform:translateX(-30px)}80%{-ms-transform:translateX(10px)}100%{-ms-transform:translateX(0)}}@keyframes bounceinR{0%{opacity:0;transform:translateX(100px)}60%{opacity:1;transform:translateX(-30px)}80%{transform:translateX(10px)}100%{transform:translateX(0)}}@-webkit-keyframes bounceinB{0%{opacity:0;-webkit-transform:translateY(100px)}60%{opacity:1;-webkit-transform:translateY(-30px)}80%{-webkit-transform:translateY(10px)}100%{-webkit-transform:translateY(0)}}@-moz-keyframes bounceinB{0%{opacity:0;-moz-transform:translateY(100px)}60%{opacity:1;-moz-transform:translateY(-30px)}80%{-moz-transform:translateY(10px)}100%{-moz-transform:translateY(0)}}@-ms-keyframes bounceinB{0%{opacity:0;-ms-transform:translateY(100px)}60%{opacity:1;-ms-transform:translateY(-30px)}80%{-ms-transform:translateY(10px)}100%{-ms-transform:translateY(0)}}@keyframes bounceinB{0%{opacity:0;transform:translateY(100px)}60%{opacity:1;transform:translateY(-30px)}80%{transform:translateY(10px)}100%{transform:translateY(0)}}@-webkit-keyframes bounceinL{0%{opacity:0;-webkit-transform:translateX(-100px)}60%{opacity:1;-webkit-transform:translateX(30px)}80%{-webkit-transform:translateX(-10px)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes bounceinL{0%{opacity:0;-moz-transform:translateX(-100px)}60%{opacity:1;-moz-transform:translateX(30px)}80%{-moz-transform:translateX(-10px)}100%{-moz-transform:translateX(0)}}@-ms-keyframes bounceinL{0%{opacity:0;-ms-transform:translateX(-100px)}60%{opacity:1;-ms-transform:translateX(30px)}80%{-ms-transform:translateX(-10px)}100%{-ms-transform:translateX(0)}}@keyframes bounceinL{0%{opacity:0;transform:translateX(-100px)}60%{opacity:1;transform:translateX(30px)}80%{transform:translateX(-10px)}100%{transform:translateX(0)}}@-webkit-keyframes bounceout{0%{-webkit-transform:scale(1)}25%{-webkit-transform:scale(0.95)}50%{opacity:1;-webkit-transform:scale(1.1)}100%{opacity:0;-webkit-transform:scale(0.3)}}@-moz-keyframes bounceout{0%{-moz-transform:scale(1)}25%{-moz-transform:scale(0.95)}50%{opacity:1;-moz-transform:scale(1.1)}100%{opacity:0;-moz-transform:scale(0.3)}}@-ms-keyframes bounceout{0%{-ms-transform:scale(1)}25%{-ms-transform:scale(0.95)}50%{opacity:1;-ms-transform:scale(1.1)}100%{opacity:0;-ms-transform:scale(0.3)}}@keyframes bounceout{0%{transform:scale(1)}25%{transform:scale(0.95)}50%{opacity:1;transform:scale(1.1)}100%{opacity:0;transform:scale(0.3)}}@-webkit-keyframes bounceoutT{0%{-webkit-transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(20px)}100%{opacity:0;-webkit-transform:translateY(-100px)}}@-moz-keyframes bounceoutT{0%{-moz-transform:translateY(0)}20%{opacity:1;-moz-transform:translateY(20px)}100%{opacity:0;-moz-transform:translateY(-100px)}}@-ms-keyframes bounceoutT{0%{-ms-transform:translateY(0)}20%{opacity:1;-ms-transform:translateY(20px)}100%{opacity:0;-ms-transform:translateY(-100px)}}@keyframes bounceoutT{0%{transform:translateY(0)}20%{opacity:1;transform:translateY(20px)}100%{opacity:0;transform:translateY(-100px)}}@-webkit-keyframes bounceoutR{0%{-webkit-transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(-20px)}100%{opacity:0;-webkit-transform:translateX(100px)}}@-moz-keyframes bounceoutR{0%{-moz-transform:translateX(0)}20%{opacity:1;-moz-transform:translateX(-20px)}100%{opacity:0;-moz-transform:translateX(100px)}}@-ms-keyframes bounceoutR{0%{-ms-transform:translateX(0)}20%{opacity:1;-ms-transform:translateX(-20px)}100%{opacity:0;-ms-transform:translateX(100px)}}@keyframes bounceoutR{0%{transform:translateX(0)}20%{opacity:1;transform:translateX(-20px)}100%{opacity:0;transform:translateX(100px)}}@-webkit-keyframes bounceoutB{0%{-webkit-transform:translateY(0)}20%{opacity:1;-webkit-transform:translateY(-20px)}100%{opacity:0;-webkit-transform:translateY(100px)}}@-moz-keyframes bounceoutB{0%{-moz-transform:translateY(0)}20%{opacity:1;-moz-transform:translateY(-20px)}100%{opacity:0;-moz-transform:translateY(100px)}}@-ms-keyframes bounceoutB{0%{-ms-transform:translateY(0)}20%{opacity:1;-ms-transform:translateY(-20px)}100%{opacity:0;-ms-transform:translateY(100px)}}@keyframes bounceoutB{0%{transform:translateY(0)}20%{opacity:1;transform:translateY(-20px)}100%{opacity:0;transform:translateY(100px)}}@-webkit-keyframes bounceoutL{0%{-webkit-transform:translateX(0)}20%{opacity:1;-webkit-transform:translateX(20px)}100%{opacity:0;-webkit-transform:translateX(-100px)}}@-moz-keyframes bounceoutL{0%{-moz-transform:translateX(0)}20%{opacity:1;-moz-transform:translateX(20px)}100%{opacity:0;-moz-transform:translateX(-100px)}}@-ms-keyframes bounceoutL{0%{-ms-transform:translateX(0)}20%{opacity:1;-ms-transform:translateX(20px)}100%{opacity:0;-ms-transform:translateX(-100px)}}@keyframes bounceoutL{0%{transform:translateX(0)}20%{opacity:1;transform:translateX(20px)}100%{opacity:0;transform:translateX(-200px)}}@-webkit-keyframes rotatein{0%{opacity:0;-webkit-transform:rotate(-200deg)}100%{opacity:1;-webkit-transform:rotate(0)}}@-moz-keyframes rotatein{0%{opacity:0;-moz-transform:rotate(-200deg)}100%{opacity:1;-moz-transform:rotate(0)}}@-ms-keyframes rotatein{0%{opacity:0;-ms-transform:rotate(-200deg)}100%{opacity:1;-ms-transform:rotate(0)}}@keyframes rotatein{0%{opacity:0;transform:rotate(-200deg)}100%{opacity:1;transform:rotate(0)}}@-webkit-keyframes rotateinLT{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinLT{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinLT{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinLT{0%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}100%{transform-origin:left bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateineftB{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateineftB{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateineftB{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateineftB{0%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}100%{transform-origin:left bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateinRT{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinRT{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinRT{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinRT{0%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}100%{transform-origin:right bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateinRB{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}}@-moz-keyframes rotateinRB{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}}@-ms-keyframes rotateinRB{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}}@keyframes rotateinRB{0%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}100%{transform-origin:right bottom;transform:rotate(0);opacity:1}}@-webkit-keyframes rotateout{0%{-webkit-transform-origin:center center;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:center center;-webkit-transform:rotate(200deg);opacity:0}}@-moz-keyframes rotateout{0%{-moz-transform-origin:center center;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:center center;-moz-transform:rotate(200deg);opacity:0}}@-ms-keyframes rotateout{0%{-ms-transform-origin:center center;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:center center;-ms-transform:rotate(200deg);opacity:0}}@keyframes rotateout{0%{transform-origin:center center;transform:rotate(0);opacity:1}100%{transform-origin:center center;transform:rotate(200deg);opacity:0}}@-webkit-keyframes rotateoutLT{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}}@-moz-keyframes rotateoutLT{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}}@-ms-keyframes rotateoutLT{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}}@keyframes rotateoutLT{0%{transform-origin:left bottom;transform:rotate(0);opacity:1}100%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}}@-webkit-keyframes rotateoutLB{0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}}@-moz-keyframes rotateoutLB{0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}}@-ms-keyframes rotateoutLB{0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}}@keyframes rotateoutLB{0%{transform-origin:left bottom;transform:rotate(0);opacity:1}100%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}}@-webkit-keyframes rotateoutRT{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}}@-moz-keyframes rotateoutRT{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}}@-ms-keyframes rotateoutRT{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}}@keyframes rotateoutRT{0%{transform-origin:right bottom;transform:rotate(0);opacity:1}100%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}}@-webkit-keyframes rotateoutBR{0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}}@-moz-keyframes rotateoutBR{0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}100%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}}@-ms-keyframes rotateoutBR{0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}100%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}}@keyframes rotateoutBR{0%{transform-origin:right bottom;transform:rotate(0);opacity:1}100%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotateY(0);-webkit-animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(170deg);-webkit-animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-webkit-animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) rotateY(360deg) scale(0.95);-webkit-animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px) scale(1);-webkit-animation-timing-function:ease-in}}@-moz-keyframes flip{0%{-moz-transform:perspective(400px) rotateY(0);-moz-animation-timing-function:ease-out}40%{-moz-transform:perspective(400px) translateZ(150px) rotateY(170deg);-moz-animation-timing-function:ease-out}50%{-moz-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-moz-animation-timing-function:ease-in}80%{-moz-transform:perspective(400px) rotateY(360deg) scale(0.95);-moz-animation-timing-function:ease-in}100%{-moz-transform:perspective(400px) scale(1);-moz-animation-timing-function:ease-in}}@-ms-keyframes flip{0%{-ms-transform:perspective(400px) rotateY(0);-ms-animation-timing-function:ease-out}40%{-ms-transform:perspective(400px) translateZ(150px) rotateY(170deg);-ms-animation-timing-function:ease-out}50%{-ms-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-ms-animation-timing-function:ease-in}80%{-ms-transform:perspective(400px) rotateY(360deg) scale(0.95);-ms-animation-timing-function:ease-in}100%{-ms-transform:perspective(400px) scale(1);-ms-animation-timing-function:ease-in}}@keyframes flip{0%{transform:perspective(400px) rotateY(0);animation-timing-function:ease-out}40%{transform:perspective(400px) translateZ(150px) rotateY(170deg);animation-timing-function:ease-out}50%{transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);animation-timing-function:ease-in}80%{transform:perspective(400px) rotateY(360deg) scale(0.95);animation-timing-function:ease-in}100%{transform:perspective(400px) scale(1);animation-timing-function:ease-in}}@-webkit-keyframes flipinX{0%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-10deg)}70%{-webkit-transform:perspective(400px) rotateX(10deg)}100%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}}@-moz-keyframes flipinX{0%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-moz-transform:perspective(400px) rotateX(-10deg)}70%{-moz-transform:perspective(400px) rotateX(10deg)}100%{-moz-transform:perspective(400px) rotateX(0);opacity:1}}@-ms-keyframes flipinX{0%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}40%{-ms-transform:perspective(400px) rotateX(-10deg)}70%{-ms-transform:perspective(400px) rotateX(10deg)}100%{-ms-transform:perspective(400px) rotateX(0);opacity:1}}@keyframes flipinX{0%{transform:perspective(400px) rotateX(90deg);opacity:0}40%{transform:perspective(400px) rotateX(-10deg)}70%{transform:perspective(400px) rotateX(10deg)}100%{transform:perspective(400px) rotateX(0);opacity:1}}@-webkit-keyframes flipinY{0%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-10deg)}70%{-webkit-transform:perspective(400px) rotateY(10deg)}100%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}}@-moz-keyframes flipinY{0%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-moz-transform:perspective(400px) rotateY(-10deg)}70%{-moz-transform:perspective(400px) rotateY(10deg)}100%{-moz-transform:perspective(400px) rotateY(0);opacity:1}}@-ms-keyframes flipinY{0%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}40%{-ms-transform:perspective(400px) rotateY(-10deg)}70%{-ms-transform:perspective(400px) rotateY(10deg)}100%{-ms-transform:perspective(400px) rotateY(0);opacity:1}}@keyframes flipinY{0%{transform:perspective(400px) rotateY(90deg);opacity:0}40%{transform:perspective(400px) rotateY(-10deg)}70%{transform:perspective(400px) rotateY(10deg)}100%{transform:perspective(400px) rotateY(0);opacity:1}}@-webkit-keyframes flipoutX{0%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}100%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}}@-moz-keyframes flipoutX{0%{-moz-transform:perspective(400px) rotateX(0);opacity:1}100%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}}@-ms-keyframes flipoutX{0%{-ms-transform:perspective(400px) rotateX(0);opacity:1}100%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}}@keyframes flipoutX{0%{transform:perspective(400px) rotateX(0);opacity:1}100%{transform:perspective(400px) rotateX(90deg);opacity:0}}@-webkit-keyframes flipoutY{0%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}100%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}}@-moz-keyframes flipoutY{0%{-moz-transform:perspective(400px) rotateY(0);opacity:1}100%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}}@-ms-keyframes flipoutY{0%{-ms-transform:perspective(400px) rotateY(0);opacity:1}100%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}}@keyframes flipoutY{0%{transform:perspective(400px) rotateY(0);opacity:1}100%{transform:perspective(400px) rotateY(90deg);opacity:0}}@-webkit-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-moz-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-ms-keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,100%{opacity:1}25%,75%{opacity:0}}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px)}}@-moz-keyframes shake{0%,100%{-moz-transform:translateX(0)}10%,30%,50%,70%,90%{-moz-transform:translateX(-10px)}20%,40%,60%,80%{-moz-transform:translateX(10px)}}@-ms-keyframes shake{0%,100%{-ms-transform:translateX(0)}10%,30%,50%,70%,90%{-ms-transform:translateX(-10px)}20%,40%,60%,80%{-ms-transform:translateX(10px)}}@keyframes shake{0%,100%{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-10px)}20%,40%,60%,80%{transform:translateX(10px)}}@-webkit-keyframes swing{20%{-webkit-transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg)}100%{-webkit-transform:rotate(0)}}@-moz-keyframes swing{20%{-moz-transform:rotate(15deg)}40%{-moz-transform:rotate(-10deg)}60%{-moz-transform:rotate(5deg)}80%{-moz-transform:rotate(-5deg)}100%{-moz-transform:rotate(0)}}@-ms-keyframes swing{20%{-ms-transform:rotate(15deg)}40%{-ms-transform:rotate(-10deg)}60%{-ms-transform:rotate(5deg)}80%{-ms-transform:rotate(-5deg)}100%{-ms-transform:rotate(0)}}@keyframes swing{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}100%{transform:rotate(0)}}@-webkit-keyframes wobble{0%{-webkit-transform:translateX(0)}15%{-webkit-transform:translateX(-100px) rotate(-5deg)}30%{-webkit-transform:translateX(80px) rotate(3deg)}45%{-webkit-transform:translateX(-65px) rotate(-3deg)}60%{-webkit-transform:translateX(40px) rotate(2deg)}75%{-webkit-transform:translateX(-20px) rotate(-1deg)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes wobble{0%{-moz-transform:translateX(0)}15%{-moz-transform:translateX(-100px) rotate(-5deg)}30%{-moz-transform:translateX(80px) rotate(3deg)}45%{-moz-transform:translateX(-65px) rotate(-3deg)}60%{-moz-transform:translateX(40px) rotate(2deg)}75%{-moz-transform:translateX(-20px) rotate(-1deg)}100%{-moz-transform:translateX(0)}}@-ms-keyframes wobble{0%{-ms-transform:translateX(0)}15%{-ms-transform:translateX(-100px) rotate(-5deg)}30%{-ms-transform:translateX(80px) rotate(3deg)}45%{-ms-transform:translateX(-65px) rotate(-3deg)}60%{-ms-transform:translateX(40px) rotate(2deg)}75%{-ms-transform:translateX(-20px) rotate(-1deg)}100%{-ms-transform:translateX(0)}}@keyframes wobble{0%{transform:translateX(0)}15%{transform:translateX(-100px) rotate(-5deg)}30%{transform:translateX(80px) rotate(3deg)}45%{transform:translateX(-65px) rotate(-3deg)}60%{transform:translateX(40px) rotate(2deg)}75%{transform:translateX(-20px) rotate(-1deg)}100%{transform:translateX(0)}}@-webkit-keyframes ring{0%{-webkit-transform:scale(1)}10%,20%{-webkit-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg)}100%{-webkit-transform:scale(1) rotate(0)}}@-moz-keyframes ring{0%{-moz-transform:scale(1)}10%,20%{-moz-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-moz-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-moz-transform:scale(1.1) rotate(-3deg)}100%{-moz-transform:scale(1) rotate(0)}}@-ms-keyframes ring{0%{-ms-transform:scale(1)}10%,20%{-ms-transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{-ms-transform:scale(1.1) rotate(3deg)}40%,60%,80%{-ms-transform:scale(1.1) rotate(-3deg)}100%{-ms-transform:scale(1) rotate(0)}}@keyframes ring{0%{transform:scale(1)}10%,20%{transform:scale(0.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale(1.1) rotate(3deg)}40%,60%,80%{transform:scale(1.1) rotate(-3deg)}100%{transform:scale(1) rotate(0)}}.btn-group{font-size:0}.btn-group .btn{margin-left:-1px}.btn-group .btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.navbar-wrapper{height:45px}.navbar{position:relative;z-index:1030;background-color:#fff}.navbar-black{background-color:#222}.navbar-fixed-top{position:fixed;top:0;left:0;right:0;z-index:1030}.logo{display:inline-block;text-decoration:none;cursor:pointer;background-repeat:no-repeat;background-position:left center;background-size:auto 100%}a.logo:hover{text-decoration:none}.navbar .logo{height:44px;line-height:44px;margin-right:10px;float:left}.navbar-logo,.navbar-logo-m{font-size:16px}.navbar-slogan{font-size:12px;cursor:default}.navbar .container{position:relative}.navbar-userbar{position:absolute;top:0;right:15px}.navbar .container .navbar-userbar{right:0}.nav{z-index:1}.nav>ul{font-size:0;line-height:0}.nav>ul>li{position:relative;float:left}.nav>ul>li,.nav>ul>li>a{display:inline-block;text-align:center}.nav>ul>li>a{padding:0 20px}.nav>ul>li>a:hover,.nav>ul>li.current>a{background-color:rgba(255,255,255,0.2);text-decoration:none;-webkit-transition:background-color .3s ease 0s;-moz-transition:background-color .3s ease 0s;-o-transition:background-color .3s ease 0s;-ms-transition:background-color .3s ease 0s;transition:background-color .3s ease 0s}.navbar-nav>ul>li,.navbar-nav>ul>li>a{line-height:44px;font-size:14px}@media(max-width:767px){.navbar-wrapper{height:45px!important}.logo{margin-right:0}.navbar .logo{height:44px!important;line-height:44px!important}.navbar-nav{display:none;float:none!important}.navbar-nav>ul>li{width:100%;text-align:left;border-bottom:solid 1px #eee}.navbar-nav>ul>li>a{display:block;padding:0 15px;text-align:left}.navbar-nav>ul>li.dropDown.open>.dropDown-menu{display:none}.navbar-nav>ul>li.dropDown>.dropDown_A>.Hui-iconfont{display:none}.navbar-nav>ul>li,.navbar-nav>ul>li>a{height:44px!important;line-height:44px!important}.nav-collapse>ul,.nav-collapse>ul>li{width:100%;display:block}.js .nav-collapse{position:absolute;display:block;float:none;clear:both;max-height:0;clip:rect(0 0 0 0);margin-left:-15px;margin-right:-15px;overflow:hidden;-webkt-transition:max-height 284ms ease 0s;-moz-transition:max-height 284ms ease 0s;-o-transition:max-height 284ms ease 0s;-ms-transition:max-height 284ms ease 0s;transition:max-height 284ms ease 0s}.js-nav-active .nav-collapse.closed{max-height:none}.nav-collapse.opened{max-height:9999px}}.navbar-black{background-color:#222;border-bottom:#080808 1px solid;-moz-box-shadow:0 0 4px #333;-webkit-box-shadow:0 0 4px #333;box-shadow:0 0 4px #333}.navbar-black .logo{color:#fff}.navbar-black .navbar-logo-m{color:#eee}.navbar-black .navbar-nav>ul>li,.navbar-black .navbar-nav>ul>li>a{color:#fff}.navbar-black .navbar-nav>ul>li>a:hover,.navbar-black .navbar-nav>ul>li.current>a{color:#fff}.navbar-black .navbar-userbar{color:#fff}@media(max-width:767px){.navbar-black .navbar-nav>ul>li{border-bottom:solid 1px #222}.navbar-black .navbar-nav>ul>li>a:hover,.navbar-black .navbar-nav>ul>li.current>a{background:#777}}.nav-toggle,a.nav-toggle{position:absolute;top:0;right:15px;font-size:20px;color:#999;padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.nav-toggle:hover,a.nav-toggle:hover{text-decoration:none;color:#fff}.mainnav{z-index:1;background-color:#222}.mainnav>ul{font-size:0;line-height:0}.mainnav>ul>li,.mainnav>ul>li>a{height:40px;line-height:40px}.mainnav>ul>li{display:inline-block;color:#fff;font-size:14px;font-weight:bold}.mainnav>ul>li>a{display:inline-block;padding:0 20px;color:#fff;text-align:center}.mainnav>ul>li>a:hover,.mainnav>ul>li.current>a{color:#fff;text-decoration:none;background-color:#000;-webkit-transition:background-color .3s ease 0s;-moz-transition:background-color .3s ease 0s;-o-transition:background-color .3s ease 0s;-ms-transition:background-color .3s ease 0s;transition:background-color .3s ease 0s}.Hui-nav-toggle,a.Hui-nav-toggle{position:absolute;top:0;right:15px;font-size:20px;color:#999;padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff}.Hui-nav-toggle:hover,a.Hui-nav-toggle:hover{text-decoration:none;color:#fff}@media(max-width:767px){.mainnav>ul>li{font-size:1.125em}}@media(max-width:480px){.mainnav>ul>li{text-align:center}.mainnav>ul>li{width:20%}.mainnav>ul>li>a{padding:0;padding:0;display:block}}.breadcrumb{border-bottom:1px solid #e5e5e5;line-height:39px;height:39px;overflow:hidden}.breadcrumb span{padding:0 5px}@media(max-width:767px){.breadcrumb>.container{padding:0}}.pageNav{float:none;clear:both;font-size:0;font-family:Arial,Helvetica,sans-serif;padding:18px 0;text-align:center}.pageNav span,.pageNav a,.pageNav b{font-size:14px;margin-right:5px;overflow:hidden;padding:3px 8px}.pageNav a{border:1px solid #ccdbe4;cursor:pointer}.pageNav b{color:#000}.pageNav .mor{padding:3px;font-weight:bold}.topnav{height:30px;line-height:30px;background-color;#f7f7f7;border-bottom:1px solid #ebebeb;font-size:12px}.topbar{background-color:#ececec;border-bottom:1px solid #ddd}.topbar a{margin-right:5px}.r_nav{display:inline-block;color:#999}.steps,.step{display:inline-block;position:relative;padding:1em 2em 1em 3em;vertical-align:top;background-color:#FFF;color:#888;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.step:after,.steps .step:after{position:absolute;z-index:2;content:'';top:0;right:-1.45em;border-bottom:1.5em solid transparent;border-left:1.5em solid #FFF;border-top:1.5em solid transparent;width:0;height:0}.step,.steps .step,.steps .step:after{-webkit-transition:opacity .1s ease,color .1s ease,-webkit-box-shadow .1s ease;transition:opacity .1s ease,color .1s ease,box-shadow .1s ease}.steps{cursor:pointer;display:inline-block;font-size:0;box-shadow:0 0 0 1px rgba(0,0,0,.1);border-radius:.3125rem;line-height:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.steps .step:first-child{padding-left:1.35em;border-radius:.3125em 0 0 .3125em}.steps .step:last-child{border-radius:0 .3125em .3125em 0}.steps .step:only-child{border-radius:.3125em}.steps .step:last-child{margin-right:0}.steps .step:last-child:after{display:none}.step:hover,.step.hover{background-color:#f7f7f7;color:rgba(0,0,0,.8)}.steps .step.hover:after,.steps .step:hover:after,.step:hover,.step.hover::after{border-left-color:#f7f7f7}.steps .step.down,.steps .step:active,.step.down,.step:active{background-color:#f0f0f0}.steps .step.down:after,.steps .step:active:after,.steps.down::after,.steps:active::after{border-left-color:#f0f0f0}.steps .step.active,.active.step{cursor:auto;background-color:#428bca;color:#FFF;font-weight:700}.steps .step.active:after,.active.steps:after{border-left-color:#428bca}.steps .disabled.step,.disabled.step{cursor:auto;background-color:#FFF;color:#cbcbcb}.disabled.step:after{border:0;background-color:#FFF;top:.42em;right:-1em;width:2.15em;height:2.15em;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);box-shadow:-1px -1px 0 0 rgba(0,0,0,.1) inset}.attached.steps{margin:0;border-radius:.3125em .3125em 0 0}.attached.steps .step:first-child{border-radius:.3125em 0 0}.attached.steps .step:last-child{border-radius:0 .3125em 0 0}.bottom.attached.steps{margin-top:-1px;border-radius:0 0 .3125em .3125em}.bottom.attached.steps .step:first-child{border-radius:0 0 0 .3125em}.bottom.attached.steps .step:last-child{border-radius:0 0 .3125em}.one.steps,.two.steps,.three.steps,.four.steps,.five.steps,.six.steps,.seven.steps,.eight.steps{display:block}.one.steps>.step{width:100%}.two.steps>.step{width:50%}.three.steps>.step{width:33.333%}.four.steps>.step{width:25%}.five.steps>.step{width:20%}.six.steps>.step{width:16.666%}.seven.steps>.step{width:14.285%}.eight.steps>.step{width:12.5%}.small.step,.small.steps .step{font-size:.8rem}.step,.steps .step{font-size:1rem}.large.step,.large.steps .step{font-size:1.25rem}.steps-ie,.step-ie,.step-ie .arrow{height:44px;line-height:44px}.steps-ie{background-color:#eaf4fd;border:solid 1px #afcfcc}.step-ie{position:relative;display:inline-block;float:left;cursor:pointer;padding:0 20px 0 40px;background:url(../images/steps/step_bg.png) repeat-x 0 center}.step-ie .arrow{position:absolute;right:-21px;top:0;width:21px;height:44px;display:block;cursor:pointer;background:url(../images/steps/step_arrow.png) no-repeat 0 center;z-index:50}.step-ie.active{background-image:url(../images/steps/step_bg-active.png);color:#fff;z-index:100}.step-ie.active .arrow{background-image:url(../images/steps/step_arrow-active.png)}.verticalTab{background:#fff url(../images/verticalTab/tab_bg.png) repeat-y 0 0;width:38px}.verticalTab a{position:relative;display:block;width:18px;height:auto;text-align:center;position:relative;padding:26px 10px 6px 10px;background:url(../images/verticalTab/tabNav.png) no-repeat 0 0}.verticalTab a em{position:absolute;left:0;bottom:-20px;width:38px;height:20px;background:url(../images/tabNav_right.png) no-repeat 0 0;z-index:50}.verticalTab a.active{background-image:url(../images/verticalTab/tabNav-active.png);color:#fff;z-index:99}.verticalTab a.active em{background-image:url(../images/verticalTab/tabNav_right-active.png)}.acrossTab,.acrossTab li,.acrossTab li em{background-image:url(../images/acrossTab/acrossTab-bg.png)}.acrossTab{height:29px;background-repeat:repeat-x;background-position:0 0;padding-top:1px}.acrossTab li,.acrossTab li em{background-repeat:no-repeat;background-position:0 0}.acrossTab li{position:relative;float:left;display:inline-block;height:29px;line-height:29px;font-size:12px;cursor:pointer;padding:0 30px;white-space:nowrap;color:#282828;background-position:0 0}.acrossTab li em{position:absolute;width:23px;height:29px;right:-20px;top:0;z-index:50;background-position:right -30px}.acrossTab li:hover{background-position:0 -60px}.acrossTab li:hover em{background-position:right -90px}.acrossTab li.active{background-position:0 -120px;z-index:99}.acrossTab li.active em{background-position:right -150px}.acrossTab li i{position:absolute;display:block;width:13px;height:13px;top:50%;margin-top:-6px;right:5px;font-size:0;line-height:0;cursor:pointer;background-image:url(../images/acrossTab/acrossTab-close.png);background-repeat:no-repeat;background-position:0 0}.acrossTab li i:hover{background-position:0 bottom}.dropDown{display:inline-block}.dropDown_A{display:inline-block}.dropDown-menu{display:none;transition:all .3s ease 0s}.dropDown:focus,.dropDown-menu:focus{outline:0}.dropDown-menu li.arrow{position:absolute;display:block;width:12px;height:8px;margin-top:-13px;margin-left:20%;line-height:0;background:url(../images/dropDown/icon-jt.png) no-repeat 0 0}.dropDown.hover .dropDown_A,.dropDown.open .dropDown_A{text-decoration:none;}.dropDown.open .dropDown_A .menu_dropdown-arrow{transition-duration:.3s;transition-property:all;_background-position:0 0;transform:rotate(180deg)}.menu{background-color:#fff;border:solid 1px #f2f2f2;display:inline-block}.menu.radius{border-top-left-radius:0;border-top-right-radius:0}.menu.box-shadow{border-top:0}.menu>li{position:relative;clear:both;* float:left}.menu>li>a{display:block;border-bottom:solid 1px #f2f2f2;padding:5px 20px;line-height:1.8;text-align:left;font-weight:normal;white-space:nowrap;vertical-align:top}.menu>li:last-child>a{border-bottom:0}.menu>li>a:hover,.menu>li>a:focus,.menu>li.open>a{text-decoration:none;background-color:#fafafa}.menu>li>a .arrow{position:absolute;top:50%;margin-top:-10px;right:5px;line-height:20px;height:20px;color:#999}.menu>li>.menu{display:none}.menu>li.open>.menu{display:inline-block;position:absolute;left:100%;top:-1px;min-width:100%}.menu>li.disabled>a{color:#999;text-decoration:none;cursor:no-drop;background-color:transparent}.menu>li.divider{display:block;height:0;line-height:0;margin:9px 0;overflow:hidden;border-top:solid 1px #eee}.dropDown>.dropDown-menu{display:none}.dropDown.open{position:relative;z-index:990}.dropDown.open>.dropDown-menu{position:absolute;z-index:1000;display:inline-block;top:100%;left:-1px;min-width:100%;background-color:#fff;border:solid 1px #f2f2f2}.dropDown.open.right>.dropDown-menu{right:-1px!important;left:auto!important}.slider{position:relative;text-align:center;margin:0 auto;z-index:1}.slider .bd,.slider .bd li,.slider .bd img{width:100%;height:100%}.slider .bd{z-index:2;overflow:hidden}.slider .bd li{float:left;width:100%;overflow:hidden;background-position:center;background-repeat:no-repeat}.slider .bd li a{display:block;width:100%;height:100%}.slider .bd li img{display:block}.slider .hd{position:absolute;z-index:3;left:0;right:0;bottom:10px;padding:0 10px;text-align:center}.slider .hd li{display:inline-block;text-align:center;margin-right:10px;cursor:pointer;background-color:#c2c2c2}.slider .hd li.active{background-color:#222}.dots li{width:10px;height:10px;font-size:0;line-height:0;border-radius:50%}.numbox li{width:20px;height:20px;line-height:20px;font-size:13px;font-family:Arial;font-weight:bold;text-indent:inherit}.numbox li.active{color:#fff}.rectangle li{width:40px;height:10px;font-size:0;line-height:0}.slider-arrow{display:block;position:absolute;top:50%;margin-top:-25px;height:50px;width:50px;line-height:50px;text-align:center;z-index:3;opacity:.7;filter:alpha(opacity=70)}.slider-arrow:hover{opacity:1;filter:alpha(opacity=100)}.slider-arrow.prev{left:0}.slider-arrow.next{right:0}.tabBar{border-bottom:2px solid #222}.tabBar span{background-color:#e8e8e8;cursor:pointer;display:inline-block;float:left;font-weight:bold;height:30px;line-height:30px;padding:0 15px}.tabBar span.current{background-color:#222;color:#fff}.tabCon{display:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;white-space:nowrap;vertical-align:middle;background-color:#999;overflow:hidden}.label.radius{border-radius:3px}.badge{padding-right:9px;padding-left:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-default,.badge-default{background-color:#e6e6e6;color:#333}.label-default[href],.badge-default[href]{background-color:#e6e6e6;color:#333}.label-primary,.badge-primary{background-color:#5a98de}.label-primary[href],.badge-primary[href]{background-color:#5a98de}.label-secondary,.badge-secondary{background-color:#3bb4f2}.label-secondary[href],.badge-secondary[href]{background-color:#3bb4f2}.label-success,.badge-success{background-color:#5eb95e}.label-success[href],.badge-success[href]{background-color:#5eb95e}.label-warning,.badge-warning{background-color:#f37b1d}.label-warning[href],.badge-warning[href]{background-color:#f37b1d}.label-danger,.badge-danger{background-color:#dd514c}.label-danger[href],.badge-danger[href]{background-color:#dd514c}.Huialert{position:relative;padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5}.Huialert,.Huialert h4{color:#c09853}.Huialert h4{margin:0}.Huialert .Hui-iconfont{position:absolute;top:9px;right:10px;line-height:20px;cursor:pointer;color:#000;opacity:.2;_color:#666}.Huialert .Hui-iconfont.hover{color:#000;opacity:.8}.Huialert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.Huialert-success h4{color:#468847}.Huialert-danger{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.Huialert-danger h4{color:#b94a48}.Huialert-error{color:#fff;background-color:#f37b1d;border-color:#e56c0c}.Huialert-error h4{color:#fff}.Huialert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.Huialert-info h4{color:#31708f}.Huialert-block{padding-top:14px;padding-bottom:14px}.Huialert-block>p,.Huialert-block>ul{margin-bottom:0}.Huialert-block p+p{margin-top:5px}.progress,.progress-bar,.sr-only{height:10px;font-size:0;line-height:0}.progress{overflow:hidden;width:400px}.progress-bar{width:100%;background-color:#efefef}.sr-only{display:inline-block;background-color:#58b957}.loading{height:50px;background:url(../images/loading-b.gif) no-repeat center}.mask{position:fixed;top:0;left:0;z-index:999;width:100%;height:100%;background-color:rgba(0,0,0,0.7);-moz-transition:all .3s ease-in;-webkit-transition:all .3s ease-in;-o-transition:all .3s ease-in;transition:all .3s ease-in}* html .mask{position:absolute;left:expression(documentElement.scrollLeft+documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop+documentElement.clientHeight - this.offsetHeight)}.modal-open{overflow:hidden}.page-overflow{margin-right:16px}.modal-scrollable{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto}.modal-overflow .modal-scrollable{overflow-y:scroll}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:1040;background-color:#000}* html .modal-backdrop{position:absolute;left:expression(documentElement.scrollLeft+documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop+documentElement.clientHeight - this.offsetHeight)}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop,.modal-backdrop.fade.in{opacity:.7;filter:alpha(opacity=70)}.modal{position:absolute;top:50%;left:50%;width:500px;margin-left:-250px;z-index:1050;overflow:visible;background-color:#fff;background-clip:padding-box;box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-khtml-background-clip:padding-box;-moz-background-clip:padding-box;-ms-background-clip:padding-box;-o-background-clip:padding-box;background-clip:padding-box;border-radius:6px;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999}.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.fade.in{opacity:1;filter:alpha(opacity=100)}.modal.fade{top:-100%}.modal.fade.in{top:50%}.modal.modal-overflow.fade.in{top:0}.loading-spinner{position:absolute;top:50%;left:50%;margin:-12px 0 0 -12px}.modal-header{padding:9px 15px;border-bottom:1px solid #eee;position:relative}.modal-header .close{position:absolute;right:10px;top:10px}.modal-header h3{margin:0}.modal-body{overflow-y:visible;padding:15px;word-break:break-all}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;*zoom:1;border-radius:0 0 6px 6px;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-alert{position:fixed;width:300px;margin-left:-150px;margin-top:-30px;z-index:9999}.modal-alert-info{padding:30px;text-align:center;font-size:14px;background-color:#fff}.mask_box{background-image:none;display:none;z-index:99}.hover .mask_box{position:absolute;bottom:0;left:0;display:block;background-color:rgba(0,0,0,0.3);text-align:left}.easyDialog_wrapper{width:320px;color:#444;border:3px solid rgba(0,0,0,0);border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.4);display:none}.easyDialog_wrapper .easyDialog_content{border-radius:4px;background:#fff;border:1px solid #e5e5e5}.easyDialog_wrapper .easyDialog_title{height:30px;line-height:30px;overflow:hidden;color:#666;padding:0 10px;font-size:14px;border-bottom:1px solid #e5e5e5;background:#f7f7f7;border-radius:4px 4px 0 0;margin:0}.easyDialog_wrapper .close_btn{font-family:arial;font-size:18px;_font-size:12px;font-weight:700;color:#999;text-decoration:none;float:right}.easyDialog_wrapper .close_btn:hover{color:#333}.easyDialog_wrapper .easyDialog_text{padding:25px 10px;font-size:13px;line-height:22px}.easyDialog_wrapper .easyDialog_footer{padding:10px;text-align:right;*zoom:1}.easyDialog_wrapper .easyDialog_footer:after{content:'';display:block;height:0;overflow:hidden;visibility:hidden;clear:both}.easyDialog_wrapper .btn_highlight,.easyDialog_wrapper .btn_normal{border:1px solid;border-radius:2px;cursor:pointer;float:right;font-size:12px;padding:0 12px;height:24px;line-height:24px;margin-bottom:10px}.easyDialog_wrapper .btn_highlight{background:#4787ed;background:-webkit-gradient(linear,center bottom,center top,from(#4787ed),to(#4d90fe));background:-moz-linear-gradient(90deg,#4787ed,#4d90fe);border-color:#3079ed;color:#fff}.easyDialog_wrapper .btn_normal{margin-left:10px;border-color:#c3c3c3;background:#ececec;color:#333;background:-webkit-gradient(linear,center bottom,center top,from(#ececec),to(#f4f4f4));background:-moz-linear-gradient(90deg,#ececec,#f4f4f4)}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2070}.toTop{position:fixed;bottom:60px;right:15px;z-index:999;display:none;cursor:pointer;overflow:hidden;visibility:visible;background-color:#fff;border:1px solid #d9d9d9;color:#9c9c9c;font-size:16px;width:38px;height:38px;line-height:38px;text-align:center;text-decoration:none;_position:absolute;_top:expression(documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight)}.toTop:hover{color:#fff;text-decoration:none;background-color:#999;border-color:#999}.bdsharebuttonbox.Hui-share a.bds_more,.bdsharebuttonbox.Hui-share a.bds_weixin,.bdsharebuttonbox.Hui-share a.bds_qzone,.bdsharebuttonbox.Hui-share a.bds_sqq,.bdsharebuttonbox.Hui-share a.bds_tsina,.bdsharebuttonbox.Hui-share a.bds_tqq,.bdsharebuttonbox.Hui-share a.bds_douban{display:inline-block;background:0;padding-left:0;text-decoration:none;margin:0;margin-right:6px;height:auto;line-height:auto}.bdsharebuttonbox.Hui-share a:hover{text-decoration:none}.bdsharebuttonbox.Hui-share .share-text{display:inline-block;margin-right:6px;color:#999;cursor:default;float:left}.bdsharebuttonbox.bdshare-button-style0-16.Hui-share a,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{line-height:16px}.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{font-size:16px}.bdsharebuttonbox.bdshare-button-style0-24.Hui-share a,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{line-height:24px}.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{font-size:24px}.Hui-share.jiathis_style_24x24 .jtico{background:0;padding-left:0!important}.Hui-share.jiathis_style_24x24 .jiathis_separator{margin-left:0;margin-right:6px}.panel{background-color:#fff;border:solid 1px transparent}.panel-header{border-bottom:solid 1px transparent;padding:8px 15px;font-size:14px;font-weight:700}.panel-body{padding:15px}.panel-footer{background-color:#f5f5f5;border-top:1px solid #ddd;padding:5px 20px}.panel-default{border-color:#ddd}.panel-default>.panel-header{border-color:#ddd;background-color:#f5f5f5;color:#444}.panel-primary{border-color:#5a98de}.panel-primary>.panel-header{border-color:#5a98de;background-color:#5a98de;color:#fff}.panel-secondary{border-color:#3bb4f2}.panel-secondary>.panel-header{border-color:#3bb4f2;background-color:#3bb4f2;color:#fff}.panel-success{border-color:#5eb95e}.panel-success>.panel-header{border-color:#5eb95e;background-color:#5eb95e;color:#fff}.panel-warning{border-color:#f37b1d}.panel-warning>.panel-header{border-color:#f37b1d;background-color:#f37b1d;color:#fff}.panel-danger{border-color:#dd514c}.panel-danger>.panel-header{border-color:#dd514c;background-color:#dd514c;color:#fff}.docs-example{position:relative;*position:static;*padding-top:19px;margin:15px 0;padding:39px 19px 14px;background-color:#fff;border:1px solid #ddd;border-radius:4px}.docs-example:after{content:"Example";position:absolute;top:-1px;left:-1px;*position:static;padding:3px 7px;font-size:12px;font-weight:bold;background-color:#f5f5f5;border:1px solid #ddd;color:#9da0a4;border-radius:4px 0 4px 0}.marquee{height:22px;overflow:hidden;line-height:22px}.rollpic .prev,.rollpic .next{display:block;height:38px;width:38px;cursor:pointer;float:left;background:url(../images/unslider-arrow2.png) no-repeat 0 0;margin-top:70px}.rollpic .prev{background-position:0 0;margin-right:5px}.rollpic .prev:hover{background-position:0 -38px}.rollpic .next{background-position:0 -76px;margin-left:5px}.rollpic .next:hover{background-position:0 -114px}.rollpicshow{float:left;border:solid 1px #ddd}.rollpicshow li{padding:10px}.ac_results{position:absolute;border:solid 1px #ddd;background-color:#fff;padding:3px;display:none;margin-top:-1px;z-index:999}.ac_results ul{width:100%;list-style-position:outside;list-style:none;padding:0;margin:0}.ac_results li{padding-left:5px;padding-right:5px;display:block;height:24px;line-height:24px;cursor:pointer}.ac_results li p{float:left;margin:0;padding:0;overflow:hidden}.ac_results li p tt{color:#666}.ac_results li span{margin:0;padding:0;display:inline;float:right;color:#f93;width:90px;text-align:right;overflow:hidden}.ac_results li.ac_over{background-color:#f0f1f2}.ac_loading{background:#fff url(../images/loading-s.gif) right center no-repeat}.AD{text-align:center}.dual{top:260px;position:absolute;width:102px;overflow:hidden;display:none;z-index:100}.dual_l{left:6px}.dual_r{right:6px}.dual_con{border:#CCC solid 1px;width:100px;height:300px;overflow:hidden;background-color:#0C9}.dual_close{width:100%;height:24px;line-height:24px;text-align:center;display:block;font-size:13px;color:#555;text-decoration:none}.Hui-tags{border:solid 1px #dedede;padding:0 10px}.Hui-tags-editor{position:relative;padding:10px 0 10px 24px}.Hui-tags-editor .Hui-tags-icon{position:absolute;left:0;top:11px;font-size:14px;color:#666}.Hui-tags-token{color:#aaa;float:left;font-size:12px;height:20px;line-height:20px;margin-right:8px;padding:0 1px;white-space:nowrap;cursor:pointer}.Hui-tags-token:before{content:"#"}.Hui-tags-token:hover{text-decoration:line-through}.Hui-tags-iptwrap{position:relative;float:left}.Hui-tags-input{position:relative;height:20px;min-width:60px;border:0 none;vertical-align:top;line-height:20px;color:#333;z-index:2;background:url(../images/Hui-tags/empty.png) repeat scroll 0 0;display:inline-block;width:100%}.Hui-tags-label{position:absolute;top:0;left:2px;width:240px;height:20px;line-height:20px;font-size:14px;overflow:hidden;z-index:1;color:#ccc}.Hui-tags-list{padding:0 0 10px 0;display:none}.Hui-notag{font-size:12px}.Hui-tags-has span{cursor:pointer;font-size:12px;white-space:nowrap;margin-right:10px}.tags a{height:26px;line-height:26px;padding-right:6px}.tags1{color:#C00;font-size:24px}.tags2{color:#030;font-size:16px}.tags3{color:#00F}.tags4{font-size:16px}.tags5{color:#C00;font-size:20px}.tags6{color:#F06 font-size:20px}.tags7{color:#030;font-weight:bold;font-size:18px}.tags8{color:#F06;font-weight:bold}.tags9{color:#C00;font-weight:bold;font-size:16px}.tags a:hover{color:#F00;text-decoration:underline}#tagyun{position:relative}#tagyun a{position:absolute;top:0;left:0;font-weight:bold;text-decoration:none;padding:3px 6px}.Huifold .item{position:relative}.Huifold .item h4{margin:0;font-weight:bold;position:relative;border-top:1px solid #fff;font-size:15px;line-height:22px;padding:7px 10px;background-color:#eee;cursor:pointer;padding-right:30px}.Huifold .item h4 b{position:absolute;display:block;cursor:pointer;right:10px;top:7px;width:16px;height:16px;text-align:center;color:#666}.Huifold .item .info{display:none;padding:10px}.maskBar{position:absolute;height:auto;left:0;bottom:-100%;right:0;padding:10px;background-color:rgba(0,0,0,0.6);z-index:2;color:#fff!important}.maskWraper{position:relative;overflow:hidden}.maskWraper.hover .maskBar{bottom:0;transition:bottom 200ms;-moz-transition:bottom 200ms;-webkit-transition:bottom 200ms;-o-transition:bottom 200ms}.maskBox{position:absolute;width:100%;height:100%;top:0;left:0;bottom:0;right:0;z-index:2;color:#fff!important}.maskWraper.hover .maskBox{background-color:rgba(0,0,0,0.6);transition:all 500ms;-moz-transition:all 500ms;-webkit-transition:all 500ms;-o-transition:all 500ms}.commentList .item{list-style:none outside none;margin:1.6rem 0 0}.commentList .avatar{border:1px solid transparent;float:left}.comment-main{position:relative;margin-left:64px;border:1px solid #dedede;border-radius:2px}.comment-main:before,.comment-main:after{position:absolute;top:11px;left:-16px;right:100%;width:0;height:0;display:block;content:" ";border-color:transparent;border-style:solid solid outset;pointer-events:none}.comment-main:before{border-right-color:#dedede;border-width:8px}.comment-main:after{border-width:7px;border-right-color:#f8f8f8;margin-top:1px;margin-left:2px}.comment-header{padding:10px 15px;background:#f8f8f8;border-bottom:1px solid #eee}.comment-title{margin:0 0 8px 0;font-size:1.6rem;line-height:1.2}.comment-meta{font-size:13px;color:#999;line-height:1.2}.comment-meta a{color:#999}.comment-author{font-weight:700;color:#999}.comment-body{padding:15px;overflow:hidden}.comment-body>:last-child{margin-bottom:0}.commentList .comment-flip .avatar{float:right}.comment-flip .comment-main{margin-left:0;margin-right:64px}.comment-flip .comment-main:before{border-left-color:#dedede;border-right-color:transparent}.comment-flip .comment-main:before,.comment-flip .comment-main:after{left:100%;position:absolute;right:-16px}.comment-flip .comment-main:after{border-left-color:#f8f8f8;border-right-color:transparent;margin-left:auto;margin-right:2px}.footer{border-top:1px solid #e8e8e8;padding:15px 0;font-family:tahoma,Arial;font-size:12px;color:#999;line-height:22px;text-align:center}.footer a,.footer a:hover{color:#999}.page-404{color:#afb5bf;padding-top:60px;padding-bottom:90px}.page-404 .error-title{font-size:80px}.page-404 .error-title .iconfont{font-size:80px}.page-404 .error-description{font-size:24px}.page-404 .error-info{font-size:14px} \ No newline at end of file diff --git a/src/main/webapp/reportHtml/offlineReportTemplateNew.xml b/src/main/webapp/reportHtml/offlineReportTemplateNew.xml index 047b29a..a80f3b1 100644 --- a/src/main/webapp/reportHtml/offlineReportTemplateNew.xml +++ b/src/main/webapp/reportHtml/offlineReportTemplateNew.xml @@ -37,7 +37,7 @@ padding: 20px; margin: 30px; border: 1px solid #aaaaaa; - height: 640px; + height: 670px; } #view-html{ @@ -126,6 +126,7 @@ 报文 场景 测试环境 + 数据池 状态 @@ -153,6 +154,11 @@

    +
    +
    数据池:
    +
    +
    +
    请求返回码:
    @@ -240,7 +246,7 @@ var eventList = { layer.open({ type: 1, - area: ['760px', '750px'], + area: ['760px', '773px'], maxmin: false, fixed:false, //isOutAnim:false, @@ -249,13 +255,14 @@ var eventList = { title: resultInfo.messageInfo, shadeClose:true, content: $("#view-html").html(), - success:function(layero) { - $(".layui-layer-content > .view-details > .row:eq(0) .col-sm-9").text(resultInfo.requestUrl); - $(".layui-layer-content > .view-details > .row:eq(1) .col-sm-9").text(resultInfo.businessSystemName); - $(".layui-layer-content > .view-details > .row:eq(2) .col-sm-9").text(resultInfo.statusCode); - $(".layui-layer-content > .view-details > .row:eq(3) .col-sm-9 textarea").text(resultInfo.requestMessage); - $(".layui-layer-content > .view-details > .row:eq(4) .col-sm-9 textarea").text((resultInfo.responseMessage != null) ? resultInfo.responseMessage : ""); - $(".layui-layer-content > .view-details > .row:eq(5) .col-sm-9 textarea").text((resultInfo.mark != null) ? resultInfo.mark : ""); + success:function(layero) { + $(".layui-layer-content > .view-details > .row:eq(0) .col-sm-9").text(resultInfo.requestUrl); + $(".layui-layer-content > .view-details > .row:eq(1) .col-sm-9").text(resultInfo.businessSystemName); + $(".layui-layer-content > .view-details > .row:eq(2) .col-sm-9").text(resultInfo.poolItemName ? resultInfo.poolName + '-' + resultInfo.poolItemName : '未使用'); + $(".layui-layer-content > .view-details > .row:eq(3) .col-sm-9").text(resultInfo.statusCode); + $(".layui-layer-content > .view-details > .row:eq(4) .col-sm-9 textarea").text(resultInfo.requestMessage); + $(".layui-layer-content > .view-details > .row:eq(5) .col-sm-9 textarea").text((resultInfo.responseMessage != null) ? resultInfo.responseMessage : ""); + $(".layui-layer-content > .view-details > .row:eq(6) .col-sm-9 textarea").text((resultInfo.mark != null) ? resultInfo.mark : ""); } }); }, @@ -326,11 +333,12 @@ function renderReportView() { + '' + messageInfo[1] + '' + '' + messageInfo[2] + '' + '' + report.businessSystemName + '' + + '' + (report.poolItemName ? report.poolName + '-' + report.poolItemName : '未使用') + '' + '' + report.runStatus + '' + '' + report.useTime + '' + ''; if (report.protocolType == "FIXED") { - dataHtml += ''; + dataHtml += '