配送单据接口修改
This commit is contained in:
189
src/main/java/com/delivery/common/utils/LocalPhotoUtil.java
Normal file
189
src/main/java/com/delivery/common/utils/LocalPhotoUtil.java
Normal file
@@ -0,0 +1,189 @@
|
||||
package com.delivery.common.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 本地图片保存工具
|
||||
* - 根目录:photo.root(默认 /data/upload/images)
|
||||
* - 目录结构:{documentType}/yyyy-MM-dd/
|
||||
* - 文件命名:
|
||||
* 入库:billNo_gysMc_yyyyMMddHHmmssSSS_index.ext
|
||||
* 出库:billNo_xmMs_yyyyMMddHHmmssSSS_index.ext
|
||||
*/
|
||||
@Component
|
||||
public class LocalPhotoUtil {
|
||||
|
||||
/** 磁盘根目录(Linux 默认) */
|
||||
@Value("${photo.root:/data/upload/images}")
|
||||
private String rootPath;
|
||||
|
||||
@Value("${photo.base-url:http://192.168.1.28/files}")
|
||||
private String baseUrl;
|
||||
|
||||
private static final String ILLEGAL_CHARS = "\\/:*?\"<>|";
|
||||
private static final long MAX_SIZE = 10 * 1024 * 1024; // 10MB
|
||||
private static final Set<String> ALLOWED =
|
||||
new HashSet<>(Arrays.asList("jpg","jpeg","png","gif","webp","bmp"));
|
||||
|
||||
/** yyyy-MM-dd(目录) */
|
||||
private String today() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
||||
}
|
||||
|
||||
/** yyyyMMddHHmmssSSS(文件戳) */
|
||||
private String nowStamp() {
|
||||
return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成基础名:
|
||||
* - 入库(photoType=0):billNo_gysMc
|
||||
* - 出库(photoType=1):billNo_xmMs
|
||||
* - 若为空 → 一律替换成 "无"
|
||||
*/
|
||||
public String buildBaseName(String photoType, String billNo, String xmMs, String gysMc) {
|
||||
String safeBillNo = sanitize(defaultString(billNo));
|
||||
String part;
|
||||
if ("0".equals(photoType)) {
|
||||
part = sanitize(defaultString(gysMc, "无"));
|
||||
} else {
|
||||
part = sanitize(defaultString(xmMs, "无"));
|
||||
}
|
||||
return sanitize(safeBillNo + "_" + part);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存单个文件
|
||||
* @param file 文件
|
||||
* @param subDir 一级子目录(documentType)
|
||||
* @param baseName 基础名
|
||||
* @param index 序号(从1开始)
|
||||
*/
|
||||
public SaveResult saveOne(MultipartFile file, String subDir, String baseName, int index) throws Exception {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new IllegalArgumentException("文件为空");
|
||||
}
|
||||
if (file.getSize() > MAX_SIZE) {
|
||||
throw new IllegalArgumentException("图片不能超过10MB");
|
||||
}
|
||||
|
||||
String ext = resolveExt(file);
|
||||
String safeSub = sanitize(limitLen(defaultString(subDir, ""), 40));
|
||||
String dirPart = (safeSub.isEmpty() ? "" : safeSub + File.separator) + today() + File.separator;
|
||||
|
||||
String stamp = nowStamp();
|
||||
String safeBase = sanitize(limitLen(baseName, 80));
|
||||
String fileName = safeBase + "_" + stamp + "_" + index + ext;
|
||||
|
||||
File dir = new File(ensureTrailingSlash(rootPath), dirPart);
|
||||
Files.createDirectories(dir.toPath());
|
||||
|
||||
File dest = new File(dir, fileName);
|
||||
File tmp = new File(dir, fileName + ".uploading");
|
||||
|
||||
try (InputStream in = file.getInputStream()) {
|
||||
Files.copy(in, tmp.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
Files.move(tmp.toPath(), dest.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
SaveResult r = new SaveResult();
|
||||
String webPath = (dirPart + fileName).replace("\\", "/");
|
||||
r.setWebPath(webPath); // /{subDir}/yyyy-MM-dd/xxx.jpg
|
||||
r.setFileName(fileName);
|
||||
r.setAbsPath(dest.getAbsolutePath());
|
||||
r.setUrl(joinUrl(baseUrl, webPath)); // http://ip/files/...
|
||||
r.setSize(file.getSize());
|
||||
return r;
|
||||
}
|
||||
|
||||
/** 批量保存 */
|
||||
public List<SaveResult> saveBatch(List<MultipartFile> files, String subDir, String baseName) throws Exception {
|
||||
if (files == null || files.isEmpty()) return Collections.emptyList();
|
||||
List<SaveResult> list = new ArrayList<>(files.size());
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
list.add(saveOne(files.get(i), subDir, baseName, i + 1));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/** 扩展名解析 + 白名单校验 */
|
||||
private String resolveExt(MultipartFile file) {
|
||||
String origin = file.getOriginalFilename();
|
||||
if (origin != null) {
|
||||
int dot = origin.lastIndexOf('.');
|
||||
if (dot >= 0) {
|
||||
String pure = origin.substring(dot + 1).toLowerCase(Locale.ROOT);
|
||||
if (ALLOWED.contains(pure)) return "." + pure;
|
||||
}
|
||||
}
|
||||
String ct = String.valueOf(file.getContentType()).toLowerCase(Locale.ROOT);
|
||||
if (ct.contains("png")) return ".png";
|
||||
if (ct.contains("jpeg") || ct.contains("jpg")) return ".jpg";
|
||||
if (ct.contains("gif")) return ".gif";
|
||||
if (ct.contains("webp")) return ".webp";
|
||||
if (ct.contains("bmp")) return ".bmp";
|
||||
return ".bin";
|
||||
}
|
||||
|
||||
/** 清洗文件名 */
|
||||
public String sanitize(String name) {
|
||||
if (name == null) return "unnamed";
|
||||
String t = name.trim().replaceAll("\\s+", " ");
|
||||
StringBuilder sb = new StringBuilder(t.length());
|
||||
for (int i = 0; i < t.length(); i++) {
|
||||
char c = t.charAt(i);
|
||||
sb.append(ILLEGAL_CHARS.indexOf(c) >= 0 ? '_' : c);
|
||||
}
|
||||
String out = sb.toString();
|
||||
String upper = out.toUpperCase(Locale.ROOT);
|
||||
if (upper.matches("CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9]")) {
|
||||
out = "_" + out;
|
||||
}
|
||||
if (out.length() > 100) out = out.substring(0, 100);
|
||||
return out;
|
||||
}
|
||||
|
||||
private String defaultString(String s) { return s == null ? "" : s; }
|
||||
private String defaultString(String s, String def) { return (s == null || s.isEmpty()) ? def : s; }
|
||||
|
||||
private String ensureTrailingSlash(String p) {
|
||||
return (p.endsWith("/") || p.endsWith("\\")) ? p : (p + File.separator);
|
||||
}
|
||||
private String limitLen(String s, int max) {
|
||||
if (s == null) return "";
|
||||
return s.length() > max ? s.substring(0, max) : s;
|
||||
}
|
||||
private String joinUrl(String base, String path) {
|
||||
String b = base.endsWith("/") ? base.substring(0, base.length()-1) : base;
|
||||
String p = path.startsWith("/") ? path.substring(1) : path;
|
||||
return b + "/" + p;
|
||||
}
|
||||
|
||||
/** 返回值对象 */
|
||||
public static class SaveResult {
|
||||
private String webPath; // 相对Web路径(/subDir/yyyy-MM-dd/xxx.jpg)
|
||||
private String fileName; // 文件名
|
||||
private String absPath; // 服务器绝对路径
|
||||
private String url; // 可直接访问的URL
|
||||
private long size; // 字节
|
||||
|
||||
public String getWebPath() { return webPath; }
|
||||
public void setWebPath(String webPath) { this.webPath = webPath; }
|
||||
public String getFileName() { return fileName; }
|
||||
public void setFileName(String fileName) { this.fileName = fileName; }
|
||||
public String getAbsPath() { return absPath; }
|
||||
public void setAbsPath(String absPath) { this.absPath = absPath; }
|
||||
public String getUrl() { return url; }
|
||||
public void setUrl(String url) { this.url = url; }
|
||||
public long getSize() { return size; }
|
||||
public void setSize(long size) { this.size = size; }
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class DeliveryOrderController extends BaseController
|
||||
/**
|
||||
* 查询配送单据主列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('document:order:list')")
|
||||
// @PreAuthorize("@ss.hasPermi('document:order:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(DeliveryOrder deliveryOrder)
|
||||
{
|
||||
@@ -64,7 +64,7 @@ public class DeliveryOrderController extends BaseController
|
||||
/**
|
||||
* 获取配送单据主详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('document:order:query')")
|
||||
// @PreAuthorize("@ss.hasPermi('document:order:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
@@ -105,6 +105,11 @@ public class DeliveryOrderController extends BaseController
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存配送单
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
// @PreAuthorize("@ss.hasPermi('document:order:add')")
|
||||
// @Log(title = "配送单据主-保存(含附件)", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/save")
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.delivery.project.document.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.delivery.framework.web.domain.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
@@ -115,6 +116,12 @@ public class DeliveryOrder extends BaseEntity
|
||||
@Excel(name = "是否删除", readConverterExp = "0=正常,1=已删除")
|
||||
private String isDelete;
|
||||
|
||||
/** 连表查询用:附件列表 */
|
||||
private List<DeliveryAttachment> attachments;
|
||||
|
||||
public List<DeliveryAttachment> getAttachments() { return attachments; }
|
||||
public void setAttachments(List<DeliveryAttachment> attachments) { this.attachments = attachments; }
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
|
||||
@@ -114,3 +114,7 @@ minio:
|
||||
secretKey: admin123
|
||||
bucketName: delivery
|
||||
public-read: true
|
||||
|
||||
upload:
|
||||
base-dir: /data/upload/images
|
||||
base-url: http://192.168.1.28/files
|
||||
@@ -4,8 +4,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.delivery.project.document.mapper.DeliveryOrderMapper">
|
||||
|
||||
<resultMap type="DeliveryOrder" id="DeliveryOrderResult">
|
||||
<result property="id" column="id" />
|
||||
<resultMap type="com.delivery.project.document.domain.DeliveryOrder" id="DeliveryOrderResult">
|
||||
<!-- 用 <id> 保证连表折叠 -->
|
||||
<id property="id" column="id"/>
|
||||
<result property="xmMs" column="xm_ms"/>
|
||||
<result property="xmNo" column="xm_no"/>
|
||||
<result property="wlNo" column="wl_no"/>
|
||||
@@ -15,20 +16,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="sapNo" column="sap_no"/>
|
||||
<result property="gysMc" column="gys_mc"/>
|
||||
<result property="remark" column="remark"/>
|
||||
|
||||
<result property="originName" column="origin_name"/>
|
||||
<result property="originLng" column="origin_lng"/>
|
||||
<result property="originLat" column="origin_lat"/>
|
||||
|
||||
<result property="destName" column="dest_name"/>
|
||||
<result property="destLng" column="dest_lng"/>
|
||||
<result property="destLat" column="dest_lat"/>
|
||||
|
||||
<result property="deliveryDate" column="delivery_date"/>
|
||||
<result property="vehiclePlate" column="vehicle_plate"/>
|
||||
|
||||
<result property="shipperName" column="shipper_name"/>
|
||||
<result property="shipperPhone" column="shipper_phone"/>
|
||||
|
||||
<result property="receiverName" column="receiver_name"/>
|
||||
<result property="receiverPhone" column="receiver_phone"/>
|
||||
<result property="receiverOrgName" column="receiver_org_name"/>
|
||||
|
||||
<result property="deliveryTon" column="delivery_ton"/>
|
||||
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
@@ -36,42 +44,104 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="isDelete" column="is_delete"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 附件行(按你给的 DeliveryAttachment 字段) -->
|
||||
<resultMap id="DeliveryAttachmentInlineResult"
|
||||
type="com.delivery.project.document.domain.DeliveryAttachment">
|
||||
<id property="id" column="att_id"/>
|
||||
<result property="orderId" column="att_order_id"/>
|
||||
<result property="scene" column="att_scene"/>
|
||||
<result property="bizType" column="att_biz_type"/>
|
||||
<result property="url" column="att_url"/>
|
||||
<result property="status" column="att_status"/>
|
||||
<result property="sortNo" column="att_sort_no"/>
|
||||
<result property="remark" column="att_remark"/>
|
||||
<result property="createBy" column="att_create_by"/>
|
||||
<result property="createTime" column="att_create_time"/>
|
||||
<result property="updateBy" column="att_update_by"/>
|
||||
<result property="updateTime" column="att_update_time"/>
|
||||
<result property="isDelete" column="att_is_delete"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 主实体 + 附件集合 -->
|
||||
<resultMap id="DeliveryOrderWithAttachResult"
|
||||
type="com.delivery.project.document.domain.DeliveryOrder"
|
||||
extends="DeliveryOrderResult">
|
||||
<collection property="attachments"
|
||||
resultMap="DeliveryAttachmentInlineResult"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectDeliveryOrderVoWithAttach">
|
||||
select
|
||||
do.id, do.xm_ms, do.xm_no, do.wl_no, do.wl_ms, do.real_qty, do.dw, do.sap_no, do.gys_mc,
|
||||
do.remark, do.origin_name, do.origin_lng, do.origin_lat,
|
||||
do.dest_name, do.dest_lng, do.dest_lat,
|
||||
do.delivery_date, do.vehicle_plate,
|
||||
do.shipper_name, do.shipper_phone,
|
||||
do.receiver_name, do.receiver_phone, do.receiver_org_name,
|
||||
do.delivery_ton, do.create_by, do.create_time, do.update_by, do.update_time, do.is_delete,
|
||||
|
||||
-- 附件列(att_ 前缀)
|
||||
da.id as att_id,
|
||||
da.order_id as att_order_id,
|
||||
da.scene as att_scene,
|
||||
da.biz_type as att_biz_type,
|
||||
da.url as att_url,
|
||||
da.status as att_status,
|
||||
da.sort_no as att_sort_no,
|
||||
da.remark as att_remark,
|
||||
da.create_by as att_create_by,
|
||||
da.create_time as att_create_time,
|
||||
da.update_by as att_update_by,
|
||||
da.update_time as att_update_time,
|
||||
da.is_delete as att_is_delete
|
||||
|
||||
from delivery_order do
|
||||
left join delivery_attachment da
|
||||
on da.order_id = do.id
|
||||
and da.is_delete = '0'
|
||||
</sql>
|
||||
|
||||
<sql id="selectDeliveryOrderVo">
|
||||
select id, xm_ms, xm_no, wl_no, wl_ms, real_qty, dw, sap_no, gys_mc, remark, origin_name, origin_lng, origin_lat, dest_name, dest_lng, dest_lat, delivery_date, vehicle_plate, shipper_name, shipper_phone, receiver_name, receiver_phone, receiver_org_name, delivery_ton, create_by, create_time, update_by, update_time, is_delete from delivery_order
|
||||
</sql>
|
||||
|
||||
<select id="selectDeliveryOrderList" parameterType="DeliveryOrder" resultMap="DeliveryOrderResult">
|
||||
<include refid="selectDeliveryOrderVo"/>
|
||||
<select id="selectDeliveryOrderList"
|
||||
parameterType="com.delivery.project.document.domain.DeliveryOrder"
|
||||
resultMap="DeliveryOrderWithAttachResult">
|
||||
<include refid="selectDeliveryOrderVoWithAttach"/>
|
||||
<where>
|
||||
<if test="xmMs != null and xmMs != ''"> and xm_ms = #{xmMs}</if>
|
||||
<if test="xmNo != null and xmNo != ''"> and xm_no = #{xmNo}</if>
|
||||
<if test="wlNo != null and wlNo != ''"> and wl_no = #{wlNo}</if>
|
||||
<if test="wlMs != null and wlMs != ''"> and wl_ms = #{wlMs}</if>
|
||||
<if test="realQty != null "> and real_qty = #{realQty}</if>
|
||||
<if test="dw != null and dw != ''"> and dw = #{dw}</if>
|
||||
<if test="sapNo != null and sapNo != ''"> and sap_no = #{sapNo}</if>
|
||||
<if test="gysMc != null and gysMc != ''"> and gys_mc = #{gysMc}</if>
|
||||
<if test="originName != null and originName != ''"> and origin_name like concat('%', #{originName}, '%')</if>
|
||||
<if test="originLng != null "> and origin_lng = #{originLng}</if>
|
||||
<if test="originLat != null "> and origin_lat = #{originLat}</if>
|
||||
<if test="destName != null and destName != ''"> and dest_name like concat('%', #{destName}, '%')</if>
|
||||
<if test="destLng != null "> and dest_lng = #{destLng}</if>
|
||||
<if test="destLat != null "> and dest_lat = #{destLat}</if>
|
||||
<if test="deliveryDate != null "> and delivery_date = #{deliveryDate}</if>
|
||||
<if test="vehiclePlate != null and vehiclePlate != ''"> and vehicle_plate = #{vehiclePlate}</if>
|
||||
<if test="shipperName != null and shipperName != ''"> and shipper_name like concat('%', #{shipperName}, '%')</if>
|
||||
<if test="shipperPhone != null and shipperPhone != ''"> and shipper_phone = #{shipperPhone}</if>
|
||||
<if test="receiverName != null and receiverName != ''"> and receiver_name like concat('%', #{receiverName}, '%')</if>
|
||||
<if test="receiverPhone != null and receiverPhone != ''"> and receiver_phone = #{receiverPhone}</if>
|
||||
<if test="receiverOrgName != null and receiverOrgName != ''"> and receiver_org_name like concat('%', #{receiverOrgName}, '%')</if>
|
||||
<if test="deliveryTon != null "> and delivery_ton = #{deliveryTon}</if>
|
||||
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
|
||||
<if test="xmMs != null and xmMs != ''"> and do.xm_ms = #{xmMs}</if>
|
||||
<if test="xmNo != null and xmNo != ''"> and do.xm_no = #{xmNo}</if>
|
||||
<if test="wlNo != null and wlNo != ''"> and do.wl_no = #{wlNo}</if>
|
||||
<if test="wlMs != null and wlMs != ''"> and do.wl_ms = #{wlMs}</if>
|
||||
<if test="realQty != null "> and do.real_qty = #{realQty}</if>
|
||||
<if test="dw != null and dw != ''"> and do.dw = #{dw}</if>
|
||||
<if test="sapNo != null and sapNo != ''"> and do.sap_no = #{sapNo}</if>
|
||||
<if test="gysMc != null and gysMc != ''"> and do.gys_mc = #{gysMc}</if>
|
||||
<if test="originName != null and originName != ''"> and do.origin_name like concat('%', #{originName}, '%')</if>
|
||||
<if test="originLng != null "> and do.origin_lng = #{originLng}</if>
|
||||
<if test="originLat != null "> and do.origin_lat = #{originLat}</if>
|
||||
<if test="destName != null and destName != ''"> and do.dest_name like concat('%', #{destName}, '%')</if>
|
||||
<if test="destLng != null "> and do.dest_lng = #{destLng}</if>
|
||||
<if test="destLat != null "> and do.dest_lat = #{destLat}</if>
|
||||
<if test="deliveryDate != null "> and do.delivery_date = #{deliveryDate}</if>
|
||||
<if test="vehiclePlate != null and vehiclePlate != ''"> and do.vehicle_plate = #{vehiclePlate}</if>
|
||||
<if test="shipperName != null and shipperName != ''"> and do.shipper_name like concat('%', #{shipperName}, '%')</if>
|
||||
<if test="shipperPhone != null and shipperPhone != ''"> and do.shipper_phone = #{shipperPhone}</if>
|
||||
<if test="receiverName != null and receiverName != ''"> and do.receiver_name like concat('%', #{receiverName}, '%')</if>
|
||||
<if test="receiverPhone != null and receiverPhone != ''"> and do.receiver_phone = #{receiverPhone}</if>
|
||||
<if test="receiverOrgName != null and receiverOrgName != ''"> and do.receiver_org_name like concat('%', #{receiverOrgName}, '%')</if>
|
||||
<if test="deliveryTon != null "> and do.delivery_ton = #{deliveryTon}</if>
|
||||
<if test="isDelete != null and isDelete != ''"> and do.is_delete = #{isDelete}</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectDeliveryOrderById" parameterType="Long" resultMap="DeliveryOrderResult">
|
||||
<include refid="selectDeliveryOrderVo"/>
|
||||
where id = #{id}
|
||||
<select id="selectDeliveryOrderById"
|
||||
parameterType="long"
|
||||
resultMap="DeliveryOrderWithAttachResult">
|
||||
<include refid="selectDeliveryOrderVoWithAttach"/>
|
||||
where do.id = #{id}
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<insert id="insertDeliveryOrder" parameterType="DeliveryOrder" useGeneratedKeys="true" keyProperty="id">
|
||||
|
||||
Reference in New Issue
Block a user