This commit is contained in:
devezhao 2019-11-15 15:21:59 +08:00
parent 6ebd2c3c94
commit b6b3b77e1a
10 changed files with 121 additions and 17 deletions

View file

@ -84,7 +84,8 @@
"$countdownButton": true, "$countdownButton": true,
"ChartSelect": true, "ChartSelect": true,
"Share2": true, "Share2": true,
"$pgt": true "$pgt": true,
"$stopEvent": true
}, },
"rules": { "rules": {
"strict": 0, "strict": 0,

View file

@ -24,6 +24,7 @@ import com.rebuild.server.Application;
import com.rebuild.server.metadata.EntityHelper; import com.rebuild.server.metadata.EntityHelper;
import com.rebuild.server.service.DataSpecificationException; import com.rebuild.server.service.DataSpecificationException;
import com.rebuild.server.service.SystemEntityService; import com.rebuild.server.service.SystemEntityService;
import com.rebuild.server.service.bizz.UserHelper;
/** /**
* 文件目录 * 文件目录
@ -51,6 +52,7 @@ public class AttachmentFolderService extends SystemEntityService {
if (inFolder != null) { if (inFolder != null) {
throw new DataSpecificationException("目录内有文件不能删除"); throw new DataSpecificationException("目录内有文件不能删除");
} }
Object parent = Application.createQueryNoFilter( Object parent = Application.createQueryNoFilter(
"select parent from AttachmentFolder where parent = ?") "select parent from AttachmentFolder where parent = ?")
.setParameter(1, recordId) .setParameter(1, recordId)
@ -59,6 +61,17 @@ public class AttachmentFolderService extends SystemEntityService {
throw new DataSpecificationException("目录内有子目录不能删除"); throw new DataSpecificationException("目录内有子目录不能删除");
} }
ID user = Application.getCurrentUser();
if (!UserHelper.isAdmin(user)) {
Object[] createdBy = Application.createQueryNoFilter(
"select createdBy from AttachmentFolder where folderId = ?")
.setParameter(1, recordId)
.unique();
if (!user.equals(createdBy[0])) {
throw new DataSpecificationException("无权删除他人目录");
}
}
return super.delete(recordId); return super.delete(recordId);
} }
} }

View file

@ -136,7 +136,6 @@ public class FileListControll extends BasePageControll {
} else { } else {
sql += " order by modifiedOn desc"; sql += " order by modifiedOn desc";
} }
System.out.println(sql);
Object[][] array = Application.createQueryNoFilter(sql) Object[][] array = Application.createQueryNoFilter(sql)
.setLimit(pageSize, pageNo * pageSize - pageSize) .setLimit(pageSize, pageNo * pageSize - pageSize)
.array(); .array();

View file

@ -25,6 +25,7 @@ import com.alibaba.fastjson.JSONArray;
import com.rebuild.server.Application; import com.rebuild.server.Application;
import com.rebuild.server.business.files.FilesHelper; import com.rebuild.server.business.files.FilesHelper;
import com.rebuild.server.metadata.EntityHelper; import com.rebuild.server.metadata.EntityHelper;
import com.rebuild.server.service.bizz.UserHelper;
import com.rebuild.web.BaseControll; import com.rebuild.web.BaseControll;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -33,7 +34,9 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author devezhao * @author devezhao
@ -63,6 +66,27 @@ public class FileManagerControll extends BaseControll {
writeSuccess(response); writeSuccess(response);
} }
@RequestMapping("delete-files")
public void deleteFiles(HttpServletRequest request, HttpServletResponse response)
throws IOException {
ID user = getRequestUser(request);
String[] files = getParameter(request, "ids", "").split(",");
Set<ID> willDeletes = new HashSet<>();
for (String file : files) {
if (!ID.isId(file)) continue;
ID fileId = ID.valueOf(file);
if (!checkAllow(user, fileId)) {
writeFailure(response, "无权删除他人文件");
return;
}
willDeletes.add(fileId);
}
Application.getCommonService().delete(willDeletes.toArray(new ID[0]));
writeSuccess(response);
}
@RequestMapping("move-files") @RequestMapping("move-files")
public void moveFiles(HttpServletRequest request, HttpServletResponse response) public void moveFiles(HttpServletRequest request, HttpServletResponse response)
throws IOException { throws IOException {
@ -73,16 +97,18 @@ public class FileManagerControll extends BaseControll {
List<Record> fileRecords = new ArrayList<>(); List<Record> fileRecords = new ArrayList<>();
for (String file : files) { for (String file : files) {
if (!ID.isId(file)) continue; if (!ID.isId(file)) continue;
Record r = EntityHelper.forUpdate(ID.valueOf(file), user); ID fileId = ID.valueOf(file);
if (inFolder == null) { if (!checkAllow(user, fileId)) {
r.setNull("inFolder"); writeFailure(response, "无权更改他人文件");
} else { return;
r.setID("inFolder", inFolder);
} }
Record r = EntityHelper.forUpdate(fileId, user);
if (inFolder == null) r.setNull("inFolder");
else r.setID("inFolder", inFolder);
fileRecords.add(r); fileRecords.add(r);
} }
Application.getCommonService().createOrUpdate(fileRecords.toArray(new Record[0]), false); Application.getCommonService().createOrUpdate(fileRecords.toArray(new Record[0]), false);
writeSuccess(response); writeSuccess(response);
} }
@ -94,4 +120,17 @@ public class FileManagerControll extends BaseControll {
boolean OK = Application.getSecurityManager().allowedR(user, record); boolean OK = Application.getSecurityManager().allowedR(user, record);
writeSuccess(response, OK); writeSuccess(response, OK);
} }
// 是否允许操作指定文件管理员总是允许
private boolean checkAllow(ID user, ID file) {
if (UserHelper.isAdmin(user)) {
return true;
}
Object[] o = Application.createQueryNoFilter(
"select createdBy from Attachment where attachmentId = ?")
.setParameter(1, file)
.unique();
return o != null && o[0].equals(user);
}
} }

View file

@ -79,6 +79,7 @@
border-right-color: #fff; border-right-color: #fff;
} }
.file-list-item.active>div.type .file-icon::before,
.file-list-item:hover>div.type .file-icon::before { .file-list-item:hover>div.type .file-icon::before {
border-top-color: #f5f5f5; border-top-color: #f5f5f5;
border-right-color: #f5f5f5; border-right-color: #f5f5f5;
@ -90,6 +91,7 @@
.file-list-item>div.detail>.extras { .file-list-item>div.detail>.extras {
margin-top: 1px; margin-top: 1px;
overflow: hidden;
} }
.file-list-item>div.detail>.extras>span { .file-list-item>div.detail>.extras>span {
@ -98,6 +100,24 @@
line-height: 1; line-height: 1;
} }
.file-list-item>div.detail>.extras>span.op {
display: none;
}
.file-list-item:hover>div.detail>.extras>span.op {
display: inline-block;
}
.file-list-item>div.detail>.extras>span.op>a {
color: #999;
display: inline-block;
padding: 0 8px;
}
.file-list-item>div.detail>.extras>span.op>a:hover {
color: #555;
}
.file-list-item>div.detail .extras>span, .file-list-item>div.detail .extras>span,
.file-list-item>div.detail .extras>span>a { .file-list-item>div.detail .extras>span>a {
color: #777; color: #777;

View file

@ -1,3 +1,4 @@
/* eslint-disable react/jsx-no-target-blank */
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
/* global filesList */ /* global filesList */
// //
@ -258,6 +259,21 @@ class FolderTree extends React.Component {
class FilesList2 extends FilesList { class FilesList2 extends FilesList {
state = { ...this.props } state = { ...this.props }
__lastEntry = __DEFAULT_ALL __lastEntry = __DEFAULT_ALL
renderExtras(item) {
return <React.Fragment>
{super.renderExtras(item)}
<span className="op">
<a title="下载" onClick={(e) => $stopEvent(e)} href={`${rb.baseUrl}/filex/download/${item.filePath}?attname=${$fileCutName(item.filePath)}`} target="_blank"><i className="icon zmdi zmdi-download fs-15 down-2"></i></a>
<a title="分享" onClick={(e) => this._share(item, e)}><span><i className="icon zmdi zmdi-share fs-14 down-1"></i></span></a>
</span>
</React.Fragment>
}
_share(item, e) {
$stopEvent(e)
// eslint-disable-next-line react/jsx-no-undef
renderRbcomp(<FileShare file={item.filePath} />)
}
} }
const __findPaths = function (active, push) { const __findPaths = function (active, push) {
@ -300,7 +316,7 @@ $(document).ready(() => {
confirmText: '删除', confirmText: '删除',
confirm: function () { confirm: function () {
this.disabled(true) this.disabled(true)
$.post(`${rb.baseUrl}/app/entity/record-delete?id=${s}`, (res) => { $.post(`${rb.baseUrl}/files/delete-files?ids=${s}`, (res) => {
if (res.error_code > 0) RbHighbar.error(res.error_msg) if (res.error_code > 0) RbHighbar.error(res.error_msg)
this.hide() this.hide()
filesList.loadData() filesList.loadData()

View file

@ -78,6 +78,14 @@ var filesList
$(document).ready(() => { $(document).ready(() => {
$('.side-toggle').click(() => $('.rb-aside').toggleClass('rb-aside-collapsed')) $('.side-toggle').click(() => $('.rb-aside').toggleClass('rb-aside-collapsed'))
let $content = $('.page-aside .tab-content')
let hold = window.resize_handler
window.resize_handler = function () {
typeof hold === 'function' && hold()
$content.height($(window).height() - 147)
$content.perfectScrollbar('update')
}
window.resize_handler()
$('.J_sort .dropdown-item').click(function () { $('.J_sort .dropdown-item').click(function () {
let $this = $(this) let $this = $(this)

View file

@ -304,3 +304,13 @@ var $same = function (a, b) {
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
return a == b return a == b
} }
/**
* 停止事件传播
* @param {Event} e
*/
var $stopEvent = function (e) {
if (e && e.stopPropagation) e.stopPropagation()
if (e && e.nativeEvent) e.nativeEvent.stopImmediatePropagation()
return false
}

View file

@ -43,14 +43,14 @@
<li class="breadcrumb-item active">全部附件</li> <li class="breadcrumb-item active">全部附件</li>
</ol> </ol>
</div> </div>
<div class="file-operator"> <div class="file-operator row">
<div class="float-left"> <div class="col-lg-6 col-12">
<div class="input-group input-search"> <div class="input-group input-search">
<input class="form-control" type="text" placeholder="搜索 ..." maxlength="40"> <input class="form-control" type="text" placeholder="搜索 ..." maxlength="40">
<span class="input-group-btn"><button class="btn btn-secondary" type="button"><i class="icon zmdi zmdi-search"></i></button></span> <span class="input-group-btn"><button class="btn btn-secondary" type="button"><i class="icon zmdi zmdi-search"></i></button></span>
</div> </div>
</div> </div>
<div class="float-right"> <div class="col-lg-6 col-12 text-lg-right mt-lg-0 mt-md-2 mt-sm-2">
<div class="btn-group btn-space mb-0 mr-0 J_sort"> <div class="btn-group btn-space mb-0 mr-0 J_sort">
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span>默认排序</span> <i class="icon zmdi zmdi-chevron-down"></i></button> <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span>默认排序</span> <i class="icon zmdi zmdi-chevron-down"></i></button>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
@ -59,7 +59,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="clearfix"></div>
</div> </div>
</div> </div>
<div class="file-viewport"> <div class="file-viewport">

View file

@ -43,14 +43,14 @@
<li class="breadcrumb-item active">全部文档</li> <li class="breadcrumb-item active">全部文档</li>
</ol> </ol>
</div> </div>
<div class="file-operator"> <div class="file-operator row">
<div class="float-left"> <div class="col-lg-6 col-12">
<div class="input-group input-search"> <div class="input-group input-search">
<input class="form-control" type="text" placeholder="搜索 ..." maxlength="40"> <input class="form-control" type="text" placeholder="搜索 ..." maxlength="40">
<span class="input-group-btn"><button class="btn btn-secondary" type="button"><i class="icon zmdi zmdi-search"></i></button></span> <span class="input-group-btn"><button class="btn btn-secondary" type="button"><i class="icon zmdi zmdi-search"></i></button></span>
</div> </div>
</div> </div>
<div class="float-right"> <div class="col-lg-6 col-12 text-lg-right mt-lg-0 mt-md-2 mt-sm-2">
<div class="btn-group btn-space mb-0"> <div class="btn-group btn-space mb-0">
<button class="btn btn-primary J_upload-file" type="button"><i class="icon zmdi zmdi-upload"></i> 上传文件${entityLabel}</button> <button class="btn btn-primary J_upload-file" type="button"><i class="icon zmdi zmdi-upload"></i> 上传文件${entityLabel}</button>
<button class="btn btn-primary dropdown-toggle auto" type="button" data-toggle="dropdown"><span class="icon zmdi zmdi-chevron-down"></span></button> <button class="btn btn-primary dropdown-toggle auto" type="button" data-toggle="dropdown"><span class="icon zmdi zmdi-chevron-down"></span></button>
@ -69,7 +69,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="clearfix"></div>
</div> </div>
</div> </div>
<div class="file-viewport"> <div class="file-viewport">