添加vue-router
This commit is contained in:
parent
26a2be3751
commit
0f7149f1b0
@ -86,6 +86,12 @@
|
|||||||
<artifactId>springfox-boot-starter</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring</artifactId>
|
||||||
|
<version>1.9.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>org.springframework.amqp</groupId>-->
|
<!-- <groupId>org.springframework.amqp</groupId>-->
|
||||||
<!-- <artifactId>spring-rabbit-test</artifactId>-->
|
<!-- <artifactId>spring-rabbit-test</artifactId>-->
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package xyz.longicorn.driver.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class AuthFilter extends BasicHttpAuthenticationFilter {
|
||||||
|
|
||||||
|
//判断是否允许通过
|
||||||
|
@Override
|
||||||
|
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||||
|
return super.isAccessAllowed(request, response, mappedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//是否允许登录
|
||||||
|
@Override
|
||||||
|
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
|
||||||
|
return super.isLoginAttempt(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建shiro token
|
||||||
|
@Override
|
||||||
|
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
|
||||||
|
return super.createToken(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
//isAccessAllowed为false时调用,验证失败
|
||||||
|
@Override
|
||||||
|
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
||||||
|
this.sendChallenge(request, response);
|
||||||
|
responseError(response, "he he !");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//shiro验证成功调用
|
||||||
|
@Override
|
||||||
|
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
|
||||||
|
return super.onLoginSuccess(token, subject, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
|
||||||
|
if (!isLoginAttempt(request, response)) {
|
||||||
|
responseError(response, "verify token failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.preHandle(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCors(ServletResponse response) {
|
||||||
|
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||||
|
// httpServletResponse.addHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
httpServletResponse.addHeader("Access-Control-Allow-Methods", "*");
|
||||||
|
httpServletResponse.addHeader("Access-Control-Allow-Headers", "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void responseError(ServletResponse response, Object msg) {
|
||||||
|
setCors(response);
|
||||||
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
|
httpResponse.setStatus(401);
|
||||||
|
httpResponse.setCharacterEncoding("UTF-8");
|
||||||
|
httpResponse.setContentType("application/json;charset=UTF-8");
|
||||||
|
try {
|
||||||
|
String rj = msg instanceof String ? (String) msg : new ObjectMapper().writeValueAsString(msg);
|
||||||
|
httpResponse.getWriter().append(rj);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package xyz.longicorn.driver.config;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MybatisPlusConfig {
|
||||||
|
@Bean
|
||||||
|
public MybatisPlusInterceptor paginationInterceptor() {
|
||||||
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||||
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
|
||||||
|
return interceptor;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package xyz.longicorn.driver.config;
|
||||||
|
|
||||||
|
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
||||||
|
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
||||||
|
import org.apache.shiro.mgt.SecurityManager;
|
||||||
|
import org.apache.shiro.realm.Realm;
|
||||||
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||||
|
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||||
|
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ShiroConfig {
|
||||||
|
@Autowired
|
||||||
|
private UserRealm userRealm;
|
||||||
|
|
||||||
|
//ShiroFilter过滤所有请求
|
||||||
|
@Bean(name = "shiroFilterFactoryBean")
|
||||||
|
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
|
||||||
|
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||||
|
Map<String, Filter> filterMap = new LinkedHashMap<>();
|
||||||
|
filterMap.put("auth", new AuthFilter()); // 设置验证过滤器
|
||||||
|
|
||||||
|
shiroFilterFactoryBean.setFilters(filterMap);
|
||||||
|
//给ShiroFilter配置安全管理器
|
||||||
|
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
|
||||||
|
//配置系统公共资源
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
//匿名资源 一定是在受限资源上面
|
||||||
|
map.put("/api/**", "anon");
|
||||||
|
//受限资源需要认证和授权
|
||||||
|
map.put("/**", "auth");
|
||||||
|
|
||||||
|
// 设置认证界面路径
|
||||||
|
// shiroFilterFactoryBean.setLoginUrl("/user/login");
|
||||||
|
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
|
||||||
|
return shiroFilterFactoryBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm) {
|
||||||
|
//设置自定义Realm
|
||||||
|
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||||
|
securityManager.setRealm(userRealm);
|
||||||
|
//关闭shiro自带的session
|
||||||
|
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
|
||||||
|
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
|
||||||
|
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
|
||||||
|
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
|
||||||
|
securityManager.setSubjectDAO(subjectDAO);
|
||||||
|
return securityManager;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package xyz.longicorn.driver.config;
|
||||||
|
|
||||||
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.AuthenticationInfo;
|
||||||
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||||
|
import org.apache.shiro.authz.AuthorizationInfo;
|
||||||
|
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||||
|
import org.apache.shiro.realm.AuthorizingRealm;
|
||||||
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserRealm extends AuthorizingRealm {
|
||||||
|
// 处理授权 获取凭证对该凭证赋权
|
||||||
|
@Override
|
||||||
|
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
|
||||||
|
//获取身份信息
|
||||||
|
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
|
||||||
|
System.out.println("用户凭证:" + primaryPrincipal);
|
||||||
|
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||||
|
|
||||||
|
Set<String> roleSet = new HashSet<>(); // 角色列表
|
||||||
|
info.setRoles(roleSet);
|
||||||
|
|
||||||
|
Set<String> permsSet = new HashSet<>(); // 权限列表
|
||||||
|
info.setStringPermissions(permsSet);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理认证 验证请求的凭证是否合法
|
||||||
|
@Override
|
||||||
|
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
|
||||||
|
throws AuthenticationException {
|
||||||
|
String credentials = (String) authenticationToken.getCredentials(); // 获取凭证
|
||||||
|
System.out.println("用户凭证:" + credentials);
|
||||||
|
//TODO 完成token的验证 返回数据库信息
|
||||||
|
return new SimpleAuthenticationInfo(credentials, credentials, getName());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package xyz.longicorn.driver.controller;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import xyz.longicorn.driver.dto.ApiResult;
|
||||||
|
import xyz.longicorn.driver.dto.FileItem;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/file")
|
||||||
|
public class FileController {
|
||||||
|
@PostMapping("/rename")
|
||||||
|
public ApiResult rename(@Validated @RequestBody FileItem item) {
|
||||||
|
return ApiResult.success(null);
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import xyz.longicorn.driver.pojo.FileInfo;
|
import xyz.longicorn.driver.pojo.FileInfo;
|
||||||
import xyz.longicorn.driver.service.FileService;
|
import xyz.longicorn.driver.service.FileService;
|
||||||
import xyz.longicorn.driver.util.ImageUtils;
|
import xyz.longicorn.driver.util.FileUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
@ -28,7 +28,7 @@ public class PreviewController {
|
|||||||
if (path == null) return;
|
if (path == null) return;
|
||||||
// 设置输出头
|
// 设置输出头
|
||||||
resp.addHeader("Content-Type", "image/jpeg");
|
resp.addHeader("Content-Type", "image/jpeg");
|
||||||
ImageUtils.getPreview(path, resp.getOutputStream());
|
FileUtils.getImagePreview(path, resp.getOutputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成预览图
|
// 生成预览图
|
||||||
@ -64,7 +64,7 @@ public class PreviewController {
|
|||||||
resp.getWriter().println("file not found!");
|
resp.getWriter().println("file not found!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!ImageUtils.isImage(info.getType())) { //判断是否是图片
|
if (!FileUtils.isImage(info.getType())) { //判断是否是图片
|
||||||
resp.getWriter().println("file can not preview!");
|
resp.getWriter().println("file can not preview!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package xyz.longicorn.driver.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import xyz.longicorn.driver.dto.ApiResult;
|
||||||
|
import xyz.longicorn.driver.pojo.ShareInfo;
|
||||||
|
import xyz.longicorn.driver.service.ShareService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/share")
|
||||||
|
public class ShareController {
|
||||||
|
@Resource
|
||||||
|
private ShareService shareService;
|
||||||
|
/**
|
||||||
|
* 创建分享
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@RequestMapping("/create")
|
||||||
|
public ApiResult create(ShareInfo info){
|
||||||
|
return ApiResult.success(shareService.create(info));
|
||||||
|
}
|
||||||
|
@RequestMapping("/info")
|
||||||
|
public ApiResult info(String id){
|
||||||
|
return ApiResult.success(shareService.getById(id));
|
||||||
|
}
|
||||||
|
public ApiResult list(ShareInfo info){
|
||||||
|
return ApiResult.success(shareService.create(info));
|
||||||
|
}
|
||||||
|
}
|
@ -7,10 +7,12 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import xyz.longicorn.driver.config.BizException;
|
import xyz.longicorn.driver.config.BizException;
|
||||||
import xyz.longicorn.driver.dto.ApiResult;
|
import xyz.longicorn.driver.dto.ApiResult;
|
||||||
import xyz.longicorn.driver.dto.FastUploadFile;
|
import xyz.longicorn.driver.dto.FastUploadFile;
|
||||||
|
import xyz.longicorn.driver.pojo.enums.Category;
|
||||||
import xyz.longicorn.driver.pojo.FileInfo;
|
import xyz.longicorn.driver.pojo.FileInfo;
|
||||||
import xyz.longicorn.driver.pojo.FolderInfo;
|
import xyz.longicorn.driver.pojo.FolderInfo;
|
||||||
import xyz.longicorn.driver.service.FileService;
|
import xyz.longicorn.driver.service.FileService;
|
||||||
import xyz.longicorn.driver.service.FolderService;
|
import xyz.longicorn.driver.service.FolderService;
|
||||||
|
import xyz.longicorn.driver.util.FileUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -26,15 +28,28 @@ public class UploadController {
|
|||||||
private FileService fileService;
|
private FileService fileService;
|
||||||
@Resource
|
@Resource
|
||||||
private FolderService folderService;
|
private FolderService folderService;
|
||||||
|
|
||||||
private final static Map<String, String> FILE_MIME_TYPE = new HashMap<>();
|
private final static Map<String, String> FILE_MIME_TYPE = new HashMap<>();
|
||||||
|
|
||||||
public UploadController() {
|
public UploadController() {
|
||||||
|
FILE_MIME_TYPE.put("text/plain", "txt");
|
||||||
FILE_MIME_TYPE.put("image/png", "png");
|
FILE_MIME_TYPE.put("image/png", "png");
|
||||||
FILE_MIME_TYPE.put("image/jpeg", "jpg");
|
FILE_MIME_TYPE.put("image/jpeg", "jpg");
|
||||||
FILE_MIME_TYPE.put("image/jpg", "jpg");
|
FILE_MIME_TYPE.put("image/jpg", "jpg");
|
||||||
FILE_MIME_TYPE.put("image/bmp", "bmp");
|
FILE_MIME_TYPE.put("image/bmp", "bmp");
|
||||||
FILE_MIME_TYPE.put("image/webp", "webp");
|
FILE_MIME_TYPE.put("image/webp", "webp");
|
||||||
FILE_MIME_TYPE.put("image/gif", "gif");
|
FILE_MIME_TYPE.put("image/gif", "gif");
|
||||||
|
FILE_MIME_TYPE.put("image/svg+xml", "svg");
|
||||||
|
FILE_MIME_TYPE.put("audio/mpeg", "mp3");
|
||||||
|
FILE_MIME_TYPE.put("video/mp4", "mp4");
|
||||||
|
FILE_MIME_TYPE.put("application/msword", "doc");
|
||||||
|
FILE_MIME_TYPE.put("application/pdf", "pdf");
|
||||||
|
FILE_MIME_TYPE.put("application/vnd.ms-excel", "xls");
|
||||||
|
FILE_MIME_TYPE.put("application/vnd.ms-powerpoint", "ppt");
|
||||||
|
FILE_MIME_TYPE.put("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx");
|
||||||
|
FILE_MIME_TYPE.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx");
|
||||||
|
FILE_MIME_TYPE.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@ -59,7 +74,22 @@ public class UploadController {
|
|||||||
fileInfo.setHash(md5);//
|
fileInfo.setHash(md5);//
|
||||||
fileInfo.setName(file.getOriginalFilename());
|
fileInfo.setName(file.getOriginalFilename());
|
||||||
fileInfo.setSize(file.getSize());
|
fileInfo.setSize(file.getSize());
|
||||||
fileInfo.setType(getType(file.getContentType()));
|
String type = getType(file.getContentType());// 获取文件的扩展名类型
|
||||||
|
fileInfo.setType(type);
|
||||||
|
|
||||||
|
if (FileUtils.isImage(type)) {
|
||||||
|
fileInfo.setCategory(Category.Image);
|
||||||
|
} else if (FileUtils.isDocument(type)) {
|
||||||
|
fileInfo.setCategory(Category.Document);
|
||||||
|
} else if (FileUtils.isVideo(type)) {
|
||||||
|
fileInfo.setCategory(Category.Video);
|
||||||
|
} else if (FileUtils.isAudio(type)) {
|
||||||
|
fileInfo.setCategory(Category.Audio);
|
||||||
|
} else {
|
||||||
|
fileInfo.setCategory(Category.Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (f != null) { // 系统已经存在了该文件
|
if (f != null) { // 系统已经存在了该文件
|
||||||
// 不保存上传文件 直接copy数据
|
// 不保存上传文件 直接copy数据
|
||||||
fileInfo.setPath(f.getPath());
|
fileInfo.setPath(f.getPath());
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package xyz.longicorn.driver.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xyz.longicorn.driver.pojo.ShareInfo;
|
||||||
|
@Mapper
|
||||||
|
public interface ShareInfoMapper extends BaseMapper<ShareInfo> {
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package xyz.longicorn.driver.dto;
|
||||||
|
|
||||||
|
public class ShareDto {
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,11 @@
|
|||||||
package xyz.longicorn.driver.pojo;
|
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.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
import xyz.longicorn.driver.pojo.enums.Category;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -18,12 +16,16 @@ import java.util.Date;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class FileInfo implements Serializable {
|
public class FileInfo implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
private Integer uid;
|
private Integer uid;
|
||||||
private String name;
|
private String name;
|
||||||
private String hash;
|
private String hash;
|
||||||
private Long folderId;
|
private Long folderId;
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
private Category category;
|
||||||
private Long size;
|
private Long size;
|
||||||
private String path;
|
private String path;
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package xyz.longicorn.driver.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xyz.longicorn.driver.dao.ShareInfoMapper;
|
||||||
|
import xyz.longicorn.driver.pojo.ShareInfo;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ShareService extends ServiceImpl<ShareInfoMapper, ShareInfo> {
|
||||||
|
public ShareInfo create(ShareInfo info) {
|
||||||
|
this.save(info);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package xyz.longicorn.driver.util;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import net.coobird.thumbnailator.Thumbnails;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FileUtils {
|
||||||
|
private static final List<String> ImageTypes = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp", "webp");
|
||||||
|
private static final List<String> DocumentsTypes = Arrays.asList("doc", "pdf", "docx", "ppt", "pptx", "xls", "xlsx");
|
||||||
|
private static final List<String> VideoTypes = Arrays.asList("mp4", "mkv", "mpg");
|
||||||
|
private static final List<String> AudioTypes = Arrays.asList("mp3", "wav", "ogg", "flac");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据类型判断是否是图片
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isImage(String type) {
|
||||||
|
return ImageTypes.contains(type.toLowerCase());
|
||||||
|
}
|
||||||
|
public static boolean isDocument(String type) {
|
||||||
|
return DocumentsTypes.contains(type.toLowerCase());
|
||||||
|
}
|
||||||
|
public static boolean isVideo(String type) {return VideoTypes.contains(type.toLowerCase());
|
||||||
|
}
|
||||||
|
public static boolean isAudio(String type) {
|
||||||
|
return AudioTypes.contains(type.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void getImagePreview(String imagePath, OutputStream os) {
|
||||||
|
Thumbnails.of(new File(imagePath))
|
||||||
|
.size(256, 256) // 尺寸 256x256
|
||||||
|
.outputFormat("jpg") // 格式
|
||||||
|
.toOutputStream(os);
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
package xyz.longicorn.driver.util;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import net.coobird.thumbnailator.Thumbnails;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ImageUtils {
|
|
||||||
private static final List<String> imageTypes = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp", "webp");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据类型判断是否是图片
|
|
||||||
* @param type
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static boolean isImage(String type) {
|
|
||||||
return imageTypes.contains(type.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static void getPreview(String imagePath, OutputStream os) {
|
|
||||||
Thumbnails.of(new File(imagePath))
|
|
||||||
.size(256, 256) // 尺寸 256x256
|
|
||||||
.outputFormat("jpg") // 格式
|
|
||||||
.toOutputStream(os);
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,3 +70,4 @@ mybatis-plus:
|
|||||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
# 实体类所在的包
|
# 实体类所在的包
|
||||||
type-aliases-package: xyz.longicorn.driver.pojo
|
type-aliases-package: xyz.longicorn.driver.pojo
|
||||||
|
type-enums-package: xyz.longicorn.driver.pojo.enums
|
||||||
|
@ -15,7 +15,8 @@ create table folder_info
|
|||||||
);
|
);
|
||||||
|
|
||||||
# 编号、用户编号、文件名、目录编号 、类型、大小、位置、创建时间、状态、hash
|
# 编号、用户编号、文件名、目录编号 、类型、大小、位置、创建时间、状态、hash
|
||||||
create table file_info(
|
create table file_info
|
||||||
|
(
|
||||||
id bigint(20) not null primary key auto_increment,
|
id bigint(20) not null primary key auto_increment,
|
||||||
uid int(10) not null,
|
uid int(10) not null,
|
||||||
name varchar(50) not null,
|
name varchar(50) not null,
|
||||||
@ -27,5 +28,20 @@ create table file_info(
|
|||||||
create_time datetime default current_timestamp,
|
create_time datetime default current_timestamp,
|
||||||
update_time datetime on update current_timestamp,
|
update_time datetime on update current_timestamp,
|
||||||
status tinyint(1) default 1,
|
status tinyint(1) default 1,
|
||||||
index ix_file_name(name)
|
index ix_file_name (name)
|
||||||
|
);
|
||||||
|
-- 编号、分享名称、用户编号、分享的数据编号、分类类型(file|folder)、提取码、分享有效期、状态
|
||||||
|
create table share_info
|
||||||
|
(
|
||||||
|
id varchar(20) not null primary key,
|
||||||
|
title varchar(20) not null,
|
||||||
|
uid int(10) not null,
|
||||||
|
file_id bigint(20) not null,
|
||||||
|
type tinyint(1) default 1 comment '分类类型 1:文件 2:文件夹',
|
||||||
|
password varchar(20) null,
|
||||||
|
live int default 0 comment '有效期',
|
||||||
|
create_time datetime default current_timestamp,
|
||||||
|
update_time datetime on update current_timestamp,
|
||||||
|
status tinyint(1) default 1,
|
||||||
|
index ix_file_name (title)
|
||||||
);
|
);
|
12
driver/src/test/java/xyz/longicorn/driver/TestEnum.java
Normal file
12
driver/src/test/java/xyz/longicorn/driver/TestEnum.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package xyz.longicorn.driver;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import xyz.longicorn.driver.pojo.enums.Category;
|
||||||
|
|
||||||
|
public class TestEnum {
|
||||||
|
@Test
|
||||||
|
void testCategory(){
|
||||||
|
Category c = Category.Audio;
|
||||||
|
System.out.println(c);
|
||||||
|
}
|
||||||
|
}
|
1350
web/package-lock.json
generated
1350
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
131
web/src/App.vue
131
web/src/App.vue
@ -1,131 +1,14 @@
|
|||||||
<script setup>
|
|
||||||
import { ref } from "@vue/reactivity";
|
|
||||||
import FileIcon from "./components/FileIcon.vue";
|
|
||||||
const data = ref({
|
|
||||||
display: "block",
|
|
||||||
activeIndex: 'all'
|
|
||||||
});
|
|
||||||
const tableData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
modify_time: "2016-05-03",
|
|
||||||
name: "我的音乐",
|
|
||||||
type: "folder",
|
|
||||||
size: "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
modify_time: "2016-05-03",
|
|
||||||
name: "我的文档",
|
|
||||||
type: "folder",
|
|
||||||
size: "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
modify_time: "2016-05-03",
|
|
||||||
name: "我的视频",
|
|
||||||
type: "folder",
|
|
||||||
size: "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
modify_time: "2016-05-03",
|
|
||||||
name: "我的图片",
|
|
||||||
type: "folder",
|
|
||||||
size: "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
modify_time: "2016-05-03",
|
|
||||||
name: "APP.jpg",
|
|
||||||
type: "image",
|
|
||||||
size: "103KB",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-container>
|
<!-- 所有子页面显示在这里 -->
|
||||||
<el-aside width="200px" class="main-left-nav">
|
<router-view />
|
||||||
<el-menu :default-active="data.activeIndex" class="main-type-filter" mode="vertical">
|
|
||||||
<el-menu-item index="all">所有文件</el-menu-item>
|
|
||||||
<el-menu-item index="rencent">最近上传</el-menu-item>
|
|
||||||
<el-menu-item index="picture">图片</el-menu-item>
|
|
||||||
<el-menu-item index="document">文档</el-menu-item>
|
|
||||||
<el-menu-item index="video">视频</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</el-aside>
|
|
||||||
<el-container>
|
|
||||||
<el-header></el-header>
|
|
||||||
<el-main>
|
|
||||||
<el-button @click="data.display = data.display == 'list' ? 'block' : 'list'">{{ data.display == "list" ? "block"
|
|
||||||
:
|
|
||||||
"list"
|
|
||||||
}}</el-button>
|
|
||||||
<div class="pan-file-list-wrapper">
|
|
||||||
<div class="pan-file-list-wrapper-table" v-if="data.display == 'list'">
|
|
||||||
<el-table :data="tableData" style="width: 100%">
|
|
||||||
<el-table-column type="selection" width="40px" />
|
|
||||||
<el-table-column label="文件名称">
|
|
||||||
<template #default="file">
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
<FileIcon :file="file.row" style="margin-right: 5px; width: 20px" />
|
|
||||||
</span>
|
|
||||||
<span>{{ file.row.name }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="size" label="大小" width="180" />
|
|
||||||
<el-table-column prop="type" label="类型" width="180" />
|
|
||||||
<el-table-column prop="modify_time" width="180" label="修改时间" />
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
<el-row v-else style="margin-top: 20px" :gutter="20">
|
|
||||||
<el-col :xs="8" :md="6" :lg="4" v-for="(file, i) in 13" :key="i">
|
|
||||||
<div class="grid-content bg-purple" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</el-container>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less">
|
<script>
|
||||||
body {
|
export default {
|
||||||
padding: 0;
|
name: "App.vue"
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
.el-menu-item {
|
<style>
|
||||||
transition: all 0.5s;
|
|
||||||
opacity: 0.8;
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
background-color: var(--el-color-primary-light-9);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-left-nav,
|
|
||||||
.main-type-filter {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content {
|
|
||||||
height: 80px;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-purple {
|
|
||||||
--un-bg-opacity: 1;
|
|
||||||
background-color: rgba(192, 132, 252, var(--un-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-file-list-wrapper-table {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
387
web/src/Main.vue
387
web/src/Main.vue
@ -1,387 +0,0 @@
|
|||||||
<script>
|
|
||||||
import {ArrowDown, Grid, FolderAdd,Search} from '@element-plus/icons-vue'
|
|
||||||
import FileIcon from "./components/FileIcon.vue";
|
|
||||||
import {dayjs, ElMessage, ElMessageBox} from 'element-plus'
|
|
||||||
import api from "./service/api";
|
|
||||||
import qs from "qs";
|
|
||||||
import FileUploader from "./components/file-uploader/Index.vue";
|
|
||||||
import FileBlockItem from "./components/FileBlockItem.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
setup(){
|
|
||||||
return {Search}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
currentActiveIndex: "all",
|
|
||||||
display: 'block',
|
|
||||||
/**
|
|
||||||
* @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: ''
|
|
||||||
},
|
|
||||||
search:{
|
|
||||||
value:''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
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: {FileBlockItem, FileUploader, FileIcon, ArrowDown, Grid, FolderAdd},
|
|
||||||
mounted() {
|
|
||||||
// window.addEventListener('popstate',()=>console.log(location.href))
|
|
||||||
window.addEventListener('hashchange', this.handleHashChange) // 添加监听
|
|
||||||
this.handleHashChange();
|
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 获取获取当前目录路径
|
|
||||||
getCurrentPath() {
|
|
||||||
const hash = location.hash;
|
|
||||||
const params = qs.parse(hash.substr(2))
|
|
||||||
return params.path || '/';
|
|
||||||
},
|
|
||||||
//记载所有的子文件
|
|
||||||
handleHashChange() {
|
|
||||||
this.loadFileByPath(this.getCurrentPath()) // 有参数则使用 无参数则根目录
|
|
||||||
},
|
|
||||||
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];
|
|
||||||
},
|
|
||||||
// 对文件名进行处理
|
|
||||||
formatName(name) {
|
|
||||||
if (!name || name.length < 15) return name;
|
|
||||||
const extIndex = name.lastIndexOf('.'),
|
|
||||||
ext = name.substr(extIndex);
|
|
||||||
return name.substr(0, (15 - ext.length)) + "**" + ext;
|
|
||||||
},
|
|
||||||
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>
|
|
||||||
<div class="main-pan-app" @contextmenu="$refs.fileMenu.hideContextMenu">
|
|
||||||
<el-container>
|
|
||||||
<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>
|
|
||||||
<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">
|
|
||||||
<div class="d-flex">
|
|
||||||
<div class="d-flex flex-1">
|
|
||||||
<div class="left-tool-bar" style="padding-top: 15px;">
|
|
||||||
<file-uploader @upload-success="handleHashChange" :current-folder="currentPath"/>
|
|
||||||
|
|
||||||
<el-button @click="createFolder.visible = true" size="default"
|
|
||||||
style="margin-left: 10px" round>
|
|
||||||
<el-icon>
|
|
||||||
<folder-add/>
|
|
||||||
</el-icon>
|
|
||||||
<span style="margin-left: 4px;">新建文件夹</span>
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ul class="pan-header-user-right">
|
|
||||||
<li><el-input
|
|
||||||
v-model="search.value"
|
|
||||||
class="search-box" clearable
|
|
||||||
style="border-radius:30px;"
|
|
||||||
placeholder="搜索你的文件"
|
|
||||||
:prefix-icon="Search"
|
|
||||||
/></li>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<el-main>
|
|
||||||
<div style="line-height: 30px;" class="d-flex">
|
|
||||||
<!-- 当前路径 -->
|
|
||||||
<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>
|
|
||||||
</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" style="width: 40px;" :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">
|
|
||||||
<file-block-item :file="file" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</el-main>
|
|
||||||
</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">
|
|
||||||
|
|
||||||
|
|
||||||
// 平铺显示
|
|
||||||
.file-block-item {
|
|
||||||
margin: 10px 0;
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-info {
|
|
||||||
margin-top: 3px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -37,6 +37,15 @@
|
|||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.share-create-dialog{
|
||||||
|
.item{
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.title{
|
||||||
|
line-height: 32px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.logo-icon{
|
.logo-icon{
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="file-block-item" @click="showFile(file,$event)"
|
<div class="file-block-item" @click="showFile(file,$event)">
|
||||||
@contextmenu.prevent.stop="$parent.$refs.fileMenu.showMenu($event,file)">
|
|
||||||
<div class="file-image">
|
<div class="file-image">
|
||||||
<FileIcon :file="file" ref="fileItemIcon" style="width:90%"/>
|
<FileIcon :file="file" ref="fileItemIcon" style="width:90%"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dropdown>
|
<el-dropdown>
|
||||||
<el-button type="primary" round>
|
<el-button type="primary">
|
||||||
<label for="file_for_one">
|
<label for="file_for_one">
|
||||||
<el-icon class="el-icon--right">
|
<el-icon class="el-icon--right">
|
||||||
<Upload/>
|
<Upload/>
|
||||||
|
@ -8,9 +8,11 @@ import './assets/main.less'
|
|||||||
import ContextMenu from 'vue-simple-context-menu'
|
import ContextMenu from 'vue-simple-context-menu'
|
||||||
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';
|
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';
|
||||||
// 导入入口组件
|
// 导入入口组件
|
||||||
import App from "./Main.vue";
|
import App from "./App.vue";
|
||||||
|
import index from './router'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.component('ContextMenu', ContextMenu);
|
app.component('ContextMenu', ContextMenu);
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus)
|
||||||
|
.use(index) // 使用路由实例
|
||||||
.mount("#app");
|
.mount("#app");
|
||||||
|
362
web/src/pages/All.vue
Normal file
362
web/src/pages/All.vue
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
<template>
|
||||||
|
<div style="line-height: 30px;" class="d-flex">
|
||||||
|
<!-- 当前路径 -->
|
||||||
|
<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>
|
||||||
|
</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" style="width: 40px;" :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">
|
||||||
|
<file-block-item :file="file"
|
||||||
|
@contextmenu.prevent.stop="$refs.fileMenu.showMenu($event,file)"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<!-- 右键菜单 -->
|
||||||
|
<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>
|
||||||
|
<!-- 分享 -->
|
||||||
|
<el-dialog v-model="share.visible" title="分享文件" width="600px">
|
||||||
|
<div class="share-create-dialog">
|
||||||
|
<h2>{{ share.current?.name }}</h2>
|
||||||
|
<div class="live d-flex item">
|
||||||
|
<div class="title">有效期:</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-radio-group v-model="share.live">
|
||||||
|
<el-radio-button label="1">1天</el-radio-button>
|
||||||
|
<el-radio-button label="7">7天</el-radio-button>
|
||||||
|
<el-radio-button label="30">30天</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="password d-flex item">
|
||||||
|
<div class="title">提取码:</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-radio-group v-model="share.password">
|
||||||
|
<el-radio-button label="yes">需要</el-radio-button>
|
||||||
|
<el-radio-button label="no">不需要</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<span style="color: #999;font-size: 12px;float: left;">配合净网行动, 网盘严厉打击色情低俗等不良信息的传播行为</span>
|
||||||
|
<el-button type="primary" :loading="share.loading" @click="handleCreateFolder">创建分享</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {ArrowDown, Grid, FolderAdd, Search} from '@element-plus/icons-vue'
|
||||||
|
import FileIcon from "../components/FileIcon.vue";
|
||||||
|
import {dayjs, ElMessage, ElMessageBox} from 'element-plus'
|
||||||
|
import api from "../service/api";
|
||||||
|
import qs from "qs";
|
||||||
|
import FileBlockItem from "../components/FileBlockItem.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "All",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
display: 'block',
|
||||||
|
/**
|
||||||
|
* @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: ''
|
||||||
|
},
|
||||||
|
share: {
|
||||||
|
/**
|
||||||
|
* @var {FileItem}
|
||||||
|
*/
|
||||||
|
current: null,
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
/**
|
||||||
|
* @var {ShareInfo}
|
||||||
|
*/
|
||||||
|
info: null,
|
||||||
|
live: 1,
|
||||||
|
password: 'yes'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: {FileBlockItem, FileIcon, ArrowDown, Grid, FolderAdd},
|
||||||
|
mounted() {
|
||||||
|
console.log('记载所有的文件')
|
||||||
|
window.addEventListener('popstate',()=>console.log(location.href))
|
||||||
|
window.addEventListener('hashchange', this.handleHashChange) // 添加监听
|
||||||
|
this.handleHashChange();
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取获取当前目录路径
|
||||||
|
getCurrentPath() {
|
||||||
|
const hash = location.hash;
|
||||||
|
const params = qs.parse(hash.substr(2))
|
||||||
|
return params.path || '/';
|
||||||
|
},
|
||||||
|
//记载所有的子文件
|
||||||
|
handleHashChange() {
|
||||||
|
this.loadFileByPath(this.getCurrentPath()) // 有参数则使用 无参数则根目录
|
||||||
|
},
|
||||||
|
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];
|
||||||
|
},
|
||||||
|
// 对文件名进行处理
|
||||||
|
formatName(name) {
|
||||||
|
if (!name || name.length < 15) return name;
|
||||||
|
const extIndex = name.lastIndexOf('.'),
|
||||||
|
ext = name.substr(extIndex);
|
||||||
|
return name.substr(0, (15 - ext.length)) + "**" + ext;
|
||||||
|
},
|
||||||
|
fileMenuClick(data) {
|
||||||
|
const {item, option} = data;
|
||||||
|
console.log(data)
|
||||||
|
if (option.slug == 'share') {
|
||||||
|
// 分享
|
||||||
|
this.share.current = item
|
||||||
|
this.share.visible = true;
|
||||||
|
} else if (option.slug == 'rename') {
|
||||||
|
this.renameFile(item);
|
||||||
|
} else if (option.slug == 'delete') {
|
||||||
|
this.deleteFile(item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {FileItem} file
|
||||||
|
*/
|
||||||
|
renameFile(file) {
|
||||||
|
ElMessageBox.prompt('', '请输入新的文件名', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
inputValue: file.name,
|
||||||
|
closeOnClickModal: false
|
||||||
|
}).then(({value}) => {
|
||||||
|
api.file.rename({
|
||||||
|
...file,
|
||||||
|
name: value
|
||||||
|
}).then(() => {
|
||||||
|
file.name = value;
|
||||||
|
}).catch();
|
||||||
|
}).catch();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {FileItem} file
|
||||||
|
*/
|
||||||
|
deleteFile(file) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'确定要删除选中文件吗?',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
api.file.delete(file).then(() => this.handleHashChange()).catch();
|
||||||
|
}).catch();
|
||||||
|
},
|
||||||
|
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>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
13
web/src/pages/Documents.vue
Normal file
13
web/src/pages/Documents.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<h1>文档</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Documents"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
81
web/src/pages/Login.vue
Normal file
81
web/src/pages/Login.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<style scoped>
|
||||||
|
#page-login {
|
||||||
|
width: 500px;
|
||||||
|
margin: 200px auto 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<template>
|
||||||
|
<div id="page-login">
|
||||||
|
<el-form
|
||||||
|
ref="form"
|
||||||
|
:model="loginForm"
|
||||||
|
:rules="rules"
|
||||||
|
status-icon
|
||||||
|
label-width="120px"
|
||||||
|
class="demo-ruleForm"
|
||||||
|
>
|
||||||
|
<el-form-item label="" prop="username">
|
||||||
|
<el-input v-model="loginForm.username" placeholder="用户名" autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="" prop="password">
|
||||||
|
<el-input v-model="loginForm.password" placeholder="登录密码" type="password" autocomplete="off"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button style="width: 100%" type="primary" @click="submitForm">登录</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {defineComponent, reactive, ref} from 'vue'
|
||||||
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Login',
|
||||||
|
method:{
|
||||||
|
gotoMain(){
|
||||||
|
this.$router.push('/');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Ref<FormInstance>}
|
||||||
|
*/
|
||||||
|
const form = ref(null);
|
||||||
|
// 使用reactive将对象转换成响应对象
|
||||||
|
const loginForm = reactive({
|
||||||
|
password: '',
|
||||||
|
username: ''
|
||||||
|
})
|
||||||
|
const checkPassword = (rule, value, callback) => {
|
||||||
|
if (!value) callback(Error('请填写密码')) // 验证不通过
|
||||||
|
else callback() // 验证通过
|
||||||
|
}
|
||||||
|
const rules = reactive({
|
||||||
|
username: [
|
||||||
|
{required: true, message: '请填写用户名称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{validator: checkPassword, trigger: 'blur'}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const router = useRouter(); // 获取路由对象
|
||||||
|
const submitForm = () => {
|
||||||
|
form.value.validate((isValid) => {
|
||||||
|
if (isValid) {
|
||||||
|
ElMessage.success('登录成功')
|
||||||
|
router.replace('/')
|
||||||
|
} else {
|
||||||
|
ElMessage.info('验证不通过')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
loginForm, submitForm, rules, form
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
157
web/src/pages/Main.vue
Normal file
157
web/src/pages/Main.vue
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<script>
|
||||||
|
import {ArrowDown, Grid, FolderAdd, Search} from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
import FileUploader from "../components/file-uploader/Index.vue";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
return {Search}
|
||||||
|
},
|
||||||
|
components: {ArrowDown, Grid, FolderAdd, FileUploader},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentActiveIndex: "/",
|
||||||
|
currentPath: '/',
|
||||||
|
search: {
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.currentActiveIndex = this.$route.path
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//记载所有的子文件
|
||||||
|
handleHashChange() {
|
||||||
|
ElMessage.info({
|
||||||
|
title: '成功 加载页面'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="main-pan-app">
|
||||||
|
<el-container>
|
||||||
|
<el-aside class="pan-left-aside">
|
||||||
|
<div class="logo-block">
|
||||||
|
<svg class="logo-icon" viewBox="0 0 1024 1024" 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>
|
||||||
|
<el-menu :default-active="currentActiveIndex" class="pan-left-menu" :router="true">
|
||||||
|
<el-menu-item index="/">
|
||||||
|
<span>所有文件</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/histories">
|
||||||
|
<span>最近上传</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/pictures">
|
||||||
|
<span>我的图片</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/documents">
|
||||||
|
<span>我的文档</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/videos">
|
||||||
|
<span>我的视频</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-container>
|
||||||
|
<el-header class="pan-header">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="d-flex flex-1">
|
||||||
|
<div class="left-tool-bar" style="padding-top: 15px;">
|
||||||
|
<file-uploader @upload-success="handleHashChange" :current-folder="currentPath"/>
|
||||||
|
<el-button @click="createFolder.visible = true" size="default"
|
||||||
|
style="margin-left: 10px">
|
||||||
|
<el-icon>
|
||||||
|
<folder-add/>
|
||||||
|
</el-icon>
|
||||||
|
<span style="margin-left: 4px;">新建文件夹</span>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="pan-header-user-right">
|
||||||
|
<li>
|
||||||
|
<el-input
|
||||||
|
v-model="search.value"
|
||||||
|
class="search-box" clearable
|
||||||
|
style="border-radius:30px;"
|
||||||
|
placeholder="搜索你的文件"
|
||||||
|
:prefix-icon="Search"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main>
|
||||||
|
<!-- 子路由显示的地方 -->
|
||||||
|
<router-view/>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="less">
|
||||||
|
|
||||||
|
|
||||||
|
// 平铺显示
|
||||||
|
.file-block-item {
|
||||||
|
margin: 10px 0;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
13
web/src/pages/Pictures.vue
Normal file
13
web/src/pages/Pictures.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<h1>图片</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Pictures"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
13
web/src/pages/Reg.vue
Normal file
13
web/src/pages/Reg.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<h1>Reg</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Reg.vue"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
13
web/src/pages/Videos.vue
Normal file
13
web/src/pages/Videos.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<h1>视频</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Videos"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
13
web/src/router/index.js
Normal file
13
web/src/router/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import {createRouter, createWebHistory} from 'vue-router'
|
||||||
|
import routes from "./routes";
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes
|
||||||
|
});
|
||||||
|
router.beforeEach((to,from,next)=>{
|
||||||
|
console.log(from.path ,'==>',to.path)
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router;
|
52
web/src/router/routes.js
Normal file
52
web/src/router/routes.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import Main from '../pages/Main.vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {RouteRecordRaw[]}
|
||||||
|
*/
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
name: 'Main',
|
||||||
|
path: '/',
|
||||||
|
component: Main, // 需要在父页面添加 <router-view /> 来显示子路由页面
|
||||||
|
// 配置子路由
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'All',
|
||||||
|
path: '/',
|
||||||
|
component: () => import('../pages/All.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Histories',
|
||||||
|
path: '/histories',
|
||||||
|
component: () => import('../pages/All.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pictures',
|
||||||
|
path: '/pictures',
|
||||||
|
component: () => import('../pages/Pictures.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Documents',
|
||||||
|
path: '/documents',
|
||||||
|
component: () => import('../pages/Documents.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Videos',
|
||||||
|
path: '/videos',
|
||||||
|
component: () => import('../pages/Videos.vue'),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Reg',
|
||||||
|
path: '/reg',
|
||||||
|
component: () => import('../pages/Reg.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Login',
|
||||||
|
path: '/login',
|
||||||
|
component: () => import('../pages/Login.vue')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
export default routes
|
@ -83,6 +83,12 @@ export default {
|
|||||||
fastUpload(params) {
|
fastUpload(params) {
|
||||||
return request('/api/fast-upload', 'POST', params);
|
return request('/api/fast-upload', 'POST', params);
|
||||||
},
|
},
|
||||||
|
delete(file) {
|
||||||
|
return request('/api/file/delete', 'POST', file);
|
||||||
|
},
|
||||||
|
rename(file) {
|
||||||
|
return request('/api/file/rename', 'POST', file);
|
||||||
|
},
|
||||||
upload(parent, file, onProcess = null) {
|
upload(parent, file, onProcess = null) {
|
||||||
// 上传文件到某个目录
|
// 上传文件到某个目录
|
||||||
const postData = new FormData(); // 将数据封装成form表单
|
const postData = new FormData(); // 将数据封装成form表单
|
||||||
@ -119,5 +125,14 @@ export default {
|
|||||||
})
|
})
|
||||||
// return request('/api/upload', 'FILE', postData, onProcess)
|
// return request('/api/upload', 'FILE', postData, onProcess)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
share: {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ShareInfo} info
|
||||||
|
*/
|
||||||
|
create(info) {
|
||||||
|
return request('/api/share/create', 'POST', info)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
web/src/service/type.d.ts
vendored
15
web/src/service/type.d.ts
vendored
@ -20,3 +20,18 @@ declare type FileIconInstance = {
|
|||||||
*/
|
*/
|
||||||
showPreview: Function
|
showPreview: Function
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 分享信息
|
||||||
|
*/
|
||||||
|
declare type ShareInfo = {
|
||||||
|
id?: string,
|
||||||
|
title: string,
|
||||||
|
uid: number,
|
||||||
|
fileId: number,
|
||||||
|
type: 1 | 2,
|
||||||
|
password: string,
|
||||||
|
live: number,
|
||||||
|
createTime?: string,
|
||||||
|
updateTime?: string,
|
||||||
|
status: number
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user