Browse Source

发票下载是否已经被当前登录人下载统计以及页面展示

徐滕 3 tuần trước cách đây
mục cha
commit
dc6da2db26

+ 41 - 1
src/main/java/com/jeeplus/modules/workfullmanage/web/WorkFullManageController.java

@@ -47,6 +47,7 @@ import com.jeeplus.modules.workfullmanage.service.WorkFullDesignService;
 import com.jeeplus.modules.workfullmanage.service.WorkFullManageService;
 import com.jeeplus.modules.workfullmanage.service.WorkFullSurveyService;
 import com.jeeplus.modules.workfullmanage.utils.ZipUtils;
+import com.jeeplus.modules.workinvoice.service.WorkInvoiceDownloadRecordService;
 import com.jeeplus.modules.workproject.entity.WorkProject;
 import com.jeeplus.modules.workproject.service.WorkProjectService;
 import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
@@ -142,6 +143,8 @@ public class WorkFullManageController extends BaseController {
 	private WorkFullConstructService workFullConstructService;
 	@Autowired
 	private WorkFullSurveyService workFullSurveyService;
+	@Autowired
+	private WorkInvoiceDownloadRecordService downloadRecordService;
 
 	//生产环境域名
 	@Value("${serverDomain}")
@@ -879,14 +882,16 @@ public class WorkFullManageController extends BaseController {
 
 	/**
 	 * 下载附件(文件没有时间戳前缀)
+	 * 下载成功后记录当前用户的下载行为,仅完整下载成功才做标记
 	 */
 	@RequestMapping("/downLoadOMSInvoiceAttachzip")
-	public void downLoadOMSInvoiceAttachzip(String file, String fileName, HttpServletResponse response) {
+	public void downLoadOMSInvoiceAttachzip(String file, String fileName, String invoiceId, HttpServletResponse response) {
 		// 声明临时变量,用于finally清理
 		File localTargetDirFile = null;
 		File zipFile = null;
 		InputStream is = null;
 		OutputStream os = null;
+		boolean downloadSuccess = false; // 标记下载是否成功完成
 
 		try {
 			// 1. 解析OSS Key
@@ -953,6 +958,7 @@ public class WorkFullManageController extends BaseController {
 				os.write(buffer, 0, len);
 			}
 			os.flush();
+			downloadSuccess = true; // 文件流完整写入,标记为下载成功
 			logger.info("ZIP文件已返回给前端下载:{}", zipFileName);
 
 		} catch (Exception e) {
@@ -981,10 +987,44 @@ public class WorkFullManageController extends BaseController {
 				ZipUtils.deleteFolder(localTargetDirFile);
 			}
 		}
+
+		// 9. 下载成功后记录下载行为(在finally之后,确保只有完整下载才记录)
+		if (downloadSuccess) {
+			try {
+				downloadRecordService.recordDownloadSuccess(invoiceId, file);
+				logger.info("发票下载记录成功:invoiceId={}, userId={}", invoiceId, UserUtils.getUser().getId());
+			} catch (Exception e) {
+				logger.error("发票下载记录失败!", e);
+			}
+		}
 	}
 
 
 	/**
+	 * 查询当前登录用户对指定发票的下载状态
+	 * @param invoiceIds 逗号分隔的发票ID列表
+	 * @return 已下载的发票ID集合(JSON数组)
+	 */
+	@RequestMapping("/queryInvoiceDownloadStatus")
+	@ResponseBody
+	public Map<String, Object> queryInvoiceDownloadStatus(@RequestParam(value = "invoiceIds", required = false) String invoiceIds) {
+		Map<String, Object> result = Maps.newHashMap();
+		try {
+			if (StringUtils.isBlank(invoiceIds)) {
+				result.put("downloadedIds", new ArrayList<>());
+				return result;
+			}
+			List<String> invoiceIdList = Arrays.asList(invoiceIds.split(","));
+			List<String> downloadedIds = downloadRecordService.findDownloadedInvoiceIds(invoiceIdList);
+			result.put("downloadedIds", downloadedIds);
+		} catch (Exception e) {
+			logger.error("查询发票下载状态失败!", e);
+			result.put("downloadedIds", new ArrayList<>());
+		}
+		return result;
+	}
+
+	/**
 	 * 阿里云文件通过文件key获取临时查看url
 	 * @return
 	 */

+ 31 - 0
src/main/java/com/jeeplus/modules/workinvoice/dao/WorkInvoiceDownloadRecordDao.java

@@ -0,0 +1,31 @@
+package com.jeeplus.modules.workinvoice.dao;
+
+import com.jeeplus.common.persistence.CrudDao;
+import com.jeeplus.common.persistence.annotation.MyBatisDao;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceDownloadRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 发票下载记录DAO接口
+ */
+@MyBatisDao
+public interface WorkInvoiceDownloadRecordDao extends CrudDao<WorkInvoiceDownloadRecord> {
+
+    /**
+     * 根据用户ID和发票ID列表批量查询已下载的发票ID
+     * @param userId 用户ID
+     * @param invoiceIds 发票ID列表
+     * @return 已下载的发票ID列表
+     */
+    List<String> findDownloadedInvoiceIds(@Param("userId") String userId, @Param("invoiceIds") List<String> invoiceIds);
+
+    /**
+     * 根据用户ID和发票ID查询是否已下载
+     * @param userId 用户ID
+     * @param invoiceId 发票ID
+     * @return 下载记录数量
+     */
+    int countByUserIdAndInvoiceId(@Param("userId") String userId, @Param("invoiceId") String invoiceId);
+}

+ 69 - 0
src/main/java/com/jeeplus/modules/workinvoice/entity/WorkInvoiceDownloadRecord.java

@@ -0,0 +1,69 @@
+package com.jeeplus.modules.workinvoice.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jeeplus.common.persistence.DataEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 发票下载记录实体
+ * 对应表 work_invoice_download_record
+ * 记录当前登录用户是否成功下载指定 OSS 发票文件
+ */
+public class WorkInvoiceDownloadRecord extends DataEntity<WorkInvoiceDownloadRecord> {
+
+    /** 下载用户ID */
+    private String userId;
+
+    /** 发票ID(work_invoice表的id) */
+    private String invoiceId;
+
+    /** OSS文件URL */
+    private String fileUrl;
+
+    /** 下载成功时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date downloadTime;
+
+    public WorkInvoiceDownloadRecord() {
+        super();
+    }
+
+    public WorkInvoiceDownloadRecord(String id) {
+        super(id);
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getInvoiceId() {
+        return invoiceId;
+    }
+
+    public void setInvoiceId(String invoiceId) {
+        this.invoiceId = invoiceId;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public Date getDownloadTime() {
+        return downloadTime;
+    }
+
+    public void setDownloadTime(Date downloadTime) {
+        this.downloadTime = downloadTime;
+    }
+}

+ 77 - 0
src/main/java/com/jeeplus/modules/workinvoice/service/WorkInvoiceDownloadRecordService.java

@@ -0,0 +1,77 @@
+package com.jeeplus.modules.workinvoice.service;
+
+import com.jeeplus.common.service.CrudService;
+import com.jeeplus.common.utils.IdGen;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import com.jeeplus.modules.workinvoice.dao.WorkInvoiceDownloadRecordDao;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceDownloadRecord;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 发票下载记录Service
+ * 记录当前登录用户是否成功下载指定 OSS 发票文件
+ */
+@Service
+@Transactional(readOnly = true)
+public class WorkInvoiceDownloadRecordService extends CrudService<WorkInvoiceDownloadRecordDao, WorkInvoiceDownloadRecord> {
+
+    /**
+     * 记录下载成功
+     * 仅当文件流完整写入响应后才调用此方法
+     *
+     * @param invoiceId 发票ID
+     * @param fileUrl   OSS文件URL
+     */
+    @Transactional(readOnly = false)
+    public void recordDownloadSuccess(String invoiceId, String fileUrl) {
+        if (StringUtils.isBlank(fileUrl)) {
+            return;
+        }
+        String userId = UserUtils.getUser().getId();
+        WorkInvoiceDownloadRecord record = new WorkInvoiceDownloadRecord();
+        record.setId(IdGen.uuid());
+        record.setUserId(userId);
+        record.setInvoiceId(invoiceId);
+        record.setFileUrl(fileUrl);
+        record.setDownloadTime(new Date());
+        record.setCreateBy(UserUtils.getUser());
+        record.setCreateDate(new Date());
+        record.setUpdateBy(UserUtils.getUser());
+        record.setUpdateDate(new Date());
+        record.setDelFlag("0");
+        dao.insert(record);
+    }
+
+    /**
+     * 批量查询当前用户已下载的发票ID列表
+     *
+     * @param invoiceIds 发票ID列表
+     * @return 已下载的发票ID列表
+     */
+    public List<String> findDownloadedInvoiceIds(List<String> invoiceIds) {
+        if (invoiceIds == null || invoiceIds.isEmpty()) {
+            return java.util.Collections.emptyList();
+        }
+        String userId = UserUtils.getUser().getId();
+        return dao.findDownloadedInvoiceIds(userId, invoiceIds);
+    }
+
+    /**
+     * 查询当前用户是否已下载指定发票
+     *
+     * @param invoiceId 发票ID
+     * @return true=已下载,false=未下载
+     */
+    public boolean isDownloaded(String invoiceId) {
+        if (StringUtils.isBlank(invoiceId)) {
+            return false;
+        }
+        String userId = UserUtils.getUser().getId();
+        return dao.countByUserIdAndInvoiceId(userId, invoiceId) > 0;
+    }
+}

+ 17 - 0
src/main/java/com/jeeplus/modules/workinvoice/web/WorkInvoiceTwoController.java

@@ -48,6 +48,7 @@ import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceCloud;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceExport;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceProjectRelation;
+import com.jeeplus.modules.workinvoice.service.WorkInvoiceDownloadRecordService;
 import com.jeeplus.modules.workinvoice.service.WorkInvoiceService;
 import com.jeeplus.modules.workinvoicealter.entity.WorkInvoiceAlter;
 import com.jeeplus.modules.workinvoicealter.service.WorkInvoiceAlterService;
@@ -127,6 +128,8 @@ public class WorkInvoiceTwoController extends BaseController {
 	private ActTaskService actTaskService;
 	@Autowired
 	private ActivityService activityService;
+	@Autowired
+	private WorkInvoiceDownloadRecordService downloadRecordService;
 
 	@Autowired
 	private HttpServletRequest request;
@@ -227,9 +230,23 @@ public class WorkInvoiceTwoController extends BaseController {
 			}
 
 		}
+
+		// 查询当前登录用户对列表中发票的下载状态
+		List<String> invoiceIdList = new ArrayList<>();
+		for (WorkInvoice inv : workInvoiceList) {
+			if (StringUtils.isNotBlank(inv.getId())) {
+				invoiceIdList.add(inv.getId());
+			}
+		}
+		String downloadedInvoiceIdsStr = "";
+		if (!invoiceIdList.isEmpty()) {
+			List<String> downloadedIds = downloadRecordService.findDownloadedInvoiceIds(invoiceIdList);
+			downloadedInvoiceIdsStr = String.join(",", downloadedIds);
+		}
 		model.addAttribute("page", page);
 		model.addAttribute("sumMoney", getSumMoney);
 		model.addAttribute("workInvoiceShow", workInvoice);
+		model.addAttribute("downloadedInvoiceIds", downloadedInvoiceIdsStr);
 		return "modules/workinvoice/workInvoiceTwoList";
 	}
 	/**

+ 146 - 0
src/main/resources/mappings/modules/workinvoice/WorkInvoiceDownloadRecordDao.xml

@@ -0,0 +1,146 @@
+<?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.jeeplus.modules.workinvoice.dao.WorkInvoiceDownloadRecordDao">
+
+    <sql id="downloadRecordColumns">
+        a.id AS "id",
+        a.user_id AS "userId",
+        a.invoice_id AS "invoiceId",
+        a.file_url AS "fileUrl",
+        a.download_time AS "downloadTime",
+        a.create_by AS "createBy.id",
+        a.create_date AS "createDate",
+        a.update_by AS "updateBy.id",
+        a.update_date AS "updateDate",
+        a.del_flag AS "delFlag"
+    </sql>
+
+    <sql id="downloadRecordJoins">
+        LEFT JOIN sys_user createBy ON createBy.id = a.create_by
+        LEFT JOIN sys_user updateBy ON updateBy.id = a.update_by
+    </sql>
+
+    <!-- 根据ID获取单条记录 -->
+    <select id="get" resultType="WorkInvoiceDownloadRecord">
+        SELECT
+            <include refid="downloadRecordColumns"/>
+        FROM work_invoice_download_record a
+        <include refid="downloadRecordJoins"/>
+        WHERE a.id = #{id} AND a.del_flag = '0'
+    </select>
+
+    <!-- 查询列表 -->
+    <select id="findList" resultType="WorkInvoiceDownloadRecord">
+        SELECT
+            <include refid="downloadRecordColumns"/>
+        FROM work_invoice_download_record a
+        <include refid="downloadRecordJoins"/>
+        <where>
+            a.del_flag = '0'
+            <if test="userId != null and userId != ''">
+                AND a.user_id = #{userId}
+            </if>
+            <if test="invoiceId != null and invoiceId != ''">
+                AND a.invoice_id = #{invoiceId}
+            </if>
+            <if test="fileUrl != null and fileUrl != ''">
+                AND a.file_url = #{fileUrl}
+            </if>
+        </where>
+        ORDER BY a.download_time DESC
+    </select>
+
+    <!-- 查询所有列表 -->
+    <select id="findAllList" resultType="WorkInvoiceDownloadRecord">
+        SELECT
+            <include refid="downloadRecordColumns"/>
+        FROM work_invoice_download_record a
+        <include refid="downloadRecordJoins"/>
+        WHERE a.del_flag = '0'
+        ORDER BY a.download_time DESC
+    </select>
+
+    <!-- 插入记录 -->
+    <insert id="insert">
+        INSERT INTO work_invoice_download_record (
+            id,
+            user_id,
+            invoice_id,
+            file_url,
+            download_time,
+            create_by,
+            create_date,
+            update_by,
+            update_date,
+            del_flag
+        ) VALUES (
+            #{id},
+            #{userId},
+            #{invoiceId},
+            #{fileUrl},
+            #{downloadTime},
+            #{createBy.id},
+            #{createDate},
+            #{updateBy.id},
+            #{updateDate},
+            #{delFlag}
+        )
+    </insert>
+
+    <!-- 更新记录 -->
+    <update id="update">
+        UPDATE work_invoice_download_record SET
+            user_id = #{userId},
+            invoice_id = #{invoiceId},
+            file_url = #{fileUrl},
+            download_time = #{downloadTime},
+            update_by = #{updateBy.id},
+            update_date = #{updateDate}
+        WHERE id = #{id}
+    </update>
+
+    <!-- 删除记录(逻辑删除) -->
+    <update id="delete">
+        UPDATE work_invoice_download_record SET
+            del_flag = '1'
+        WHERE id = #{id}
+    </update>
+
+    <!-- 批量查询当前用户已下载的发票ID -->
+    <select id="findDownloadedInvoiceIds" resultType="java.lang.String">
+        SELECT DISTINCT a.invoice_id
+        FROM work_invoice_download_record a
+        WHERE a.user_id = #{userId}
+          AND a.del_flag = '0'
+          AND a.invoice_id IS NOT NULL
+          AND a.invoice_id IN
+        <foreach collection="invoiceIds" item="invoiceId" open="(" separator="," close=")">
+            #{invoiceId}
+        </foreach>
+    </select>
+
+    <!-- 查询当前用户对某发票的下载记录数量 -->
+    <select id="countByUserIdAndInvoiceId" resultType="int">
+        SELECT COUNT(1)
+        FROM work_invoice_download_record a
+        WHERE a.user_id = #{userId}
+          AND a.invoice_id = #{invoiceId}
+          AND a.del_flag = '0'
+    </select>
+
+    <!-- 分页查询总数 -->
+    <select id="queryCount" resultType="int">
+        SELECT COUNT(1)
+        FROM work_invoice_download_record a
+        <where>
+            a.del_flag = '0'
+            <if test="userId != null and userId != ''">
+                AND a.user_id = #{userId}
+            </if>
+            <if test="invoiceId != null and invoiceId != ''">
+                AND a.invoice_id = #{invoiceId}
+            </if>
+        </where>
+    </select>
+
+</mapper>

+ 17 - 0
src/main/resources/mysqlDateBase/work_invoice_download_record.sql

@@ -0,0 +1,17 @@
+-- 发票下载记录表
+-- 记录当前登录用户是否成功下载指定 OSS 发票文件
+CREATE TABLE IF NOT EXISTS `work_invoice_download_record` (
+  `id` varchar(64) NOT NULL COMMENT '主键ID',
+  `user_id` varchar(64) NOT NULL COMMENT '下载用户ID',
+  `invoice_id` varchar(64) DEFAULT NULL COMMENT '发票ID(work_invoice表的id)',
+  `file_url` varchar(1000) NOT NULL COMMENT 'OSS文件URL',
+  `download_time` datetime NOT NULL COMMENT '下载成功时间',
+  `create_by` varchar(64) DEFAULT NULL COMMENT '创建者',
+  `create_date` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) DEFAULT NULL COMMENT '更新者',
+  `update_date` datetime DEFAULT NULL COMMENT '更新时间',
+  `del_flag` char(1) DEFAULT '0' COMMENT '删除标记(0:正常;1:删除)',
+  PRIMARY KEY (`id`),
+  KEY `idx_user_invoice` (`user_id`, `invoice_id`),
+  KEY `idx_user_file` (`user_id`, `file_url`(255))
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发票下载记录表';

+ 70 - 4
src/main/webapp/webpage/modules/workinvoice/workInvoiceTwoList.jsp

@@ -8,6 +8,8 @@
 	<meta name="decorator" content="default"/>
 	<script type="text/javascript">
 		<%--var Srole = "<%= UserUtils.getSelectRole().getName()%>";--%>
+		// 当前登录用户已下载过的发票ID集合(逗号分隔字符串)
+		var downloadedInvoiceIds = "${downloadedInvoiceIds}";
 
 		$(document).ready(function() {
 			// laydate.render({
@@ -224,6 +226,55 @@
 
 
 
+		/**
+		 * 发票下载点击处理
+		 * 1. 通过隐藏iframe触发文件下载(服务端会自动记录下载成功)
+		 * 2. 延迟后更新当前行的下载状态显示
+		 */
+		function onInvoiceDownload(invoiceId) {
+			// 延迟更新UI:等待服务端完成下载记录
+			setTimeout(function() {
+				// 将该invoiceId加入已下载集合
+				if (downloadedInvoiceIds) {
+					var ids = downloadedInvoiceIds.split(',');
+					if (ids.indexOf(invoiceId) === -1) {
+						downloadedInvoiceIds += ',' + invoiceId;
+					}
+				} else {
+					downloadedInvoiceIds = invoiceId;
+				}
+				// 更新表格中对应行的下载状态
+				try {
+					var tableData = layui.table.cache['contentTable'];
+					if (tableData) {
+						for (var i = 0; i < tableData.length; i++) {
+							if (tableData[i].id === invoiceId) {
+								// 更新操作列按钮文字
+								var row = $("tr[data-index='" + i + "']");
+								row.find('.btn-xs').each(function() {
+									var text = $(this).text();
+									if (text.indexOf('下载所有格式发票') !== -1 || text.indexOf('已下载') !== -1) {
+										$(this).text('已下载-再次下载').removeClass('btn-primary').addClass('btn-default');
+									}
+								});
+								// 更新下载状态列
+								var cells = row.find('td');
+								cells.each(function() {
+									var cellText = $(this).text().trim();
+									if (cellText === '未下载') {
+										$(this).html('<span style="color:green;font-weight:bold;">已下载</span>');
+									}
+								});
+								break;
+							}
+						}
+					}
+				} catch(e) {
+					console.log('更新下载状态异常:', e);
+				}
+			}, 3000);
+		}
+
 		function receiptInvoice(title,url,width,height,target){
 
 			if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){//如果是移动端,就使用自适应大小弹窗
@@ -905,6 +956,17 @@
 							var xml = "<span style=\"cursor:default;\" class=\"status-label status-label-" + '未上传' + "\" >未上传</span>";
 						return xml;
 					}}
+				,{align:'center', title: '下载状态', fixed: 'right', width:80,templet:function(d){
+						if(d && d.omsAttachmentUrl && d.omsAttachmentUrl.trim() !== '') {
+							var downloadedSet = downloadedInvoiceIds ? downloadedInvoiceIds.split(',') : [];
+							if (downloadedSet.indexOf(d.id) !== -1) {
+								return '<span style="color:green;font-weight:bold;">已下载</span>';
+							} else {
+								return '<span style="color:#999;">未下载</span>';
+							}
+						}
+						return '';
+					}}
 				,{align:'center', title: '审核状态', fixed: 'right', width:70,templet:function(d){
 						<%--var st = getAuditState(d.status);--%>
 
@@ -1003,10 +1065,14 @@
 							var clientName = d.clientName || ''; // 开票单位
 							// 编码文件名(核心解决中文乱码)
 							var fileName = encodeURIComponent('dzfp_' + widNumber + '_' + clientName + '_' + invoiceNum + '所有发票格式');
-							// 拼接完整下载地址
-							var downLoadUrl = baseCtx + '/workfullmanage/workFullManage/downLoadOMSInvoiceAttachzip?file=' + fileUrl + '&fileName=' + fileName;
-							// 修正:HTML用class属性(不是className),href拼接转义引号,补充分号
-							xml += "<a href=\"" + downLoadUrl + "\" class=\"btn btn-xs btn-primary\">下载所有格式发票</a>";
+							// 拼接完整下载地址(包含invoiceId用于记录下载)
+							var downLoadUrl = baseCtx + '/workfullmanage/workFullManage/downLoadOMSInvoiceAttachzip?file=' + fileUrl + '&fileName=' + fileName + '&invoiceId=' + d.id;
+							// 判断是否已下载,显示不同按钮文字
+							var downloadedSet = downloadedInvoiceIds ? downloadedInvoiceIds.split(',') : [];
+							var isDownloaded = downloadedSet.indexOf(d.id) !== -1;
+							var btnText = isDownloaded ? '已下载-再次下载' : '下载所有格式发票';
+							var btnClass = isDownloaded ? 'btn btn-xs btn-default' : 'btn btn-xs btn-primary';
+							xml += "<a href=\"" + downLoadUrl + "\" class=\"" + btnClass + "\" onclick=\"onInvoiceDownload('" + d.id + "')\">" + btnText + "</a>";
 						}
 
 						if(d.redInvoice != undefined && d.redInvoice =="1"  && Math.sign(d.money) !== -1)