From e0bbd21f56757c35dc067eaa8bc67057b65fead4 Mon Sep 17 00:00:00 2001
From: sinake <sinake1@qq.com>
Date: 星期三, 21 十月 2026 15:02:28 +0800
Subject: [PATCH] 新增发票管理

---
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceInvoice.java                  |  127 ++++++++++++
 ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceInvoiceServiceImpl.java |   71 +++++++
 ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceInvoiceMapper.java            |   15 +
 ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceInvoiceService.java         |   23 ++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java           |  116 -----------
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceInvoiceController.java  |  239 +++++++++++++++++++++++
 6 files changed, 475 insertions(+), 116 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
index e6364fc..77137f3 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -51,8 +51,6 @@
     @Autowired
     private ServerConfig serverConfig;
 
-    @Value("${appcode}")
-    private String  appcode;
 
     /**
      * 閫氱敤涓嬭浇璇锋眰
@@ -131,120 +129,6 @@
         }
     }
 
-    public String aliOCR(String base64) {
-        String host = "https://mixedmulti.market.alicloudapi.com";
-        String path = "/ocrservice/mixedMultiInvoice";
-        String method = "POST";
-        Map<String, String> headers = new HashMap<String, String>();
-        //鏈�鍚庡湪header涓殑鏍煎紡(涓棿鏄嫳鏂囩┖鏍�)涓篈uthorization:APPCODE 83359fd73fe94948385f570e3c139105
-        headers.put("Authorization", "APPCODE " + appcode);
-        //鏍规嵁API鐨勮姹傦紝瀹氫箟鐩稿搴旂殑Content-Type
-        headers.put("Content-Type", "application/json; charset=UTF-8");
-        Map<String, String> querys = new HashMap<String, String>();
-        String bodys = "{\"img\":\""+base64+"\"}";
-
-
-        try {
-
-            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
-            System.out.println(response.toString());
-            //鑾峰彇response鐨刡ody
-            String content=EntityUtils.toString(response.getEntity());
-            JSONObject jsonContent=JSONObject.parseObject(content);
-            JSONArray subMsgs=jsonContent.getJSONArray("subMsgs");
-            List<Map<String,Object>> lists=new ArrayList<>();
-            for(Object row: subMsgs){
-                Map<String,Object> tempList=new HashMap<>();
-                JSONObject rowObject=(JSONObject)row;
-                tempList.put("鍙戠エ鍒嗙被",rowObject.getString("type"));
-                JSONObject result=((JSONObject)rowObject.get("result")).getJSONObject("data");
-                for(Map.Entry<String, Object> entry : result.entrySet()){
-                    tempList.put(entry.getKey(),entry.getValue());
-                }
-                if(rowObject.getString("type").equals("閾惰鎵垮厬姹囩エ")){
-                    BigDecimal totalAmount= ChineseUtils.chineseToNumber(result.getString("绁ㄦ嵁閲戦澶у啓"));
-                    tempList.put("鍙戠エ閲戦",totalAmount);
-                }
-                if(rowObject.getString("type").equals("鐏溅绁�")){
-                    tempList.put("鍙戠エ閲戦",result.getString("绁ㄤ环"));
-                }
-
-                lists.add(tempList);
-            }
-            System.out.println(content);
-            return JSON.toJSONString(lists);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return "{}";
-        }
-    }
-
-    /**
-     * 閫氱敤涓婁紶璇锋眰
-     */
-    @ApiOperation("testOCR")
-    @PostMapping("/common/testOCR")
-    public AjaxResult testOCR(@RequestBody String fileName) throws Exception {
-        Path filePath= Paths.get(fileName);
-        String base64= Base64.getEncoder().encodeToString( Files.readAllBytes(filePath));
-
-        AjaxResult ajax = AjaxResult.success();
-        ajax.put("OCRList", aliOCR(base64));
-        return ajax;
-    }
-
-    /**
-     * 閫氱敤涓婁紶璇锋眰
-     */
-    @PostMapping("/common/uploadOCR")
-    public AjaxResult uploadOCR(MultipartFile file) throws Exception {
-
-        try {
-            // 涓婁紶鏂囦欢璺緞
-            String filePath = RuoYiConfig.getUploadPath();
-
-            //鍒ゆ柇鏂囦欢鏄惁瀛樺湪
-            String filename = file.getOriginalFilename().trim();
-            String felinamePath = FileUploadUtils.extractFilename(file);
-//            String pathFileName = FileUploadUtils.getPathFileName(filePath, s);
-            for (int i=1;i<500;i++) {
-                File file1 = new File(filePath + "/" + felinamePath);
-                boolean exists = file1.exists();
-                if (exists) {
-                    int index = filename.lastIndexOf(".");
-                    String startStr = filename.substring(0, index);
-                    String endStr = filename.substring(index, filename.length());
-
-                    String newFilename = startStr + "-" + i + endStr; // your new filename
-                    felinamePath = DateUtils.datePath() + "/" + newFilename;
-                    String contentType = file.getContentType();
-                    byte[] bytes = file.getBytes();
-                    file = new MockMultipartFile(newFilename, newFilename, contentType, bytes);
-                }else{
-                    break;
-                }
-            }
-            // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
-            String fileName = FileUploadUtils.upload(filePath, file);
-            String url1 = serverConfig.getUrl();
-            log.info("url1鐨勫�紀ld :{}", url1);
-            if (url1.contains("8032")) {
-                //杩欓噷鐨�8032涓嶆槸tomcat鐨勶紝鎵�浠ヨ杞垚tomcat鐨�
-                url1 = url1.replace("8032", "8032/prod-api");
-            }
-            String base64= Base64.getEncoder().encodeToString(file.getBytes());
-
-            log.info("url1鐨勫�糿ew :{}", url1);
-            String url = url1 + fileName;
-            AjaxResult ajax = AjaxResult.success();
-            ajax.put("fileName", fileName);
-            ajax.put("url", url);
-            ajax.put("OCRList", aliOCR(base64));
-            return ajax;
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-    }
 
 //    private static void parseUTF(int[] bits) {
 //        int index = 0;//杩欎釜鎸囬拡鎸囧悜姣忎竴琛屽惊鐜椂鍒椾笅鏍囩殑浣嶇疆锛屼笅涓�琛屽紑濮嬫椂閲嶆柊缃綅0
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceInvoiceController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceInvoiceController.java
new file mode 100644
index 0000000..f90d12f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceInvoiceController.java
@@ -0,0 +1,239 @@
+package com.ruoyi.web.controller.project;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.ChineseUtils;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.config.ServerConfig;
+import com.ruoyi.project.domain.ServiceInvoice;
+import com.ruoyi.project.service.IServiceInvoiceService;
+import com.ruoyi.web.controller.tool.HttpUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+/**
+ * 鍙戠エ绠$悊Controller
+ *
+ * @author ruoyi
+ * @date 2026-10-21
+ */
+@Api("鍙戠エ绠$悊")
+@RestController
+@RequestMapping("/project/invoice")
+public class ServiceInvoiceController extends BaseController {
+    @Autowired
+    private IServiceInvoiceService serviceInvoiceService;
+    @Autowired
+    private ServerConfig serverConfig;
+
+    @Value("${appcode}")
+    private String  appcode;
+    /**
+     * 鏌ヨ鍙戠エ绠$悊鍒楄〃
+     */
+    @ApiOperation("鏌ヨ鍙戠エ绠$悊鍒楄〃")
+    @GetMapping("/list")
+    public TableDataInfo list(ServiceInvoice serviceInvoice) {
+        startPage();
+        List<ServiceInvoice> list = serviceInvoiceService.queryList(serviceInvoice);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭鍙戠エ绠$悊鍒楄〃
+     */
+    @ApiOperation("瀵煎嚭鍙戠エ绠$悊鍒楄〃")
+    @Log(title = "鍙戠エ绠$悊", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(ServiceInvoice serviceInvoice) {
+        List<ServiceInvoice> list = serviceInvoiceService.queryList(serviceInvoice);
+        ExcelUtil<ServiceInvoice> util = new ExcelUtil<ServiceInvoice>(ServiceInvoice.class);
+        return util.exportExcel(list, "鍙戠エ绠$悊鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇鍙戠エ绠$悊璇︾粏淇℃伅
+     */
+    @ApiOperation("鑾峰彇鍙戠エ绠$悊璇︾粏淇℃伅")
+    @GetMapping(value = "/getInfo/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return AjaxResult.success(serviceInvoiceService.getById(id));
+    }
+
+    /**
+     * 鏂板鍙戠エ绠$悊
+     */
+    @ApiOperation("鏂板鍙戠エ绠$悊")
+    @Log(title = "鍙戠エ绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @RepeatSubmit
+    public AjaxResult add(@RequestBody ServiceInvoice serviceInvoice) {
+        return toAjax(serviceInvoiceService.save(serviceInvoice));
+    }
+
+    /**
+     * 淇敼鍙戠エ绠$悊
+     */
+    @ApiOperation("淇敼鍙戠エ绠$悊")
+    @Log(title = "鍙戠エ绠$悊", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @RepeatSubmit
+    public AjaxResult edit(@RequestBody ServiceInvoice serviceInvoice) {
+        return toAjax(serviceInvoiceService.updateById(serviceInvoice));
+    }
+
+    /**
+     * 鍒犻櫎鍙戠エ绠$悊
+     */
+    @ApiOperation("鍒犻櫎鍙戠エ绠$悊")
+    @Log(title = "鍙戠エ绠$悊", businessType = BusinessType.DELETE)
+    @GetMapping("/remove/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(serviceInvoiceService.removeByIds(Arrays.asList(ids)));
+    }
+
+    /**
+     * 閫氱敤涓婁紶璇锋眰
+     */
+    @ApiOperation("testOCR")
+    @PostMapping("/testOCR")
+    public AjaxResult testOCR(@RequestBody String fileName) throws Exception {
+        Path filePath= Paths.get(fileName);
+        String base64= Base64.getEncoder().encodeToString( Files.readAllBytes(filePath));
+
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("OCRList", aliOCR(base64,0,0));
+        return ajax;
+    }
+
+    /**
+     * 閫氱敤涓婁紶璇锋眰
+     */
+    @PostMapping("/uploadOCR")
+    public AjaxResult uploadOCR(@RequestParam("file") MultipartFile file, @RequestParam("userId") long userId, @RequestParam("caseId") long caseId) throws Exception {
+
+        try {
+            // 涓婁紶鏂囦欢璺緞
+            String filePath = RuoYiConfig.getUploadPath();
+            //鍒ゆ柇鏂囦欢鏄惁瀛樺湪
+            String filename = file.getOriginalFilename().trim();
+            String felinamePath = FileUploadUtils.extractFilename(file);
+            String newFilename="";
+//            String pathFileName = FileUploadUtils.getPathFileName(filePath, s);
+            for (int i=1;i<500;i++) {
+                File file1 = new File(filePath + "/" + felinamePath);
+                boolean exists = file1.exists();
+                if (exists) {
+                    int index = filename.lastIndexOf(".");
+                    String startStr = filename.substring(0, index);
+                    String endStr = filename.substring(index, filename.length());
+                    newFilename = startStr + "-" + i + endStr; // your new filename
+                    felinamePath = DateUtils.datePath() + "/" + newFilename;
+                    String contentType = file.getContentType();
+                    byte[] bytes = file.getBytes();
+                    file = new MockMultipartFile(newFilename, newFilename, contentType, bytes);
+                }else{
+                    break;
+                }
+            }
+            // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
+            String fileName = FileUploadUtils.upload(filePath, file);
+            String url1 = serverConfig.getUrl();
+            String url = url1 + fileName;
+            String base64= Base64.getEncoder().encodeToString(file.getBytes());
+            List<Map<String,Object>> lists=aliOCR(base64,userId,caseId);
+            for(Map<String,Object> row : lists){
+                ServiceInvoice invoice=new ServiceInvoice();
+                invoice.setUserId(userId);
+                invoice.setCaseId(caseId);
+                invoice.setInvoiceType(row.get("type")+"");
+                invoice.setInvoiceNo(row.get("鍙戠エ鍙风爜")+"");
+                invoice.setOccurDate(row.get("寮�绁ㄦ棩鏈�")+"");
+                invoice.setInvoiceAmount(row.get("鍙戠エ閲戦")+"");
+                invoice.setSellerName(row.get("鍙楃エ鏂瑰悕绉�")+"");
+                invoice.setInvoiceUrl(url);
+                invoice.setInvoiceName(newFilename);
+                invoice.setExtContent(JSON.toJSONString(row));
+                serviceInvoiceService.save(invoice);
+            }
+
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("fileName", fileName);
+            ajax.put("url", url);
+            ajax.put("OCRList", lists);
+            return ajax;
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
+    public List<Map<String,Object>> aliOCR(String base64,long userId,long caseId) {
+        String host = "https://mixedmulti.market.alicloudapi.com";
+        String path = "/ocrservice/mixedMultiInvoice";
+        String method = "POST";
+        Map<String, String> headers = new HashMap<String, String>();
+        //鏈�鍚庡湪header涓殑鏍煎紡(涓棿鏄嫳鏂囩┖鏍�)涓篈uthorization:APPCODE 83359fd73fe94948385f570e3c139105
+        headers.put("Authorization", "APPCODE " + appcode);
+        //鏍规嵁API鐨勮姹傦紝瀹氫箟鐩稿搴旂殑Content-Type
+        headers.put("Content-Type", "application/json; charset=UTF-8");
+        Map<String, String> querys = new HashMap<String, String>();
+        String bodys = "{\"img\":\""+base64+"\"}";
+        List<Map<String,Object>> lists=new ArrayList<>();
+        try {
+            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
+            //鑾峰彇response鐨刡ody
+            String content= EntityUtils.toString(response.getEntity());
+            JSONObject jsonContent=JSONObject.parseObject(content);
+            JSONArray subMsgs=jsonContent.getJSONArray("subMsgs");
+
+            for(Object row: subMsgs){
+
+                Map<String,Object> tempList=new HashMap<>();
+                JSONObject rowObject=(JSONObject)row;
+                tempList.put("鍙戠エ鍒嗙被",rowObject.getString("type"));
+                JSONObject result=((JSONObject)rowObject.get("result")).getJSONObject("data");
+
+                for(Map.Entry<String, Object> entry : result.entrySet()){
+                    tempList.put(entry.getKey(),entry.getValue());
+                }
+                if(rowObject.getString("type").equals("閾惰鎵垮厬姹囩エ")){
+                    BigDecimal totalAmount= ChineseUtils.chineseToNumber(result.getString("绁ㄦ嵁閲戦澶у啓"));
+                    tempList.put("鍙戠エ閲戦",totalAmount);
+                }
+                if(rowObject.getString("type").equals("鐏溅绁�")){
+                    tempList.put("鍙戠エ閲戦",result.getString("绁ㄤ环"));
+                }
+
+                lists.add(tempList);
+            }
+
+            return lists;
+        } catch (Exception e) {
+            return lists;
+        }
+    }
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceInvoice.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceInvoice.java
new file mode 100644
index 0000000..7233fd4
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceInvoice.java
@@ -0,0 +1,127 @@
+package com.ruoyi.project.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 鍙戠エ绠$悊瀵硅薄 service_invoice
+ *
+ * @author ruoyi
+ * @date 2026-10-21
+ */
+@Data
+@ApiModel("鍙戠エ绠$悊")
+@TableName("service_invoice")
+public class ServiceInvoice extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭ID
+     */
+    @ApiModelProperty("涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    @ApiModelProperty("鐢ㄦ埛ID")
+    @Excel(name = "鐢ㄦ埛ID")
+    private Long userId;
+
+    /**
+     * 妗堜緥ID
+     */
+    @ApiModelProperty("妗堜緥ID")
+    @Excel(name = "妗堜緥ID")
+    private Long caseId;
+
+    /**
+     * 鍙戠エ绫诲瀷
+     */
+    @ApiModelProperty("鍙戠エ绫诲瀷")
+    @Excel(name = "鍙戠エ绫诲瀷")
+    private String invoiceType;
+
+    /**
+     * 鍙戠エ鍚嶇О
+     */
+    @ApiModelProperty("鍙戠エ鍚嶇О")
+    @Excel(name = "鍙戠エ鍚嶇О")
+    private String invoiceName;
+
+    /**
+     * 鍙戠エ鍙风爜
+     */
+    @ApiModelProperty("鍙戠エ鍙风爜")
+    @Excel(name = "鍙戠エ鍙风爜")
+    private String invoiceNo;
+
+    /**
+     * 鍙戠敓鏃ユ湡
+     */
+    @ApiModelProperty("鍙戠敓鏃ユ湡")
+    @Excel(name = "鍙戠敓鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
+    private String occurDate;
+
+    /**
+     * 鍙戠エ寮�濮嬫棩鏈�
+     */
+    @ApiModelProperty("鍙戠エ寮�濮嬫棩鏈�")
+    @Excel(name = "鍙戠エ寮�濮嬫棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
+    private String invoiceStartDate;
+
+    /**
+     * 鍙戠エ缁撴潫鏃ユ湡
+     */
+    @ApiModelProperty("鍙戠エ缁撴潫鏃ユ湡")
+    @Excel(name = "鍙戠エ缁撴潫鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
+    private String invoiceEndDate;
+
+    /**
+     * 鍙戠エ閲戦
+     */
+    @ApiModelProperty("鍙戠エ閲戦")
+    @Excel(name = "鍙戠エ閲戦")
+    private String invoiceAmount;
+
+    /**
+     * 閿�鍞柟鍚嶇О
+     */
+    @ApiModelProperty("閿�鍞柟鍚嶇О")
+    @Excel(name = "閿�鍞柟鍚嶇О")
+    private String sellerName;
+
+    /**
+     * 鍙戠エURL
+     */
+    @ApiModelProperty("鍙戠エURL")
+    @Excel(name = "鍙戠エURL")
+    private String invoiceUrl;
+
+    /**
+     * 鎵╁睍鍐呭锛坖son瀛橈級
+     */
+    @ApiModelProperty("鎵╁睍鍐呭锛坖son瀛橈級")
+    private String extContent;
+
+    /**
+     * 澶囨敞
+     */
+    @ApiModelProperty("澶囨敞")
+    @Excel(name = "澶囨敞")
+    @TableField("remark")
+    private String remark;
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceInvoiceMapper.java b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceInvoiceMapper.java
new file mode 100644
index 0000000..26662f4
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceInvoiceMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.project.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.project.domain.ServiceInvoice;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 鍙戠エ绠$悊Mapper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2026-10-21
+ */
+@Mapper
+public interface ServiceInvoiceMapper extends BaseMapper<ServiceInvoice> {
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceInvoiceService.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceInvoiceService.java
new file mode 100644
index 0000000..200c1e2
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceInvoiceService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.project.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.project.domain.ServiceInvoice;
+
+import java.util.List;
+
+/**
+ * 鍙戠エ绠$悊Service鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2026-10-21
+ */
+public interface IServiceInvoiceService extends IService<ServiceInvoice> {
+
+    /**
+     * 鏌ヨ鍙戠エ绠$悊鍒楄〃
+     *
+     * @param serviceInvoice 鍙戠エ绠$悊
+     * @return 鍙戠エ绠$悊闆嗗悎
+     */
+    List<ServiceInvoice> queryList(ServiceInvoice serviceInvoice);
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceInvoiceServiceImpl.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceInvoiceServiceImpl.java
new file mode 100644
index 0000000..a5539db
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceInvoiceServiceImpl.java
@@ -0,0 +1,71 @@
+package com.ruoyi.project.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.project.domain.ServiceInvoice;
+import com.ruoyi.project.mapper.ServiceInvoiceMapper;
+import com.ruoyi.project.service.IServiceInvoiceService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 鍙戠エ绠$悊Service涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2026-10-21
+ */
+@Service
+public class ServiceInvoiceServiceImpl extends ServiceImpl<ServiceInvoiceMapper, ServiceInvoice> implements IServiceInvoiceService {
+
+    /**
+     * 鏌ヨ鍙戠エ绠$悊鍒楄〃
+     *
+     * @param serviceInvoice 鍙戠エ绠$悊
+     * @return 鍙戠エ绠$悊
+     */
+    @Override
+    public List<ServiceInvoice> queryList(ServiceInvoice serviceInvoice) {
+        LambdaQueryWrapper<ServiceInvoice> wrappers = Wrappers.lambdaQuery();
+        if (serviceInvoice.getId() != null) {
+            wrappers.eq(ServiceInvoice::getId, serviceInvoice.getId());
+        }
+        if (serviceInvoice.getUserId() != null) {
+            wrappers.eq(ServiceInvoice::getUserId, serviceInvoice.getUserId());
+        }
+        if (serviceInvoice.getCaseId() != null) {
+            wrappers.eq(ServiceInvoice::getCaseId, serviceInvoice.getCaseId());
+        }
+        if (StringUtils.isNotBlank(serviceInvoice.getInvoiceType())) {
+            wrappers.eq(ServiceInvoice::getInvoiceType, serviceInvoice.getInvoiceType());
+        }
+        if (StringUtils.isNotBlank(serviceInvoice.getInvoiceName())) {
+            wrappers.like(ServiceInvoice::getInvoiceName, serviceInvoice.getInvoiceName());
+        }
+        if (StringUtils.isNotBlank(serviceInvoice.getInvoiceNo())) {
+            wrappers.eq(ServiceInvoice::getInvoiceNo, serviceInvoice.getInvoiceNo());
+        }
+        if (serviceInvoice.getOccurDate() != null) {
+            wrappers.eq(ServiceInvoice::getOccurDate, serviceInvoice.getOccurDate());
+        }
+        if (serviceInvoice.getInvoiceStartDate() != null) {
+            wrappers.ge(ServiceInvoice::getInvoiceStartDate, serviceInvoice.getInvoiceStartDate());
+        }
+        if (serviceInvoice.getInvoiceEndDate() != null) {
+            wrappers.le(ServiceInvoice::getInvoiceEndDate, serviceInvoice.getInvoiceEndDate());
+        }
+        if (serviceInvoice.getInvoiceAmount() != null) {
+            wrappers.eq(ServiceInvoice::getInvoiceAmount, serviceInvoice.getInvoiceAmount());
+        }
+        if (StringUtils.isNotBlank(serviceInvoice.getSellerName())) {
+            wrappers.like(ServiceInvoice::getSellerName, serviceInvoice.getSellerName());
+        }
+        if (StringUtils.isNotBlank(serviceInvoice.getRemark())) {
+            wrappers.like(ServiceInvoice::getRemark, serviceInvoice.getRemark());
+        }
+        wrappers.orderByDesc(ServiceInvoice::getCreateTime).orderByDesc(ServiceInvoice::getId);
+        return this.list(wrappers);
+    }
+}

--
Gitblit v1.9.3