Ngrinder脚本管理界面改为可拖动至文件夹改造

大致需求是这样的,页面拖动脚本文件,然后拖动到其他的文件夹,其实看起来是没啥难得,后台添加文件,删除当前根目录下的脚本文件就好了,看起来没啥。但还是有坑的。看下面代码。

1.后台代码

/**
	 * 页面拖拽脚本文件更换位置
	 * @param user
	 * @param thisScript
	 * @param folderPath
	 * @param revision
	 * @return
	 */
	@Transactional
	@RequestMapping(value = "/varyPosition",method = RequestMethod.POST)
	public String varyPosition(User user,
							   @RequestParam(value = "thisScript")String thisScript,
							   @RequestParam(value = "folderPath")String folderPath,
							   @RequestParam(value = "r", required = false) Long revision) throws ScriptFileException{

		//1.判断脚本名称是否符合规则
		boolean flag = regexpContants.isExist(thisScript);

		//2.判断文件夹名称是否符合规则,不能包含点
		int i = folderPath.indexOf(".");

		//3.两个都需要符合条件
		if (flag && (i == -1)){

			//4.首先根据传过来得脚本名称查询到该脚本对象信息,当前thisScript只是脚本名称,thisScript.path就是脚本名称,不包含文件夹名
			FileEntry script = fileEntryService.getOne(user, thisScript, revision);

			String thisPath = script.getPath();

			String scriptPath = folderPath+"/"+script.getPath();

			//5.判断目标文件夹内是否有重复名称的脚本存在,如果一样的位置出现重复会出问题,可能会被完全覆盖
			if(fileEntryService.getOne(user, scriptPath, revision) == null){

				//6.进行save操作
				script.setPath(scriptPath);
				script.setLastRevision(script.getRevision()+1);

				Map<String, String> map = Maps.newHashMap();
				map.put("validated", script.getProperties().get("validated"));
				map.put("targetHosts", StringUtils.trim(script.getProperties().get("targetHosts")));
				script.setProperties(map);

				//7.删除根目录下的script文件
				fileEntryService.delete(user, thisPath);

				//8.最后一步添加操作
				fileEntryService.save(user, script);

			}else {
				throw new ScriptFileException(ResultEnum.SCRIPT_REPEAT);
			}

		}else {
			throw new ScriptFileException(ResultEnum.SCRIPT_RULES);
		}

		return "script/list";
	}

 以下编号代表上面的编号:

1.isExist方法,自己定义的正则表达式,主要是判断后缀名,判断是不是groovy、Jython脚本文件

2.这里是文件夹名称里不能有“.”

3.符合条件

4.user对象前端可以不传,前端只穿了需要移动的脚本名称和目标文件夹名称,通过fileEntryService.getOne(user, thisScript, revision)方法,revision可以为0,thisScript就是FileEntry当中的path属性,最后获得一个对象。

5.就是把目标文件名称和脚本名称组合起来,查询一下,看看目标文件夹是否存在该脚本,如果存在的话还强制save,则不会有任何变化或者被覆盖。

6.save操作

//6.进行save操作
				script.setPath(scriptPath);
				script.setLastRevision(script.getRevision()+1);

				Map<String, String> map = Maps.newHashMap();
				map.put("validated", script.getProperties().get("validated"));
				map.put("targetHosts", StringUtils.trim(script.getProperties().get("targetHosts")));
				script.setProperties(map);

这里的script.setPath,则是覆盖值,比如说你要移动到hello文件夹,值应该是hello/test.groovy,Revision可以不写。下面的setProperties必须重新覆盖,要不然会出错。在你第一次添加脚本的十会,debug的时候可以看到FileEntry对象中有个属性properties,初始添加的时候里面只有两个值,一个是targetHosts目标主机,一个好像是validated,看下面图片:

 但在你添加脚本完成后,脚本对象中的properties中则会多了很多数据,比如说UUID、checkSum、这些数据是为了保证脚本文件唯一

 然后最下面,先新增,后删除。

当你报错ong.tmatesoft.svn.core.SVNException: sVn:E165002: Storage of non-regular property 'svn:entry:nevision' is disallowed ,●through the repository interface,and could indicate a bug in your client的时候,那就是证明添加了同样UUID的脚本。properties中的属性是重复的。

下面是前端代码,前端代码在src/main/webapp/WEB-INF/ftl/script/list.ftl,我觉得前端代码没啥问题,直接赋值过去可以直接使用得。

<!DOCTYPE html>
<html>
	<head>
		<#include "../common/common.ftl">
		<#include "../common/datatables.ftl">
		<title><@spring.message "script.list.title"/></title>
            <style>
                .script-img-unit {
                    background-image: url('${req.getContextPath()}/img/bg_script_banner_en.png?${nGrinderVersion}');
                    height: 110px;
                    padding: 0;
                    margin-top: 0px;
                }

            </style>
	</head>
