23 changed files with 553 additions and 261 deletions
@ -0,0 +1,67 @@ |
|||||
|
package com.bx.implatform.entity; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
/** |
||||
|
* @author Blue |
||||
|
* @version 1.0 |
||||
|
*/ |
||||
|
@Data |
||||
|
@TableName("im_file_info") |
||||
|
public class FileInfo { |
||||
|
|
||||
|
/** |
||||
|
* 文件ID |
||||
|
*/ |
||||
|
@TableId |
||||
|
private Long id; |
||||
|
|
||||
|
/** |
||||
|
* 文件名 |
||||
|
*/ |
||||
|
private String fileName; |
||||
|
|
||||
|
/** |
||||
|
* 原始文件存储路径 |
||||
|
*/ |
||||
|
private String filePath; |
||||
|
|
||||
|
/** |
||||
|
* 压缩文件存储路径 |
||||
|
*/ |
||||
|
private String compressedPath; |
||||
|
|
||||
|
/** |
||||
|
* 封面文件路径 |
||||
|
*/ |
||||
|
private String coverPath; |
||||
|
|
||||
|
/** |
||||
|
* 原始文件大小(字节) |
||||
|
*/ |
||||
|
private Long fileSize; |
||||
|
|
||||
|
/** |
||||
|
* 上传时间 |
||||
|
*/ |
||||
|
private Date uploadTime; |
||||
|
|
||||
|
/** |
||||
|
* 文件类型,枚举: FileType |
||||
|
*/ |
||||
|
private Integer fileType; |
||||
|
|
||||
|
/** |
||||
|
* 是否永久存储 |
||||
|
*/ |
||||
|
private Boolean isPermanent; |
||||
|
|
||||
|
/** |
||||
|
* 文件MD5哈希值 |
||||
|
*/ |
||||
|
private String md5; |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.bx.implatform.mapper; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
import com.bx.implatform.entity.FileInfo; |
||||
|
|
||||
|
public interface FileInfoMapper extends BaseMapper<FileInfo> { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
package com.bx.implatform.service; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||
|
import com.bx.implatform.entity.FileInfo; |
||||
|
import com.bx.implatform.vo.UploadImageVO; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
public interface FileService extends IService<FileInfo> { |
||||
|
|
||||
|
String uploadFile(MultipartFile file); |
||||
|
|
||||
|
UploadImageVO uploadImage(MultipartFile file,Boolean isPermanent); |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,191 @@ |
|||||
|
package com.bx.implatform.service; |
||||
|
|
||||
|
import cn.hutool.core.util.StrUtil; |
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
|
import com.bx.implatform.config.props.MinioProperties; |
||||
|
import com.bx.implatform.contant.Constant; |
||||
|
import com.bx.implatform.entity.FileInfo; |
||||
|
import com.bx.implatform.enums.FileType; |
||||
|
import com.bx.implatform.enums.ResultCode; |
||||
|
import com.bx.implatform.exception.GlobalException; |
||||
|
import com.bx.implatform.mapper.FileInfoMapper; |
||||
|
import com.bx.implatform.session.SessionContext; |
||||
|
import com.bx.implatform.thirdparty.MinioService; |
||||
|
import com.bx.implatform.util.FileUtil; |
||||
|
import com.bx.implatform.util.ImageUtil; |
||||
|
import com.bx.implatform.vo.UploadImageVO; |
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
import org.springframework.util.DigestUtils; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
import java.io.IOException; |
||||
|
import java.util.Date; |
||||
|
import java.util.Objects; |
||||
|
|
||||
|
/** |
||||
|
* 文件上传服务 |
||||
|
* |
||||
|
* author: Blue date: 2024-09-28 version: 1.0 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
public class FileServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements FileService { |
||||
|
|
||||
|
private final MinioService minioSerivce; |
||||
|
|
||||
|
private final MinioProperties minioProps; |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
if (!minioSerivce.bucketExists(minioProps.getBucketName())) { |
||||
|
// 创建bucket
|
||||
|
minioSerivce.makeBucket(minioProps.getBucketName()); |
||||
|
// 公开bucket
|
||||
|
minioSerivce.setBucketPublic(minioProps.getBucketName()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String uploadFile(MultipartFile file) { |
||||
|
try { |
||||
|
Long userId = SessionContext.getSession().getUserId(); |
||||
|
// 大小校验
|
||||
|
if (file.getSize() > Constant.MAX_FILE_SIZE) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "文件大小不能超过20M"); |
||||
|
} |
||||
|
// 如果文件已存在,直接复用
|
||||
|
String md5 = DigestUtils.md5DigestAsHex(file.getInputStream()); |
||||
|
FileInfo fileInfo = findByMd5(md5); |
||||
|
if (!Objects.isNull(fileInfo)) { |
||||
|
// 更新上传时间
|
||||
|
fileInfo.setUploadTime(new Date()); |
||||
|
this.updateById(fileInfo); |
||||
|
// 返回
|
||||
|
return fileInfo.getFilePath(); |
||||
|
} |
||||
|
// 上传
|
||||
|
String fileName = minioSerivce.upload(minioProps.getBucketName(), minioProps.getFilePath(), file); |
||||
|
if (StringUtils.isEmpty(fileName)) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "文件上传失败"); |
||||
|
} |
||||
|
String url = generUrl(FileType.FILE, fileName); |
||||
|
// 保存文件
|
||||
|
saveFileInfo(file, md5, url); |
||||
|
log.info("文件文件成功,用户id:{},url:{}", userId, url); |
||||
|
return url; |
||||
|
} catch (IOException e) { |
||||
|
log.error("上传图片失败,{}", e.getMessage(), e); |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "上传图片失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
@Override |
||||
|
public UploadImageVO uploadImage(MultipartFile file, Boolean isPermanent) { |
||||
|
try { |
||||
|
Long userId = SessionContext.getSession().getUserId(); |
||||
|
// 大小校验
|
||||
|
if (file.getSize() > Constant.MAX_IMAGE_SIZE) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片大小不能超过20M"); |
||||
|
} |
||||
|
// 图片格式校验
|
||||
|
if (!FileUtil.isImage(file.getOriginalFilename())) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片格式不合法"); |
||||
|
} |
||||
|
UploadImageVO vo = new UploadImageVO(); |
||||
|
// 如果文件已存在,直接复用
|
||||
|
String md5 = DigestUtils.md5DigestAsHex(file.getInputStream()); |
||||
|
FileInfo fileInfo = findByMd5(md5); |
||||
|
if (!Objects.isNull(fileInfo)) { |
||||
|
// 更新上传时间和持久化标记
|
||||
|
fileInfo.setIsPermanent(isPermanent || fileInfo.getIsPermanent()); |
||||
|
fileInfo.setUploadTime(new Date()); |
||||
|
this.updateById(fileInfo); |
||||
|
// 返回
|
||||
|
vo.setOriginUrl(fileInfo.getFilePath()); |
||||
|
vo.setThumbUrl(fileInfo.getCompressedPath()); |
||||
|
return vo; |
||||
|
} |
||||
|
// 上传原图
|
||||
|
String fileName = minioSerivce.upload(minioProps.getBucketName(), minioProps.getImagePath(), file); |
||||
|
if (StringUtils.isEmpty(fileName)) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
||||
|
} |
||||
|
vo.setOriginUrl(generUrl(FileType.IMAGE, fileName)); |
||||
|
if (file.getSize() > 50 * 1024) { |
||||
|
// 大于50K的文件需上传缩略图
|
||||
|
byte[] imageByte = ImageUtil.compressForScale(file.getBytes(), 30); |
||||
|
String thumbFileName = minioSerivce.upload(minioProps.getBucketName(), minioProps.getImagePath(), |
||||
|
file.getOriginalFilename(), imageByte, file.getContentType()); |
||||
|
if (StringUtils.isEmpty(thumbFileName)) { |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
||||
|
} |
||||
|
vo.setThumbUrl(generUrl(FileType.IMAGE, thumbFileName)); |
||||
|
// 保存文件信息
|
||||
|
saveImageFileInfo(file, md5, vo.getOriginUrl(), vo.getThumbUrl(), isPermanent); |
||||
|
}else{ |
||||
|
// 小于50k,用原图充当缩略图
|
||||
|
vo.setThumbUrl(generUrl(FileType.IMAGE, fileName)); |
||||
|
// 保存文件信息,由于缩略图不允许删除,此时原图也不允许删除
|
||||
|
saveImageFileInfo(file, md5, vo.getOriginUrl(), vo.getThumbUrl(), true); |
||||
|
} |
||||
|
log.info("文件图片成功,用户id:{},url:{}", userId, vo.getOriginUrl()); |
||||
|
return vo; |
||||
|
} catch (IOException e) { |
||||
|
log.error("上传图片失败,{}", e.getMessage(), e); |
||||
|
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private String generUrl(FileType fileType, String fileName) { |
||||
|
return StrUtil.join("/", minioProps.getDomain(), minioProps.getBucketName(), getBucketPath(fileType), fileName); |
||||
|
} |
||||
|
|
||||
|
private String getBucketPath(FileType fileType) { |
||||
|
return switch (fileType) { |
||||
|
case FILE -> minioProps.getFilePath(); |
||||
|
case IMAGE -> minioProps.getImagePath(); |
||||
|
case VIDEO -> minioProps.getVideoPath(); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private FileInfo findByMd5(String md5) { |
||||
|
LambdaQueryWrapper<FileInfo> wrapper = Wrappers.lambdaQuery(); |
||||
|
wrapper.eq(FileInfo::getMd5, md5); |
||||
|
return getOne(wrapper); |
||||
|
} |
||||
|
|
||||
|
private void saveImageFileInfo(MultipartFile file, String md5, String filePath, String compressedPath, |
||||
|
Boolean isPermanent) throws IOException { |
||||
|
FileInfo fileInfo = new FileInfo(); |
||||
|
fileInfo.setFileName(file.getOriginalFilename()); |
||||
|
fileInfo.setFileSize(file.getSize()); |
||||
|
fileInfo.setFileType(FileType.IMAGE.code()); |
||||
|
fileInfo.setFilePath(filePath); |
||||
|
fileInfo.setCompressedPath(compressedPath); |
||||
|
fileInfo.setMd5(md5); |
||||
|
fileInfo.setIsPermanent(isPermanent); |
||||
|
fileInfo.setUploadTime(new Date()); |
||||
|
this.save(fileInfo); |
||||
|
} |
||||
|
|
||||
|
private void saveFileInfo(MultipartFile file, String md5, String filePath) throws IOException { |
||||
|
FileInfo fileInfo = new FileInfo(); |
||||
|
fileInfo.setFileName(file.getOriginalFilename()); |
||||
|
fileInfo.setFileSize(file.getSize()); |
||||
|
fileInfo.setFileType(FileType.FILE.code()); |
||||
|
fileInfo.setFilePath(filePath); |
||||
|
fileInfo.setMd5(md5); |
||||
|
fileInfo.setIsPermanent(false); |
||||
|
fileInfo.setUploadTime(new Date()); |
||||
|
this.save(fileInfo); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,121 +0,0 @@ |
|||||
package com.bx.implatform.service.thirdparty; |
|
||||
|
|
||||
import com.bx.implatform.config.props.MinioProperties; |
|
||||
import com.bx.implatform.contant.Constant; |
|
||||
import com.bx.implatform.enums.FileType; |
|
||||
import com.bx.implatform.enums.ResultCode; |
|
||||
import com.bx.implatform.exception.GlobalException; |
|
||||
import com.bx.implatform.session.SessionContext; |
|
||||
import com.bx.implatform.util.FileUtil; |
|
||||
import com.bx.implatform.util.ImageUtil; |
|
||||
import com.bx.implatform.util.MinioUtil; |
|
||||
import com.bx.implatform.vo.UploadImageVO; |
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.apache.commons.lang3.StringUtils; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
import org.springframework.web.multipart.MultipartFile; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Objects; |
|
||||
|
|
||||
/** |
|
||||
* todo 通过校验文件MD5实现重复文件秒传 |
|
||||
* 文件上传服务 |
|
||||
* |
|
||||
* @author Blue |
|
||||
* @date 2022/10/28 |
|
||||
*/ |
|
||||
@Slf4j |
|
||||
@Service |
|
||||
@RequiredArgsConstructor |
|
||||
public class FileService { |
|
||||
private final MinioUtil minioUtil; |
|
||||
|
|
||||
private final MinioProperties minioProps; |
|
||||
|
|
||||
|
|
||||
@PostConstruct |
|
||||
public void init() { |
|
||||
if (!minioUtil.bucketExists(minioProps.getBucketName())) { |
|
||||
// 创建bucket
|
|
||||
minioUtil.makeBucket(minioProps.getBucketName()); |
|
||||
// 公开bucket
|
|
||||
minioUtil.setBucketPublic(minioProps.getBucketName()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public String uploadFile(MultipartFile file) { |
|
||||
Long userId = SessionContext.getSession().getUserId(); |
|
||||
// 大小校验
|
|
||||
if (file.getSize() > Constant.MAX_FILE_SIZE) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "文件大小不能超过20M"); |
|
||||
} |
|
||||
// 上传
|
|
||||
String fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getFilePath(), file); |
|
||||
if (StringUtils.isEmpty(fileName)) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "文件上传失败"); |
|
||||
} |
|
||||
String url = generUrl(FileType.FILE, fileName); |
|
||||
log.info("文件文件成功,用户id:{},url:{}", userId, url); |
|
||||
return url; |
|
||||
} |
|
||||
|
|
||||
public UploadImageVO uploadImage(MultipartFile file) { |
|
||||
try { |
|
||||
Long userId = SessionContext.getSession().getUserId(); |
|
||||
// 大小校验
|
|
||||
if (file.getSize() > Constant.MAX_IMAGE_SIZE) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片大小不能超过20M"); |
|
||||
} |
|
||||
// 图片格式校验
|
|
||||
if (!FileUtil.isImage(file.getOriginalFilename())) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片格式不合法"); |
|
||||
} |
|
||||
// 上传原图
|
|
||||
UploadImageVO vo = new UploadImageVO(); |
|
||||
String fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getImagePath(), file); |
|
||||
if (StringUtils.isEmpty(fileName)) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
|
||||
} |
|
||||
vo.setOriginUrl(generUrl(FileType.IMAGE, fileName)); |
|
||||
// 大于30K的文件需上传缩略图
|
|
||||
if (file.getSize() > 30 * 1024) { |
|
||||
byte[] imageByte = ImageUtil.compressForScale(file.getBytes(), 30); |
|
||||
fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getImagePath(), Objects.requireNonNull(file.getOriginalFilename()), imageByte, file.getContentType()); |
|
||||
if (StringUtils.isEmpty(fileName)) { |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
|
||||
} |
|
||||
} |
|
||||
vo.setThumbUrl(generUrl(FileType.IMAGE, fileName)); |
|
||||
log.info("文件图片成功,用户id:{},url:{}", userId, vo.getOriginUrl()); |
|
||||
return vo; |
|
||||
} catch (IOException e) { |
|
||||
log.error("上传图片失败,{}", e.getMessage(), e); |
|
||||
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public String generUrl(FileType fileTypeEnum, String fileName) { |
|
||||
String url = minioProps.getDomain() + "/" + minioProps.getBucketName(); |
|
||||
switch (fileTypeEnum) { |
|
||||
case FILE: |
|
||||
url += "/" + minioProps.getFilePath() + "/"; |
|
||||
break; |
|
||||
case IMAGE: |
|
||||
url += "/" + minioProps.getImagePath() + "/"; |
|
||||
break; |
|
||||
case VIDEO: |
|
||||
url += "/" + minioProps.getVideoPath() + "/"; |
|
||||
break; |
|
||||
default: |
|
||||
break; |
|
||||
} |
|
||||
url += fileName; |
|
||||
return url; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -0,0 +1,78 @@ |
|||||
|
package com.bx.implatform.task.schedule; |
||||
|
|
||||
|
import cn.hutool.core.util.StrUtil; |
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||
|
import com.bx.implatform.annotation.RedisLock; |
||||
|
import com.bx.implatform.config.props.MinioProperties; |
||||
|
import com.bx.implatform.contant.RedisKey; |
||||
|
import com.bx.implatform.entity.FileInfo; |
||||
|
import com.bx.implatform.service.FileService; |
||||
|
import com.bx.implatform.thirdparty.MinioService; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.time.DateUtils; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 过期文件清理任务 |
||||
|
* |
||||
|
* @author Blue |
||||
|
* @version 1.0 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Component |
||||
|
@RequiredArgsConstructor |
||||
|
public class FileExpireTask { |
||||
|
|
||||
|
private final FileService fileService; |
||||
|
private final MinioService minioService; |
||||
|
private final MinioProperties minioProps; |
||||
|
|
||||
|
@RedisLock(prefixKey = RedisKey.IM_LOCK_FILE_TASK) |
||||
|
@Scheduled(cron = "0 * * * * ?") |
||||
|
public void run() { |
||||
|
log.info("【定时任务】过期文件处理..."); |
||||
|
int batchSize = 100; |
||||
|
List<FileInfo> files = loadBatch(batchSize); |
||||
|
while (true) { |
||||
|
for (FileInfo fileInfo : files) { |
||||
|
String url = fileInfo.getFilePath(); |
||||
|
String relativePath = url.substring(fileInfo.getFilePath().indexOf(minioProps.getBucketName())); |
||||
|
String[] arr = relativePath.split("/"); |
||||
|
String bucket = minioProps.getBucketName(); |
||||
|
String path = arr[1]; |
||||
|
String fileNme = StrUtil.join("/", arr[2], arr[3]); |
||||
|
if (minioService.isExist(bucket, path, fileNme)) { |
||||
|
if (!minioService.remove(bucket, path, fileNme)) { |
||||
|
// 删除失败,不再往下执行
|
||||
|
log.error("删除过期文件异常, id:{},文件名:{}", fileInfo.getId(), fileInfo.getFileName()); |
||||
|
return; |
||||
|
} |
||||
|
// 删除文件信息
|
||||
|
fileService.removeById(fileInfo.getId()); |
||||
|
} |
||||
|
} |
||||
|
if (files.size() < batchSize) { |
||||
|
break; |
||||
|
} |
||||
|
// 下一批
|
||||
|
files = loadBatch(batchSize); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
List<FileInfo> loadBatch(int size) { |
||||
|
Date minDate = DateUtils.addDays(new Date(), -minioProps.getExpireIn()); |
||||
|
LambdaQueryWrapper<FileInfo> wrapper = Wrappers.lambdaQuery(); |
||||
|
wrapper.eq(FileInfo::getIsPermanent, false); |
||||
|
wrapper.le(FileInfo::getUploadTime, minDate); |
||||
|
wrapper.orderByAsc(FileInfo::getId); |
||||
|
wrapper.last("limit " + size); |
||||
|
return fileService.list(wrapper); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 22 KiB |
@ -1,140 +1,141 @@ |
|||||
<template> |
<template> |
||||
<el-dialog class="setting" title="设置" :visible.sync="visible" width="420px" :before-close="onClose"> |
<el-dialog class="setting" title="设置" :visible.sync="visible" width="420px" :before-close="onClose"> |
||||
<el-form :model="userInfo" label-width="80px" :rules="rules" ref="settingForm" size="small"> |
<el-form :model="userInfo" label-width="80px" :rules="rules" ref="settingForm" size="small"> |
||||
<el-form-item label="头像" style="margin-bottom: 0 !important;"> |
<el-form-item label="头像" style="margin-bottom: 0 !important;"> |
||||
<file-upload class="avatar-uploader" :action="imageAction" :showLoading="true" :maxSize="maxSize" |
<file-upload class="avatar-uploader" :action="imageAction" :showLoading="true" :maxSize="maxSize" |
||||
@success="onUploadSuccess" :fileTypes="['image/jpeg', 'image/png', 'image/jpg', 'image/webp']"> |
:isPermanent="true" @success="onUploadSuccess" |
||||
<img v-if="userInfo.headImage" :src="userInfo.headImage" class="avatar"> |
:fileTypes="['image/jpeg', 'image/png', 'image/jpg', 'image/webp']"> |
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i> |
<img v-if="userInfo.headImage" :src="userInfo.headImage" class="avatar"> |
||||
</file-upload> |
<i v-else class="el-icon-plus avatar-uploader-icon"></i> |
||||
</el-form-item> |
</file-upload> |
||||
<el-form-item label="用户名"> |
</el-form-item> |
||||
<el-input disabled v-model="userInfo.userName" autocomplete="off" size="small"></el-input> |
<el-form-item label="用户名"> |
||||
</el-form-item> |
<el-input disabled v-model="userInfo.userName" autocomplete="off" size="small"></el-input> |
||||
<el-form-item prop="nickName" label="昵称"> |
</el-form-item> |
||||
<el-input v-model="userInfo.nickName" autocomplete="off" size="small"></el-input> |
<el-form-item prop="nickName" label="昵称"> |
||||
</el-form-item> |
<el-input v-model="userInfo.nickName" autocomplete="off" size="small"></el-input> |
||||
<el-form-item label="性别"> |
</el-form-item> |
||||
<el-radio-group v-model="userInfo.sex"> |
<el-form-item label="性别"> |
||||
<el-radio :label="0">男</el-radio> |
<el-radio-group v-model="userInfo.sex"> |
||||
<el-radio :label="1">女</el-radio> |
<el-radio :label="0">男</el-radio> |
||||
</el-radio-group> |
<el-radio :label="1">女</el-radio> |
||||
</el-form-item> |
</el-radio-group> |
||||
<el-form-item label="个性签名"> |
</el-form-item> |
||||
<el-input type="textarea" v-model="userInfo.signature" :rows="3" maxlength="64"></el-input> |
<el-form-item label="个性签名"> |
||||
</el-form-item> |
<el-input type="textarea" v-model="userInfo.signature" :rows="3" maxlength="64"></el-input> |
||||
</el-form> |
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
<span slot="footer" class="dialog-footer"> |
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="onClose()">取 消</el-button> |
<el-button @click="onClose()">取 消</el-button> |
||||
<el-button type="primary" @click="onSubmit()">确 定</el-button> |
<el-button type="primary" @click="onSubmit()">确 定</el-button> |
||||
</span> |
</span> |
||||
</el-dialog> |
</el-dialog> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
import FileUpload from "../common/FileUpload.vue"; |
import FileUpload from "../common/FileUpload.vue"; |
||||
|
|
||||
export default { |
export default { |
||||
name: "setting", |
name: "setting", |
||||
components: { |
components: { |
||||
FileUpload |
FileUpload |
||||
}, |
}, |
||||
data() { |
data() { |
||||
return { |
return { |
||||
userInfo: {}, |
userInfo: {}, |
||||
maxSize: 5 * 1024 * 1024, |
maxSize: 5 * 1024 * 1024, |
||||
action: "/image/upload", |
action: "/image/upload", |
||||
rules: { |
rules: { |
||||
nickName: [{ |
nickName: [{ |
||||
required: true, |
required: true, |
||||
message: '请输入昵称', |
message: '请输入昵称', |
||||
trigger: 'blur' |
trigger: 'blur' |
||||
}] |
}] |
||||
} |
} |
||||
} |
} |
||||
}, |
}, |
||||
methods: { |
methods: { |
||||
|
|
||||
onClose() { |
onClose() { |
||||
this.$emit("close"); |
this.$emit("close"); |
||||
}, |
}, |
||||
onSubmit() { |
onSubmit() { |
||||
this.$refs['settingForm'].validate((valid) => { |
this.$refs['settingForm'].validate((valid) => { |
||||
if (!valid) { |
if (!valid) { |
||||
return false; |
return false; |
||||
} |
} |
||||
this.$http({ |
this.$http({ |
||||
url: "/user/update", |
url: "/user/update", |
||||
method: "put", |
method: "put", |
||||
data: this.userInfo |
data: this.userInfo |
||||
}).then(() => { |
}).then(() => { |
||||
this.$store.commit("setUserInfo", this.userInfo); |
this.$store.commit("setUserInfo", this.userInfo); |
||||
this.$emit("close"); |
this.$emit("close"); |
||||
this.$message.success("修改成功"); |
this.$message.success("修改成功"); |
||||
}) |
}) |
||||
}); |
}); |
||||
}, |
}, |
||||
onUploadSuccess(data, file) { |
onUploadSuccess(data, file) { |
||||
this.userInfo.headImage = data.originUrl; |
this.userInfo.headImage = data.originUrl; |
||||
this.userInfo.headImageThumb = data.thumbUrl; |
this.userInfo.headImageThumb = data.thumbUrl; |
||||
} |
} |
||||
}, |
}, |
||||
props: { |
props: { |
||||
visible: { |
visible: { |
||||
type: Boolean |
type: Boolean |
||||
} |
} |
||||
}, |
}, |
||||
computed: { |
computed: { |
||||
imageAction() { |
imageAction() { |
||||
return `/image/upload`; |
return `/image/upload`; |
||||
} |
} |
||||
}, |
}, |
||||
watch: { |
watch: { |
||||
visible: function (newData, oldData) { |
visible: function(newData, oldData) { |
||||
// 深拷贝 |
// 深拷贝 |
||||
let mine = this.$store.state.userStore.userInfo; |
let mine = this.$store.state.userStore.userInfo; |
||||
this.userInfo = JSON.parse(JSON.stringify(mine)); |
this.userInfo = JSON.parse(JSON.stringify(mine)); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
</script> |
</script> |
||||
|
|
||||
<style lang="scss"> |
<style lang="scss"> |
||||
.setting { |
.setting { |
||||
.el-form { |
.el-form { |
||||
padding: 10px 0 0 10px; |
padding: 10px 0 0 10px; |
||||
} |
} |
||||
|
|
||||
.avatar-uploader { |
.avatar-uploader { |
||||
--width: 112px; |
--width: 112px; |
||||
|
|
||||
.el-upload { |
.el-upload { |
||||
border: 1px dashed #d9d9d9 !important; |
border: 1px dashed #d9d9d9 !important; |
||||
border-radius: 6px; |
border-radius: 6px; |
||||
cursor: pointer; |
cursor: pointer; |
||||
position: relative; |
position: relative; |
||||
overflow: hidden; |
overflow: hidden; |
||||
} |
} |
||||
|
|
||||
.el-upload:hover { |
.el-upload:hover { |
||||
border-color: #409EFF; |
border-color: #409EFF; |
||||
} |
} |
||||
|
|
||||
.avatar-uploader-icon { |
.avatar-uploader-icon { |
||||
font-size: 24px; |
font-size: 24px; |
||||
color: #8c939d; |
color: #8c939d; |
||||
width: var(--width); |
width: var(--width); |
||||
height: var(--width); |
height: var(--width); |
||||
line-height: var(--width); |
line-height: var(--width); |
||||
text-align: center; |
text-align: center; |
||||
} |
} |
||||
|
|
||||
.avatar { |
.avatar { |
||||
width: var(--width); |
width: var(--width); |
||||
height: var(--width); |
height: var(--width); |
||||
display: block; |
display: block; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
</style> |
</style> |
||||
Loading…
Reference in new issue