Forráskód Böngészése

Merge remote-tracking branch 'remotes/origin/developer' into developerB

plf 3 éve
szülő
commit
589c9f52db

+ 36 - 0
src/main/java/com/caimei/modules/archive/dao/CmOrderArchiveDao.java

@@ -0,0 +1,36 @@
+package com.caimei.modules.archive.dao;
+
+import com.caimei.modules.archive.entity.CmOrderArchiveFile;
+import com.thinkgem.jeesite.common.persistence.CrudDao;
+import com.thinkgem.jeesite.common.persistence.annotation.MyBatisDao;
+import com.caimei.modules.archive.entity.CmOrderArchive;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 订单资料DAO接口
+ * @author Aslee
+ * @version 2021-07-30
+ */
+@MyBatisDao
+public interface CmOrderArchiveDao extends CrudDao<CmOrderArchive> {
+
+    List<CmOrderArchiveFile> getArchiveFileList(@Param("archiveId") int archiveId);
+
+    void insertArchiveFile(CmOrderArchiveFile archiveFile);
+
+    CmOrderArchiveFile getArchiveFileById(@Param("fileId") Integer fileId);
+
+    void deleteArchiveFile(Integer fileId);
+
+    void updateArchiveFile(@Param("fileId") Integer fileId, @Param("orderArchiveId") Integer orderArchiveId);
+
+    String getAllFileIds(Integer orderArchiveId);
+
+    Integer checkFileName(@Param("fileName") String fileName,@Param("orderArchiveId") Integer orderArchiveId,@Param("fileIds") String fileIds);
+
+    Integer checkShopOrderIdExist(Integer shopOrderId);
+
+    Integer checkShopOrderIdAble(Integer shopOrderId);
+}

+ 138 - 0
src/main/java/com/caimei/modules/archive/entity/CmOrderArchive.java

@@ -0,0 +1,138 @@
+package com.caimei.modules.archive.entity;
+
+import org.hibernate.validator.constraints.Length;
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import com.thinkgem.jeesite.common.persistence.DataEntity;
+
+/**
+ * 订单资料Entity
+ * @author Aslee
+ * @version 2021-07-30
+ */
+public class CmOrderArchive extends DataEntity<CmOrderArchive> {
+	
+	private static final long serialVersionUID = 1L;
+	private String archiveNo;		// 资料编号
+	private String title;		// 资料标题
+	private Integer shopOrderId;		// 子订单id
+	private String shopName;		// 供应商名称
+	private String clubName;		// 机构名称
+	private String tag;		// 商品标签,以| 隔开
+	private Integer rebateFlag;		// 返佣订单标识:0非返佣,1返佣
+	private String remark;		// 备注
+	private Date addTime;		// 添加时间
+
+	private Integer orderId;	// 主订单id
+
+	/**
+	 * 上传文件id,以","隔开
+	 */
+	private String fileIds;
+
+
+	public CmOrderArchive() {
+		super();
+	}
+
+	public CmOrderArchive(String id){
+		super(id);
+	}
+
+	@Length(min=0, max=16, message="资料编号长度必须介于 0 和 15 之间")
+	public String getArchiveNo() {
+		return archiveNo;
+	}
+
+	public void setArchiveNo(String archiveNo) {
+		this.archiveNo = archiveNo;
+	}
+	
+	@Length(min=0, max=35, message="资料标题长度必须介于 0 和 35 之间")
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+	
+	public Integer getShopOrderId() {
+		return shopOrderId;
+	}
+
+	public void setShopOrderId(Integer shopOrderId) {
+		this.shopOrderId = shopOrderId;
+	}
+	
+	@Length(min=0, max=55, message="供应商名称长度必须介于 0 和 55 之间")
+	public String getShopName() {
+		return shopName;
+	}
+
+	public void setShopName(String shopName) {
+		this.shopName = shopName;
+	}
+	
+	@Length(min=0, max=55, message="机构名称长度必须介于 0 和 55 之间")
+	public String getClubName() {
+		return clubName;
+	}
+
+	public void setClubName(String clubName) {
+		this.clubName = clubName;
+	}
+	
+	public String getTag() {
+		return tag;
+	}
+
+	public void setTag(String tag) {
+		this.tag = tag;
+	}
+	
+	public Integer getRebateFlag() {
+		return rebateFlag;
+	}
+
+	public void setRebateFlag(Integer rebateFlag) {
+		this.rebateFlag = rebateFlag;
+	}
+	
+	@Length(min=0, max=200, message="备注长度必须介于 0 和 200 之间")
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+	
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	public Date getAddTime() {
+		return addTime;
+	}
+
+	public void setAddTime(Date addTime) {
+		this.addTime = addTime;
+	}
+
+	public Integer getOrderId() {
+		return orderId;
+	}
+
+	public void setOrderId(Integer orderId) {
+		this.orderId = orderId;
+	}
+
+	public String getFileIds() {
+		return fileIds;
+	}
+
+	public void setFileIds(String fileIds) {
+		this.fileIds = fileIds;
+	}
+}

+ 62 - 0
src/main/java/com/caimei/modules/archive/entity/CmOrderArchiveFile.java

@@ -0,0 +1,62 @@
+package com.caimei.modules.archive.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.thinkgem.jeesite.common.persistence.DataEntity;
+import org.hibernate.validator.constraints.Length;
+
+import java.util.Date;
+
+/**
+ * 订单资料文件Entity
+ * @author Aslee
+ * @version 2021-07-30
+ */
+public class CmOrderArchiveFile extends DataEntity<CmOrderArchiveFile> {
+
+	private static final long serialVersionUID = 1L;
+	private Integer orderArchiveId;		// 订单资料id
+	private String fileName;			// 文件名称
+	private String ossName;			// 文件名称
+	private String ossUrl;			// 文件链接
+	private Date uploadTime;		//上传时间
+
+	public Integer getOrderArchiveId() {
+		return orderArchiveId;
+	}
+
+	public void setOrderArchiveId(Integer orderArchiveId) {
+		this.orderArchiveId = orderArchiveId;
+	}
+
+	public String getFileName() {
+		return fileName;
+	}
+
+	public void setFileName(String fileName) {
+		this.fileName = fileName;
+	}
+
+	public String getOssName() {
+		return ossName;
+	}
+
+	public void setOssName(String ossName) {
+		this.ossName = ossName;
+	}
+
+	public String getOssUrl() {
+		return ossUrl;
+	}
+
+	public void setOssUrl(String ossUrl) {
+		this.ossUrl = ossUrl;
+	}
+
+	public Date getUploadTime() {
+		return uploadTime;
+	}
+
+	public void setUploadTime(Date uploadTime) {
+		this.uploadTime = uploadTime;
+	}
+}

+ 234 - 0
src/main/java/com/caimei/modules/archive/service/CmOrderArchiveService.java