<#--	<script src="~/Content/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.js"></script>-->
	<body>
    <div id="wrap">
    <#include "../common/navigator.ftl">
	<div class="container nav-right">
		<div class="script-img-unit "></div>
		<div class="well form-inline search-bar" style="margin-top:0;margin-bottom:0" >
			<table style="width:100%">
				<tr>
					<td>
						<table style="width:100%">
							<colgroup>
								<col width="400px"/>
								<col width="*"/>
							</colgroup>
							<tr>
								<td>
									<input type="text" class="search-query span3" placeholder="Keywords" id="searchText" value="${query!}">
									<button type="submit" class="btn" id="search_btn"><i class="icon-search"></i> <@spring.message "common.button.search"/></button>
								</td>
								<td>
								<#if svnUrl?has_content>
									<div class="input-prepend pull-right" rel="popover"
										title="Subversion" data-placement="bottom"
										data-content='<@spring.message "script.message.svn"/>'
										data-html="true">
										<span class="add-on" style="cursor:default">SVN</span><span class="input-xlarge uneditable-input span7" style="cursor:text">${svnUrl}</span>
						        	</div>
					        	</#if>
				        		</td>
				        	</tr>
			        	</table>
					</td>
				</tr>
				<tr>
			     	<td>
						<table  style="width:100%; margin-top:5px">
							<colgroup>
								<col width="600px"/>
								<col width="340px"/>
							</colgroup>
							<tr>
								<td>
									<#if !(query??)>
										<a class="btn btn-primary" href="#create_script_modal" data-toggle="modal">
											<i class="icon-file icon-white"></i>
											<@spring.message "script.action.createScript"/>
										</a>
										<a class="btn" href="#create_folder_modal" data-toggle="modal">
											<i class=" icon-folder-open"></i>
											<@spring.message "script.action.createFolder"/>
										</a>
										<a class="btn" href="#upload_file_modal" data-toggle="modal">
											<i class="icon-upload"></i>
											<@spring.message "script.action.uploadResources"/>
										</a>
									</#if>
								</td>
								<td>
									<a class="pointer-cursor btn btn-danger pull-right" id="delete_script_button">
										<i class="icon-remove icon-white"></i>
										<@spring.message "script.action.delete"/>
									</a>
								</td>
							</tr>
						</table>
					</td>
				</tr>
			</table>
		</div>

		<table class="table table-striped table-bordered ellipsis" id="script_list_table" style="width:100%">
			<colgroup>
				<col width="30">
				<col width="32">
				<col width="230">
				<col>
				<col width="150">
				<col width="80">
				<col width="80">
				<col width="80">
			</colgroup>
			<thead>
				<tr>
					<th><input type="checkbox" class="checkbox" value=""></th>
					<th class="no-click">
						<a href="${req.getContextPath()}/script/list/${currentPath}/../" target="_self">
							<img src="${req.getContextPath()}/img/up_folder.png?${nGrinderVersion}"/>
						</a>
					</th>
					<th><@spring.message "script.list.name"/></th>
					<th class="no-click"><@spring.message "script.list.commit"/></th>
					<th><@spring.message "script.list.lastDate"/></th>
					<th><@spring.message "script.list.revision"/></th>
					<th><@spring.message "script.list.size"/></th>
					<th class="no-click"><@spring.message "script.list.download"/></th>
				</tr>
			</thead>
			<tbody>
				<@list list_items=files others="table_list" colspan="8"; script>
					<tr>
						<td><#if script.fileName != ".."><input type="checkbox" class="checkbox"  value="${script.fileName}"></#if></td>
						<td>
							<#if script.fileType.fileCategory.isEditable()>
								<i class="icon-file"></i>
							<#elseif script.fileType == "dir">
								<i class="icon-folder-open"></i>
							<#else>
								<i class="icon-briefcase"></i>
							</#if>
						</td>
						<td class="ellipsis" draggable="true" id="dragtarget">
							<#if script.fileType.fileCategory.isEditable()>
								<a href="${req.getContextPath()}/script/detail/${script.path}" target="_self" title="${script.path}">${script.fileName}</a>
							<#elseif script.fileType == "dir">
								<a href="${req.getContextPath()}/script/list/${script.path}" target="_self" title="${script.path}">${script.fileName}</a>
							<#else>
								<a href="${req.getContextPath()}/script/download/${script.path}" target="_blank" title="${script.path}">${script.fileName}</a>
							</#if>
						</td>
						<td title="${(script.description)!?html}">${(script.description)!}</td>
						<td><#if script.lastModifiedDate??>${script.lastModifiedDate?string('yyyy-MM-dd HH:mm')}</#if></td>
						<td>${script.revision}</td>
						<td>
							<#if script.fileType != "dir">
								<#assign floatSize = script.fileSize?number/1024>${floatSize?string("0.##")}
							</#if>
						</td>
						<td class="center">
							<#if script.fileType != "dir">
								<i class="pointer-cursor icon-download-alt script-download" spath="${script.path}"></i>
							</#if>
						</td>
					</tr>
				</@list>
			</tbody>
		</table>
	</div>
	<#if !(query??)>
	<#include "create_script_modal.ftl">
	<#include "create_folder_modal.ftl">validate_btn
	<#include "upload_file_modal.ftl">
	</#if>
    </div>
	<#include "../common/copyright.ftl">
	<script type="text/javascript">
		$(document).ready(function() {
			$("#nav_script").addClass("active");
			$("#delete_script_button").click(function() {
				var list = $("td input:checked");
				if(list.length == 0) {
					bootbox.alert("<@spring.message "script.message.delete.alert"/>", "<@spring.message "common.button.ok"/>");
					return;
				}
	      		bootbox.confirm("<@spring.message "script.message.delete.confirm"/>", "<@spring.message "common.button.cancel"/>", "<@spring.message "common.button.ok"/>", function(result) {
					if (result) {
						var scriptsStr = list.map(function() {
							return $(this).val();
						}).get().join(",");

						var ajaxObj = new AjaxObj("/script/delete/${currentPath}");
						ajaxObj.type = "POST";
						ajaxObj.params = {'filesString': scriptsStr};
						ajaxObj.success = function () {
							document.location.reload();
						};
						ajaxObj.call();
					}
				});
			});

			$("#search_btn").on('click', function() {
				searchScriptList();
			});

			enableCheckboxSelectAll("script_list_table");

			$("i.script-download").on('click', function() {
				window.location  = "${req.getContextPath()}/script/download/" + $(this).attr("spath");
			});

			<#if files?has_content>
				$("#script_list_table").dataTable({
					"bAutoWidth": false,
					"bFilter": false,
					"bLengthChange": false,
					"bInfo": false,
					"iDisplayLength": 10,
					"aaSorting": [],
					"aoColumns": [{"asSorting": []}, {"asSorting": []}, null, {"asSorting": []}, null, null, null, {"asSorting": []}],
					"sPaginationType": "bootstrap",
					"oLanguage": {
						"oPaginate": {
							"sPrevious": "<@spring.message "common.paging.previous"/>",
							"sNext":     "<@spring.message "common.paging.next"/>"
						}
					}
				});
				$(".no-click").off('click');
			</#if>
			let starEvent = ''
			let endEvent = ''
			/* 拖动时触发*/
			document.addEventListener("dragstart", function(event) {
				//dataTransfer.setData()方法设置数据类型和拖动的数据
				event.dataTransfer.setData("Text", event.target.id);
				//修改拖动元素的透明度
				event.target.style.opacity = "0.4";
				// console.log(event.target.innerText)
				if (event.target.innerText != starEvent) {
					starEvent = event.target.innerText
				}
			});
			// 当拖完p元素输出一些文本元素和重置透明度
			document.addEventListener("dragend", function(event) {
				event.target.style.opacity = "1";
				console.log(starEvent,endEvent)
				if ((starEvent.indexOf('.groovy') != -1 || starEvent.indexOf('.py') != -1) && starEvent) {
					if (endEvent.indexOf('.') == -1 && endEvent) {
						// starEvent = ''
						// starEvent = ''
						<#--document.location.href = "${req.getContextPath()}/script/list"-->
						console.log(starEvent,endEvent)
						var ajaxObj = new AjaxObj("/script/varyPosition");
						ajaxObj.type = "POST";
						ajaxObj.params = {'thisScript': starEvent,'folderPath':endEvent};
						ajaxObj.success = function () {

						};
						ajaxObj.call();
					}
				}
			});
			/* 拖动完成后触发 */
			// 当p元素完成拖动进入droptarget,改变div的边框样式
			document.addEventListener("dragenter", function(event) {
				if ( event.target.className.indexOf("ellipsis") != -1 ) {
					if (endEvent != event.target.innerText) {
						endEvent = event.target.innerText
					}
				}else {
					endEvent = ''
				}
			});
			// 默认情况下,数据/元素不能在其他元素中被拖放。对于drop我们必须防止元素的默认处理
			document.addEventListener("dragover", function(event) {
				event.preventDefault();
			});

			// function fixHelper(e,ui){
			// 	// console.log(ui.context.children[2].innerText)
			// 	ui.children().each(function() {
			// 		$(this).width($(this).width());
			// 	});
			// 	return ui;
			// }
			// $( "#script_list_table tbody").sortable({
			// 	helper: fixHelper,
			// 	axis:"y",
			// 	revert: false, //释放时,增加动画
			// });
			// $( "#script_list_table").disableSelection();
		});

		function searchScriptList() {
			document.location.href = "${req.getContextPath()}/script/search?query=" + $("#searchText").val();
		}
	</script>
	</body>
</html>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值