Files
smartDriveEE/src/main/java/com/rj/service/impl/CustomerManagementServiceImpl.java

244 lines
9.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.rj.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.config.MinIOConfig;
import com.rj.dto.CustomerPhotoPreviewResult;
import com.rj.dto.CustomerPhotoUploadResult;
import com.rj.dto.CustomerStageUpdateResult;
import com.rj.entity.CustomerManagement;
import com.rj.mapper.CustomerManagementMapper;
import com.rj.service.ICustomerManagementService;
import com.rj.service.MinIOService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* <p>
* 客户管理表 服务实现类
* </p>
*
* @author 李中华 ,spllzh
* @since 2025-08-07
*/
@Slf4j
@Service
public class CustomerManagementServiceImpl extends ServiceImpl<CustomerManagementMapper, CustomerManagement>
implements ICustomerManagementService {
@Autowired
private MinIOService minIOService;
@Autowired
private MinIOConfig minioConfig;
@Override
public CustomerPhotoUploadResult uploadCustomerPhoto(String id, MultipartFile file) {
try {
if (id == null || id.trim().isEmpty()) {
return CustomerPhotoUploadResult.badRequest("客户ID不能为空");
}
if (file == null || file.isEmpty()) {
return CustomerPhotoUploadResult.badRequest("请选择要上传的文件");
}
CustomerManagement customer = getById(id.trim());
if (customer == null) {
return CustomerPhotoUploadResult.badRequest("客户不存在");
}
String original = file.getOriginalFilename();
String ext = "";
if (original != null && original.contains(".")) {
ext = original.substring(original.lastIndexOf("."));
}
String objectName = "customer-management/photo/" + id.trim() + "/"
+ UUID.randomUUID().toString().replace("-", "") + ext;
String url = minIOService.uploadFileWithName(file, objectName);
log.info("客户照片已上传 MinIOcustomerId={}, url={}", id, url);
return CustomerPhotoUploadResult.ok(url);
} catch (Exception e) {
log.error("客户照片上传失败: {}", e.getMessage(), e);
return CustomerPhotoUploadResult.serverError("上传失败:" + e.getMessage());
}
}
@Override
public CustomerStageUpdateResult updateCustomerStage(String id, String stage) {
try {
if (id == null || id.trim().isEmpty()) {
return CustomerStageUpdateResult.badRequest("客户ID不能为空");
}
String idTrim = id.trim();
if (getById(idTrim) == null) {
return CustomerStageUpdateResult.badRequest("客户不存在");
}
LocalDateTime now = LocalDateTime.now();
boolean updated = update(
new LambdaUpdateWrapper<CustomerManagement>()
.eq(CustomerManagement::getId, idTrim)
.set(CustomerManagement::getStage, stage)
.set(CustomerManagement::getUpdateTime, now));
if (!updated) {
return CustomerStageUpdateResult.badRequest("阶段更新失败");
}
return CustomerStageUpdateResult.ok(getById(idTrim));
} catch (Exception e) {
log.error("客户阶段更新失败: {}", e.getMessage(), e);
return CustomerStageUpdateResult.serverError("阶段更新异常:" + e.getMessage());
}
}
@Override
public CustomerPhotoPreviewResult openCustomerPhotoPreview(String url, String id, String photoType) {
String photoUrl = null;
if (url != null && !url.trim().isEmpty()) {
photoUrl = url.trim();
} else if (id != null && !id.trim().isEmpty() && photoType != null && !photoType.trim().isEmpty()) {
CustomerManagement customer = getById(id.trim());
if (customer == null) {
return CustomerPhotoPreviewResult.notFound();
}
String type = photoType.trim().toLowerCase();
switch (type) {
case "front":
photoUrl = customer.getFrontPhotoUrl();
break;
case "side":
photoUrl = customer.getSidePhotoUrl();
break;
case "life":
photoUrl = customer.getLifePhotoUrl();
break;
default:
return CustomerPhotoPreviewResult.badRequest();
}
} else {
return CustomerPhotoPreviewResult.badRequest();
}
if (photoUrl == null || photoUrl.trim().isEmpty()) {
return CustomerPhotoPreviewResult.notFound();
}
String loc = photoUrl.trim();
String nameProbe = lastPathSegmentForPreview(loc);
if (!isImageFile(nameProbe)) {
log.warn("预览拒绝非图片扩展名: {}", nameProbe);
return CustomerPhotoPreviewResult.badRequest();
}
String objectName = resolveMinioObjectNameForPreview(loc);
if (objectName == null || objectName.isEmpty()) {
log.warn("无法从 URL 解析 MinIO 对象名: {}", loc);
return CustomerPhotoPreviewResult.badRequest();
}
try {
InputStream inputStream = minIOService.downloadFile(objectName);
String contentType = imageContentType(nameProbe);
return CustomerPhotoPreviewResult.ok(inputStream, contentType);
} catch (Exception e) {
log.error("从 MinIO 读取客户照片失败, objectName={}", objectName, e);
return CustomerPhotoPreviewResult.notFound();
}
}
private static String lastPathSegmentForPreview(String urlOrPath) {
if (urlOrPath == null) {
return "";
}
String s = urlOrPath.trim();
int q = s.indexOf('?');
if (q >= 0) {
s = s.substring(0, q);
}
int slash = Math.max(s.lastIndexOf('/'), s.lastIndexOf('\\'));
return slash >= 0 ? s.substring(slash + 1) : s;
}
private static boolean isImageFile(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return false;
}
String ext = getFileExtension(fileName).toLowerCase();
switch (ext) {
case "jpg":
case "jpeg":
case "png":
case "gif":
case "webp":
case "bmp":
case "ico":
return true;
default:
return false;
}
}
private static String getFileExtension(String fileName) {
if (fileName == null) {
return "";
}
int i = fileName.lastIndexOf('.');
return i >= 0 ? fileName.substring(i + 1) : "";
}
private static String imageContentType(String fileName) {
String ext = getFileExtension(fileName).toLowerCase();
switch (ext) {
case "jpg":
case "jpeg":
return MediaType.IMAGE_JPEG_VALUE;
case "png":
return MediaType.IMAGE_PNG_VALUE;
case "gif":
return MediaType.IMAGE_GIF_VALUE;
case "webp":
return "image/webp";
case "bmp":
return "image/bmp";
case "ico":
return "image/x-icon";
default:
return MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
}
private String resolveMinioObjectNameForPreview(String fileUrl) {
if (fileUrl == null || fileUrl.trim().isEmpty()) {
return null;
}
String trimmed = fileUrl.trim();
String withoutQuery = trimmed;
int q = trimmed.indexOf('?');
if (q >= 0) {
withoutQuery = trimmed.substring(0, q);
}
String prefix = minioConfig.getFileUrlPrefix();
if (prefix != null && !prefix.isEmpty() && withoutQuery.startsWith(prefix)) {
return withoutQuery.substring(prefix.length());
}
return extractObjectNameFromUrlFallback(trimmed);
}
private static String extractObjectNameFromUrlFallback(String url) {
if (url == null || url.trim().isEmpty()) {
return null;
}
try {
String urlWithoutParams = url.contains("?") ? url.substring(0, url.indexOf('?')) : url;
String[] parts = urlWithoutParams.split("/");
for (int i = parts.length - 1; i >= 0; i--) {
if (parts[i] != null && !parts[i].trim().isEmpty()) {
return parts[i];
}
}
return null;
} catch (Exception e) {
return null;
}
}
}