feat(seal): 实现印章编辑与删除功能及优化上传组件
- 后端新增印章更新与删除接口及相关业务逻辑
- 删除印章时校验是否存在进行中的用印审批申请
- 重构图片读取与哈希计算逻辑以提高代码复用性
- 前端新增印章编辑与删除的API请求方法
- 页面增加编辑与删除操作入口并完善删除确认弹窗
- 升级图片上传组件为拖拽上传并支持编辑时回显图片
| | |
| | | public CommonResult<List<Map<String,Object>>> available(){ return success(service.seals(true)); } |
| | | @PostMapping("/upload") @PreAuthorize("@ss.hasPermission('mes:pd-seal:manage')") |
| | | public CommonResult<Long> upload(@RequestParam String name,@RequestParam MultipartFile file) throws Exception { return success(service.upload(name,file,getLoginUserId())); } |
| | | @PutMapping("/update") @PreAuthorize("@ss.hasPermission('mes:pd-seal:manage')") |
| | | public CommonResult<Boolean> update(@RequestParam long id,@RequestParam String name,@RequestParam(required=false) MultipartFile file) throws Exception { service.update(id,name,file); return success(true); } |
| | | @DeleteMapping("/delete") @PreAuthorize("@ss.hasPermission('mes:pd-seal:manage')") |
| | | public CommonResult<Boolean> delete(@RequestParam long id){ service.delete(id); return success(true); } |
| | | @PutMapping("/enabled") @PreAuthorize("@ss.hasPermission('mes:pd-seal:manage')") |
| | | public CommonResult<Boolean> enabled(@RequestParam long id,@RequestParam boolean enabled){service.setEnabled(id,enabled);return success(true);} |
| | | public record ApplyReq(Long projectId, Long sealId, String reason) {} |
| | |
| | | return (byte[]) rows.get(0).get("image_data"); |
| | | } |
| | | public long upload(String name, MultipartFile file, Long userId) throws Exception { |
| | | checkName(name); |
| | | byte[] data = readImage(file); |
| | | String imageHash = hash(data); |
| | | var keys = new GeneratedKeyHolder(); |
| | | jdbc.update(c -> { var ps=c.prepareStatement("INSERT INTO pd_seal(name,image_data,image_hash,enabled,created_by,tenant_id) VALUES(?,?,?,1,?,?)", Statement.RETURN_GENERATED_KEYS); ps.setString(1,name.trim()); ps.setBytes(2,data); ps.setString(3,imageHash); ps.setLong(4,userId); ps.setLong(5,tenant()); return ps; }, keys); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | } |
| | | public void update(long id, String name, MultipartFile file) throws Exception { |
| | | checkName(name); |
| | | int updated; |
| | | if (file == null || file.isEmpty()) { |
| | | updated = jdbc.update("UPDATE pd_seal SET name=? WHERE id=? AND tenant_id=? AND deleted=0", name.trim(), id, tenant()); |
| | | } else { |
| | | byte[] data = readImage(file); |
| | | updated = jdbc.update("UPDATE pd_seal SET name=?,image_data=?,image_hash=? WHERE id=? AND tenant_id=? AND deleted=0", name.trim(), data, hash(data), id, tenant()); |
| | | } |
| | | if (updated != 1) throw fail("印章不存在"); |
| | | } |
| | | public void delete(long id) { |
| | | Integer pending = jdbc.queryForObject("SELECT COUNT(*) FROM pd_seal_application WHERE seal_id=? AND tenant_id=? AND status=1", Integer.class, id, tenant()); |
| | | if (pending != null && pending > 0) throw fail("该印章有进行中的用印审批申请,请待审批完成后再删除"); |
| | | if (jdbc.update("UPDATE pd_seal SET deleted=1 WHERE id=? AND tenant_id=? AND deleted=0", id, tenant()) != 1) throw fail("印章不存在"); |
| | | } |
| | | private void checkName(String name) { |
| | | if (name == null || name.isBlank() || name.length() > 100) throw fail("印章名称不能为空且不能超过100字"); |
| | | } |
| | | private byte[] readImage(MultipartFile file) throws Exception { |
| | | if (file == null || file.isEmpty() || file.getSize() > 2 * 1024 * 1024) throw fail("请上传不超过2MB的PNG印章图片"); |
| | | byte[] data = file.getBytes(); |
| | | byte[] sig = {(byte)137,80,78,71,13,10,26,10}; |
| | |
| | | try { reader.setInput(input); if (reader.getWidth(0) > 2048 || reader.getHeight(0) > 2048) throw fail("图片尺寸不能超过2048×2048"); reader.read(0); } |
| | | finally { reader.dispose(); } |
| | | } |
| | | String hash = HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(data)); |
| | | var keys = new GeneratedKeyHolder(); |
| | | jdbc.update(c -> { var ps=c.prepareStatement("INSERT INTO pd_seal(name,image_data,image_hash,enabled,created_by,tenant_id) VALUES(?,?,?,1,?,?)", Statement.RETURN_GENERATED_KEYS); ps.setString(1,name.trim()); ps.setBytes(2,data); ps.setString(3,hash); ps.setLong(4,userId); ps.setLong(5,tenant()); return ps; }, keys); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | return data; |
| | | } |
| | | private String hash(byte[] data) throws Exception { |
| | | return HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(data)); |
| | | } |
| | | public void setEnabled(long id, boolean enabled) { |
| | | if (jdbc.update("UPDATE pd_seal SET enabled=? WHERE id=? AND tenant_id=? AND deleted=0", enabled, id, tenant()) != 1) throw fail("印章不存在"); |