完成目录创建
This commit is contained in:
parent
bb4e78ef97
commit
6600a6e697
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
@ -79,3 +79,9 @@ server:
|
||||
|
||||
```
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
@ -4,15 +4,16 @@ import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import xyz.longicorn.driver.dto.ApiResult;
|
||||
import xyz.longicorn.driver.dto.FileItem;
|
||||
import xyz.longicorn.driver.dto.FolderDto;
|
||||
import xyz.longicorn.driver.pojo.FolderInfo;
|
||||
import xyz.longicorn.driver.service.FolderService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/folder")
|
||||
@ -23,14 +24,20 @@ public class FolderController {
|
||||
|
||||
@RequestMapping("/list")
|
||||
//接口文档的名称
|
||||
@ApiOperation(value = "查询目录信息", notes = "查询相应目录下的所有文件(夹)信息",httpMethod = "GET")
|
||||
@ApiOperation(value = "查询目录信息", notes = "查询相应目录下的所有文件(夹)信息", httpMethod = "GET")
|
||||
public ApiResult listFolder(@RequestParam(required = false, defaultValue = "/") String folderPath) {
|
||||
return ApiResult.success(folderService.listFolder(1, folderPath));
|
||||
return ApiResult.success(
|
||||
folderService.listFolder(1, folderPath)
|
||||
);
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
@PostMapping("/create")
|
||||
@ApiOperation(value = "创建目录", notes = "创建目录1")
|
||||
public FolderInfo create(String parent, String name) {
|
||||
return null;
|
||||
public ApiResult create(@RequestBody FolderDto f) {
|
||||
String parent = f.getParent(), name = f.getName();
|
||||
return ApiResult.success(
|
||||
folderService.create(1, parent, name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
package xyz.longicorn.driver.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import xyz.longicorn.driver.pojo.FileInfo;
|
||||
import xyz.longicorn.driver.pojo.FolderInfo;
|
||||
|
||||
@Mapper
|
||||
public interface FileInfoMapper extends BaseMapper<FileInfo> {
|
||||
}
|
69
driver/src/main/java/xyz/longicorn/driver/dto/FileItem.java
Normal file
69
driver/src/main/java/xyz/longicorn/driver/dto/FileItem.java
Normal file
@ -0,0 +1,69 @@
|
||||
package xyz.longicorn.driver.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import xyz.longicorn.driver.pojo.FileInfo;
|
||||
import xyz.longicorn.driver.pojo.FolderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件项 可以是文件也可以是目录
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class FileItem {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Integer size;
|
||||
private String path;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
private String type;
|
||||
|
||||
public static List<FileItem> buildFolderList(List<FolderInfo> list) {
|
||||
List<FileItem> listItems = new ArrayList<>();
|
||||
list.forEach(f -> listItems.add(build(f)));
|
||||
return listItems;
|
||||
}
|
||||
|
||||
public static FileItem build(FolderInfo f) {
|
||||
return new FileItem()
|
||||
.setCreateTime(f.getCreateTime())
|
||||
.setId(f.getId())
|
||||
.setName(f.getName())
|
||||
.setSize(0)
|
||||
.setType("folder")
|
||||
.setPath(f.getPath())
|
||||
.setUpdateTime(f.getUpdateTime());
|
||||
}
|
||||
|
||||
public static List<FileItem> buildFileList(List<FileInfo> list) {
|
||||
List<FileItem> listItems = new ArrayList<>();
|
||||
list.forEach(f -> listItems.add(build(f)));
|
||||
return listItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件转成fileItem
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
public static FileItem build(FileInfo f) {
|
||||
return new FileItem()
|
||||
.setCreateTime(f.getCreateTime())
|
||||
.setId(f.getId())
|
||||
.setName(f.getName())
|
||||
.setSize(f.getSize())
|
||||
.setType(f.getType())
|
||||
.setPath(f.getPath())
|
||||
.setUpdateTime(f.getUpdateTime());
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package xyz.longicorn.driver.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FolderDto {
|
||||
private String parent;
|
||||
private String name;
|
||||
}
|
32
driver/src/main/java/xyz/longicorn/driver/pojo/FileInfo.java
Normal file
32
driver/src/main/java/xyz/longicorn/driver/pojo/FileInfo.java
Normal file
@ -0,0 +1,32 @@
|
||||
package xyz.longicorn.driver.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.models.auth.In;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class FileInfo implements Serializable {
|
||||
private Long id;
|
||||
private Long uid;
|
||||
private String name;
|
||||
private String hash;
|
||||
private Long folderId;
|
||||
private String type;
|
||||
private Integer size;
|
||||
private String path;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
private Long status;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package xyz.longicorn.driver.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.longicorn.driver.dao.FileInfoMapper;
|
||||
import xyz.longicorn.driver.pojo.FileInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class FileService extends ServiceImpl<FileInfoMapper, FileInfo> {
|
||||
/**
|
||||
* 查询了目录下的文件列表集合
|
||||
* @param uid
|
||||
* @param folderId
|
||||
* @return
|
||||
*/
|
||||
public List<FileInfo> listByFolderId(int uid,long folderId){
|
||||
QueryWrapper q = new QueryWrapper();
|
||||
q.eq("uid",uid);
|
||||
q.eq("folder_id",folderId);
|
||||
q.eq("status",1); // TODO 枚举
|
||||
return this.list(q);
|
||||
}
|
||||
}
|
@ -5,12 +5,26 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xyz.longicorn.driver.config.BizException;
|
||||
import xyz.longicorn.driver.dao.FolderInfoMapper;
|
||||
import xyz.longicorn.driver.dto.FileItem;
|
||||
import xyz.longicorn.driver.pojo.FileInfo;
|
||||
import xyz.longicorn.driver.pojo.FolderInfo;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class FolderService extends ServiceImpl<FolderInfoMapper, FolderInfo> {
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
/**
|
||||
* 根据路径查询目录信息
|
||||
*
|
||||
* @param uid
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public FolderInfo getByPath(int uid, String path) {
|
||||
QueryWrapper q = new QueryWrapper();
|
||||
q.eq("uid", uid);
|
||||
@ -18,7 +32,23 @@ public class FolderService extends ServiceImpl<FolderInfoMapper, FolderInfo> {
|
||||
return this.getOne(q);
|
||||
}
|
||||
|
||||
public List<FolderInfo> listFolder(int uid, String path) {
|
||||
/**
|
||||
* 根据目录的名称查询信息
|
||||
*
|
||||
* @param uid
|
||||
* @param name
|
||||
* @param parentId
|
||||
* @return
|
||||
*/
|
||||
public FolderInfo getByNameAndParent(int uid, String name, long parentId) {
|
||||
QueryWrapper q = new QueryWrapper();
|
||||
q.eq("uid", uid);
|
||||
q.eq("name", name);
|
||||
q.eq("parent_id", parentId);
|
||||
return this.getOne(q);
|
||||
}
|
||||
|
||||
public List<FileItem> listFolder(int uid, String path) {
|
||||
long parentId = 0; // 默认查询根目录
|
||||
// 路径为空或者 / 表示根目录
|
||||
if (path != null && !path.equals("/")) {
|
||||
@ -29,12 +59,34 @@ public class FolderService extends ServiceImpl<FolderInfoMapper, FolderInfo> {
|
||||
QueryWrapper q = new QueryWrapper();
|
||||
q.eq("parent_id", parentId); // 设置查询条件
|
||||
q.eq("uid", uid);
|
||||
return this.list(q);
|
||||
// 查询目录集合
|
||||
final List<FolderInfo> folderList = this.list(q);
|
||||
List<FileItem> fsList = FileItem.buildFolderList(folderList); // 直接将folder集合转成fileitem集合
|
||||
|
||||
final List<FileInfo> fileInfos = fileService.listByFolderId(uid, parentId);//文件信息
|
||||
fsList.addAll(FileItem.buildFileList(fileInfos)); // 合并目录和文件
|
||||
return fsList;
|
||||
}
|
||||
|
||||
public FolderInfo create() {
|
||||
// 验证是否存在相同路径的文件夹
|
||||
// if(xxx) throw new RuntimeException("创建失败,名称相同l")
|
||||
return null;
|
||||
|
||||
public FolderInfo create(int uid, String parent, String name) {
|
||||
long parentId = 0; // 默认根目录
|
||||
if (parent != null && !parent.equals("/")) {
|
||||
FolderInfo f = this.getByPath(uid, parent); // 根据路径查询目录信息
|
||||
if (f == null) throw BizException.create("父目录不存在"); // 没有查询到信息
|
||||
parentId = f.getId(); // 设置查询的父目录id
|
||||
}
|
||||
// 根据目录查询是否存在
|
||||
FolderInfo myFolderInfo = this.getByNameAndParent(uid, name, parentId);//根据名称查询目录信息
|
||||
if (myFolderInfo != null) {
|
||||
throw BizException.create("文件夹已经存在了");
|
||||
}
|
||||
FolderInfo fNew = new FolderInfo();
|
||||
fNew.setUid(uid);
|
||||
fNew.setName(name);
|
||||
fNew.setParentId(parentId);
|
||||
fNew.setPath(parent + "/" + name);
|
||||
;
|
||||
return this.save(fNew) ? fNew : null;
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,20 @@ create table folder_info
|
||||
index ix_name (name),
|
||||
index ix_path (path),
|
||||
index ix_uid (uid)
|
||||
);
|
||||
|
||||
# 编号、用户编号、文件名、目录编号 、类型、大小、位置、创建时间、状态、hash
|
||||
create table file_info(
|
||||
id bigint(20) not null primary key auto_increment,
|
||||
uid int(10) not null,
|
||||
name varchar(50) not null,
|
||||
hash varchar(32) not null comment '文件MD5特征码',
|
||||
folder_id bigint(20) null default 0 comment '所在目录的编号,0表示根目录',
|
||||
type varchar(5) null,
|
||||
size int null default 0,
|
||||
path varchar(500) not null comment '文件的物理存储位置,可以是本地路径也可以是一个网址', -- file://d:/a/b/c.txt http://
|
||||
create_time datetime default current_timestamp,
|
||||
update_time datetime on update current_timestamp,
|
||||
status tinyint(1) default 1,
|
||||
index ix_file_name(name)
|
||||
);
|
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="icon" href="/logo.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>天牛网盘</title>
|
||||
</head>
|
||||
|
35
web/package-lock.json
generated
35
web/package-lock.json
generated
@ -14,7 +14,8 @@
|
||||
"less-loader": "^10.2.0",
|
||||
"qs": "^6.10.3",
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.0.15"
|
||||
"vue-router": "^4.0.15",
|
||||
"vue-simple-context-menu": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
@ -539,6 +540,14 @@
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/click-outside-vue3": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/click-outside-vue3/-/click-outside-vue3-4.0.1.tgz",
|
||||
"integrity": "sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
|
||||
@ -1799,6 +1808,17 @@
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-simple-context-menu": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/vue-simple-context-menu/-/vue-simple-context-menu-4.0.2.tgz",
|
||||
"integrity": "sha512-3DcKuNtEZkh6Gi70NIODTXvPlHnVJgyg3ejXNqVHFWTRWSGoZsfeqZKAfSRANAPLshEhUGcVzT4kTPrXvC5WNQ==",
|
||||
"dependencies": {
|
||||
"click-outside-vue3": "^4.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.31"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.3.1.tgz",
|
||||
@ -2337,6 +2357,11 @@
|
||||
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||
"peer": true
|
||||
},
|
||||
"click-outside-vue3": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/click-outside-vue3/-/click-outside-vue3-4.0.1.tgz",
|
||||
"integrity": "sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
|
||||
@ -3193,6 +3218,14 @@
|
||||
"@vue/devtools-api": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"vue-simple-context-menu": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/vue-simple-context-menu/-/vue-simple-context-menu-4.0.2.tgz",
|
||||
"integrity": "sha512-3DcKuNtEZkh6Gi70NIODTXvPlHnVJgyg3ejXNqVHFWTRWSGoZsfeqZKAfSRANAPLshEhUGcVzT4kTPrXvC5WNQ==",
|
||||
"requires": {
|
||||
"click-outside-vue3": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.3.1.tgz",
|
||||
|
@ -14,7 +14,8 @@
|
||||
"less-loader": "^10.2.0",
|
||||
"qs": "^6.10.3",
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.0.15"
|
||||
"vue-router": "^4.0.15",
|
||||
"vue-simple-context-menu": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
|
1
web/public/logo.svg
Normal file
1
web/public/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1651895924070" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2966" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><defs><style type="text/css"></style></defs><path d="M549.766 97.925c19.974 4.609 50.703 35.339 62.995 55.312 35.339-13.828 36.875 41.484 46.094 55.312 23.047-16.901 46.094-35.339 46.094-55.312 0-21.51-30.729-35.339-30.729-41.484 0-12.292 38.411-12.292 41.484-12.292 50.703 0 106.016 39.948 106.016 96.797 0 27.656-9.219 41.484-33.802 70.677h32.266c21.51 0 27.656-3.073 55.312 7.682C923.125 294.591 960 348.367 960 389.852c0 3.073 0 9.219-1.536 13.828-4.609 3.073-12.292 3.073-16.901 4.609-15.365 1.536-32.266 6.146-47.63 7.682-47.63 0-50.703 0-53.776-1.536-1.536 1.536-1.536 0-1.536 4.609 0 3.073 7.682 44.557 10.755 67.604 9.219 56.849 12.292 115.234 19.974 173.62 1.536 7.682 7.682 15.365 9.219 23.047 3.073 13.828 6.146 27.656 6.146 39.948 0 153.646-245.833 208.958-321.119 208.958h-86.042c-115.234-9.219-248.906-52.24-301.145-138.281-4.609-7.682-18.437-39.948-18.437-50.703v-36.875c3.073-16.901 7.682-33.802 21.51-50.703v-84.505l12.292-132.135c-12.292 1.536-33.802 1.536-38.411 1.536-21.51 0-38.411-3.073-61.458-6.146-7.682-1.536-18.437-3.073-24.583-6.146-4.609-1.536-3.073-12.292-3.073-13.828 0-44.557 44.557-107.552 98.333-119.844 4.609-1.536 13.828-1.536 19.974-3.073l41.484-1.536c-13.828-10.755-36.875-46.094-36.875-59.922v-29.193c13.828-58.385 62.995-82.969 106.016-82.969 1.536 0 41.484 0 41.484 12.292 0 6.146-30.729 19.974-30.729 41.484 0 1.536 6.146 32.266 16.901 32.266 3.073 0-1.536-3.073 3.073-3.073 3.073 0 32.266 10.755 36.875 10.755h12.292l3.073-3.073c-19.974-16.901-30.729-36.875-36.875-53.776 12.292 7.682 18.438 9.219 29.193 9.219 27.656 0 46.094-15.365 78.359-29.193 24.583-10.755 52.24-13.828 78.359-18.437-12.292-9.219-24.583-16.901-36.875-23.047l38.411-1.536c7.68 1.537 15.362 4.61 23.044 6.146z" p-id="2967"></path></svg>
|
After Width: | Height: | Size: 2.0 KiB |
425
web/src/Main.vue
425
web/src/Main.vue
@ -1,147 +1,360 @@
|
||||
<script>
|
||||
import {ArrowDown, Grid} from '@element-plus/icons-vue'
|
||||
import FileIcon from "./components/FileIcon.vue";
|
||||
import {dayjs, ElMessage} from 'element-plus'
|
||||
import {dayjs, ElMessage, ElMessageBox} from 'element-plus'
|
||||
import api from "./service/api";
|
||||
import qs from "qs";
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentActiveIndex: "all",
|
||||
display: 'block',
|
||||
fileData: []
|
||||
/**
|
||||
* @var {FileItem[]}
|
||||
*/
|
||||
fileData: [],
|
||||
currentPath: '/',
|
||||
fileMenuOption: [
|
||||
{
|
||||
name: '打开',
|
||||
slug: 'open',
|
||||
},
|
||||
{
|
||||
name: '下载',
|
||||
slug: 'download',
|
||||
},
|
||||
{
|
||||
name: '分享',
|
||||
slug: 'share',
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: '复制',
|
||||
slug: 'copy',
|
||||
},
|
||||
{
|
||||
name: '移动',
|
||||
slug: 'move',
|
||||
},
|
||||
{
|
||||
name: '重命名',
|
||||
slug: 'rename',
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
slug: 'delete',
|
||||
},
|
||||
],
|
||||
createFolder: {
|
||||
visible: false,
|
||||
value: '',
|
||||
loading: false,
|
||||
message: ''
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {FileIcon},
|
||||
computed: {
|
||||
currentPathList() {
|
||||
if (this.currentPath == '/') return []
|
||||
const arr = this.currentPath.replace(/^\//, '').split('/');
|
||||
const pathList = [], last = arr.pop();
|
||||
let prefix = '';
|
||||
arr.forEach(name => {
|
||||
prefix += '/' + name;
|
||||
pathList.push({name: name, path: prefix})
|
||||
})
|
||||
pathList.push({name: last, path: null})
|
||||
return pathList;
|
||||
}
|
||||
},
|
||||
components: {FileIcon, ArrowDown, Grid},
|
||||
mounted() {
|
||||
// window.addEventListener('popstate',()=>console.log(location.href))
|
||||
window.addEventListener('hashchange', this.handlePathChange) // 添加监听
|
||||
this.handlePathChange();
|
||||
window.addEventListener('hashchange', this.handleHashChange) // 添加监听
|
||||
this.handleHashChange();
|
||||
},
|
||||
unmounted() {
|
||||
window.removeEventListener('hashchange', this.handlePathChange); // 取消监听
|
||||
window.removeEventListener('hashchange', this.handleHashChange); // 取消监听
|
||||
},
|
||||
methods: {
|
||||
// 加载目录下的所有文件
|
||||
async loadFileByPath(path = '/') {
|
||||
this.currentPath = path // 保存了当前的请求路径
|
||||
// 调用接口
|
||||
try {
|
||||
this.fileData = [];
|
||||
const list = await api.folder.list(path);
|
||||
this.fileData = list;
|
||||
} catch (e) {
|
||||
ElMessage.error(e.message)
|
||||
}
|
||||
},
|
||||
handlePathChange() {
|
||||
// 获取获取当前目录路径
|
||||
getCurrentPath() {
|
||||
const hash = location.hash;
|
||||
const params = qs.parse(hash.substr(2))
|
||||
this.loadFileByPath(params.path || '/') // 有参数则使用 无参数则根目录
|
||||
return params.path || '/';
|
||||
},
|
||||
formatDate(time) {
|
||||
return dayjs(time).format('MM-DD');
|
||||
//记载所有的子文件
|
||||
handleHashChange() {
|
||||
this.loadFileByPath(this.getCurrentPath()) // 有参数则使用 无参数则根目录
|
||||
},
|
||||
showFile(file) {
|
||||
console.log(file)
|
||||
this.loadFileByPath(file.path)
|
||||
// if (file.type != 'folder') {
|
||||
// ElMessage('暂不支持此文件的预览');
|
||||
// return;
|
||||
// }
|
||||
formatDate(time, format = 'MM-DD') {
|
||||
return dayjs(time).format(format);
|
||||
},
|
||||
formatSize(a, b = 2) {
|
||||
if (0 == a) return "0 B";
|
||||
let c = 1024, d = b || 2, e = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
|
||||
f = Math.floor(Math.log(a) / Math.log(c));
|
||||
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + " " + e[f];
|
||||
},
|
||||
showFile(file, e) {
|
||||
console.log(e)
|
||||
if (file.type != 'folder') {
|
||||
console.log(this.$refs.fileIcon)
|
||||
this.$refs.fileIcon?.showPreview(file);
|
||||
return;
|
||||
}
|
||||
// this.loadFileByPath(file.path)
|
||||
// console.log(file)
|
||||
// window.history.pushState({},null,'/show?path=' + file.name)
|
||||
location.hash = '?path=' + file.path
|
||||
},
|
||||
fileMenuClick(e) {
|
||||
window.alert(JSON.stringify(e));
|
||||
},
|
||||
createFolderClick() {
|
||||
ElMessageBox.prompt(
|
||||
'', '新建文件夹',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
closeOnClickModal: false,
|
||||
// inputPattern:/[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
|
||||
inputValidator(value) {
|
||||
return !!value;
|
||||
},
|
||||
inputErrorMessage: '必须填写文件夹名称',
|
||||
inputPlaceholder: '请输入文件夹名称'
|
||||
})
|
||||
.then(({value}) => {
|
||||
// 此处开始进行创建
|
||||
})
|
||||
.catch()
|
||||
},
|
||||
async handleCreateFolder() {
|
||||
this.createFolder.message = ''
|
||||
if (!this.createFolder.value) {
|
||||
this.createFolder.message = '请填写文件夹名称'
|
||||
return;
|
||||
}
|
||||
// 开始新建
|
||||
this.createFolder.loading = true;
|
||||
try {
|
||||
await api.folder.create(this.getCurrentPath(),this.createFolder.value);
|
||||
this.createFolder.visible = false;
|
||||
this.handleHashChange();
|
||||
} catch (e) {
|
||||
this.createFolder.message = e.message;
|
||||
}finally {
|
||||
this.createFolder.loading = false // 取消loading
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<el-container>
|
||||
<el-aside class="pan-left-aside">
|
||||
<div class="logo-block">牛牛的网盘</div>
|
||||
<el-menu :default-active="currentActiveIndex" class="pan-left-menu">
|
||||
<el-menu-item index="all">
|
||||
<span>所有文件</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="最近上传">
|
||||
<span>所有文件</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="picture">
|
||||
<span>我的图片</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="document">
|
||||
<span>我的文档</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="video">
|
||||
<span>我的视频</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<div class="main-pan-app" @contextmenu="$refs.fileMenu.hideContextMenu">
|
||||
<el-container>
|
||||
<el-header class="pan-header">
|
||||
<ul class="pan-header-user-right">
|
||||
<li>帮助</li>
|
||||
<li>
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
张三
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down/>
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>修改资料</el-dropdown-item>
|
||||
<el-dropdown-item>登录日志查看</el-dropdown-item>
|
||||
<el-dropdown-item>退出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<el-button @click="display = (display == 'block' ? 'list' : 'block')">
|
||||
{{ (display == 'block' ? 'list' : 'block') }}
|
||||
</el-button>
|
||||
<div class="display-type-list" v-if="display == 'list'">
|
||||
<el-table :data="fileData" style="width: 100%">
|
||||
<el-table-column type="selection"/>
|
||||
<el-table-column label="名称">
|
||||
<!-- 自定义单元格内容 -->
|
||||
<template #default="file">
|
||||
<div>
|
||||
<FileIcon :file="file.row" style="width:20px"/>
|
||||
<span>{{ file.row.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="200"/>
|
||||
<el-table-column prop="size" label="大小" width="200"/>
|
||||
<el-table-column prop="createTime" label="创建时间" width="200"/>
|
||||
</el-table>
|
||||
<el-aside class="pan-left-aside">
|
||||
<div class="logo-block">
|
||||
<svg class="logo-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="1000" height="1000">
|
||||
<path
|
||||
d="M549.766 97.925c19.974 4.609 50.703 35.339 62.995 55.312 35.339-13.828 36.875 41.484 46.094 55.312 23.047-16.901 46.094-35.339 46.094-55.312 0-21.51-30.729-35.339-30.729-41.484 0-12.292 38.411-12.292 41.484-12.292 50.703 0 106.016 39.948 106.016 96.797 0 27.656-9.219 41.484-33.802 70.677h32.266c21.51 0 27.656-3.073 55.312 7.682C923.125 294.591 960 348.367 960 389.852c0 3.073 0 9.219-1.536 13.828-4.609 3.073-12.292 3.073-16.901 4.609-15.365 1.536-32.266 6.146-47.63 7.682-47.63 0-50.703 0-53.776-1.536-1.536 1.536-1.536 0-1.536 4.609 0 3.073 7.682 44.557 10.755 67.604 9.219 56.849 12.292 115.234 19.974 173.62 1.536 7.682 7.682 15.365 9.219 23.047 3.073 13.828 6.146 27.656 6.146 39.948 0 153.646-245.833 208.958-321.119 208.958h-86.042c-115.234-9.219-248.906-52.24-301.145-138.281-4.609-7.682-18.437-39.948-18.437-50.703v-36.875c3.073-16.901 7.682-33.802 21.51-50.703v-84.505l12.292-132.135c-12.292 1.536-33.802 1.536-38.411 1.536-21.51 0-38.411-3.073-61.458-6.146-7.682-1.536-18.437-3.073-24.583-6.146-4.609-1.536-3.073-12.292-3.073-13.828 0-44.557 44.557-107.552 98.333-119.844 4.609-1.536 13.828-1.536 19.974-3.073l41.484-1.536c-13.828-10.755-36.875-46.094-36.875-59.922v-29.193c13.828-58.385 62.995-82.969 106.016-82.969 1.536 0 41.484 0 41.484 12.292 0 6.146-30.729 19.974-30.729 41.484 0 1.536 6.146 32.266 16.901 32.266 3.073 0-1.536-3.073 3.073-3.073 3.073 0 32.266 10.755 36.875 10.755h12.292l3.073-3.073c-19.974-16.901-30.729-36.875-36.875-53.776 12.292 7.682 18.438 9.219 29.193 9.219 27.656 0 46.094-15.365 78.359-29.193 24.583-10.755 52.24-13.828 78.359-18.437-12.292-9.219-24.583-16.901-36.875-23.047l38.411-1.536c7.68 1.537 15.362 4.61 23.044 6.146z"
|
||||
p-id="2967"></path>
|
||||
</svg>
|
||||
<span>牛牛的网盘</span>
|
||||
</div>
|
||||
<div class="display-type-block" v-else>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" :xl="2" v-for="(file, index) in fileData" :key="index">
|
||||
<div class="file-block-item" @click="showFile(file)">
|
||||
<div>
|
||||
<FileIcon :file="file" style="width:90%"/>
|
||||
<el-menu :default-active="currentActiveIndex" class="pan-left-menu">
|
||||
<el-menu-item index="all">
|
||||
<span>所有文件</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="最近上传">
|
||||
<span>所有文件</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="picture">
|
||||
<span>我的图片</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="document">
|
||||
<span>我的文档</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="video">
|
||||
<span>我的视频</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header class="pan-header">
|
||||
<ul class="pan-header-user-right">
|
||||
<li>帮助</li>
|
||||
<li>
|
||||
<el-dropdown>
|
||||
<div class="el-dropdown-link">
|
||||
<el-avatar class="avatar" :size="30"
|
||||
src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png"/>
|
||||
<span class="username">张三</span>
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="file-name">{{ file.name }}</div>
|
||||
<div class="file-info">{{ formatDate(file.createTime) }}</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>修改资料</el-dropdown-item>
|
||||
<el-dropdown-item>登录日志查看</el-dropdown-item>
|
||||
<el-dropdown-item>退出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<div class="d-flex">
|
||||
<div class="left-tool-bar">
|
||||
<el-dropdown>
|
||||
<el-button size="default" round>上传</el-button>
|
||||
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>上传文件</el-dropdown-item>
|
||||
<el-dropdown-item>上传文件夹</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-button @click="createFolder.visible = true" style="margin-left: 10px" size="default"
|
||||
round
|
||||
type="primary">新建文件夹
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;padding: 10px 0;line-height: 30px;">
|
||||
<!-- 当前路径 -->
|
||||
<div style="flex:1;display: flex">
|
||||
<div v-if="currentPath === '/'" style="font-weight: 700;font-size: 14px;">全部文件</div>
|
||||
<div v-else>
|
||||
<el-breadcrumb separator="/" style="line-height: 30px">
|
||||
<el-breadcrumb-item>
|
||||
<a href="#?path=/">全部文件</a>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-for="p in currentPathList" :key="p.path">
|
||||
<a v-if="p.path" :href="'#?path=' + p.path">{{ p.name }}</a>
|
||||
<span v-else>{{ p.name }}</span>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
|
||||
<div class="d-flex">
|
||||
<span
|
||||
style="margin-right: 10px;color:#999;font-size: 12px;">已全部加载,共{{
|
||||
fileData.length
|
||||
}}个</span>
|
||||
<el-radio-group v-model="display" size="small">
|
||||
<el-radio-button label="block">
|
||||
<el-icon :size="16">
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M384 128H213.333333a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h170.666667a85.333333 85.333333 0 0 0 85.333333-85.333333V213.333333a85.333333 85.333333 0 0 0-85.333333-85.333333zM810.666667 128h-170.666667a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h170.666667a85.333333 85.333333 0 0 0 85.333333-85.333333V213.333333a85.333333 85.333333 0 0 0-85.333333-85.333333zM384 554.666667H213.333333a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h170.666667a85.333333 85.333333 0 0 0 85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 0-85.333333-85.333333zM810.666667 554.666667h-170.666667a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h170.666667a85.333333 85.333333 0 0 0 85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 0-85.333333-85.333333z"
|
||||
p-id="2910"></path>
|
||||
</svg>
|
||||
</el-icon>
|
||||
</el-radio-button>
|
||||
<el-radio-button label="list">
|
||||
<el-icon :size="16">
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M146.285714 749.714286v109.714285c0 9.728-8.557714 18.285714-18.285714 18.285715h-109.714286a18.797714 18.797714 0 0 1-18.285714-18.285715v-109.714285c0-9.728 8.557714-18.285714 18.285714-18.285715h109.714286c9.728 0 18.285714 8.557714 18.285714 18.285715z m0-219.428572v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-109.714286a18.797714 18.797714 0 0 1-18.285714-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285714-18.285714h109.714286c9.728 0 18.285714 8.557714 18.285714 18.285714z m0-219.428571v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-109.714286a18.797714 18.797714 0 0 1-18.285714-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285714-18.285714h109.714286c9.728 0 18.285714 8.557714 18.285714 18.285714z m877.714286 438.857143v109.714285c0 9.728-8.557714 18.285714-18.285714 18.285715h-768a18.797714 18.797714 0 0 1-18.285715-18.285715v-109.714285c0-9.728 8.557714-18.285714 18.285715-18.285715h768c9.728 0 18.285714 8.557714 18.285714 18.285715zM146.285714 91.428571v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-109.714286a18.797714 18.797714 0 0 1-18.285714-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285714-18.285714h109.714286c9.728 0 18.285714 8.557714 18.285714 18.285714z m877.714286 438.857143v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-768a18.797714 18.797714 0 0 1-18.285715-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285715-18.285714h768c9.728 0 18.285714 8.557714 18.285714 18.285714z m0-219.428571v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-768a18.797714 18.797714 0 0 1-18.285715-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285715-18.285714h768c9.728 0 18.285714 8.557714 18.285714 18.285714z m0-219.428572v109.714286c0 9.728-8.557714 18.285714-18.285714 18.285714h-768a18.797714 18.797714 0 0 1-18.285715-18.285714v-109.714286c0-9.728 8.557714-18.285714 18.285715-18.285714h768c9.728 0 18.285714 8.557714 18.285714 18.285714z"></path>
|
||||
</svg>
|
||||
</el-icon>
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="display-type-list" v-if="display == 'list'">
|
||||
<el-table :data="fileData" style="width: 100%">
|
||||
<el-table-column type="selection"/>
|
||||
<el-table-column label="名称">
|
||||
<!-- 自定义单元格内容 -->
|
||||
<template #default="file">
|
||||
<div class="list-file-info">
|
||||
<FileIcon class="list-file-icon" :file="file.row"
|
||||
:ext="file.row.type"/>
|
||||
<span class="list-file-name">{{ file.row.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="200"/>
|
||||
<el-table-column prop="size" label="大小" width="200"/>
|
||||
<el-table-column label="创建时间" width="200">
|
||||
<template #default="file">
|
||||
<span class="list-file-time">{{ formatDate(file.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="display-type-block" v-else>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" :xl="2" v-for="(file, index) in fileData"
|
||||
:key="index">
|
||||
<div class="file-block-item" @click="showFile(file,$event)"
|
||||
@contextmenu.prevent.stop="$refs.fileMenu.showMenu($event,file)">
|
||||
<div class="file-image">
|
||||
<FileIcon :file="file" style="width:90%"/>
|
||||
</div>
|
||||
<div class="file-name">{{ file.name }}</div>
|
||||
<div class="file-info">
|
||||
{{
|
||||
file.type == 'folder' ? formatDate(file.createTime) : formatSize(file.size)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<!-- <context-menu class="file-cxt-menu" element-id="myMenu1" ref="fileMenu" :options="fileMenuOption"-->
|
||||
<!-- @option-clicked="fileMenuClick"/>-->
|
||||
<!-- 新建目录 -->
|
||||
<el-dialog v-model="createFolder.visible" title="新建文件夹" width="500px">
|
||||
<div>
|
||||
<el-input placeholder="请输入文件夹名称" v-model="createFolder.value"/>
|
||||
<div style="color: red;height: 30px;line-height: 30px;">{{ createFolder.message }}</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<!-- 将此模板的内容指定插入到footer的位置-->
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="createFolder.visible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="createFolder.loading" @click="handleCreateFolder">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less">
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.logo-block {
|
||||
line-height: 60px;
|
||||
@ -165,14 +378,6 @@ export default {
|
||||
background-color: #dedede;
|
||||
}
|
||||
|
||||
.pan-header-user-right {
|
||||
float: right;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.pan-header-user-right li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
// 平铺显示
|
||||
.file-block-item {
|
||||
@ -186,6 +391,16 @@ export default {
|
||||
background-color: var(--el-color-primary-light-8);
|
||||
}
|
||||
|
||||
.file-image {
|
||||
height: 130px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> span {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
1
web/src/assets/icons/icon_list.svg
Normal file
1
web/src/assets/icons/icon_list.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2063" width="1000" height="1000"><path d="M128 469.333333h85.333333v85.333334H128zM128 298.666667h85.333333v85.333333H128zM128 640h85.333333v85.333333H128zM128 128h85.333333v85.333333H128zM128 810.666667h85.333333v85.333333H128z" fill="#2196F3" p-id="2064"></path><path d="M298.666667 469.333333h597.333333v85.333334H298.666667zM298.666667 298.666667h597.333333v85.333333H298.666667zM298.666667 640h597.333333v85.333333H298.666667zM298.666667 128h597.333333v85.333333H298.666667zM298.666667 810.666667h597.333333v85.333333H298.666667z" fill="#2196F3" p-id="2065"></path></svg>
|
After Width: | Height: | Size: 673 B |
93
web/src/assets/main.less
Normal file
93
web/src/assets/main.less
Normal file
@ -0,0 +1,93 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
|
||||
::-webkit-scrollbar
|
||||
{
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
/*定义滚动条轨道 内阴影+圆角*/
|
||||
::-webkit-scrollbar-track
|
||||
{
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
border-radius: 2px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
/*定义滑块 内阴影+圆角*/
|
||||
::-webkit-scrollbar-thumb
|
||||
{
|
||||
border-radius: 2px;
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.d-flex{
|
||||
display: flex;
|
||||
}
|
||||
.logo-icon{
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
fill: #fff;
|
||||
vertical-align: middle;
|
||||
transform: translate(0px, -2px);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.pan-header-user-right {
|
||||
float: right;
|
||||
list-style: none;
|
||||
li {
|
||||
float: left;
|
||||
line-height: 60px;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.el-dropdown-link{
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
display: inline-block;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.avatar{
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.list-file-icon{
|
||||
width: 20px;
|
||||
img{
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.list-file-name{
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.file-cxt-menu{
|
||||
font-size: 12px;
|
||||
.vue-simple-context-menu{
|
||||
min-width: 130px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.vue-simple-context-menu__item{
|
||||
color:#333;
|
||||
&:hover{
|
||||
background-color: var(--el-fill-color);
|
||||
color:#333;
|
||||
}
|
||||
}
|
||||
.vue-simple-context-menu__divider{
|
||||
height: 1px;
|
||||
background-color: var(--el-border-color-lighter);
|
||||
padding: 2px 0;
|
||||
}
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<span style="display:inline-block">
|
||||
<img class="file-icon" :src="currentSrc" />
|
||||
<el-image v-if="type == 'picture'"
|
||||
:src="currentSrc" :previewSrcList="[currentSrc]"
|
||||
:initial-index="4" fit="cover" :hide-on-click-modal="true"
|
||||
/>
|
||||
<img v-else class="file-icon" :src="currentSrc"/>
|
||||
<!-- <img class="file-icon" :src="file.row.path" v-if="file.row.type == 'png'" /> -->
|
||||
</span>
|
||||
</template>
|
||||
@ -9,32 +13,46 @@
|
||||
import FolderIcon from '../assets/icons/folder.svg'
|
||||
import UnknownIcon from '../assets/icons/icon.svg'
|
||||
import ExeIcon from '../assets/icons/exe.svg'
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
export default {
|
||||
// 定义组件所需的属性
|
||||
props: {
|
||||
file: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
ext: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentSrc: FolderIcon
|
||||
currentSrc: FolderIcon,
|
||||
type: 'icon'
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
const type = this.file.type?.toLowerCase(); // 拿到文件类型
|
||||
if(['png','jpg','jpeg','gif','webp'].includes(type)){
|
||||
mounted() {
|
||||
const type = this.file.type.toLowerCase(); // 拿到文件类型
|
||||
if (['png', 'jpg', 'jpeg', 'gif', 'webp'].includes(type)) {
|
||||
this.currentSrc = this.file.path || UnknownIcon; // 图片
|
||||
}else if(type == 'exe') {
|
||||
this.type = 'picture';
|
||||
} else if (type == 'exe') {
|
||||
this.currentSrc = ExeIcon; // 图片
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showPreview(file) {
|
||||
//
|
||||
ElMessage('暂不支持此文件的预览');
|
||||
console.log(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.file-icon{
|
||||
.file-icon {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -1,11 +1,16 @@
|
||||
import { createApp } from "vue";
|
||||
import {createApp} from "vue";
|
||||
|
||||
// 导入element-plus的依赖
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/dist/index.css";
|
||||
import './assets/main.less'
|
||||
|
||||
import ContextMenu from 'vue-simple-context-menu'
|
||||
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';
|
||||
// 导入入口组件
|
||||
import App from "./Main.vue";
|
||||
|
||||
createApp(App)
|
||||
.use(ElementPlus)
|
||||
const app = createApp(App)
|
||||
app.component('ContextMenu', ContextMenu);
|
||||
app.use(ElementPlus)
|
||||
.mount("#app");
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
const API_PATH = "http://localhost:8080"
|
||||
|
||||
/**
|
||||
@ -64,6 +63,9 @@ export default {
|
||||
*/
|
||||
list(folderPath = '/') {
|
||||
return request(`/api/folder/list`, 'GET', {folderPath})
|
||||
},
|
||||
create(parent, name) {
|
||||
return request(`/api/folder/create`, 'POST', {parent, name});
|
||||
}
|
||||
}
|
||||
}
|
11
web/src/service/type.d.ts
vendored
11
web/src/service/type.d.ts
vendored
@ -1 +1,10 @@
|
||||
declare type ApiResult = { code: number, message: string, data: any }
|
||||
declare type ApiResult = { code: number, message: string, data: any }
|
||||
declare type FileItem = {
|
||||
createTime: string,
|
||||
id: number,
|
||||
name: string,
|
||||
path: string,
|
||||
size: number,
|
||||
type: 'folder' | string,
|
||||
updateTime: string
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user