@@ -0,0 +1,234 @@
+package com.caimei.modules.archive.service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.caimei.modules.archive.entity.CmOrderArchiveFile;
+import com.caimei.modules.archive.utils.OssArchiveUtil;
+import com.caimei.modules.oss.entity.CmOssArchivePdf;
+import com.caimei.modules.oss.utils.OSSUtils;
+import com.caimei.modules.product.entity.Product;
+import com.caimei.utils.CodeUtil;
+import com.caimei.utils.StringUtil;
+import com.thinkgem.jeesite.common.config.Global;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.thinkgem.jeesite.common.persistence.Page;
+import com.thinkgem.jeesite.common.service.CrudService;
+import com.caimei.modules.archive.entity.CmOrderArchive;
+import com.caimei.modules.archive.dao.CmOrderArchiveDao;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 订单资料Service
+ * @author Aslee
+ * @version 2021-07-30
+ */
+@Service
+@Transactional(readOnly = true)
+public class CmOrderArchiveService extends CrudService<CmOrderArchiveDao, CmOrderArchive> {
+	@Resource
+	private CmOrderArchiveDao cmOrderArchiveDao;
+
+	public CmOrderArchive get(String id) {
+		return super.get(id);
+	}
+	
+	public List<CmOrderArchive> findList(CmOrderArchive cmOrderArchive) {
+		return super.findList(cmOrderArchive);
+	}
+	
+	public Page<CmOrderArchive> findPage(Page<CmOrderArchive> page, CmOrderArchive cmOrderArchive) {
+		return super.findPage(page, cmOrderArchive);
+	}
+
+
+	@Transactional(readOnly = false)
+	public void saveArchive(CmOrderArchive cmOrderArchive) {
+        if (cmOrderArchive.getIsNewRecord()) {
+            SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
+            StringBuilder orderArchiveNo = new StringBuilder(format.format(new Date()));
+            Random random = new Random();
+            for (int i = 0; i < 8; i++) {
+                orderArchiveNo.append(random.nextInt(10));
+            }
+            cmOrderArchive.setArchiveNo(orderArchiveNo.toString());
+            cmOrderArchive.setAddTime(new Date());
+        }
+		super.save(cmOrderArchive);
+        String fileIds = cmOrderArchive.getFileIds();
+        if (StringUtil.isNotEmpty(fileIds)) {
+            for (String id : fileIds.split(",")) {
+                if (StringUtil.isNotBlank(id)) {
+                    cmOrderArchiveDao.updateArchiveFile(Integer.valueOf(id),Integer.valueOf(cmOrderArchive.getId()));
+                }
+            }
+        }
+	}
+	
+	@Transactional(readOnly = false)
+	public void delete(CmOrderArchive cmOrderArchive) {
+		super.delete(cmOrderArchive);
+	}
+
+    public List<CmOrderArchiveFile> getArchiveFileList(String archiveId) {
+        return cmOrderArchiveDao.getArchiveFileList(Integer.parseInt(archiveId));
+    }
+
+    @Transactional(readOnly = false)
+    public Map<String, Object> upload(MultipartFile multipartFile, String fileName, Integer orderArchiveId, String fileIds) {
+        Map<String, Object> map = new HashMap<>();
+        Integer fileIdByFileName = cmOrderArchiveDao.checkFileName(fileName, orderArchiveId, fileIds);
+        if (null != fileIdByFileName) {
+            map.put("success", false);
+            map.put("msg", "文件已存在");
+            return map;
+        }
+        String fileAllName = multipartFile.getOriginalFilename();
+        String fileType = fileAllName.substring(fileAllName.lastIndexOf(".") + 1);
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        String filePath = uuid + "." + fileType;
+        String contentType = OssArchiveUtil.getContentType(fileAllName);
+        try {
+            //保存本地
+            File file = OssArchiveUtil.ossUpload(multipartFile);
+            logger.info("默认路径>>>" + file.getAbsolutePath());
+            //上传oss
+            String url = OssArchiveUtil.ossUpload(filePath, "archiveFile/", file, contentType);
+            //删除本地文件
+            OssArchiveUtil.deleteFile(file);
+            //保存关联关系
+            CmOrderArchiveFile archiveFile = new CmOrderArchiveFile();
+            archiveFile.setFileName(fileName);
+            archiveFile.setOssName(filePath);
+            archiveFile.setOssUrl(url);
+            archiveFile.setUploadTime(new Date());
+            cmOrderArchiveDao.insertArchiveFile(archiveFile);
+            map.put("success", true);
+            map.put("msg", "操作成功");
+            map.put("archiveFile", archiveFile);
+        } catch (Exception e) {
+            e.printStackTrace();
+            map.put("success", false);
+            map.put("msg", "操作失败");
+            logger.info("上传异常!!!");
+        }
+        return map;
+    }
+
+    @Transactional(readOnly = false)
+    public void deleteFile(Integer fileId) {
+        CmOrderArchiveFile archiveFile = cmOrderArchiveDao.getArchiveFileById(fileId);
+        if (archiveFile != null) {
+            //删除oss服务器上的文件
+            OssArchiveUtil.deleteSingleFile("archiveFile/", archiveFile.getOssName());
+            cmOrderArchiveDao.deleteArchiveFile(fileId);
+        }
+    }
+
+    public Page<CmOrderArchiveFile> findArchiveFilePage(Page<CmOrderArchiveFile> cmOrderArchiveFilePage, CmOrderArchiveFile cmOrderArchiveFile) {
+        cmOrderArchiveFile.setPage(cmOrderArchiveFilePage);
+        cmOrderArchiveFilePage.setList(cmOrderArchiveDao.getArchiveFileList(cmOrderArchiveFile.getOrderArchiveId()));
+        return cmOrderArchiveFilePage;
+    }
+
+    public void downFile(Integer fileId, HttpServletRequest request, HttpServletResponse response) throws IOException {
+        CmOrderArchiveFile archiveFile = cmOrderArchiveDao.getArchiveFileById(fileId);
+        String fileName = archiveFile.getFileName();
+        OssArchiveUtil.downFile("archiveFile/", archiveFile.getOssName(), fileName);
+        download(request, response, fileName);
+    }
+
+    public void download(HttpServletRequest request, HttpServletResponse response, String fileName) throws IOException {
+        File file = new File("./" + fileName);
+        //  文件存在才下载
+        if (file.exists()) {
+            OutputStream out = null;
+            FileInputStream in = null;
+            try {
+                // 1.读取要下载的内容
+                in = new FileInputStream(file);
+
+                // 2. 告诉浏览器下载的方式以及一些设置
+                // 解决文件名乱码问题,获取浏览器类型,转换对应文件名编码格式,IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码
+                String agent = request.getHeader("user-agent");
+                if (agent.contains("FireFox")) {
+                    fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
+                } else {
+                    fileName = URLEncoder.encode(fileName, "UTF-8");
+                }
+                // 设置下载文件的mineType,告诉浏览器下载文件类型
+                String mineType = request.getServletContext().getMimeType(fileName);
+                response.setContentType(mineType);
+                // 设置一个响应头,无论是否被浏览器解析,都下载
+                response.setHeader("Content-disposition", "attachment; filename=" + fileName);
+                // 将要下载的文件内容通过输出流写到浏览器
+                out = response.getOutputStream();
+                int len = 0;
+                byte[] buffer = new byte[1024];
+                while ((len = in.read(buffer)) > 0) {
+                    out.write(buffer, 0, len);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                if (out != null) {
+                    out.close();
+                }
+                if (in != null) {
+                    in.close();
+                }
+                file.delete();
+            }
+        }
+    }
+
+    public String getAllFileIds(Integer orderArchiveId) {
+        return cmOrderArchiveDao.getAllFileIds(orderArchiveId);
+    }
+
+    public Map<String, Object> checkShopOrderId(CmOrderArchive cmOrderArchive) {
+        HashMap<String, Object> result = new HashMap<>(2);
+        if (StringUtil.isEmpty(cmOrderArchive.getId())) {
+            result.put("code", -1);
+            result.put("msg", "请输入资料id");
+            return result;
+        }
+        // 当新的子订单id和数据库中的子订单id不同时,校验新的子订单id是否可用
+        CmOrderArchive dbArchive = cmOrderArchiveDao.get(cmOrderArchive.getId());
+        if (!cmOrderArchive.getShopOrderId().equals(dbArchive.getShopOrderId())) {
+            // 检查子订单id是否存在
+            Integer existId = cmOrderArchiveDao.checkShopOrderIdExist(cmOrderArchive.getShopOrderId());
+            if (null == existId) {
+                result.put("code", -2);
+                result.put("msg", "子订单id不存在");
+                return result;
+            } else {
+                // 检查子订单是否已被使用
+                Integer ableId = cmOrderArchiveDao.checkShopOrderIdAble(cmOrderArchive.getShopOrderId());
+                if (null == ableId) {
+                    result.put("code", -3);
+                    result.put("msg", "该子订单id已使用");
+                    return result;
+                }
+            }
+        }
+        result.put("code", 0);
+        result.put("msg", "该子订单id可以使用");
+        return result;
+    }
+}

+ 190 - 0
src/main/java/com/caimei/modules/archive/utils/OssArchiveUtil.java

@@ -0,0 +1,190 @@
+package com.caimei.modules.archive.utils;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.model.GetObjectRequest;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.UploadFileRequest;
+import com.thinkgem.jeesite.common.config.Global;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.UUID;
+
+public class OssArchiveUtil {
+    private static String endpoint = Global.getConfig("aliyun.endpoint");
+    private static String accessKeyId = Global.getConfig("aliyun.accessKeyId");
+    private static String accessKeySecret = Global.getConfig("aliyun.accessKeySecret");
+    private static String privateBucket = Global.getConfig("aliyun.bucketName");
+    private static String config = Global.getConfig("cm.config");
+
+    public static String ossUpload(String fileName, String path, File file, String contentType) {
+        String url = null;
+        try {
+            if ("product".equals(config)) {
+                fileName = "prod/" + path + fileName;
+            } else {
+                fileName = config + "/" + path + fileName;
+            }
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            ObjectMetadata meta = new ObjectMetadata();
+            meta.setContentType(contentType);
+            UploadFileRequest uploadFileRequest = new UploadFileRequest(privateBucket, fileName);
+            // 指定上传的本地文件。
+            uploadFileRequest.setUploadFile(file.toString());
+            // 指定上传并发线程数,默认为1。
+            uploadFileRequest.setTaskNum(10);
+            // 指定上传的分片大小,范围为100KB~5GB,默认为文件大小/10000。
+            uploadFileRequest.setPartSize(1024 * 1024);
+            // 开启断点续传,默认关闭。
+            uploadFileRequest.setEnableCheckpoint(true);
+            uploadFileRequest.setCheckpointFile(file.getAbsolutePath() + "uploadFile.ucp");
+            // 文件的元数据。
+            uploadFileRequest.setObjectMetadata(meta);
+            // 设置上传成功回调,参数为Callback类型。
+            //uploadFileRequest.setCallback("<yourCallbackEvent>");
+            // 断点续传上传。
+            ossClient.uploadFile(uploadFileRequest);
+            // 有效期100年
+            Date expiration = new Date(System.currentTimeMillis() + 60L * 60 * 24 * 365 * 100 * 1000);
+            url = ossClient.generatePresignedUrl(privateBucket, fileName, expiration).toString();
+            // 关闭OSSClient。
+            ossClient.shutdown();
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+        return url;
+    }
+
+
+    /**
+     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
+     */
+    public static String getContentType(String fileName) {
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        if (".bmp".equalsIgnoreCase(fileExtension)) {
+            return "image/bmp";
+        }
+        if (".gif".equalsIgnoreCase(fileExtension)) {
+            return "image/gif";
+        }
+        if (".jpeg".equalsIgnoreCase(fileExtension)) {
+            return "image/jpeg";
+        }
+        if (".jpg".equalsIgnoreCase(fileExtension)) {
+            return "image/jpg";
+        }
+        if (".png".equalsIgnoreCase(fileExtension)) {
+            return "image/png";
+        }
+        if (".html".equalsIgnoreCase(fileExtension)) {
+            return "text/html";
+        }
+        if (".txt".equalsIgnoreCase(fileExtension)) {
+            return "text/plain";
+        }
+        if (".vsd".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.visio";
+        }
+        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.ms-powerpoint";
+        }
+        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
+            return "application/msword";
+        }
+        if (".xml".equalsIgnoreCase(fileExtension)) {
+            return "text/xml";
+        }
+        if (".mp4".equalsIgnoreCase(fileExtension)) {
+            return "video/mp4";
+        }
+        if (".mp3".equalsIgnoreCase(fileExtension)) {
+            return "audio/mp3";
+        }
+        if (".pdf".equalsIgnoreCase(fileExtension)) {
+            return "application/pdf";
+        }
+        return "text/html";
+    }
+
+    public static void deleteFile(File... files) {
+        for (File file : files) {
+            //logger.info("File:[{}]",file.getAbsolutePath());
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+    }
+
+    public static File ossUpload(MultipartFile file) throws IOException {
+        // 获取文件名
+        String fileName = file.getOriginalFilename();
+        // 获取文件后缀
+        String prefix = fileName.substring(fileName.lastIndexOf("."));
+        // 用uuid作为文件名,防止生成的临时文件重复
+        File excelFile = File.createTempFile(UUID.randomUUID().toString(), prefix);
+        // MultipartFile to File
+        file.transferTo(excelFile);
+        //程序结束时,删除临时文件
+        return excelFile;
+    }
+
+    /**
+     * 授权生成签名URL临时访问
+     *
+     * @param fileName 文件名称
+     */
+    public static String getOssUrl(String path, String fileName) {
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 设置URL过期时间为1个小时
+        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000);
+        if ("product".equals(config)) {
+            fileName = "prod/" + path + fileName;
+        } else {
+            fileName = config + "/" + path + fileName;
+        }
+        String url = ossClient.generatePresignedUrl(privateBucket, fileName, expiration).toString();
+        // 关闭OSSClient。
+        ossClient.shutdown();
+        return url;
+    }
+
+    /**
+     * oss单个文件删除
+     *
+     * @param fileName 文件名称或文件夹名称
+     */
+    public static void deleteSingleFile(String path, String fileName) {
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 删除文件。如需删除文件夹,请将ObjectName设置为对应的文件夹名称。
+        // 如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。
+        if ("product".equals(config)) {
+            fileName = "prod/" + path + fileName;
+        } else {
+            fileName = config + "/" + path + fileName;
+        }
+        ossClient.deleteObject(privateBucket, fileName);
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
+
+    /**
+     * oss单个文件下载
+     */
+    public static void downFile(String path, String ossName, String fileName) {
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
+        if ("product".equals(config)) {
+            ossName = "prod/" + path + ossName;
+        } else {
+            ossName = config + "/" + path + ossName;
+        }
+        ossClient.getObject(new GetObjectRequest(privateBucket, ossName), new File("./" + fileName));
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
+}

+ 132 - 0
src/main/java/com/caimei/modules/archive/web/CmOrderArchiveController.java

@@ -0,0 +1,132 @@
+package com.caimei.modules.archive.web;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.caimei.modules.archive.entity.CmOrderArchiveFile;
+import com.caimei.modules.product.entity.Product;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import com.thinkgem.jeesite.common.config.Global;
+import com.thinkgem.jeesite.common.persistence.Page;
+import com.thinkgem.jeesite.common.web.BaseController;
+import com.thinkgem.jeesite.common.utils.StringUtils;
+import com.caimei.modules.archive.entity.CmOrderArchive;
+import com.caimei.modules.archive.service.CmOrderArchiveService;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 订单资料Controller
+ * @author Aslee
+ * @version 2021-07-30
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/archive/cmOrderArchive")
+public class CmOrderArchiveController extends BaseController {
+
+	@Autowired
+	private CmOrderArchiveService cmOrderArchiveService;
+	
+	@ModelAttribute
+	public CmOrderArchive get(@RequestParam(required=false) String id) {
+		CmOrderArchive entity = null;
+		if (StringUtils.isNotBlank(id)){
+			entity = cmOrderArchiveService.get(id);
+		}
+		if (entity == null){
+			entity = new CmOrderArchive();
+		}
+		return entity;
+	}
+	
+	@RequestMapping(value = {"list", ""})
+	public String list(CmOrderArchive cmOrderArchive, HttpServletRequest request, HttpServletResponse response, Model model) {
+		Page<CmOrderArchive> page = cmOrderArchiveService.findPage(new Page<CmOrderArchive>(request, response), cmOrderArchive); 
+		model.addAttribute("page", page);
+		return "modules/archive/cmOrderArchiveList";
+	}
+
+	@RequestMapping(value = "form")
+	public String form(CmOrderArchive cmOrderArchive, Model model) {
+        List<CmOrderArchiveFile> archiveFileList = null;
+        if (StringUtils.isNotEmpty(cmOrderArchive.getId())) {
+            archiveFileList = cmOrderArchiveService.getArchiveFileList(cmOrderArchive.getId());
+        }
+		model.addAttribute("cmOrderArchive", cmOrderArchive);
+		model.addAttribute("archiveFileList", archiveFileList);
+		return "modules/archive/cmOrderArchiveForm";
+	}
+
+	@RequestMapping(value = "save")
+	public String save(CmOrderArchive cmOrderArchive, Model model, RedirectAttributes redirectAttributes) {
+		if (!beanValidator(model, cmOrderArchive)){
+			return form(cmOrderArchive, model);
+		}
+		cmOrderArchiveService.saveArchive(cmOrderArchive);
+		addMessage(redirectAttributes, "保存订单资料成功");
+		return "redirect:"+Global.getAdminPath()+"/archive/cmOrderArchive/?repage";
+	}
+
+	@RequestMapping(value = "checkShopOrderId")
+    @ResponseBody
+    public Map<String,Object> checkShopOrderId(CmOrderArchive cmOrderArchive) {
+        return cmOrderArchiveService.checkShopOrderId(cmOrderArchive);
+    }
+
+	@RequestMapping(value = "delete")
+	public String delete(CmOrderArchive cmOrderArchive, RedirectAttributes redirectAttributes) {
+		cmOrderArchiveService.delete(cmOrderArchive);
+		addMessage(redirectAttributes, "删除订单资料成功");
+		return "redirect:"+Global.getAdminPath()+"/archive/cmOrderArchive/?repage";
+	}
+
+	@ResponseBody
+	@RequestMapping(value = "upload")
+	public Map<String, Object> upload(@RequestParam("file") MultipartFile file, @RequestParam("fileName") String fileName,
+									  @RequestParam("orderArchiveId") Integer orderArchiveId, @RequestParam("fileIds") String fileIds) {
+		return cmOrderArchiveService.upload(file, fileName, orderArchiveId, fileIds);
+	}
+
+	/**
+	 * oss文件删除
+	 */
+	@RequestMapping(value = "deleteFile")
+	public void deleteFile(Integer fileId) {
+		cmOrderArchiveService.deleteFile(fileId);
+	}
+
+	@RequestMapping(value = "findArchiveFilePage")
+	public String findArchiveFilePage(CmOrderArchiveFile cmOrderArchiveFile, Model model, HttpServletRequest request, HttpServletResponse response) {
+		Page<CmOrderArchiveFile> page = cmOrderArchiveService.findArchiveFilePage(new Page<CmOrderArchiveFile>(request, response), cmOrderArchiveFile);
+		CmOrderArchive cmOrderArchive = cmOrderArchiveService.get(cmOrderArchiveFile.getOrderArchiveId().toString());
+		String allFileIds = cmOrderArchiveService.getAllFileIds(cmOrderArchiveFile.getOrderArchiveId());
+		model.addAttribute("page", page);
+		model.addAttribute("cmOrderArchive", cmOrderArchive);
+		model.addAttribute("allFileIds", allFileIds);
+		return "modules/archive/cmOrderArchiveFileList";
+	}
+
+	/**
+	 * 下载单个文件
+	 */
+	@RequestMapping("/downFile")
+	public void downFile(Integer fileId, HttpServletRequest request, HttpServletResponse response) {
+		try {
+			cmOrderArchiveService.downFile(fileId, request, response);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+}

+ 9 - 0
src/main/java/com/caimei/modules/order/entity/NewShopOrder.java

@@ -123,6 +123,7 @@ public class NewShopOrder extends DataEntity<NewShopOrder> {
     private String modifyShouldPayDate;   //修改应付金额的时间
     private Double payed;//已付金额
     private String clubName; //会所名称
+    private Integer orderArchiveId; //订单资料id
 
     // 备注图片
     private String remarkImage1;
@@ -1102,4 +1103,12 @@ public class NewShopOrder extends DataEntity<NewShopOrder> {
     public void setPayShopOtherFee(boolean payShopOtherFee) {
         this.payShopOtherFee = payShopOtherFee;
     }
+
+    public Integer getOrderArchiveId() {
+        return orderArchiveId;
+    }
+
+    public void setOrderArchiveId(Integer orderArchiveId) {
+        this.orderArchiveId = orderArchiveId;
+    }
 }

+ 184 - 0
src/main/resources/mappings/modules/archive/CmOrderArchiveMapper.xml

@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.caimei.modules.archive.dao.CmOrderArchiveDao">
+    
+	<sql id="cmOrderArchiveColumns">
+		a.id AS "id",
+		a.archiveNo AS "archiveNo",
+		a.title AS "title",
+		a.shopOrderId AS "shopOrderId",
+		a.shopName AS "shopName",
+		a.clubName AS "clubName",
+		a.tag AS "tag",
+		a.rebateFlag AS "rebateFlag",
+		a.remark AS "remark",
+		a.addTime AS "addTime",
+		so.orderID AS "orderId"
+	</sql>
+	
+	<sql id="cmOrderArchiveJoins">
+		left join cm_shop_order so on a.shopOrderId = so.shopOrderID
+	</sql>
+    
+	<select id="get" resultType="CmOrderArchive">
+		SELECT 
+			<include refid="cmOrderArchiveColumns"/>
+		FROM cm_order_archive a
+		<include refid="cmOrderArchiveJoins"/>
+		WHERE a.id = #{id}
+	</select>
+	
+	<select id="findList" resultType="CmOrderArchive">
+		SELECT 
+			<include refid="cmOrderArchiveColumns"/>
+		FROM cm_order_archive a
+		<include refid="cmOrderArchiveJoins"/>
+		<where>
+			
+			<if test="archiveNo != null and archiveNo != ''">
+				AND a.archiveNo LIKE 
+					<if test="dbName == 'oracle'">'%'||#{archiveNo}||'%'</if>
+					<if test="dbName == 'mssql'">'%'+#{archiveNo}+'%'</if>
+					<if test="dbName == 'mysql'">concat('%',#{archiveNo},'%')</if>
+			</if>
+			<if test="title != null and title != ''">
+				AND a.title LIKE 
+					<if test="dbName == 'oracle'">'%'||#{title}||'%'</if>
+					<if test="dbName == 'mssql'">'%'+#{title}+'%'</if>
+					<if test="dbName == 'mysql'">concat('%',#{title},'%')</if>
+			</if>
+			<if test="shopOrderId != null and shopOrderId != ''">
+				AND a.shopOrderId = #{shopOrderId}
+			</if>
+			<if test="shopName != null and shopName != ''">
+				AND a.shopName LIKE 
+					<if test="dbName == 'oracle'">'%'||#{shopName}||'%'</if>
+					<if test="dbName == 'mssql'">'%'+#{shopName}+'%'</if>
+					<if test="dbName == 'mysql'">concat('%',#{shopName},'%')</if>
+			</if>
+			<if test="clubName != null and clubName != ''">
+				AND a.clubName LIKE 
+					<if test="dbName == 'oracle'">'%'||#{clubName}||'%'</if>
+					<if test="dbName == 'mssql'">'%'+#{clubName}+'%'</if>
+					<if test="dbName == 'mysql'">concat('%',#{clubName},'%')</if>
+			</if>
+			<if test="tag != null and tag != ''">
+				AND a.tag LIKE 
+					<if test="dbName == 'oracle'">'%'||#{tag}||'%'</if>
+					<if test="dbName == 'mssql'">'%'+#{tag}+'%'</if>
+					<if test="dbName == 'mysql'">concat('%',#{tag},'%')</if>
+			</if>
+			<if test="rebateFlag != null">
+				AND a.rebateFlag = #{rebateFlag}
+			</if>
+		</where>
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+                order by a.id desc
+			</otherwise>
+		</choose>
+	</select>
+	
+	<select id="findAllList" resultType="CmOrderArchive">
+		SELECT 
+			<include refid="cmOrderArchiveColumns"/>
+		FROM cm_order_archive a
+		<include refid="cmOrderArchiveJoins"/>
+		<where>
+			
+		</where>		
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+			</otherwise>
+		</choose>
+	</select>
+	<select id="getArchiveFileList" resultType="com.caimei.modules.archive.entity.CmOrderArchiveFile">
+		select id, fileName, ossName, ossUrl
+		from cm_order_archive_file
+		where orderArchiveId = #{archiveId}
+	</select>
+	<select id="getArchiveFileById" resultType="com.caimei.modules.archive.entity.CmOrderArchiveFile">
+		select id, fileName, ossName
+		from cm_order_archive_file
+		where id = #{fileId}
+	</select>
+	<select id="getAllFileIds" resultType="java.lang.String">
+		select GROUP_CONCAT(id) from cm_order_archive_file where orderArchiveId = #{orderArchiveId} group by orderArchiveId
+	</select>
+	<select id="checkFileName" resultType="java.lang.Integer">
+		select id from cm_order_archive_file
+		<where>
+			fileName = #{fileName} and (
+			<if test="orderArchiveId != null">
+				orderArchiveId = #{orderArchiveId}
+			</if>
+			<if test="fileIds != null and fileIds != ''">
+				or id in
+				<foreach collection="fileIds.split(',')" item="fileId" index="index" open="(" separator="," close=")" >
+					#{fileId}
+				</foreach>
+			</if>
+			)
+		</where>
+	</select>
+    <select id="checkShopOrderIdExist" resultType="java.lang.Integer">
+        select so.shopOrderID from cm_shop_order so
+        where so.shopOrderID = #{shopOrderId}
+    </select>
+
+    <select id="checkShopOrderIdAble" resultType="java.lang.Integer">
+        select so.shopOrderID from cm_shop_order so
+        where so.shopOrderID = #{shopOrderId}
+        and so.shopOrderID not in
+        (select a.shopOrderId from cm_order_archive a
+        where a.shopOrderId is not null) limit 1
+    </select>
+
+    <insert id="insert" parameterType="CmOrderArchive"  keyProperty="id" useGeneratedKeys="true">
+		INSERT INTO cm_order_archive(
+			archiveNo,
+			addTime
+		) VALUES (
+			#{archiveNo},
+			#{addTime}
+		)
+	</insert>
+	<insert id="insertArchiveFile" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
+		insert into cm_order_archive_file(fileName, ossName, ossUrl, uploadTime)
+		values (#{fileName}, #{ossName}, #{ossUrl}, #{uploadTime})
+	</insert>
+
+	<update id="update">
+		UPDATE cm_order_archive SET 	
+			title = #{title},
+			shopOrderId = #{shopOrderId},
+			shopName = #{shopName},
+			clubName = #{clubName},
+			tag = #{tag},
+			rebateFlag = #{rebateFlag},
+			remark = #{remark}
+		WHERE id = #{id}
+	</update>
+	<update id="updateArchiveFile">
+		update cm_order_archive_file
+		set orderArchiveId = #{orderArchiveId}
+		where id = #{fileId}
+	</update>
+
+	<delete id="delete">
+		DELETE FROM cm_order_archive
+		WHERE id = #{id}
+	</delete>
+	<delete id="deleteArchiveFile">
+		delete
+		from cm_order_archive_file
+		where id = #{fileId}
+	</delete>
+
+</mapper>

+ 3 - 2
src/main/resources/mappings/modules/order/ShopOrderMapper.xml

@@ -243,8 +243,9 @@
 	<select id="findListByOrderID" resultType="newShopOrder">
 		SELECT <include refid="shopOrderColumns"/>,
         b.name as shopName,
-        b.commercialCode as commercialCode
-		FROM cm_shop_order a left join shop b on a.shopID = b.shopID
+        b.commercialCode as commercialCode,
+	    oa.id as orderArchiveId
+		FROM cm_shop_order a left join shop b on a.shopID = b.shopID left join cm_order_archive oa on a.shopOrderID = oa.shopOrderId
 		WHERE a.orderID = #{orderID} ORDER BY a.shopOrderNo DESC
 	</select>
 

+ 97 - 0
src/main/webapp/WEB-INF/views/modules/archive/cmOrderArchiveFileList.jsp

@@ -0,0 +1,97 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp" %>
+<html>
+<head>
+    <title>资料列表</title>
+    <meta name="decorator" content="default"/>
+    <style type="text/css">
+        .table th {
+            text-align: center;
+        }
+
+        .table td {
+            text-align: center;
+        }
+
+        #searchForm label {
+            width: 90px;
+            text-align: left;
+            margin-top: 15px
+        }
+    </style>
+    <script type="text/javascript">
+        $(document).ready(function () {
+
+        });
+
+        function page(n, s) {
+            $("#pageNo").val(n);
+            $("#pageSize").val(s);
+            $("#searchForm").submit();
+            return false;
+        }
+
+        function onlynum(obj) {
+            obj.value = obj.value.replace(/[^\d]/g, ""); //清除"数字"以外的字符
+        }
+
+        function downAllFile(allFileIds) {
+            var fileIdArr = allFileIds.toString().split(",");
+            for (var i = 0; i < fileIdArr.length; i++) {
+                var fileId = fileIdArr[i];
+                if (fileId != '') {
+                    if (i > 0) {
+                        sleep(500);
+                        window.location.href = "${ctx}/archive/cmOrderArchive/downFile?fileId=" + fileId;
+                    } else {
+                        window.location.href = "${ctx}/archive/cmOrderArchive/downFile?fileId=" + fileId;
+                    }
+                }
+            }
+        }
+        function sleep(numberMillis) {
+            var now = new Date();
+            var exitTime = now.getTime() + numberMillis;
+            while (true) {
+                now = new Date();
+                if (now.getTime() > exitTime)
+                    return;
+            }
+        }
+    </script>
+</head>
+<body>
+<ul class="nav nav-tabs">
+</ul>
+<sys:message content="${message}"/>
+<div>
+    <label style="margin:10px 15px;font-size: 15px;display: inline">资料列表(订单资料编号:${cmOrderArchive.archiveNo})</label>
+    <a href="javascript:;" class="btn btn-primary" style="display: inline;float: right;margin:0 10px 5px 0" onclick="downAllFile('${allFileIds}')">下载全部</a>
+</div>
+
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>序号</th>
+        <th>资料</th>
+        <th>操作</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${page.list}" var="cmOrderArchiveFile" varStatus="varIndex">
+        <tr>
+            <td>${varIndex.index+1}</td>
+            <td>
+                    ${cmOrderArchiveFile.fileName}
+            </td>
+            <td>
+                <a href="${cmOrderArchiveFile.ossUrl}" target="_blank">预览</a>
+                <a href="${ctx}/archive/cmOrderArchive/downFile?fileId=${cmOrderArchiveFile.id}">下载</a>
+            </td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<div class="pagination">${page}</div>
+</body>
+</html>

+ 489 - 0
src/main/webapp/WEB-INF/views/modules/archive/cmOrderArchiveForm.jsp

@@ -0,0 +1,489 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+	<title>订单资料管理</title>
+	<meta name="decorator" content="default"/>
+	<script type="text/javascript">
+		$(document).ready(function() {
+			//$("#name").focus();
+			$("#inputForm").validate({
+				submitHandler: function(form){
+					var orderArchiveId = $("#id").val();
+					var shopOrderId = $("#shopOrderId").val();
+					$.post("${ctx}/archive/cmOrderArchive/checkShopOrderId",{"id":orderArchiveId,"shopOrderId":shopOrderId},function (result) {
+						if (result.code != 0) {
+							var errorMsg = result.msg;
+							jBox.tip(errorMsg, "error");
+						} else {
+							loading('正在提交,请稍等...');
+							form.submit();
+						}
+					})
+				},
+				errorContainer: "#messageBox",
+				errorPlacement: function(error, element) {
+					$("#messageBox").text("输入有误,请先更正。");
+					if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
+						error.appendTo(element.parent().parent());
+					} else {
+						error.insertAfter(element);
+					}
+				}
+			});
+		});
+
+        /**
+         * @param obj
+         * jquery控制input只能输入数字
+         */
+        function onlynum(obj) {
+            obj.value = obj.value.replace(/[^\d]/g, ""); //清除"数字"以外的字符
+        }
+	</script>
+	<style>
+		.controls .new-tag {
+			display: inline-block;
+			width: 78px;
+			height: 30px;
+			border: 1px solid #e5e5e5;
+			border-radius: 5px;
+			margin: 7px;
+			text-align: center;
+			line-height: 30px;
+			font-size: 14px;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			white-space: nowrap;
+			cursor: pointer;
+		}
+
+		.controls .new-tag.active {
+			border-color: #e15616;
+			color: #e15616;
+		}
+
+		#tagInput {
+			width: 263px;
+			margin: 7px;
+			display: inline-block;
+			height: 30px;
+		}
+
+		.controls .tags-operate .tag-add {
+			height: 40px;
+			line-height: 40px;
+			vertical-align: middle;
+		}
+
+		.upload {
+			position: relative;
+			display: inline-block;
+			background: #D0EEFF;
+			border: 1px solid #99D3F5;
+			border-radius: 4px;
+			padding: 4px 12px;
+			color: #1E88C7;
+			text-decoration: none;
+			text-indent: 0;
+			line-height: 20px;
+			margin-left: 20px;
+			cursor: pointer;
+			width: 52px;
+			height: 20px;
+		}
+
+		.upload input {
+			position: absolute;
+			width: 170px;
+			font-size: 20px;
+			right: 0;
+			top: 0;
+			opacity: 0;
+			cursor: pointer;
+		}
+
+		.upload:hover {
+			background: #AADFFD;
+			border-color: #78C3F3;
+			color: #004974;
+			text-decoration: none;
+		}
+
+		.add-submit {
+			position: relative;
+			display: inline;
+			background: #D0EEFF;
+			border: 1px solid #99D3F5;
+			border-radius: 4px;
+			padding: 4px 12px;
+			color: #1E88C7;
+			text-decoration: none;
+			text-indent: 0;
+			line-height: 20px;
+			margin-left: 20px;
+			cursor: pointer;
+			width: 52px;
+			height: 30px;
+		}
+
+		.add-submit input {
+			position: absolute;
+			width: 50px;
+			font-size: 20px;
+			right: 0;
+			top: 0;
+			opacity: 0;
+			cursor: pointer;
+		}
+
+		.add-submit:hover {
+			background: #AADFFD;
+			border-color: #78C3F3;
+			color: #004974;
+			text-decoration: none;
+		}
+
+		.upload-loading{
+			display: none;
+			width: 32px;
+			height: 32px;
+			margin-left: 10px;
+		}
+		.upload-loading img{
+			width: 16px;
+			height: 16px;
+			margin: 0 auto 0;
+		}
+
+		#file-list-display {
+			width: 600px;
+			height: auto;
+			float: left;
+			margin-left: 20px;
+		}
+
+		#file-list-display p {
+			line-height: 30px;
+			font-size: 14px;
+			color: #333333;
+			margin: 0;
+		}
+
+		#file-list-display p .del {
+			color: #2fa4e7;
+			font-size: 12px;
+			cursor: pointer;
+			margin-left: 20px;
+		}
+
+		.Main-content{
+			height: 100px;
+		}
+	</style>
+</head>
+<body>
+	<ul class="nav nav-tabs">
+		<li><a href="${ctx}/archive/cmOrderArchive/">订单资料列表</a></li>
+		<li class="active"><a href="${ctx}/archive/cmOrderArchive/form?id=${cmOrderArchive.id}">订单资料${not empty cmOrderArchive.id?'编辑':'添加'}</a></li>
+	</ul><br/>
+	<form:form id="inputForm" modelAttribute="cmOrderArchive" action="${ctx}/archive/cmOrderArchive/save" method="post" class="form-horizontal">
+		<form:hidden path="id"/>
+		<form:hidden path="fileIds" id="fileIds"/>
+		<sys:message content="${message}"/>
+		<div class="control-group">
+			<label class="control-label">订单资料标题:</label>
+			<div class="controls">
+				<form:input path="title" htmlEscape="false" maxlength="30" class="input-xlarge "/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label"><font color="red">*</font>子订单ID:</label>
+			<div class="controls">
+                <form:input path="shopOrderId" htmlEscape="false" maxlength="8" class="input-xlarge required" onkeyup="onlynum(this)"/>
+            </div>
+		</div>
+		<div class="control-group">
+			<label class="control-label"><font color="red">*</font>供应商名称:</label>
+			<div class="controls">
+				<form:input path="shopName" htmlEscape="false" maxlength="50" class="input-xlarge required"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label"><font color="red">*</font>机构名称:</label>
+			<div class="controls">
+				<form:input path="clubName" htmlEscape="false" maxlength="50" class="input-xlarge required"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label" style="margin-top: 14px">商品标签:</label>
+			<div class="controls Main-content">
+				<div class="tags-operate">
+					<input type="text" class="reg-input tag-input" id="tagInput" placeholder="输入商品标签,支持添加多个"
+						   maxlength="15">
+					<span class="new-tag tag-add" id="tagAdd">添加</span>
+				</div>
+				<div class="tags-area" id="tagArea"></div>
+				<span class="err-tip" style="display: inline-block;margin-left:-55px;"></span>
+				<input type="hidden" name="tag" value="${cmOrderArchive.tag}" id="tag">
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label"><font color="red">*</font>返佣订单:</label>
+			<div class="controls">
+				<form:select path="rebateFlag" class="input-small ">
+                    <form:option value="0" label="否"/>
+                    <form:option value="1" label="是"/>
+				</form:select>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">备注:</label>
+			<div class="controls">
+                <form:textarea path="remark" htmlEscape="false" rows="3" maxlength="200" class="input-xlarge"/>
+            </div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">资料上传:</label>
+			<input id="uploadFileName" type="text" style="display: inline;margin-left:20px" placeholder="支持pdf、word、png、jpg" disabled="true" class="input-xlarge required" />
+			<div class="upload">
+				<input type="file" name="file" id="archiveFile" accept=".pdf,.doc,.docx,.png,.jpg">选择文件
+            </div>
+			<div class="add-submit">
+				<input id="addSubmit" type="button" value="上传"/>上传&nbsp;
+			</div>
+			<div class="upload-loading">
+				<img alt="gif" src="/static/images/upload.gif" width="32px" border="none">
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">资料列表:</label>
+			<div id='file-list-display'>
+				<c:if test="${not empty archiveFileList}">
+					<c:forEach items="${archiveFileList}" var="archiveFile" varStatus="statusIndex">
+						<p>${archiveFile.fileName}
+							<span class="del"><a href="${archiveFile.ossUrl}" target="_blank">预览</a></span>
+							<span class="del" onclick="dataDelete(this,'${archiveFile.id}')">删除</span>
+						</p>
+					</c:forEach>
+				</c:if>
+			</div>
+		</div>
+		<div class="form-actions">
+			<input id="btnSubmit" class="btn btn-primary" type="submit" value="保 存"/>&nbsp;
+			<input id="btnCancel" class="btn" type="button" value="返 回" onclick="history.go(-1)"/>
+		</div>
+	</form:form>
+<script>
+	// 初始化主营内容数据
+	$(function () {
+
+		var html = '';
+		$('#tagArea').html(html);
+		$('.Main-content').show();
+
+		//主营项目
+		var cMainProVal = $('#tag').val();
+		if (cMainProVal != null && cMainProVal != "") {
+			var _mainPros = cMainProVal.split('|');
+			var proList = $('#tagArea').find('.new-tag');
+			for (var j = 0; j < _mainPros.length; j++) {
+				var _flag = false;
+				for (var i = 0; i < proList.length; i++) {
+					if ($(proList[i]).attr('data-typeName') == _mainPros[j]) {
+						_flag = true;
+					}
+				}
+				if (_flag) {
+					for (var i = 0; i < proList.length; i++) {
+						if ($(proList[i]).attr('data-typeName') == _mainPros[j]) {
+							$(proList[i]).addClass('active');
+						}
+					}
+				} else {
+					$('#tagArea').append('<span class="new-tag up-club-tag active" data-typeName="' + _mainPros[j] + '">' + _mainPros[j] + '</span> ');
+					$('.Main-content').show();
+				}
+			}
+			$('#cMainPro').val(cMainProVal);
+		}
+		//机构品项选择
+		var optsClub = {
+			$tag: $('.up-club-tag'),
+			$tagArea: $('#tagArea'),
+			$mainPro: $('#tag'),
+			$other: $('#tagOther'),
+			$input: $('#tagInput'),
+			$add: $('#tagAdd'),
+			$type: 'club'
+		};
+		getTags(optsClub);
+
+		//点击上传按钮后上传文件
+		$('#addSubmit').click(function () {
+			var filesById = document.getElementById('archiveFile');
+			var files = $('#archiveFile');
+			var fileList = files.prop('files');
+			var fileName = $('#uploadFileName').val();
+			if (files === '' || files.length == 0 || fileName == '') {
+				alertx('请选择上传文件');
+				return;
+			}
+			$("#uploadFileName").val("");
+			var data = new FormData();
+			var orderArchiveId = $("#id").val();
+			var fileIds = $("#fileIds").val();
+			data.append('file', fileList[0]);
+			data.append('fileName', fileName);
+			data.append('orderArchiveId', orderArchiveId);
+			data.append('fileIds', fileIds);
+			$('.upload-loading').css("display", "inline");
+			$.ajax({
+				url: "${ctx}/archive/cmOrderArchive/upload",
+				data: data,
+				type: "POST",
+				processData: false,
+				contentType: false,
+				dataType: "json",
+				success: function (res) {
+					if (res.success) {
+						filesById.value = '';
+						renderFileList(res.archiveFile);
+						$('.upload-loading').hide();
+					} else {
+						$.jBox.tip(res.msg, 'error');
+						$("#uploadFileName").val(fileName);
+						$('.upload-loading').hide();
+					}
+
+				},
+				error: function (json) {
+
+				}
+			});
+		})
+
+		var fileList = [];
+		var fileIds = '';
+		var files = document.getElementById("archiveFile"), renderFileList;
+		//选择上传文件后显示文件名称
+		files.addEventListener("change", function (event) {
+			var name = event.target.files[0].name;
+			console.log(name)
+			$('#uploadFileName').val(name);
+		});
+		var fileListDisplay = document.getElementById('file-list-display');
+		renderFileList = function (data) {
+			fileIds += data.id + ',';
+			console.log(fileIds);
+			$('#fileIds').val(fileIds);
+			fileList.push({fileName: data.fileName, id: data.id, ossUrl: data.ossUrl});
+			fileList.forEach(function (file, index) {
+				var fileDisplayEl = document.createElement("p");
+				var deleteFile = document.createElement("span");
+				var viewFile = document.createElement("span");
+				var viewFileUrl = document.createElement("a");
+				//预览链接
+				viewFileUrl.innerHTML = '预览';
+				viewFileUrl.setAttribute("href", file.ossUrl);
+				viewFileUrl.setAttribute("target", "_blank");
+				//预览按钮
+				viewFile.className = 'viewFile';
+				console.log(viewFile);
+				viewFile.setAttribute("class","del");
+				viewFile.appendChild(viewFileUrl);
+				//删除按钮
+				deleteFile.innerHTML = '删除';
+				deleteFile.className = 'deleteFile';
+				console.log(deleteFile);
+				deleteFile.setAttribute("class","del");
+				deleteFile.setAttribute("onclick", "dataDelete(this, " + file.id + ")");
+
+				fileDisplayEl.setAttribute("id", file.id);
+				fileDisplayEl.innerHTML = file.fileName;
+				fileDisplayEl.appendChild(viewFile);
+				fileDisplayEl.appendChild(deleteFile);
+				fileListDisplay.appendChild(fileDisplayEl);
+			});
+			fileList.splice(0, fileList.length);
+		};
+	});
+
+
+	//选择tags(主营和服务类型通用)
+	function getTags(opts) {
+		opts.$tagArea.on('click', '.new-tag', function () {
+			var $this = $(this);
+			$this.toggleClass('active');
+			setTags(opts);
+		});
+		opts.$other.on('click', function () {
+			opts.$input.css('display', 'inline-block');
+			opts.$add.css('display', 'inline-block');
+		});
+		opts.$add.on('click', function () {
+			var _tag = $.trim(opts.$input.val());
+			if (_tag) {
+				var flag = false;
+				opts.$tagArea.find('.new-tag').each(function (i, v) {
+					var _name = $(v).attr('data-typeName');
+					if (_tag == _name) {
+						flag = true;
+						return false;
+					} else {
+						if (i == opts.$tagArea.find('.new-tag').length) {
+							flag = false;
+						}
+					}
+
+				})
+				if (flag) {
+					opts.$tagArea.find('.new-tag').each(function (i, v) {
+						var _name = $(v).attr('data-typeName');
+						if (_tag == _name) {
+							$(v).addClass('active');
+							alertx('该类型已存在', opts.$add);
+							flag = true;
+							return false;
+						}
+
+					})
+				} else {
+					opts.$tagArea.append('<span class="new-tag up-' + opts.$type + '-tag active" data-typeName="' + _tag + '">' + _tag + '</span> ');
+					setTags(opts);
+					opts.$input.val('');
+					return;
+				}
+			}
+		})
+	}
+
+	//设置tags(主营和服务类型通用)
+	function setTags(opts) {
+		var tagArr = [];
+		opts.$mainPro.val('')
+		opts.$tagArea.find('.new-tag.active').each(function (i, v) {
+			var _typeName = $(v).attr('data-typeName');
+			tagArr.push(_typeName);
+			opts.$mainPro.val(tagArr.join(' | '));
+		})
+	}
+
+	//删除文件
+	function dataDelete(that, id) {
+		console.log($(that).text());
+		$(that).parent().remove();
+		/*var fileIds = $("#fileIds").val();
+		if (fileIds.indexOf(id)) {
+			fileIds.replace(id + ",", "");
+		}*/
+		$.ajax({
+			url: "${ctx}/archive/cmOrderArchive/deleteFile",
+			data: {"fileId": id},
+			async: false,
+			type: "POST"
+		});
+	}
+</script>
+</body>
+</html>

+ 146 - 0
src/main/webapp/WEB-INF/views/modules/archive/cmOrderArchiveList.jsp

@@ -0,0 +1,146 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp" %>
+<html>
+<head>
+    <title>订单资料管理</title>
+    <meta name="decorator" content="default"/>
+    <style type="text/css">
+        .table th {
+            text-align: center;
+        }
+
+        .table td {
+            text-align: center;
+        }
+
+        #searchForm label {
+            width: 90px;
+            text-align: left;
+            margin-top: 15px
+        }
+    </style>
+    <script type="text/javascript">
+        $(document).ready(function () {
+
+        });
+
+        function page(n, s) {
+            $("#pageNo").val(n);
+            $("#pageSize").val(s);
+            $("#searchForm").submit();
+            return false;
+        }
+
+        function onlynum(obj) {
+            obj.value = obj.value.replace(/[^\d]/g, ""); //清除"数字"以外的字符
+        }
+
+        //选择添加商品
+        function showArchiveList(orderArchiveId) {
+            var url = '';
+            var title = '';
+            url = "${ctx}/archive/cmOrderArchive/findArchiveFilePage?orderArchiveId=" + orderArchiveId;
+            title = "资料列表";
+            top.$.jBox("iframe:" + url, {
+                iframeScrolling: 'yes',
+                width: $(top.document).width() - 800,
+                height: $(top.document).height() - 320,
+                persistent: true,
+                title: title,
+                buttons: {"关闭": '-1'}
+            });
+        }
+    </script>
+</head>
+<body>
+<ul class="nav nav-tabs">
+    <li class="active"><a href="${ctx}/archive/cmOrderArchive/">订单资料列表</a></li>
+</ul>
+<form:form id="searchForm" modelAttribute="cmOrderArchive" action="${ctx}/archive/cmOrderArchive/" method="post"
+           class="breadcrumb form-search">
+    <input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
+    <input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
+    <div class="ul-form">
+        <label>资料编号:</label>
+        <form:input path="archiveNo" htmlEscape="false" maxlength="15" class="input-medium"/>
+        <label>资料标题:</label>
+        <form:input path="title" htmlEscape="false" maxlength="35" class="input-medium"/>
+        <label>子订单id:</label>
+        <form:input path="shopOrderId" htmlEscape="false" class="input-medium" onkeyup="onlynum(this)"/>
+        <label>供应商名称:</label>
+        <form:input path="shopName" htmlEscape="false" maxlength="55" class="input-medium"/>
+        <label>机构名称:</label>
+        <form:input path="clubName" htmlEscape="false" maxlength="55" class="input-medium"/>
+        <label>商品标签:</label>
+        <form:input path="tag" htmlEscape="false" class="input-medium"/>
+        <label>返佣订单:</label>
+        <form:select path="rebateFlag" class="input-medium">
+            <form:option value="" label="请选择"/>
+            <form:option value="0" label="否"/>
+            <form:option value="1" label="是"/>
+        </form:select>
+        &nbsp;&nbsp;<input id="btnSubmit" class="btn btn-primary" type="submit" value="查询"/>
+        &nbsp;&nbsp;<input class="btn btn-primary" style="width: 120px"
+                           onclick="window.location='${ctx}/archive/cmOrderArchive/save'" value="生成订单资料编号"/>
+        <div class="clearfix"></div>
+    </div>
+</form:form>
+<sys:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>序号</th>
+        <th>订单资料编号</th>
+        <th>订单资料标题</th>
+        <th>子订单ID</th>
+        <th>供应商名称</th>
+        <th>机构名称</th>
+        <th>商品标签</th>
+        <th>返佣订单</th>
+        <th>添加时间</th>
+        <th>操作</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${page.list}" var="cmOrderArchive" varStatus="varIndex">
+        <tr>
+            <td>${varIndex.index+1}</td>
+            <td>
+                    ${cmOrderArchive.archiveNo}
+            </td>
+            <td>
+                    ${cmOrderArchive.title}
+            </td>
+            <td>
+                <a href="${ctx}/order/detail?id=${cmOrderArchive.orderId}">
+                        ${cmOrderArchive.shopOrderId}
+                </a>
+            </td>
+            <td>
+                    ${cmOrderArchive.shopName}
+            </td>
+            <td>
+                    ${cmOrderArchive.clubName}
+            </td>
+            <td>
+                    ${cmOrderArchive.tag}
+            </td>
+            <td>
+                    ${cmOrderArchive.rebateFlag eq 0?'否':(cmOrderArchive.rebateFlag eq 1?'是':'')}
+            </td>
+            <td>
+                <fmt:formatDate value="${cmOrderArchive.addTime}" pattern="yyyy-MM-dd HH:mm:ss"/>
+            </td>
+            <td>
+                <a href="${ctx}/archive/cmOrderArchive/form?id=${cmOrderArchive.id}">编辑</a>
+                <a href="${ctx}/archive/cmOrderArchive/delete?id=${cmOrderArchive.id}"
+                   onclick="return confirmx('确认要删除该数据吗?', this.href)">删除</a>
+                <a href="JavaScript:;" onclick="showArchiveList(${cmOrderArchive.id})">资料列表</a>
+            </td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<div class="pagination">${page}</div>
+</body>
+</html>

+ 3 - 0
src/main/webapp/WEB-INF/views/modules/order/orderDetail.jsp

@@ -415,6 +415,9 @@
                 <c:if test="${order.status ne '0'}">
                     <a onclick="copyText('${shopOrder.shopOrderID}')" style="cursor:pointer;">供应商订单二维码</a>
                 </c:if>
+                <c:if test="${shopOrder.orderArchiveId ne null}">
+                    <a href="${ctx}/archive/cmOrderArchive/form?id=${shopOrder.orderArchiveId}">查看订单资料</a>
+                </c:if>
             </div>
             <c:if test="${order.status ne 0 && order.status ne 11}">
                 <div class="delivery-wrapper">