feat(config): 更新多环境配置并添加AI模块支持
- 修改默认激活环境为glt2 - 在application.yml中启用SqlRunner功能以支持动态SQL执行 - 新增AI模块Ollama配置,包括基础URL、模型设置和RAG参数 - 删除废弃的application-cms.yml和application-yd.yml配置文件 - 更新开发环境数据库连接配置至新服务器地址 - 为glt环境添加业务模块接口URL配置 - 新增glt2环境配置文件,包含完整的开发环境设置
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.clinic.service.ClinicAppointmentService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicAppointment;
|
||||
import com.gxwebsoft.clinic.param.ClinicAppointmentParam;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 挂号控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Tag(name = "挂号管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-appointment")
|
||||
public class ClinicAppointmentController extends BaseController {
|
||||
@Resource
|
||||
private ClinicAppointmentService clinicAppointmentService;
|
||||
|
||||
@Operation(summary = "分页查询挂号")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicAppointment>> page(ClinicAppointmentParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicAppointmentService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:list')")
|
||||
@Operation(summary = "查询全部挂号")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicAppointment>> list(ClinicAppointmentParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicAppointmentService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:list')")
|
||||
@Operation(summary = "根据id查询挂号")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicAppointment> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicAppointmentService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加挂号")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicAppointment clinicAppointment) {
|
||||
if (clinicAppointmentService.save(clinicAppointment)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改挂号")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicAppointment clinicAppointment) {
|
||||
if (clinicAppointmentService.updateById(clinicAppointment)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除挂号")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicAppointmentService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加挂号")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicAppointment> list) {
|
||||
if (clinicAppointmentService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改挂号")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicAppointment> batchParam) {
|
||||
if (batchParam.update(clinicAppointmentService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicAppointment:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除挂号")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicAppointmentService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.clinic.service.ClinicDoctorApplyService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorApply;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorApplyParam;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生入驻申请控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Tag(name = "医生入驻申请管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-doctor-apply")
|
||||
public class ClinicDoctorApplyController extends BaseController {
|
||||
@Resource
|
||||
private ClinicDoctorApplyService clinicDoctorApplyService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:list')")
|
||||
@Operation(summary = "分页查询医生入驻申请")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicDoctorApply>> page(ClinicDoctorApplyParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorApplyService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:list')")
|
||||
@Operation(summary = "查询全部医生入驻申请")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicDoctorApply>> list(ClinicDoctorApplyParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorApplyService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:list')")
|
||||
@Operation(summary = "根据id查询医生入驻申请")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicDoctorApply> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorApplyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加医生入驻申请")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicDoctorApply clinicDoctorApply) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// clinicDoctorApply.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (clinicDoctorApplyService.save(clinicDoctorApply)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改医生入驻申请")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicDoctorApply clinicDoctorApply) {
|
||||
if (clinicDoctorApplyService.updateById(clinicDoctorApply)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除医生入驻申请")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicDoctorApplyService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加医生入驻申请")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicDoctorApply> list) {
|
||||
if (clinicDoctorApplyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改医生入驻申请")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicDoctorApply> batchParam) {
|
||||
if (batchParam.update(clinicDoctorApplyService, "apply_id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorApply:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除医生入驻申请")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicDoctorApplyService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorUserParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicDoctorUserService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-23 15:58:21
|
||||
*/
|
||||
@Tag(name = "分销商用户记录表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-doctor-user")
|
||||
public class ClinicDoctorUserController extends BaseController {
|
||||
@Resource
|
||||
private ClinicDoctorUserService clinicDoctorUserService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:list')")
|
||||
@Operation(summary = "分页查询分销商用户记录表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicDoctorUser>> page(ClinicDoctorUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorUserService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:list')")
|
||||
@Operation(summary = "查询全部分销商用户记录表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicDoctorUser>> list(ClinicDoctorUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorUserService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:list')")
|
||||
@Operation(summary = "根据id查询分销商用户记录表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicDoctorUser> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicDoctorUserService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加分销商用户记录表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicDoctorUser clinicDoctorUser) {
|
||||
// 记录当前登录用户id
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
clinicDoctorUser.setUserId(loginUser.getUserId());
|
||||
}
|
||||
if (clinicDoctorUserService.save(clinicDoctorUser)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改分销商用户记录表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicDoctorUser clinicDoctorUser) {
|
||||
if (clinicDoctorUserService.updateById(clinicDoctorUser)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除分销商用户记录表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicDoctorUserService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加分销商用户记录表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicDoctorUser> list) {
|
||||
if (clinicDoctorUserService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改分销商用户记录表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicDoctorUser> batchParam) {
|
||||
if (batchParam.update(clinicDoctorUserService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicDoctorUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除分销商用户记录表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicDoctorUserService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicine;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Tag(name = "药品库管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-medicine")
|
||||
public class ClinicMedicineController extends BaseController {
|
||||
@Resource
|
||||
private ClinicMedicineService clinicMedicineService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:list')")
|
||||
@Operation(summary = "分页查询药品库")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicMedicine>> page(ClinicMedicineParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:list')")
|
||||
@Operation(summary = "查询全部药品库")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicMedicine>> list(ClinicMedicineParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:list')")
|
||||
@Operation(summary = "根据id查询药品库")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicMedicine> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加药品库")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicMedicine clinicMedicine) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// clinicMedicine.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (clinicMedicineService.save(clinicMedicine)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改药品库")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicMedicine clinicMedicine) {
|
||||
if (clinicMedicineService.updateById(clinicMedicine)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除药品库")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicMedicineService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加药品库")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicMedicine> list) {
|
||||
if (clinicMedicineService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改药品库")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicMedicine> batchParam) {
|
||||
if (batchParam.update(clinicMedicineService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicine:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除药品库")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicMedicineService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineInout;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineInoutParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineInoutService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出入库控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Tag(name = "出入库管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-medicine-inout")
|
||||
public class ClinicMedicineInoutController extends BaseController {
|
||||
@Resource
|
||||
private ClinicMedicineInoutService clinicMedicineInoutService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:list')")
|
||||
@Operation(summary = "分页查询出入库")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicMedicineInout>> page(ClinicMedicineInoutParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineInoutService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:list')")
|
||||
@Operation(summary = "查询全部出入库")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicMedicineInout>> list(ClinicMedicineInoutParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineInoutService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:list')")
|
||||
@Operation(summary = "根据id查询出入库")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicMedicineInout> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineInoutService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加出入库")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicMedicineInout clinicMedicineInout) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// clinicMedicineInout.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (clinicMedicineInoutService.save(clinicMedicineInout)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改出入库")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicMedicineInout clinicMedicineInout) {
|
||||
if (clinicMedicineInoutService.updateById(clinicMedicineInout)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除出入库")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicMedicineInoutService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加出入库")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicMedicineInout> list) {
|
||||
if (clinicMedicineInoutService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改出入库")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicMedicineInout> batchParam) {
|
||||
if (batchParam.update(clinicMedicineInoutService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineInout:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除出入库")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicMedicineInoutService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineStock;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineStockParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineStockService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库存控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Tag(name = "药品库存管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-medicine-stock")
|
||||
public class ClinicMedicineStockController extends BaseController {
|
||||
@Resource
|
||||
private ClinicMedicineStockService clinicMedicineStockService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:list')")
|
||||
@Operation(summary = "分页查询药品库存")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicMedicineStock>> page(ClinicMedicineStockParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineStockService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:list')")
|
||||
@Operation(summary = "查询全部药品库存")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicMedicineStock>> list(ClinicMedicineStockParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineStockService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:list')")
|
||||
@Operation(summary = "根据id查询药品库存")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicMedicineStock> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicMedicineStockService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加药品库存")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicMedicineStock clinicMedicineStock) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// clinicMedicineStock.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (clinicMedicineStockService.save(clinicMedicineStock)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改药品库存")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicMedicineStock clinicMedicineStock) {
|
||||
if (clinicMedicineStockService.updateById(clinicMedicineStock)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除药品库存")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicMedicineStockService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加药品库存")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicMedicineStock> list) {
|
||||
if (clinicMedicineStockService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改药品库存")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicMedicineStock> batchParam) {
|
||||
if (batchParam.update(clinicMedicineStockService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicMedicineStock:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除药品库存")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicMedicineStockService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.clinic.service.ClinicPatientUserService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPatientUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicPatientUserParam;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Tag(name = "患者管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-patient-user")
|
||||
public class ClinicPatientUserController extends BaseController {
|
||||
@Resource
|
||||
private ClinicPatientUserService clinicPatientUserService;
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:list')")
|
||||
@Operation(summary = "分页查询患者")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicPatientUser>> page(ClinicPatientUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPatientUserService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:list')")
|
||||
@Operation(summary = "查询全部患者")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicPatientUser>> list(ClinicPatientUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPatientUserService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:list')")
|
||||
@Operation(summary = "根据id查询患者")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicPatientUser> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicPatientUserService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加患者")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicPatientUser clinicPatientUser) {
|
||||
// 记录当前登录用户id
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
clinicPatientUser.setUserId(loginUser.getUserId());
|
||||
}
|
||||
if (clinicPatientUserService.save(clinicPatientUser)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改患者")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicPatientUser clinicPatientUser) {
|
||||
if (clinicPatientUserService.updateById(clinicPatientUser)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除患者")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicPatientUserService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加患者")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicPatientUser> list) {
|
||||
if (clinicPatientUserService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改患者")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicPatientUser> batchParam) {
|
||||
if (batchParam.update(clinicPatientUserService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPatientUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除患者")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicPatientUserService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.gxwebsoft.clinic.dto.PrescriptionOrderRequest;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescription;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicPrescriptionService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Tag(name = "处方主表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-prescription")
|
||||
public class ClinicPrescriptionController extends BaseController {
|
||||
@Resource
|
||||
private ClinicPrescriptionService clinicPrescriptionService;
|
||||
|
||||
@Operation(summary = "分页查询处方主表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicPrescription>> page(ClinicPrescriptionParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:list')")
|
||||
@Operation(summary = "查询全部处方主表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicPrescription>> list(ClinicPrescriptionParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询处方主表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicPrescription> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加处方主表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicPrescription clinicPrescription) {
|
||||
// 记录当前登录用户id
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
clinicPrescription.setDoctorId(loginUser.getUserId());
|
||||
// 生成订单号
|
||||
String orderNo = Long.toString(IdUtil.getSnowflakeNextId());
|
||||
clinicPrescription.setOrderNo(orderNo);
|
||||
}
|
||||
if (clinicPrescriptionService.save(clinicPrescription)) {
|
||||
// 返回处方数据,包含处方ID
|
||||
return success("添加成功",clinicPrescriptionService.getByLastId(clinicPrescription));
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改处方主表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicPrescription clinicPrescription) {
|
||||
if (clinicPrescriptionService.updateById(clinicPrescription)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除处方主表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicPrescriptionService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加处方主表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicPrescription> list) {
|
||||
if (clinicPrescriptionService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改处方主表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicPrescription> batchParam) {
|
||||
if (batchParam.update(clinicPrescriptionService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除处方主表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicPrescriptionService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@Operation(summary = "创建处方订单")
|
||||
@PostMapping("/order")
|
||||
public ApiResult<?> createOrder(@RequestBody PrescriptionOrderRequest request) {
|
||||
try {
|
||||
// 1. 参数校验
|
||||
if (request.getPrescriptionId() == null) {
|
||||
return fail("处方ID不能为空");
|
||||
}
|
||||
if (request.getPayType() == null) {
|
||||
return fail("支付方式不能为空");
|
||||
}
|
||||
|
||||
// 2. 查询处方信息
|
||||
ClinicPrescription prescription = clinicPrescriptionService.getById(request.getPrescriptionId());
|
||||
if (prescription == null) {
|
||||
return fail("处方不存在");
|
||||
}
|
||||
|
||||
// 3. 检查处方状态
|
||||
if (prescription.getStatus() != null && prescription.getStatus() == 2) {
|
||||
return fail("该处方已支付,无需重复支付");
|
||||
}
|
||||
if (prescription.getStatus() != null && prescription.getStatus() == 3) {
|
||||
return fail("该处方已取消,无法支付");
|
||||
}
|
||||
|
||||
// 4. 更新处方订单信息
|
||||
ClinicPrescription updatePrescription = new ClinicPrescription();
|
||||
updatePrescription.setId(request.getPrescriptionId());
|
||||
|
||||
// 根据支付类型更新状态
|
||||
if (request.getPayType() == 1) {
|
||||
// 微信支付,状态保持为正常,等待支付回调
|
||||
updatePrescription.setStatus(0);
|
||||
} else if (request.getPayType() == 4 || request.getPayType() == 5) {
|
||||
// 现金支付或POS机支付,直接标记为已支付
|
||||
updatePrescription.setStatus(2);
|
||||
updatePrescription.setIsSettled(1);
|
||||
updatePrescription.setSettleTime(LocalDateTime.now());
|
||||
} else if (request.getPayType() == 6) {
|
||||
// 免费,直接标记为已完成
|
||||
updatePrescription.setStatus(1);
|
||||
updatePrescription.setIsSettled(1);
|
||||
updatePrescription.setSettleTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
if (clinicPrescriptionService.updateById(updatePrescription)) {
|
||||
return success("订单创建成功", prescription);
|
||||
}
|
||||
return fail("订单创建失败");
|
||||
|
||||
} catch (Exception e) {
|
||||
return fail("订单创建失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package com.gxwebsoft.clinic.controller;
|
||||
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionItemParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicPrescriptionItemService;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Tag(name = "处方明细表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/clinic/clinic-prescription-item")
|
||||
public class ClinicPrescriptionItemController extends BaseController {
|
||||
@Resource
|
||||
private ClinicPrescriptionItemService clinicPrescriptionItemService;
|
||||
|
||||
@Operation(summary = "分页查询处方明细表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<ClinicPrescriptionItem>> page(ClinicPrescriptionItemParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionItemService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:list')")
|
||||
@Operation(summary = "查询全部处方明细表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<ClinicPrescriptionItem>> list(ClinicPrescriptionItemParam param) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionItemService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询处方明细表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<ClinicPrescriptionItem> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(clinicPrescriptionItemService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加处方明细表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody ClinicPrescriptionItem clinicPrescriptionItem) {
|
||||
if (clinicPrescriptionItemService.save(clinicPrescriptionItem)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改处方明细表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody ClinicPrescriptionItem clinicPrescriptionItem) {
|
||||
if (clinicPrescriptionItemService.updateById(clinicPrescriptionItem)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除处方明细表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (clinicPrescriptionItemService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加处方明细表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<ClinicPrescriptionItem> list) {
|
||||
if (clinicPrescriptionItemService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改处方明细表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ClinicPrescriptionItem> batchParam) {
|
||||
if (batchParam.update(clinicPrescriptionItemService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('clinic:clinicPrescription:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除处方明细表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (clinicPrescriptionItemService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -1,24 +0,0 @@
|
||||
package com.gxwebsoft.clinic.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 处方订单请求参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-11-03
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "PrescriptionOrderRequest", description = "处方订单请求参数")
|
||||
public class PrescriptionOrderRequest implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "处方ID", required = true)
|
||||
private Integer prescriptionId;
|
||||
|
||||
@Schema(description = "支付方式:0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付", required = true)
|
||||
private Integer payType;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 挂号
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:03
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicAppointment对象", description = "挂号")
|
||||
public class ClinicAppointment implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "就诊原因")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "挂号时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime evaluateTime;
|
||||
|
||||
@Schema(description = "医生")
|
||||
private Integer doctorId;
|
||||
|
||||
@Schema(description = "医生名称")
|
||||
@TableField(exist = false)
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "医生职位")
|
||||
@TableField(exist = false)
|
||||
private String doctorPosition;
|
||||
|
||||
@Schema(description = "患者")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "患者名称")
|
||||
@TableField(exist = false)
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "手机")
|
||||
@TableField(exist = false)
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
private Integer isDelete;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDate;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 医生入驻申请
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicDoctorApply对象", description = "医生入驻申请")
|
||||
public class ClinicDoctorApply implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "apply_id", type = IdType.AUTO)
|
||||
private Integer applyId;
|
||||
|
||||
@Schema(description = "类型 0医生")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "性别 1男 2女")
|
||||
private Integer gender;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "客户名称")
|
||||
private String dealerName;
|
||||
|
||||
@Schema(description = "证件号码")
|
||||
private String idCard;
|
||||
|
||||
@Schema(description = "生日")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate birthDate;
|
||||
|
||||
@Schema(description = "区分职称等级(如主治医师、副主任医师)")
|
||||
private String professionalTitle;
|
||||
|
||||
@Schema(description = "工作单位")
|
||||
private String workUnit;
|
||||
|
||||
@Schema(description = "执业资格核心凭证")
|
||||
private String practiceLicense;
|
||||
|
||||
@Schema(description = "限定可执业科室或疾病类型")
|
||||
private String practiceScope;
|
||||
|
||||
@Schema(description = "开始工作时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime startWorkDate;
|
||||
|
||||
@Schema(description = "简历")
|
||||
private String resume;
|
||||
|
||||
@Schema(description = "使用 JSON 存储多个证件文件路径(如执业证、学历证)")
|
||||
private String certificationFiles;
|
||||
|
||||
@Schema(description = "详细地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "签约价格")
|
||||
private BigDecimal money;
|
||||
|
||||
@Schema(description = "推荐人用户ID")
|
||||
private Integer refereeId;
|
||||
|
||||
@Schema(description = "申请方式(10需后台审核 20无需审核)")
|
||||
private Integer applyType;
|
||||
|
||||
@Schema(description = "审核状态 (10待审核 20审核通过 30驳回)")
|
||||
private Integer applyStatus;
|
||||
|
||||
@Schema(description = "申请时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime applyTime;
|
||||
|
||||
@Schema(description = "审核时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime auditTime;
|
||||
|
||||
@Schema(description = "合同时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime contractTime;
|
||||
|
||||
@Schema(description = "过期时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime expirationTime;
|
||||
|
||||
@Schema(description = "驳回原因")
|
||||
private String rejectReason;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "商城ID")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-23 15:58:20
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicDoctorUser对象", description = "分销商用户记录表")
|
||||
public class ClinicDoctorUser implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型 0经销商 1企业 2集团")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "昵称")
|
||||
@TableField(exist = false)
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "头像")
|
||||
@TableField(exist = false)
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
@TableField(exist = false)
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "部门")
|
||||
private Integer departmentId;
|
||||
|
||||
@Schema(description = "专业领域")
|
||||
private String specialty;
|
||||
|
||||
@Schema(description = "职务级别")
|
||||
private String position;
|
||||
|
||||
@Schema(description = "执业资格")
|
||||
private String qualification;
|
||||
|
||||
@Schema(description = "医生简介")
|
||||
private String introduction;
|
||||
|
||||
@Schema(description = "挂号费")
|
||||
private BigDecimal consultationFee;
|
||||
|
||||
@Schema(description = "工作年限")
|
||||
private Integer workYears;
|
||||
|
||||
@Schema(description = "问诊人数")
|
||||
private Integer consultationCount;
|
||||
|
||||
@Schema(description = "专属二维码")
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
private Integer isDelete;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 药品库
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:31
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicMedicine对象", description = "药品库")
|
||||
public class ClinicMedicine implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "药名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "拼音")
|
||||
private String pinyin;
|
||||
|
||||
@Schema(description = "分类(如“清热解毒”、“补气养血”)")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "规格(如“饮片”、“颗粒”)")
|
||||
private String specification;
|
||||
|
||||
@Schema(description = "单位(如“克”、“袋”)")
|
||||
private String unit;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "单价")
|
||||
private BigDecimal pricePerUnit;
|
||||
|
||||
@Schema(description = "是否活跃")
|
||||
private Integer isActive;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "商城ID")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 出入库
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicMedicineInout对象", description = "出入库")
|
||||
public class ClinicMedicineInout implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "分销商用户id(一级)")
|
||||
private Integer firstUserId;
|
||||
|
||||
@Schema(description = "分销商用户id(二级)")
|
||||
private Integer secondUserId;
|
||||
|
||||
@Schema(description = "分销商用户id(三级)")
|
||||
private Integer thirdUserId;
|
||||
|
||||
@Schema(description = "分销佣金(一级)")
|
||||
private BigDecimal firstMoney;
|
||||
|
||||
@Schema(description = "分销佣金(二级)")
|
||||
private BigDecimal secondMoney;
|
||||
|
||||
@Schema(description = "分销佣金(三级)")
|
||||
private BigDecimal thirdMoney;
|
||||
|
||||
@Schema(description = "单价")
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "订单总金额")
|
||||
private BigDecimal orderPrice;
|
||||
|
||||
@Schema(description = "结算金额")
|
||||
private BigDecimal settledPrice;
|
||||
|
||||
@Schema(description = "换算成度")
|
||||
private BigDecimal degreePrice;
|
||||
|
||||
@Schema(description = "实发金额")
|
||||
private BigDecimal payPrice;
|
||||
|
||||
@Schema(description = "税率")
|
||||
private BigDecimal rate;
|
||||
|
||||
@Schema(description = "结算月份")
|
||||
private String month;
|
||||
|
||||
@Schema(description = "订单是否失效(0未失效 1已失效)")
|
||||
private Integer isInvalid;
|
||||
|
||||
@Schema(description = "佣金结算(0未结算 1已结算)")
|
||||
private Integer isSettled;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime settleTime;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "商城ID")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 药品库存
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicMedicineStock对象", description = "药品库存")
|
||||
public class ClinicMedicineStock implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "药品")
|
||||
private Integer medicineId;
|
||||
|
||||
@Schema(description = "库存数量")
|
||||
private Integer stockQuantity;
|
||||
|
||||
@Schema(description = "最小库存预警")
|
||||
private Integer minStockLevel;
|
||||
|
||||
@Schema(description = "上次更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime lastUpdated;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "商城ID")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 患者
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicPatientUser对象", description = "患者")
|
||||
public class ClinicPatientUser implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型 0经销商 1企业 2集团")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "头像")
|
||||
@TableField(exist = false)
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
@TableField(exist = false)
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "性别 0未知 1男 2女")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "年龄")
|
||||
private Integer age;
|
||||
|
||||
@Schema(description = "身高")
|
||||
private String height;
|
||||
|
||||
@Schema(description = "体重")
|
||||
private String weight;
|
||||
|
||||
@Schema(description = "过敏史")
|
||||
private String allergyHistory;
|
||||
|
||||
@Schema(description = "专属二维码")
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
private Integer isDelete;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.gxwebsoft.shop.entity.ShopOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicPrescription对象", description = "处方主表")
|
||||
public class ClinicPrescription implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "患者")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "患者名称")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "年龄")
|
||||
@TableField(exist = false)
|
||||
private String age;
|
||||
|
||||
@Schema(description = "身高")
|
||||
@TableField(exist = false)
|
||||
private String height;
|
||||
|
||||
@Schema(description = "体重")
|
||||
@TableField(exist = false)
|
||||
private String weight;
|
||||
|
||||
@Schema(description = "医生")
|
||||
private Integer doctorId;
|
||||
|
||||
@Schema(description = "医生名称")
|
||||
@TableField(exist = false)
|
||||
private String doctorName;
|
||||
|
||||
@Schema(description = "医生资格")
|
||||
@TableField(exist = false)
|
||||
private String qualification;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "0未付款,1已付款")
|
||||
@TableField(exist = false)
|
||||
private Boolean payStatus;
|
||||
|
||||
@Schema(description = "0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款")
|
||||
@TableField(exist = false)
|
||||
private Integer orderStatus;
|
||||
|
||||
@Schema(description = "关联就诊表")
|
||||
private Integer visitRecordId;
|
||||
|
||||
@Schema(description = "处方类型 0中药 1西药")
|
||||
private Integer prescriptionType;
|
||||
|
||||
@Schema(description = "诊断结果")
|
||||
private String diagnosis;
|
||||
|
||||
@Schema(description = "治疗方案")
|
||||
private String treatmentPlan;
|
||||
|
||||
@Schema(description = "煎药说明")
|
||||
private String decoctionInstructions;
|
||||
|
||||
@Schema(description = "上传附件")
|
||||
private String image;
|
||||
|
||||
@Schema(description = "订单总金额")
|
||||
private BigDecimal orderPrice;
|
||||
|
||||
@Schema(description = "单价")
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "实付金额")
|
||||
private BigDecimal payPrice;
|
||||
|
||||
@Schema(description = "订单是否失效(0未失效 1已失效)")
|
||||
private Integer isInvalid;
|
||||
|
||||
@Schema(description = "结算(0未结算 1已结算)")
|
||||
private Integer isSettled;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime settleTime;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1已完成,2已支付,3已取消")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "商城ID")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "处方明细")
|
||||
@TableField(exist = false)
|
||||
private List<ClinicPrescriptionItem> items;
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.gxwebsoft.clinic.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "ClinicPrescriptionItem对象", description = "处方明细表")
|
||||
public class ClinicPrescriptionItem implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "关联处方")
|
||||
private Integer prescriptionId;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String prescriptionNo;
|
||||
|
||||
@Schema(description = "关联药品")
|
||||
private Integer medicineId;
|
||||
|
||||
@Schema(description = "药品名称")
|
||||
@TableField(exist = false)
|
||||
private String medicineName;
|
||||
|
||||
@Schema(description = "规格")
|
||||
@TableField(exist = false)
|
||||
private String specification;
|
||||
|
||||
@Schema(description = "单位")
|
||||
@TableField(exist = false)
|
||||
private String unit;
|
||||
|
||||
@Schema(description = "单价")
|
||||
@TableField(exist = false)
|
||||
private BigDecimal pricePerUnit;
|
||||
|
||||
@Schema(description = "药品")
|
||||
@TableField(exist = false)
|
||||
private ClinicMedicine clinicMedicine;
|
||||
|
||||
@Schema(description = "剂量(如“10g”)")
|
||||
private String dosage;
|
||||
|
||||
@Schema(description = "用法频率(如“每日三次”)")
|
||||
private String usageFrequency;
|
||||
|
||||
@Schema(description = "服用天数")
|
||||
private Integer days;
|
||||
|
||||
@Schema(description = "购买数量")
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "单价")
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer quantity;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicAppointment;
|
||||
import com.gxwebsoft.clinic.param.ClinicAppointmentParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 挂号Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:03
|
||||
*/
|
||||
public interface ClinicAppointmentMapper extends BaseMapper<ClinicAppointment> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicAppointment>
|
||||
*/
|
||||
List<ClinicAppointment> selectPageRel(@Param("page") IPage<ClinicAppointment> page,
|
||||
@Param("param") ClinicAppointmentParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicAppointment> selectListRel(@Param("param") ClinicAppointmentParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorApply;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorApplyParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生入驻申请Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicDoctorApplyMapper extends BaseMapper<ClinicDoctorApply> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicDoctorApply>
|
||||
*/
|
||||
List<ClinicDoctorApply> selectPageRel(@Param("page") IPage<ClinicDoctorApply> page,
|
||||
@Param("param") ClinicDoctorApplyParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicDoctorApply> selectListRel(@Param("param") ClinicDoctorApplyParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorUserParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicDoctorUserMapper extends BaseMapper<ClinicDoctorUser> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicDoctorUser>
|
||||
*/
|
||||
List<ClinicDoctorUser> selectPageRel(@Param("page") IPage<ClinicDoctorUser> page,
|
||||
@Param("param") ClinicDoctorUserParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicDoctorUser> selectListRel(@Param("param") ClinicDoctorUserParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineInout;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineInoutParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出入库Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
public interface ClinicMedicineInoutMapper extends BaseMapper<ClinicMedicineInout> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicineInout>
|
||||
*/
|
||||
List<ClinicMedicineInout> selectPageRel(@Param("page") IPage<ClinicMedicineInout> page,
|
||||
@Param("param") ClinicMedicineInoutParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicMedicineInout> selectListRel(@Param("param") ClinicMedicineInoutParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicine;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:31
|
||||
*/
|
||||
public interface ClinicMedicineMapper extends BaseMapper<ClinicMedicine> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicine>
|
||||
*/
|
||||
List<ClinicMedicine> selectPageRel(@Param("page") IPage<ClinicMedicine> page,
|
||||
@Param("param") ClinicMedicineParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicMedicine> selectListRel(@Param("param") ClinicMedicineParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineStock;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineStockParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库存Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
public interface ClinicMedicineStockMapper extends BaseMapper<ClinicMedicineStock> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicineStock>
|
||||
*/
|
||||
List<ClinicMedicineStock> selectPageRel(@Param("page") IPage<ClinicMedicineStock> page,
|
||||
@Param("param") ClinicMedicineStockParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicMedicineStock> selectListRel(@Param("param") ClinicMedicineStockParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPatientUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicPatientUserParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicPatientUserMapper extends BaseMapper<ClinicPatientUser> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPatientUser>
|
||||
*/
|
||||
List<ClinicPatientUser> selectPageRel(@Param("page") IPage<ClinicPatientUser> page,
|
||||
@Param("param") ClinicPatientUserParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicPatientUser> selectListRel(@Param("param") ClinicPatientUserParam param);
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionItemParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
public interface ClinicPrescriptionItemMapper extends BaseMapper<ClinicPrescriptionItem> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPrescriptionItem>
|
||||
*/
|
||||
List<ClinicPrescriptionItem> selectPageRel(@Param("page") IPage<ClinicPrescriptionItem> page,
|
||||
@Param("param") ClinicPrescriptionItemParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicPrescriptionItem> selectListRel(@Param("param") ClinicPrescriptionItemParam param);
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.gxwebsoft.clinic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescription;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
public interface ClinicPrescriptionMapper extends BaseMapper<ClinicPrescription> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPrescription>
|
||||
*/
|
||||
List<ClinicPrescription> selectPageRel(@Param("page") IPage<ClinicPrescription> page,
|
||||
@Param("param") ClinicPrescriptionParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<ClinicPrescription> selectListRel(@Param("param") ClinicPrescriptionParam param);
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicAppointmentMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.nickname, b.phone, c.real_name as doctorName, c.position as doctorPosition
|
||||
FROM clinic_appointment a
|
||||
LEFT JOIN gxwebsoft_core.sys_user b ON a.user_id = b.user_id
|
||||
LEFT JOIN clinic_doctor_user c ON a.doctor_id = c.user_id
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
<if test="param.reason != null">
|
||||
AND a.reason LIKE CONCAT('%', #{param.reason}, '%')
|
||||
</if>
|
||||
<if test="param.evaluateTime != null">
|
||||
AND a.evaluate_time LIKE CONCAT('%', #{param.evaluateTime}, '%')
|
||||
</if>
|
||||
<if test="param.doctorId != null">
|
||||
AND a.doctor_id = #{param.doctorId}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.sortNumber != null">
|
||||
AND a.sort_number = #{param.sortNumber}
|
||||
</if>
|
||||
<if test="param.isDelete != null">
|
||||
AND a.is_delete = #{param.isDelete}
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicAppointment">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicAppointment">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,114 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicDoctorApplyMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*
|
||||
FROM clinic_doctor_apply a
|
||||
<where>
|
||||
<if test="param.applyId != null">
|
||||
AND a.apply_id = #{param.applyId}
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.realName != null">
|
||||
AND a.real_name LIKE CONCAT('%', #{param.realName}, '%')
|
||||
</if>
|
||||
<if test="param.gender != null">
|
||||
AND a.gender = #{param.gender}
|
||||
</if>
|
||||
<if test="param.mobile != null">
|
||||
AND a.mobile LIKE CONCAT('%', #{param.mobile}, '%')
|
||||
</if>
|
||||
<if test="param.dealerName != null">
|
||||
AND a.dealer_name LIKE CONCAT('%', #{param.dealerName}, '%')
|
||||
</if>
|
||||
<if test="param.idCard != null">
|
||||
AND a.id_card LIKE CONCAT('%', #{param.idCard}, '%')
|
||||
</if>
|
||||
<if test="param.birthDate != null">
|
||||
AND a.birth_date LIKE CONCAT('%', #{param.birthDate}, '%')
|
||||
</if>
|
||||
<if test="param.professionalTitle != null">
|
||||
AND a.professional_title LIKE CONCAT('%', #{param.professionalTitle}, '%')
|
||||
</if>
|
||||
<if test="param.workUnit != null">
|
||||
AND a.work_unit LIKE CONCAT('%', #{param.workUnit}, '%')
|
||||
</if>
|
||||
<if test="param.practiceLicense != null">
|
||||
AND a.practice_license LIKE CONCAT('%', #{param.practiceLicense}, '%')
|
||||
</if>
|
||||
<if test="param.practiceScope != null">
|
||||
AND a.practice_scope LIKE CONCAT('%', #{param.practiceScope}, '%')
|
||||
</if>
|
||||
<if test="param.startWorkDate != null">
|
||||
AND a.start_work_date LIKE CONCAT('%', #{param.startWorkDate}, '%')
|
||||
</if>
|
||||
<if test="param.resume != null">
|
||||
AND a.resume LIKE CONCAT('%', #{param.resume}, '%')
|
||||
</if>
|
||||
<if test="param.certificationFiles != null">
|
||||
AND a.certification_files LIKE CONCAT('%', #{param.certificationFiles}, '%')
|
||||
</if>
|
||||
<if test="param.address != null">
|
||||
AND a.address LIKE CONCAT('%', #{param.address}, '%')
|
||||
</if>
|
||||
<if test="param.money != null">
|
||||
AND a.money = #{param.money}
|
||||
</if>
|
||||
<if test="param.refereeId != null">
|
||||
AND a.referee_id = #{param.refereeId}
|
||||
</if>
|
||||
<if test="param.applyType != null">
|
||||
AND a.apply_type = #{param.applyType}
|
||||
</if>
|
||||
<if test="param.applyStatus != null">
|
||||
AND a.apply_status = #{param.applyStatus}
|
||||
</if>
|
||||
<if test="param.applyTime != null">
|
||||
AND a.apply_time LIKE CONCAT('%', #{param.applyTime}, '%')
|
||||
</if>
|
||||
<if test="param.auditTime != null">
|
||||
AND a.audit_time LIKE CONCAT('%', #{param.auditTime}, '%')
|
||||
</if>
|
||||
<if test="param.contractTime != null">
|
||||
AND a.contract_time LIKE CONCAT('%', #{param.contractTime}, '%')
|
||||
</if>
|
||||
<if test="param.expirationTime != null">
|
||||
AND a.expiration_time LIKE CONCAT('%', #{param.expirationTime}, '%')
|
||||
</if>
|
||||
<if test="param.rejectReason != null">
|
||||
AND a.reject_reason LIKE CONCAT('%', #{param.rejectReason}, '%')
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicDoctorApply">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicDoctorApply">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,86 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicDoctorUserMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.nickname, b.phone, b.avatar
|
||||
FROM clinic_doctor_user a
|
||||
LEFT JOIN gxwebsoft_core.sys_user b ON a.user_id = b.user_id
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.realName != null">
|
||||
AND a.real_name LIKE CONCAT('%', #{param.realName}, '%')
|
||||
</if>
|
||||
<if test="param.phone != null">
|
||||
AND a.phone LIKE CONCAT('%', #{param.phone}, '%')
|
||||
</if>
|
||||
<if test="param.departmentId != null">
|
||||
AND a.department_id = #{param.departmentId}
|
||||
</if>
|
||||
<if test="param.specialty != null">
|
||||
AND a.specialty LIKE CONCAT('%', #{param.specialty}, '%')
|
||||
</if>
|
||||
<if test="param.position != null">
|
||||
AND a.position LIKE CONCAT('%', #{param.position}, '%')
|
||||
</if>
|
||||
<if test="param.qualification != null">
|
||||
AND a.qualification LIKE CONCAT('%', #{param.qualification}, '%')
|
||||
</if>
|
||||
<if test="param.introduction != null">
|
||||
AND a.introduction LIKE CONCAT('%', #{param.introduction}, '%')
|
||||
</if>
|
||||
<if test="param.consultationFee != null">
|
||||
AND a.consultation_fee = #{param.consultationFee}
|
||||
</if>
|
||||
<if test="param.workYears != null">
|
||||
AND a.work_years = #{param.workYears}
|
||||
</if>
|
||||
<if test="param.consultationCount != null">
|
||||
AND a.consultation_count = #{param.consultationCount}
|
||||
</if>
|
||||
<if test="param.qrcode != null">
|
||||
AND a.qrcode LIKE CONCAT('%', #{param.qrcode}, '%')
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.sortNumber != null">
|
||||
AND a.sort_number = #{param.sortNumber}
|
||||
</if>
|
||||
<if test="param.isDelete != null">
|
||||
AND a.is_delete = #{param.isDelete}
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR a.real_name = #{param.keywords}
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicDoctorUser">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicDoctorUser">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,93 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicMedicineInoutMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*
|
||||
FROM clinic_medicine_inout a
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.orderNo != null">
|
||||
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%')
|
||||
</if>
|
||||
<if test="param.firstUserId != null">
|
||||
AND a.first_user_id = #{param.firstUserId}
|
||||
</if>
|
||||
<if test="param.secondUserId != null">
|
||||
AND a.second_user_id = #{param.secondUserId}
|
||||
</if>
|
||||
<if test="param.thirdUserId != null">
|
||||
AND a.third_user_id = #{param.thirdUserId}
|
||||
</if>
|
||||
<if test="param.firstMoney != null">
|
||||
AND a.first_money = #{param.firstMoney}
|
||||
</if>
|
||||
<if test="param.secondMoney != null">
|
||||
AND a.second_money = #{param.secondMoney}
|
||||
</if>
|
||||
<if test="param.thirdMoney != null">
|
||||
AND a.third_money = #{param.thirdMoney}
|
||||
</if>
|
||||
<if test="param.price != null">
|
||||
AND a.price = #{param.price}
|
||||
</if>
|
||||
<if test="param.orderPrice != null">
|
||||
AND a.order_price = #{param.orderPrice}
|
||||
</if>
|
||||
<if test="param.settledPrice != null">
|
||||
AND a.settled_price = #{param.settledPrice}
|
||||
</if>
|
||||
<if test="param.degreePrice != null">
|
||||
AND a.degree_price = #{param.degreePrice}
|
||||
</if>
|
||||
<if test="param.payPrice != null">
|
||||
AND a.pay_price = #{param.payPrice}
|
||||
</if>
|
||||
<if test="param.rate != null">
|
||||
AND a.rate = #{param.rate}
|
||||
</if>
|
||||
<if test="param.month != null">
|
||||
AND a.month LIKE CONCAT('%', #{param.month}, '%')
|
||||
</if>
|
||||
<if test="param.isInvalid != null">
|
||||
AND a.is_invalid = #{param.isInvalid}
|
||||
</if>
|
||||
<if test="param.isSettled != null">
|
||||
AND a.is_settled = #{param.isSettled}
|
||||
</if>
|
||||
<if test="param.settleTime != null">
|
||||
AND a.settle_time LIKE CONCAT('%', #{param.settleTime}, '%')
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicineInout">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicineInout">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,66 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicMedicineMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*
|
||||
FROM clinic_medicine a
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.name != null">
|
||||
AND a.name LIKE CONCAT('%', #{param.name}, '%')
|
||||
</if>
|
||||
<if test="param.pinyin != null">
|
||||
AND a.pinyin LIKE CONCAT('%', #{param.pinyin}, '%')
|
||||
</if>
|
||||
<if test="param.category != null">
|
||||
AND a.category LIKE CONCAT('%', #{param.category}, '%')
|
||||
</if>
|
||||
<if test="param.specification != null">
|
||||
AND a.specification LIKE CONCAT('%', #{param.specification}, '%')
|
||||
</if>
|
||||
<if test="param.unit != null">
|
||||
AND a.unit LIKE CONCAT('%', #{param.unit}, '%')
|
||||
</if>
|
||||
<if test="param.content != null">
|
||||
AND a.content LIKE CONCAT('%', #{param.content}, '%')
|
||||
</if>
|
||||
<if test="param.pricePerUnit != null">
|
||||
AND a.price_per_unit = #{param.pricePerUnit}
|
||||
</if>
|
||||
<if test="param.isActive != null">
|
||||
AND a.is_active = #{param.isActive}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicine">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicine">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicMedicineStockMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*
|
||||
FROM clinic_medicine_stock a
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.medicineId != null">
|
||||
AND a.medicine_id = #{param.medicineId}
|
||||
</if>
|
||||
<if test="param.stockQuantity != null">
|
||||
AND a.stock_quantity = #{param.stockQuantity}
|
||||
</if>
|
||||
<if test="param.minStockLevel != null">
|
||||
AND a.min_stock_level = #{param.minStockLevel}
|
||||
</if>
|
||||
<if test="param.lastUpdated != null">
|
||||
AND a.last_updated LIKE CONCAT('%', #{param.lastUpdated}, '%')
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicineStock">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicMedicineStock">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,71 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicPatientUserMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.phone, b.avatar
|
||||
FROM clinic_patient_user a
|
||||
LEFT JOIN gxwebsoft_core.sys_user b ON a.user_id = b.user_id
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.realName != null">
|
||||
AND a.real_name LIKE CONCAT('%', #{param.realName}, '%')
|
||||
</if>
|
||||
<if test="param.age != null">
|
||||
AND a.age LIKE CONCAT('%', #{param.age}, '%')
|
||||
</if>
|
||||
<if test="param.qrcode != null">
|
||||
AND a.qrcode LIKE CONCAT('%', #{param.qrcode}, '%')
|
||||
</if>
|
||||
<if test="param.height != null">
|
||||
AND a.height LIKE CONCAT('%', #{param.height}, '%')
|
||||
</if>
|
||||
<if test="param.weight != null">
|
||||
AND a.weight LIKE CONCAT('%', #{param.weight}, '%')
|
||||
</if>
|
||||
<if test="param.allergyHistory != null">
|
||||
AND a.allergy_history LIKE CONCAT('%', #{param.allergyHistory}, '%')
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.sortNumber != null">
|
||||
AND a.sort_number = #{param.sortNumber}
|
||||
</if>
|
||||
<if test="param.isDelete != null">
|
||||
AND a.is_delete = #{param.isDelete}
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR a.real_name = #{param.keywords}
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicPatientUser">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicPatientUser">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,73 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicPrescriptionItemMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.name AS medicineName, b.specification, b.unit, b.price_per_unit AS pricePerUnit
|
||||
FROM clinic_prescription_item a
|
||||
LEFT JOIN clinic_medicine b ON a.id = b.id
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.prescriptionId != null">
|
||||
AND a.prescription_id = #{param.prescriptionId}
|
||||
</if>
|
||||
<if test="param.prescriptionNo != null">
|
||||
AND a.prescription_no LIKE CONCAT('%', #{param.prescriptionNo}, '%')
|
||||
</if>
|
||||
<if test="param.medicineId != null">
|
||||
AND a.medicine_id = #{param.medicineId}
|
||||
</if>
|
||||
<if test="param.dosage != null">
|
||||
AND a.dosage LIKE CONCAT('%', #{param.dosage}, '%')
|
||||
</if>
|
||||
<if test="param.usageFrequency != null">
|
||||
AND a.usage_frequency LIKE CONCAT('%', #{param.usageFrequency}, '%')
|
||||
</if>
|
||||
<if test="param.days != null">
|
||||
AND a.days = #{param.days}
|
||||
</if>
|
||||
<if test="param.amount != null">
|
||||
AND a.amount = #{param.amount}
|
||||
</if>
|
||||
<if test="param.unitPrice != null">
|
||||
AND a.unit_price = #{param.unitPrice}
|
||||
</if>
|
||||
<if test="param.quantity != null">
|
||||
AND a.quantity = #{param.quantity}
|
||||
</if>
|
||||
<if test="param.sortNumber != null">
|
||||
AND a.sort_number = #{param.sortNumber}
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicPrescriptionItem">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicPrescriptionItem">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,132 +0,0 @@
|
||||
<?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.gxwebsoft.clinic.mapper.ClinicPrescriptionMapper">
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.real_name, b.age, b.sex, b.height, b.weight, c.real_name as doctorName, c.qualification, d.order_status as orderStatus, d.pay_status as payStatus
|
||||
FROM clinic_prescription a
|
||||
LEFT JOIN clinic_patient_user b ON a.user_id = b.user_id
|
||||
LEFT JOIN clinic_doctor_user c ON a.doctor_id = c.user_id
|
||||
LEFT JOIN shop_order d ON a.order_no = d.order_no
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
AND a.id = #{param.id}
|
||||
</if>
|
||||
<if test="param.userId != null">
|
||||
AND a.user_id = #{param.userId}
|
||||
</if>
|
||||
<if test="param.doctorId != null">
|
||||
AND a.doctor_id = #{param.doctorId}
|
||||
</if>
|
||||
<if test="param.orderNo != null">
|
||||
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%')
|
||||
</if>
|
||||
<if test="param.visitRecordId != null">
|
||||
AND a.visit_record_id = #{param.visitRecordId}
|
||||
</if>
|
||||
<if test="param.prescriptionType != null">
|
||||
AND a.prescription_type = #{param.prescriptionType}
|
||||
</if>
|
||||
<if test="param.diagnosis != null">
|
||||
AND a.diagnosis LIKE CONCAT('%', #{param.diagnosis}, '%')
|
||||
</if>
|
||||
<if test="param.treatmentPlan != null">
|
||||
AND a.treatment_plan LIKE CONCAT('%', #{param.treatmentPlan}, '%')
|
||||
</if>
|
||||
<if test="param.decoctionInstructions != null">
|
||||
AND a.decoction_instructions LIKE CONCAT('%', #{param.decoctionInstructions}, '%')
|
||||
</if>
|
||||
<if test="param.orderPrice != null">
|
||||
AND a.order_price = #{param.orderPrice}
|
||||
</if>
|
||||
<if test="param.price != null">
|
||||
AND a.price = #{param.price}
|
||||
</if>
|
||||
<if test="param.payPrice != null">
|
||||
AND a.pay_price = #{param.payPrice}
|
||||
</if>
|
||||
<if test="param.isInvalid != null">
|
||||
AND a.is_invalid = #{param.isInvalid}
|
||||
</if>
|
||||
<if test="param.isSettled != null">
|
||||
AND a.is_settled = #{param.isSettled}
|
||||
</if>
|
||||
<if test="param.ids != null">
|
||||
AND a.id IN
|
||||
<foreach collection="param.ids" item="item" separator="," open="(" close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="param.settleTime != null">
|
||||
AND a.settle_time LIKE CONCAT('%', #{param.settleTime}, '%')
|
||||
</if>
|
||||
<if test="param.status != null">
|
||||
AND a.status = #{param.status}
|
||||
</if>
|
||||
<if test="param.comments != null">
|
||||
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||
</if>
|
||||
<if test="param.createTimeStart != null">
|
||||
AND a.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test="param.createTimeEnd != null">
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
<!-- 订单状态筛选:-1全部,0待支付,1待发货,2待核销,3待收货,4待评价,5已完成,6已退款,7已删除 -->
|
||||
<if test="param.statusFilter != null and param.statusFilter != -1">
|
||||
<if test="param.statusFilter == 0">
|
||||
<!-- 0待支付:未付款 -->
|
||||
AND d.pay_status = 0 AND d.order_status = 0
|
||||
</if>
|
||||
<if test="param.statusFilter == 1">
|
||||
<!-- 1待发货:已付款但未发货 -->
|
||||
AND d.pay_status = 1 AND d.delivery_status = 10 AND d.order_status = 0
|
||||
</if>
|
||||
<if test="param.statusFilter == 2">
|
||||
<!-- 2待核销:已付款但订单状态为未使用 -->
|
||||
AND d.pay_status = 1 AND d.order_status = 0
|
||||
</if>
|
||||
<if test="param.statusFilter == 3">
|
||||
<!-- 3待收货:已发货但订单状态不是已完成 -->
|
||||
AND d.delivery_status = 20 AND d.order_status != 1
|
||||
</if>
|
||||
<if test="param.statusFilter == 4">
|
||||
<!-- 4待评价:订单已完成但可能需要评价 -->
|
||||
AND d.order_status = 1 AND d.evaluate_status = 0
|
||||
</if>
|
||||
<if test="param.statusFilter == 5">
|
||||
<!-- 5已完成:订单状态为已完成 -->
|
||||
AND d.order_status = 1
|
||||
</if>
|
||||
<if test="param.statusFilter == 6">
|
||||
<!-- 6退款/售后:订单状态为退款成功 -->
|
||||
AND (d.order_status = 4 OR d.order_status = 5 OR d.order_status = 6 OR d.order_status = 7)
|
||||
</if>
|
||||
<if test="param.statusFilter == 7">
|
||||
<!-- 7已删除:订单被删除 -->
|
||||
AND d.deleted = 1
|
||||
</if>
|
||||
<if test="param.statusFilter == 8">
|
||||
<!-- 8已取消:订单已取消 -->
|
||||
AND a.order_status = 2
|
||||
</if>
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询 -->
|
||||
<select id="selectPageRel" resultType="com.gxwebsoft.clinic.entity.ClinicPrescription">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
<!-- 查询全部 -->
|
||||
<select id="selectListRel" resultType="com.gxwebsoft.clinic.entity.ClinicPrescription">
|
||||
<include refid="selectSql"></include>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 挂号查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:03
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicAppointmentParam对象", description = "挂号查询参数")
|
||||
public class ClinicAppointmentParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "就诊原因")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "挂号时间")
|
||||
private String evaluateTime;
|
||||
|
||||
@Schema(description = "医生")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer doctorId;
|
||||
|
||||
@Schema(description = "患者")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isDelete;
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 医生入驻申请查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicDoctorApplyParam对象", description = "医生入驻申请查询参数")
|
||||
public class ClinicDoctorApplyParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer applyId;
|
||||
|
||||
@Schema(description = "类型 0医生")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "性别 1男 2女")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer gender;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "客户名称")
|
||||
private String dealerName;
|
||||
|
||||
@Schema(description = "证件号码")
|
||||
private String idCard;
|
||||
|
||||
@Schema(description = "生日")
|
||||
private String birthDate;
|
||||
|
||||
@Schema(description = "区分职称等级(如主治医师、副主任医师)")
|
||||
private String professionalTitle;
|
||||
|
||||
@Schema(description = "工作单位")
|
||||
private String workUnit;
|
||||
|
||||
@Schema(description = "执业资格核心凭证")
|
||||
private String practiceLicense;
|
||||
|
||||
@Schema(description = "限定可执业科室或疾病类型")
|
||||
private String practiceScope;
|
||||
|
||||
@Schema(description = "开始工作时间")
|
||||
private String startWorkDate;
|
||||
|
||||
@Schema(description = "简历")
|
||||
private String resume;
|
||||
|
||||
@Schema(description = "使用 JSON 存储多个证件文件路径(如执业证、学历证)")
|
||||
private String certificationFiles;
|
||||
|
||||
@Schema(description = "详细地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "签约价格")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal money;
|
||||
|
||||
@Schema(description = "推荐人用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer refereeId;
|
||||
|
||||
@Schema(description = "申请方式(10需后台审核 20无需审核)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer applyType;
|
||||
|
||||
@Schema(description = "审核状态 (10待审核 20审核通过 30驳回)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer applyStatus;
|
||||
|
||||
@Schema(description = "申请时间")
|
||||
private String applyTime;
|
||||
|
||||
@Schema(description = "审核时间")
|
||||
private String auditTime;
|
||||
|
||||
@Schema(description = "合同时间")
|
||||
private String contractTime;
|
||||
|
||||
@Schema(description = "过期时间")
|
||||
private String expirationTime;
|
||||
|
||||
@Schema(description = "驳回原因")
|
||||
private String rejectReason;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-23 15:58:20
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicDoctorUserParam对象", description = "分销商用户记录表查询参数")
|
||||
public class ClinicDoctorUserParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型 0经销商 1企业 2集团")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "部门")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer departmentId;
|
||||
|
||||
@Schema(description = "专业领域")
|
||||
private String specialty;
|
||||
|
||||
@Schema(description = "职务级别")
|
||||
private String position;
|
||||
|
||||
@Schema(description = "执业资格")
|
||||
private String qualification;
|
||||
|
||||
@Schema(description = "医生简介")
|
||||
private String introduction;
|
||||
|
||||
@Schema(description = "挂号费")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal consultationFee;
|
||||
|
||||
@Schema(description = "工作年限")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer workYears;
|
||||
|
||||
@Schema(description = "问诊人数")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer consultationCount;
|
||||
|
||||
@Schema(description = "专属二维码")
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isDelete;
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 出入库查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicMedicineInoutParam对象", description = "出入库查询参数")
|
||||
public class ClinicMedicineInoutParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "分销商用户id(一级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer firstUserId;
|
||||
|
||||
@Schema(description = "分销商用户id(二级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer secondUserId;
|
||||
|
||||
@Schema(description = "分销商用户id(三级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer thirdUserId;
|
||||
|
||||
@Schema(description = "分销佣金(一级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal firstMoney;
|
||||
|
||||
@Schema(description = "分销佣金(二级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal secondMoney;
|
||||
|
||||
@Schema(description = "分销佣金(三级)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal thirdMoney;
|
||||
|
||||
@Schema(description = "单价")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "订单总金额")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal orderPrice;
|
||||
|
||||
@Schema(description = "结算金额")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal settledPrice;
|
||||
|
||||
@Schema(description = "换算成度")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal degreePrice;
|
||||
|
||||
@Schema(description = "实发金额")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal payPrice;
|
||||
|
||||
@Schema(description = "税率")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal rate;
|
||||
|
||||
@Schema(description = "结算月份")
|
||||
private String month;
|
||||
|
||||
@Schema(description = "订单是否失效(0未失效 1已失效)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isInvalid;
|
||||
|
||||
@Schema(description = "佣金结算(0未结算 1已结算)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isSettled;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
private String settleTime;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 药品库查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:31
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicMedicineParam对象", description = "药品库查询参数")
|
||||
public class ClinicMedicineParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "药名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "拼音")
|
||||
private String pinyin;
|
||||
|
||||
@Schema(description = "分类(如“清热解毒”、“补气养血”)")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "规格(如“饮片”、“颗粒”)")
|
||||
private String specification;
|
||||
|
||||
@Schema(description = "单位(如“克”、“袋”)")
|
||||
private String unit;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "单价")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal pricePerUnit;
|
||||
|
||||
@Schema(description = "是否活跃")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isActive;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 药品库存查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicMedicineStockParam对象", description = "药品库存查询参数")
|
||||
public class ClinicMedicineStockParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "药品")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer medicineId;
|
||||
|
||||
@Schema(description = "库存数量")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer stockQuantity;
|
||||
|
||||
@Schema(description = "最小库存预警")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer minStockLevel;
|
||||
|
||||
@Schema(description = "上次更新时间")
|
||||
private String lastUpdated;
|
||||
|
||||
@Schema(description = "买家用户ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 患者查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-23 15:27:17
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicPatientUserParam对象", description = "患者查询参数")
|
||||
public class ClinicPatientUserParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "类型 0经销商 1企业 2集团")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "年龄")
|
||||
private String age;
|
||||
|
||||
@Schema(description = "专属二维码")
|
||||
private String qrcode;
|
||||
|
||||
@Schema(description = "身高")
|
||||
private String height;
|
||||
|
||||
@Schema(description = "体重")
|
||||
private String weight;
|
||||
|
||||
@Schema(description = "过敏史")
|
||||
private String allergyHistory;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isDelete;
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicPrescriptionItemParam对象", description = "处方明细表 查询参数")
|
||||
public class ClinicPrescriptionItemParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "自增ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "关联处方")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer prescriptionId;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String prescriptionNo;
|
||||
|
||||
@Schema(description = "关联药品")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer medicineId;
|
||||
|
||||
@Schema(description = "剂量(如“10g”)")
|
||||
private String dosage;
|
||||
|
||||
@Schema(description = "用法频率(如“每日三次”)")
|
||||
private String usageFrequency;
|
||||
|
||||
@Schema(description = "服用天数")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer days;
|
||||
|
||||
@Schema(description = "购买数量")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "单价")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
@Schema(description = "数量")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer quantity;
|
||||
|
||||
@Schema(description = "排序号")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "处方ID集查询")
|
||||
@TableField(exist = false)
|
||||
private Set<Integer> prescriptionIds;
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package com.gxwebsoft.clinic.param;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.gxwebsoft.common.core.annotation.QueryField;
|
||||
import com.gxwebsoft.common.core.annotation.QueryType;
|
||||
import com.gxwebsoft.common.core.web.BaseParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
查询参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:12
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(name = "ClinicPrescriptionParam对象", description = "处方主表查询参数")
|
||||
public class ClinicPrescriptionParam extends BaseParam {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "患者")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "医生")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer doctorId;
|
||||
|
||||
@Schema(description = "订单编号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "订单类型 0商城订单 1处方订单")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "关联就诊表")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer visitRecordId;
|
||||
|
||||
@Schema(description = "处方类型 0中药 1西药")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer prescriptionType;
|
||||
|
||||
@Schema(description = "诊断结果")
|
||||
private String diagnosis;
|
||||
|
||||
@Schema(description = "治疗方案")
|
||||
private String treatmentPlan;
|
||||
|
||||
@Schema(description = "煎药说明")
|
||||
private String decoctionInstructions;
|
||||
|
||||
@Schema(description = "订单总金额")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal orderPrice;
|
||||
|
||||
@Schema(description = "单价")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "实付金额")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private BigDecimal payPrice;
|
||||
|
||||
@Schema(description = "订单是否失效(0未失效 1已失效)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isInvalid;
|
||||
|
||||
@Schema(description = "结算(0未结算 1已结算)")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer isSettled;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
private String settleTime;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1已完成,2已支付,3已取消")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "处方ID集查询")
|
||||
@TableField(exist = false)
|
||||
private Set<Integer> ids;
|
||||
|
||||
@Schema(description = "订单状态筛选:-1全部,0待支付,1待发货,2待核销,3待收货,4待评价,5已完成,6已退款,7已删除")
|
||||
private Integer statusFilter;
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.clinic.entity.ClinicAppointment;
|
||||
import com.gxwebsoft.clinic.param.ClinicAppointmentParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 挂号Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicAppointmentService extends IService<ClinicAppointment> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicAppointment>
|
||||
*/
|
||||
PageResult<ClinicAppointment> pageRel(ClinicAppointmentParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicAppointment>
|
||||
*/
|
||||
List<ClinicAppointment> listRel(ClinicAppointmentParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicAppointment
|
||||
*/
|
||||
ClinicAppointment getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorApply;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorApplyParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生入驻申请Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicDoctorApplyService extends IService<ClinicDoctorApply> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicDoctorApply>
|
||||
*/
|
||||
PageResult<ClinicDoctorApply> pageRel(ClinicDoctorApplyParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicDoctorApply>
|
||||
*/
|
||||
List<ClinicDoctorApply> listRel(ClinicDoctorApplyParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param applyId 主键ID
|
||||
* @return ClinicDoctorApply
|
||||
*/
|
||||
ClinicDoctorApply getByIdRel(Integer applyId);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorUserParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicDoctorUserService extends IService<ClinicDoctorUser> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicDoctorUser>
|
||||
*/
|
||||
PageResult<ClinicDoctorUser> pageRel(ClinicDoctorUserParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicDoctorUser>
|
||||
*/
|
||||
List<ClinicDoctorUser> listRel(ClinicDoctorUserParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicDoctorUser
|
||||
*/
|
||||
ClinicDoctorUser getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineInout;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineInoutParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出入库Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
public interface ClinicMedicineInoutService extends IService<ClinicMedicineInout> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicMedicineInout>
|
||||
*/
|
||||
PageResult<ClinicMedicineInout> pageRel(ClinicMedicineInoutParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicineInout>
|
||||
*/
|
||||
List<ClinicMedicineInout> listRel(ClinicMedicineInoutParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicMedicineInout
|
||||
*/
|
||||
ClinicMedicineInout getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicine;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:31
|
||||
*/
|
||||
public interface ClinicMedicineService extends IService<ClinicMedicine> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicMedicine>
|
||||
*/
|
||||
PageResult<ClinicMedicine> pageRel(ClinicMedicineParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicine>
|
||||
*/
|
||||
List<ClinicMedicine> listRel(ClinicMedicineParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicMedicine
|
||||
*/
|
||||
ClinicMedicine getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineStock;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineStockParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库存Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
public interface ClinicMedicineStockService extends IService<ClinicMedicineStock> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicMedicineStock>
|
||||
*/
|
||||
PageResult<ClinicMedicineStock> pageRel(ClinicMedicineStockParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicMedicineStock>
|
||||
*/
|
||||
List<ClinicMedicineStock> listRel(ClinicMedicineStockParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicMedicineStock
|
||||
*/
|
||||
ClinicMedicineStock getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPatientUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicPatientUserParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
public interface ClinicPatientUserService extends IService<ClinicPatientUser> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicPatientUser>
|
||||
*/
|
||||
PageResult<ClinicPatientUser> pageRel(ClinicPatientUserParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPatientUser>
|
||||
*/
|
||||
List<ClinicPatientUser> listRel(ClinicPatientUserParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicPatientUser
|
||||
*/
|
||||
ClinicPatientUser getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionItemParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
public interface ClinicPrescriptionItemService extends IService<ClinicPrescriptionItem> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicPrescriptionItem>
|
||||
*/
|
||||
PageResult<ClinicPrescriptionItem> pageRel(ClinicPrescriptionItemParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPrescriptionItem>
|
||||
*/
|
||||
List<ClinicPrescriptionItem> listRel(ClinicPrescriptionItemParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 自增ID
|
||||
* @return ClinicPrescriptionItem
|
||||
*/
|
||||
ClinicPrescriptionItem getByIdRel(Integer id);
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescription;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
Service
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
public interface ClinicPrescriptionService extends IService<ClinicPrescription> {
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return PageResult<ClinicPrescription>
|
||||
*/
|
||||
PageResult<ClinicPrescription> pageRel(ClinicPrescriptionParam param);
|
||||
|
||||
/**
|
||||
* 关联查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<ClinicPrescription>
|
||||
*/
|
||||
List<ClinicPrescription> listRel(ClinicPrescriptionParam param);
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return ClinicPrescription
|
||||
*/
|
||||
ClinicPrescription getByIdRel(Integer id);
|
||||
|
||||
// 添加成功后返回数据
|
||||
ClinicPrescription getByLastId(ClinicPrescription clinicPrescription);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicAppointmentMapper;
|
||||
import com.gxwebsoft.clinic.service.ClinicAppointmentService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicAppointment;
|
||||
import com.gxwebsoft.clinic.param.ClinicAppointmentParam;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 挂号Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Service
|
||||
public class ClinicAppointmentServiceImpl extends ServiceImpl<ClinicAppointmentMapper, ClinicAppointment> implements ClinicAppointmentService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicAppointment> pageRel(ClinicAppointmentParam param) {
|
||||
PageParam<ClinicAppointment, ClinicAppointmentParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicAppointment> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicAppointment> listRel(ClinicAppointmentParam param) {
|
||||
List<ClinicAppointment> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicAppointment, ClinicAppointmentParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicAppointment getByIdRel(Integer id) {
|
||||
ClinicAppointmentParam param = new ClinicAppointmentParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicDoctorApplyMapper;
|
||||
import com.gxwebsoft.clinic.service.ClinicDoctorApplyService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorApply;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorApplyParam;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生入驻申请Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Service
|
||||
public class ClinicDoctorApplyServiceImpl extends ServiceImpl<ClinicDoctorApplyMapper, ClinicDoctorApply> implements ClinicDoctorApplyService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicDoctorApply> pageRel(ClinicDoctorApplyParam param) {
|
||||
PageParam<ClinicDoctorApply, ClinicDoctorApplyParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicDoctorApply> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicDoctorApply> listRel(ClinicDoctorApplyParam param) {
|
||||
List<ClinicDoctorApply> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicDoctorApply, ClinicDoctorApplyParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicDoctorApply getByIdRel(Integer applyId) {
|
||||
ClinicDoctorApplyParam param = new ClinicDoctorApplyParam();
|
||||
param.setApplyId(applyId);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicDoctorUserMapper;
|
||||
import com.gxwebsoft.clinic.service.ClinicDoctorUserService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicDoctorUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicDoctorUserParam;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分销商用户记录表Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Service
|
||||
public class ClinicDoctorUserServiceImpl extends ServiceImpl<ClinicDoctorUserMapper, ClinicDoctorUser> implements ClinicDoctorUserService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicDoctorUser> pageRel(ClinicDoctorUserParam param) {
|
||||
PageParam<ClinicDoctorUser, ClinicDoctorUserParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicDoctorUser> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicDoctorUser> listRel(ClinicDoctorUserParam param) {
|
||||
List<ClinicDoctorUser> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicDoctorUser, ClinicDoctorUserParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicDoctorUser getByIdRel(Integer id) {
|
||||
ClinicDoctorUserParam param = new ClinicDoctorUserParam();
|
||||
param.setUserId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineInout;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicMedicineInoutMapper;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineInoutParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineInoutService;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出入库Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Service
|
||||
public class ClinicMedicineInoutServiceImpl extends ServiceImpl<ClinicMedicineInoutMapper, ClinicMedicineInout> implements ClinicMedicineInoutService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicMedicineInout> pageRel(ClinicMedicineInoutParam param) {
|
||||
PageParam<ClinicMedicineInout, ClinicMedicineInoutParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicMedicineInout> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicMedicineInout> listRel(ClinicMedicineInoutParam param) {
|
||||
List<ClinicMedicineInout> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicMedicineInout, ClinicMedicineInoutParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicMedicineInout getByIdRel(Integer id) {
|
||||
ClinicMedicineInoutParam param = new ClinicMedicineInoutParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicine;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicMedicineMapper;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineService;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:31
|
||||
*/
|
||||
@Service
|
||||
public class ClinicMedicineServiceImpl extends ServiceImpl<ClinicMedicineMapper, ClinicMedicine> implements ClinicMedicineService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicMedicine> pageRel(ClinicMedicineParam param) {
|
||||
PageParam<ClinicMedicine, ClinicMedicineParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicMedicine> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicMedicine> listRel(ClinicMedicineParam param) {
|
||||
List<ClinicMedicine> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicMedicine, ClinicMedicineParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicMedicine getByIdRel(Integer id) {
|
||||
ClinicMedicineParam param = new ClinicMedicineParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.entity.ClinicMedicineStock;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicMedicineStockMapper;
|
||||
import com.gxwebsoft.clinic.param.ClinicMedicineStockParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicMedicineStockService;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 药品库存Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:06:32
|
||||
*/
|
||||
@Service
|
||||
public class ClinicMedicineStockServiceImpl extends ServiceImpl<ClinicMedicineStockMapper, ClinicMedicineStock> implements ClinicMedicineStockService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicMedicineStock> pageRel(ClinicMedicineStockParam param) {
|
||||
PageParam<ClinicMedicineStock, ClinicMedicineStockParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicMedicineStock> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicMedicineStock> listRel(ClinicMedicineStockParam param) {
|
||||
List<ClinicMedicineStock> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicMedicineStock, ClinicMedicineStockParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicMedicineStock getByIdRel(Integer id) {
|
||||
ClinicMedicineStockParam param = new ClinicMedicineStockParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicPatientUserMapper;
|
||||
import com.gxwebsoft.clinic.service.ClinicPatientUserService;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPatientUser;
|
||||
import com.gxwebsoft.clinic.param.ClinicPatientUserParam;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-19 09:27:04
|
||||
*/
|
||||
@Service
|
||||
public class ClinicPatientUserServiceImpl extends ServiceImpl<ClinicPatientUserMapper, ClinicPatientUser> implements ClinicPatientUserService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicPatientUser> pageRel(ClinicPatientUserParam param) {
|
||||
PageParam<ClinicPatientUser, ClinicPatientUserParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicPatientUser> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicPatientUser> listRel(ClinicPatientUserParam param) {
|
||||
List<ClinicPatientUser> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicPatientUser, ClinicPatientUserParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicPatientUser getByIdRel(Integer id) {
|
||||
ClinicPatientUserParam param = new ClinicPatientUserParam();
|
||||
param.setUserId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicPrescriptionItemMapper;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionItemParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicPrescriptionItemService;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 处方明细表
|
||||
Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Service
|
||||
public class ClinicPrescriptionItemServiceImpl extends ServiceImpl<ClinicPrescriptionItemMapper, ClinicPrescriptionItem> implements ClinicPrescriptionItemService {
|
||||
|
||||
@Override
|
||||
public PageResult<ClinicPrescriptionItem> pageRel(ClinicPrescriptionItemParam param) {
|
||||
PageParam<ClinicPrescriptionItem, ClinicPrescriptionItemParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicPrescriptionItem> list = baseMapper.selectPageRel(page, param);
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicPrescriptionItem> listRel(ClinicPrescriptionItemParam param) {
|
||||
List<ClinicPrescriptionItem> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicPrescriptionItem, ClinicPrescriptionItemParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicPrescriptionItem getByIdRel(Integer id) {
|
||||
ClinicPrescriptionItemParam param = new ClinicPrescriptionItemParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package com.gxwebsoft.clinic.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescription;
|
||||
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
|
||||
import com.gxwebsoft.clinic.mapper.ClinicPrescriptionMapper;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionItemParam;
|
||||
import com.gxwebsoft.clinic.param.ClinicPrescriptionParam;
|
||||
import com.gxwebsoft.clinic.service.ClinicPrescriptionItemService;
|
||||
import com.gxwebsoft.clinic.service.ClinicPrescriptionService;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.shop.entity.ShopOrder;
|
||||
import com.gxwebsoft.shop.entity.ShopOrderGoods;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 处方主表
|
||||
Service实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-10-22 02:01:13
|
||||
*/
|
||||
@Service
|
||||
public class ClinicPrescriptionServiceImpl extends ServiceImpl<ClinicPrescriptionMapper, ClinicPrescription> implements ClinicPrescriptionService {
|
||||
|
||||
@Resource
|
||||
private ClinicPrescriptionItemService clinicPrescriptionItemService;
|
||||
@Override
|
||||
public PageResult<ClinicPrescription> pageRel(ClinicPrescriptionParam param) {
|
||||
PageParam<ClinicPrescription, ClinicPrescriptionParam> page = new PageParam<>(param);
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
List<ClinicPrescription> list = baseMapper.selectPageRel(page, param);
|
||||
// 查询处方明细
|
||||
Set<Integer> collectIds = list.stream().map(ClinicPrescription::getId).collect(Collectors.toSet());
|
||||
final ClinicPrescriptionItemParam itemParam = new ClinicPrescriptionItemParam();
|
||||
itemParam.setPrescriptionIds(collectIds);
|
||||
final List<ClinicPrescriptionItem> clinicPrescriptionItems = clinicPrescriptionItemService.listRel(itemParam);
|
||||
final Map<Integer, List<ClinicPrescriptionItem>> collect = clinicPrescriptionItems.stream().collect(Collectors.groupingBy(ClinicPrescriptionItem::getPrescriptionId));
|
||||
list.forEach(d -> {
|
||||
d.setItems(collect.get(d.getId()));
|
||||
});
|
||||
return new PageResult<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClinicPrescription> listRel(ClinicPrescriptionParam param) {
|
||||
List<ClinicPrescription> list = baseMapper.selectListRel(param);
|
||||
// 排序
|
||||
PageParam<ClinicPrescription, ClinicPrescriptionParam> page = new PageParam<>();
|
||||
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||
return page.sortRecords(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicPrescription getByIdRel(Integer id) {
|
||||
ClinicPrescriptionParam param = new ClinicPrescriptionParam();
|
||||
param.setId(id);
|
||||
return param.getOne(baseMapper.selectListRel(param));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClinicPrescription getByLastId(ClinicPrescription clinicPrescription) {
|
||||
return getOne(new LambdaQueryWrapper<ClinicPrescription>().orderByDesc(ClinicPrescription::getId).eq(ClinicPrescription::getUserId, clinicPrescription.getUserId()).last("limit 1"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,8 +12,6 @@ import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.common.system.service.CompanyService;
|
||||
import com.gxwebsoft.common.system.service.UserService;
|
||||
import com.gxwebsoft.project.entity.Project;
|
||||
import com.gxwebsoft.project.service.ProjectService;
|
||||
import com.gxwebsoft.shop.vo.ShopVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -70,8 +68,6 @@ public class CmsWebsiteServiceImpl extends ServiceImpl<CmsWebsiteMapper, CmsWebs
|
||||
@Resource
|
||||
private CmsWebsiteMapper cmsWebsiteMapper;
|
||||
@Resource
|
||||
private ProjectService projectService;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@@ -284,22 +280,6 @@ public class CmsWebsiteServiceImpl extends ServiceImpl<CmsWebsiteMapper, CmsWebs
|
||||
log.warn("没有有效的模板ID,跳过复制操作");
|
||||
}
|
||||
|
||||
// 新增项目
|
||||
final Project project = new Project();
|
||||
project.setUserId(website.getUserId());
|
||||
project.setAppName(website.getWebsiteName());
|
||||
project.setAppIcon(website.getWebsiteIcon());
|
||||
project.setAppCode(website.getWebsiteCode());
|
||||
project.setAdminUrl(website.getAdminUrl());
|
||||
project.setRenewMoney(website.getPrice());
|
||||
project.setWebsiteId(website.getWebsiteId());
|
||||
project.setAdminUrl(website.getAdminUrl());
|
||||
project.setAppType(website.getWebsiteType());
|
||||
project.setAppIcon(website.getWebsiteLogo());
|
||||
project.setAppUrl(website.getDomain());
|
||||
project.setCompanyId(website.getUserId());
|
||||
project.setTenantId(5);
|
||||
projectService.save(project);
|
||||
}
|
||||
return website;
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ public class SwaggerConfig {
|
||||
public GroupedOpenApi otherApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("other")
|
||||
.pathsToMatch("/api/docs/**", "/api/project/**", "/api/pwl/**", "/api/bszx/**", "/api/hjm/**")
|
||||
.packagesToScan("com.gxwebsoft.docs", "com.gxwebsoft.project", "com.gxwebsoft.pwl", "com.gxwebsoft.bszx", "com.gxwebsoft.hjm")
|
||||
.pathsToMatch("/api/docs/**", "/api/project/**","/api/bszx/**")
|
||||
.packagesToScan("com.gxwebsoft.docs", "com.gxwebsoft.project", "com.gxwebsoft.bszx")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,855 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* credit 模块 Excel 导入批处理支持:
|
||||
* - 分批 upsert(批内一次查库 + 批量 insert/update)
|
||||
* - 每批独立事务(REQUIRES_NEW),避免单次导入事务过大拖垮数据库
|
||||
*/
|
||||
@Component
|
||||
public class BatchImportSupport {
|
||||
|
||||
private final TransactionTemplate requiresNewTx;
|
||||
private static final Pattern PARTY_SPLIT_PATTERN = Pattern.compile("[,,;;、\\n\\r\\t/|]+");
|
||||
|
||||
public BatchImportSupport(PlatformTransactionManager transactionManager) {
|
||||
TransactionTemplate template = new TransactionTemplate(transactionManager);
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
this.requiresNewTx = template;
|
||||
}
|
||||
|
||||
public int runInNewTx(Supplier<Integer> supplier) {
|
||||
return requiresNewTx.execute(status -> supplier.get());
|
||||
}
|
||||
|
||||
public static final class CompanyIdRefreshStats {
|
||||
public final boolean anyDataRead;
|
||||
public final int updated;
|
||||
public final int matched;
|
||||
public final int notFound;
|
||||
public final int ambiguous;
|
||||
|
||||
private CompanyIdRefreshStats(boolean anyDataRead, int updated, int matched, int notFound, int ambiguous) {
|
||||
this.anyDataRead = anyDataRead;
|
||||
this.updated = updated;
|
||||
this.matched = matched;
|
||||
this.notFound = notFound;
|
||||
this.ambiguous = ambiguous;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("updated", updated);
|
||||
result.put("matched", matched);
|
||||
result.put("notFound", notFound);
|
||||
result.put("ambiguous", ambiguous);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按企业名称匹配 CreditCompany(name / matchName) 并回填 companyId。
|
||||
*
|
||||
* <p>默认仅更新 companyId 为空/0 的记录(onlyNull=true);onlyNull=false 时会覆盖更新(仅当 companyId 不同)。</p>
|
||||
*
|
||||
* <p>注意:为避免跨租户误更新,当 currentTenantId 为空时会按记录自身 tenantId 维度匹配,
|
||||
* tenantId 为空的记录将被跳过并计入 notFound。</p>
|
||||
*/
|
||||
public <T> CompanyIdRefreshStats refreshCompanyIdByCompanyName(IService<T> service,
|
||||
CreditCompanyService creditCompanyService,
|
||||
Integer currentTenantId,
|
||||
Boolean onlyNull,
|
||||
Integer limit,
|
||||
SFunction<T, Integer> idGetter,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, String> nameGetter,
|
||||
SFunction<T, Integer> companyIdGetter,
|
||||
BiConsumer<T, Integer> companyIdSetter,
|
||||
SFunction<T, Boolean> hasDataGetter,
|
||||
BiConsumer<T, Boolean> hasDataSetter,
|
||||
SFunction<T, Integer> tenantIdGetter,
|
||||
Supplier<T> patchFactory) {
|
||||
// Keep existing API; delegate to the multi-column implementation.
|
||||
return refreshCompanyIdByCompanyNames(service,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
idGetter,
|
||||
idSetter,
|
||||
companyIdGetter,
|
||||
companyIdSetter,
|
||||
hasDataGetter,
|
||||
hasDataSetter,
|
||||
tenantIdGetter,
|
||||
patchFactory,
|
||||
nameGetter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按多列“当事人/企业名称”匹配 CreditCompany(name / matchName) 并回填 companyId。
|
||||
*
|
||||
* <p>按传入列顺序优先匹配:原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人等。</p>
|
||||
*
|
||||
* <p>同一列若匹配到多个不同企业则视为歧义;若最终无法得到唯一 companyId,则跳过并计入 ambiguous/notFound。</p>
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final <T> CompanyIdRefreshStats refreshCompanyIdByCompanyNames(IService<T> service,
|
||||
CreditCompanyService creditCompanyService,
|
||||
Integer currentTenantId,
|
||||
Boolean onlyNull,
|
||||
Integer limit,
|
||||
SFunction<T, Integer> idGetter,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, Integer> companyIdGetter,
|
||||
BiConsumer<T, Integer> companyIdSetter,
|
||||
SFunction<T, Boolean> hasDataGetter,
|
||||
BiConsumer<T, Boolean> hasDataSetter,
|
||||
SFunction<T, Integer> tenantIdGetter,
|
||||
Supplier<T> patchFactory,
|
||||
SFunction<T, String>... nameGetters) {
|
||||
boolean onlyNullFlag = (onlyNull == null) || Boolean.TRUE.equals(onlyNull);
|
||||
|
||||
if (nameGetters == null || nameGetters.length == 0) {
|
||||
return new CompanyIdRefreshStats(false, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// 1) 读取待处理数据(仅取必要字段,避免一次性拉全表字段)
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
SFunction<T, ?>[] selectColumns = (SFunction<T, ?>[]) new SFunction[4 + nameGetters.length];
|
||||
int colIdx = 0;
|
||||
selectColumns[colIdx++] = idGetter;
|
||||
selectColumns[colIdx++] = companyIdGetter;
|
||||
selectColumns[colIdx++] = hasDataGetter;
|
||||
selectColumns[colIdx++] = tenantIdGetter;
|
||||
for (SFunction<T, String> ng : nameGetters) {
|
||||
selectColumns[colIdx++] = ng;
|
||||
}
|
||||
|
||||
var query = service.lambdaQuery()
|
||||
.select(selectColumns)
|
||||
.eq(currentTenantId != null, tenantIdGetter, currentTenantId)
|
||||
.and(w -> {
|
||||
// Only process rows that have at least one name column populated.
|
||||
for (int i = 0; i < nameGetters.length; i++) {
|
||||
if (i == 0) {
|
||||
w.isNotNull(nameGetters[i]);
|
||||
} else {
|
||||
w.or().isNotNull(nameGetters[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (onlyNullFlag) {
|
||||
// Historically some tables used 0 as the "unset" companyId, while others left it NULL.
|
||||
// Treat both as "unset" so refresh won't silently do nothing.
|
||||
query.and(w -> w.isNull(companyIdGetter).or().eq(companyIdGetter, 0));
|
||||
}
|
||||
if (limit != null && limit > 0) {
|
||||
query.last("limit " + Math.min(limit, 200000));
|
||||
}
|
||||
List<T> rows = query.list();
|
||||
|
||||
if (CollectionUtils.isEmpty(rows)) {
|
||||
return new CompanyIdRefreshStats(false, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// 2) 按租户维度匹配(避免管理员/跨租户场景误匹配)
|
||||
Map<Integer, List<T>> rowsByTenant = new LinkedHashMap<>();
|
||||
int missingTenant = 0;
|
||||
for (T row : rows) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Integer tenantId = currentTenantId != null ? currentTenantId : tenantIdGetter.apply(row);
|
||||
if (tenantId == null) {
|
||||
// 未知租户下不做跨租户匹配,避免误更新
|
||||
missingTenant++;
|
||||
continue;
|
||||
}
|
||||
rowsByTenant.computeIfAbsent(tenantId, k -> new ArrayList<>()).add(row);
|
||||
}
|
||||
|
||||
// 3) 批量更新 companyId
|
||||
int updated = 0;
|
||||
int matched = 0;
|
||||
int notFound = 0;
|
||||
int ambiguous = 0;
|
||||
final int batchSize = 500;
|
||||
List<T> updates = new ArrayList<>(batchSize);
|
||||
|
||||
final int inChunkSize = 900;
|
||||
for (Map.Entry<Integer, List<T>> entry : rowsByTenant.entrySet()) {
|
||||
Integer tenantId = entry.getKey();
|
||||
List<T> tenantRows = entry.getValue();
|
||||
if (tenantId == null || CollectionUtils.isEmpty(tenantRows)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3.1) 查询当前租户下的 companyId 映射
|
||||
LinkedHashMap<String, Integer> companyIdByName = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> ambiguousByName = new LinkedHashMap<>();
|
||||
LinkedHashSet<String> nameSet = new LinkedHashSet<>();
|
||||
for (T row : tenantRows) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
for (SFunction<T, String> ng : nameGetters) {
|
||||
for (String name : splitPartyNames(ng.apply(row))) {
|
||||
if (name != null) {
|
||||
nameSet.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> allNames = new ArrayList<>(nameSet);
|
||||
for (int i = 0; i < allNames.size(); i += inChunkSize) {
|
||||
List<String> chunk = allNames.subList(i, Math.min(allNames.size(), i + inChunkSize));
|
||||
if (CollectionUtils.isEmpty(chunk)) {
|
||||
continue;
|
||||
}
|
||||
List<CreditCompany> companies = creditCompanyService.lambdaQuery()
|
||||
.select(CreditCompany::getId, CreditCompany::getName, CreditCompany::getMatchName, CreditCompany::getTenantId)
|
||||
.eq(CreditCompany::getTenantId, tenantId)
|
||||
.and(w -> w.in(CreditCompany::getName, chunk).or().in(CreditCompany::getMatchName, chunk))
|
||||
.list();
|
||||
|
||||
for (CreditCompany c : companies) {
|
||||
if (c == null || c.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
addCompanyNameMapping(companyIdByName, ambiguousByName, normalizeCompanyName(c.getName()), c.getId());
|
||||
addCompanyNameMapping(companyIdByName, ambiguousByName, normalizeCompanyName(c.getMatchName()), c.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// 3.2) 更新当前租户下的数据 companyId
|
||||
for (T row : tenantRows) {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Integer companyId = null;
|
||||
boolean hasAmbiguousName = false;
|
||||
for (SFunction<T, String> ng : nameGetters) {
|
||||
LinkedHashSet<Integer> idsForColumn = new LinkedHashSet<>();
|
||||
for (String key : splitPartyNames(ng.apply(row))) {
|
||||
if (key == null) {
|
||||
continue;
|
||||
}
|
||||
Integer amb = ambiguousByName.get(key);
|
||||
if (amb != null && amb > 0) {
|
||||
hasAmbiguousName = true;
|
||||
continue;
|
||||
}
|
||||
Integer cid = companyIdByName.get(key);
|
||||
if (cid != null) {
|
||||
idsForColumn.add(cid);
|
||||
}
|
||||
}
|
||||
if (idsForColumn.size() == 1) {
|
||||
companyId = idsForColumn.iterator().next();
|
||||
break;
|
||||
}
|
||||
if (idsForColumn.size() > 1) {
|
||||
// Multiple companies matched within one column (e.g. multiple plaintiffs) -> ambiguous.
|
||||
hasAmbiguousName = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (companyId == null) {
|
||||
if (hasAmbiguousName) {
|
||||
ambiguous++;
|
||||
} else {
|
||||
notFound++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
matched++;
|
||||
|
||||
Integer oldCompanyId = row != null ? companyIdGetter.apply(row) : null;
|
||||
Boolean oldHasData = row != null ? hasDataGetter.apply(row) : null;
|
||||
boolean needUpdate;
|
||||
if (onlyNullFlag) {
|
||||
needUpdate = (oldCompanyId == null) || oldCompanyId == 0;
|
||||
} else {
|
||||
needUpdate = oldCompanyId == null || !companyId.equals(oldCompanyId);
|
||||
}
|
||||
// 若已匹配到企业,但 hasData 未标记,则也需要回填 hasData=1
|
||||
if (!Boolean.TRUE.equals(oldHasData)) {
|
||||
needUpdate = true;
|
||||
}
|
||||
if (!needUpdate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Integer id = row != null ? idGetter.apply(row) : null;
|
||||
if (id == null) {
|
||||
continue;
|
||||
}
|
||||
T patch = patchFactory.get();
|
||||
idSetter.accept(patch, id);
|
||||
companyIdSetter.accept(patch, companyId);
|
||||
hasDataSetter.accept(patch, Boolean.TRUE);
|
||||
updates.add(patch);
|
||||
if (updates.size() >= batchSize) {
|
||||
List<T> batch = new ArrayList<>(updates);
|
||||
updates.clear();
|
||||
updated += runInNewTx(() -> service.updateBatchById(batch, batchSize) ? batch.size() : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// currentTenantId 为空时,租户缺失的数据不做匹配更新,避免误更新
|
||||
if (currentTenantId == null && missingTenant > 0) {
|
||||
notFound += missingTenant;
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
List<T> batch = new ArrayList<>(updates);
|
||||
updates.clear();
|
||||
updated += runInNewTx(() -> service.updateBatchById(batch, batchSize) ? batch.size() : 0);
|
||||
}
|
||||
|
||||
return new CompanyIdRefreshStats(true, updated, matched, notFound, ambiguous);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量 upsert:优先按 code 匹配;code 为空时按 name 匹配。
|
||||
*/
|
||||
public <T> int upsertByCodeOrName(IService<T> service,
|
||||
List<T> items,
|
||||
SFunction<T, Integer> idColumn,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, String> codeColumn,
|
||||
Function<T, String> codeGetter,
|
||||
SFunction<T, String> nameColumn,
|
||||
Function<T, String> nameGetter,
|
||||
Consumer<LambdaQueryWrapper<T>> extraConditions,
|
||||
int batchSize) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> codes = new ArrayList<>();
|
||||
List<String> names = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String code = normalize(codeGetter.apply(item));
|
||||
if (code != null) {
|
||||
codes.add(code);
|
||||
} else {
|
||||
String name = normalize(nameGetter.apply(item));
|
||||
if (name != null) {
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByCode = new HashMap<>();
|
||||
if (!codes.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(codeColumn, codes);
|
||||
wrapper.select(idColumn, codeColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String code = normalize(codeGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (code != null && id != null) {
|
||||
idByCode.putIfAbsent(code, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByName = new HashMap<>();
|
||||
if (!names.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(nameColumn, names);
|
||||
wrapper.select(idColumn, nameColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String name = normalize(nameGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (name != null && id != null) {
|
||||
idByName.putIfAbsent(name, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<T> updates = new ArrayList<>();
|
||||
List<T> inserts = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String code = normalize(codeGetter.apply(item));
|
||||
Integer id = null;
|
||||
if (code != null) {
|
||||
id = idByCode.get(code);
|
||||
} else {
|
||||
String name = normalize(nameGetter.apply(item));
|
||||
if (name != null) {
|
||||
id = idByName.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
idSetter.accept(item, id);
|
||||
updates.add(item);
|
||||
} else {
|
||||
inserts.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
service.updateBatchById(updates, batchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
service.saveBatch(inserts, batchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量 upsert:按单字段 key 匹配(key 非空)。
|
||||
*/
|
||||
public <T> int upsertBySingleKey(IService<T> service,
|
||||
List<T> items,
|
||||
SFunction<T, Integer> idColumn,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, String> keyColumn,
|
||||
Function<T, String> keyGetter,
|
||||
Consumer<LambdaQueryWrapper<T>> extraConditions,
|
||||
int batchSize) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> keys = new ArrayList<>(items.size());
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = normalize(keyGetter.apply(item));
|
||||
if (key != null) {
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByKey = new HashMap<>();
|
||||
if (!keys.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(keyColumn, keys);
|
||||
wrapper.select(idColumn, keyColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String key = normalize(keyGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (key != null && id != null) {
|
||||
idByKey.putIfAbsent(key, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<T> updates = new ArrayList<>();
|
||||
List<T> inserts = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = normalize(keyGetter.apply(item));
|
||||
Integer id = key != null ? idByKey.get(key) : null;
|
||||
if (id != null) {
|
||||
idSetter.accept(item, id);
|
||||
updates.add(item);
|
||||
} else {
|
||||
inserts.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
service.updateBatchById(updates, batchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
service.saveBatch(inserts, batchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量 upsert:按单字段 key 匹配(key 非空)。当匹配到已存在记录时:
|
||||
* - 覆盖更新
|
||||
* - 将 counter(通常是 recommend)在数据库原值基础上 +1,用于记录“被更新次数”
|
||||
*
|
||||
* <p>注意:counter 会被覆盖写入(不是 SQL 自增),因此该方法适合导入场景。</p>
|
||||
*/
|
||||
public <T> int upsertBySingleKeyAndIncrementCounterOnUpdate(IService<T> service,
|
||||
List<T> items,
|
||||
SFunction<T, Integer> idColumn,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, String> keyColumn,
|
||||
Function<T, String> keyGetter,
|
||||
SFunction<T, Integer> counterColumn,
|
||||
BiConsumer<T, Integer> counterSetter,
|
||||
Consumer<LambdaQueryWrapper<T>> extraConditions,
|
||||
int batchSize) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> keys = new ArrayList<>(items.size());
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = normalize(keyGetter.apply(item));
|
||||
if (key != null) {
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByKey = new HashMap<>();
|
||||
Map<String, Integer> counterByKey = new HashMap<>();
|
||||
if (!keys.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(keyColumn, keys);
|
||||
wrapper.select(idColumn, keyColumn, counterColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String key = normalize(keyGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (key == null || id == null) {
|
||||
continue;
|
||||
}
|
||||
idByKey.putIfAbsent(key, id);
|
||||
if (counterColumn != null) {
|
||||
counterByKey.putIfAbsent(key, counterColumn.apply(dbRow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<T> updates = new ArrayList<>();
|
||||
List<T> inserts = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = normalize(keyGetter.apply(item));
|
||||
Integer id = key != null ? idByKey.get(key) : null;
|
||||
if (id != null) {
|
||||
idSetter.accept(item, id);
|
||||
Integer old = key != null ? counterByKey.get(key) : null;
|
||||
if (counterSetter != null) {
|
||||
counterSetter.accept(item, old == null ? 1 : old + 1);
|
||||
}
|
||||
updates.add(item);
|
||||
} else {
|
||||
// insert:如果未提供 counterSetter,则不做处理;如果提供则默认 0。
|
||||
if (counterSetter != null) {
|
||||
counterSetter.accept(item, 0);
|
||||
}
|
||||
inserts.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
service.updateBatchById(updates, batchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
service.saveBatch(inserts, batchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量 upsert:优先按 code 匹配;code 为空时按 name 匹配。匹配到已存在记录时 counter +1。
|
||||
*/
|
||||
public <T> int upsertByCodeOrNameAndIncrementCounterOnUpdate(IService<T> service,
|
||||
List<T> items,
|
||||
SFunction<T, Integer> idColumn,
|
||||
BiConsumer<T, Integer> idSetter,
|
||||
SFunction<T, String> codeColumn,
|
||||
Function<T, String> codeGetter,
|
||||
SFunction<T, String> nameColumn,
|
||||
Function<T, String> nameGetter,
|
||||
SFunction<T, Integer> counterColumn,
|
||||
BiConsumer<T, Integer> counterSetter,
|
||||
Consumer<LambdaQueryWrapper<T>> extraConditions,
|
||||
int batchSize) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> codes = new ArrayList<>();
|
||||
List<String> names = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String code = normalize(codeGetter.apply(item));
|
||||
if (code != null) {
|
||||
codes.add(code);
|
||||
} else {
|
||||
String name = normalize(nameGetter.apply(item));
|
||||
if (name != null) {
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByCode = new HashMap<>();
|
||||
Map<String, Integer> counterByCode = new HashMap<>();
|
||||
if (!codes.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(codeColumn, codes);
|
||||
wrapper.select(idColumn, codeColumn, counterColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String code = normalize(codeGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (code == null || id == null) {
|
||||
continue;
|
||||
}
|
||||
idByCode.putIfAbsent(code, id);
|
||||
if (counterColumn != null) {
|
||||
counterByCode.putIfAbsent(code, counterColumn.apply(dbRow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> idByName = new HashMap<>();
|
||||
Map<String, Integer> counterByName = new HashMap<>();
|
||||
if (!names.isEmpty()) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
if (extraConditions != null) {
|
||||
extraConditions.accept(wrapper);
|
||||
}
|
||||
wrapper.in(nameColumn, names);
|
||||
wrapper.select(idColumn, nameColumn, counterColumn);
|
||||
for (T dbRow : service.list(wrapper)) {
|
||||
String name = normalize(nameGetter.apply(dbRow));
|
||||
Integer id = extractId(dbRow, idColumn);
|
||||
if (name == null || id == null) {
|
||||
continue;
|
||||
}
|
||||
idByName.putIfAbsent(name, id);
|
||||
if (counterColumn != null) {
|
||||
counterByName.putIfAbsent(name, counterColumn.apply(dbRow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<T> updates = new ArrayList<>();
|
||||
List<T> inserts = new ArrayList<>();
|
||||
for (T item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String code = normalize(codeGetter.apply(item));
|
||||
Integer id = null;
|
||||
Integer old = null;
|
||||
if (code != null) {
|
||||
id = idByCode.get(code);
|
||||
old = counterByCode.get(code);
|
||||
} else {
|
||||
String name = normalize(nameGetter.apply(item));
|
||||
if (name != null) {
|
||||
id = idByName.get(name);
|
||||
old = counterByName.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
idSetter.accept(item, id);
|
||||
if (counterSetter != null) {
|
||||
counterSetter.accept(item, old == null ? 1 : old + 1);
|
||||
}
|
||||
updates.add(item);
|
||||
} else {
|
||||
if (counterSetter != null) {
|
||||
counterSetter.accept(item, 0);
|
||||
}
|
||||
inserts.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
service.updateBatchById(updates, batchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
service.saveBatch(inserts, batchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量失败时降级逐行,尽量保留“第 N 行”错误定位。
|
||||
*/
|
||||
public <T> int persistChunkWithFallback(List<T> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
Supplier<Integer> batchPersist,
|
||||
BiFunction<T, Integer, Boolean> rowPersist,
|
||||
List<String> errorMessages) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return runInNewTx(batchPersist);
|
||||
} catch (Exception batchException) {
|
||||
int successCount = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
T item = items.get(i);
|
||||
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
|
||||
try {
|
||||
int delta = runInNewTx(() -> rowPersist.apply(item, excelRowNumber) ? 1 : 0);
|
||||
successCount += delta;
|
||||
} catch (Exception e) {
|
||||
if (errorMessages != null) {
|
||||
if (excelRowNumber > 0) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
} else {
|
||||
errorMessages.add(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return successCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量失败时降级逐行:允许调用方自定义“成功条数”的计算口径(例如:仅统计 insert 入库条数)。
|
||||
*
|
||||
* <p>batchPersistCount / rowPersistCount 返回的是“需要累计的条数增量”,并不等同于“是否成功”。</p>
|
||||
*/
|
||||
public <T> int persistChunkWithFallbackCount(List<T> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
Supplier<Integer> batchPersistCount,
|
||||
BiFunction<T, Integer, Integer> rowPersistCount,
|
||||
List<String> errorMessages) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return runInNewTx(batchPersistCount);
|
||||
} catch (Exception batchException) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
T item = items.get(i);
|
||||
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
|
||||
try {
|
||||
Integer delta = runInNewTx(() -> rowPersistCount.apply(item, excelRowNumber));
|
||||
if (delta != null && delta > 0) {
|
||||
count += delta;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (errorMessages != null) {
|
||||
if (excelRowNumber > 0) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
} else {
|
||||
errorMessages.add(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
private static String normalize(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private static String normalizeCompanyName(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
// 兼容 Excel/网页复制带来的全角空格
|
||||
String v = name.replace(' ', ' ').trim();
|
||||
return v.isEmpty() ? null : v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a "party names" cell into normalized company name candidates.
|
||||
* Supports common separators used in Excel/web copy (comma/semicolon/Chinese list delimiter/newlines).
|
||||
*/
|
||||
private static List<String> splitPartyNames(String raw) {
|
||||
List<String> result = new ArrayList<>();
|
||||
String v = normalizeCompanyName(raw);
|
||||
if (v == null) {
|
||||
return result;
|
||||
}
|
||||
String[] parts = PARTY_SPLIT_PATTERN.split(v);
|
||||
if (parts == null || parts.length == 0) {
|
||||
result.add(v);
|
||||
return result;
|
||||
}
|
||||
for (String p : parts) {
|
||||
String item = normalizeCompanyName(p);
|
||||
if (item != null) {
|
||||
result.add(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void addCompanyNameMapping(Map<String, Integer> idByName,
|
||||
Map<String, Integer> ambiguousByName,
|
||||
String key,
|
||||
Integer companyId) {
|
||||
if (key == null || companyId == null) {
|
||||
return;
|
||||
}
|
||||
Integer existing = idByName.get(key);
|
||||
if (existing == null) {
|
||||
idByName.put(key, companyId);
|
||||
return;
|
||||
}
|
||||
if (!existing.equals(companyId)) {
|
||||
ambiguousByName.put(key, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Integer extractId(T entity, SFunction<T, Integer> idColumn) {
|
||||
// SFunction 是 getter method ref,直接调用即可
|
||||
return idColumn.apply(entity);
|
||||
}
|
||||
}
|
||||
@@ -1,696 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditAdministrativeLicense;
|
||||
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditAdministrativeLicenseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 行政许可控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "行政许可管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-administrative-license")
|
||||
public class CreditAdministrativeLicenseController extends BaseController {
|
||||
@Resource
|
||||
private CreditAdministrativeLicenseService creditAdministrativeLicenseService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询行政许可")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditAdministrativeLicense>> page(CreditAdministrativeLicenseParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部行政许可")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditAdministrativeLicense>> list(CreditAdministrativeLicenseParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询行政许可")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditAdministrativeLicense> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加行政许可")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditAdministrativeLicense.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditAdministrativeLicenseService.save(creditAdministrativeLicense)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改行政许可")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
|
||||
if (creditAdministrativeLicenseService.updateById(creditAdministrativeLicense)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除行政许可")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditAdministrativeLicenseService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加行政许可")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditAdministrativeLicense> list) {
|
||||
if (creditAdministrativeLicenseService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改行政许可")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditAdministrativeLicense> batchParam) {
|
||||
if (batchParam.update(creditAdministrativeLicenseService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除行政许可")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditAdministrativeLicenseService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditAdministrativeLicenseService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getCompanyId,
|
||||
CreditAdministrativeLicense::setCompanyId,
|
||||
CreditAdministrativeLicense::getHasData,
|
||||
CreditAdministrativeLicense::setHasData,
|
||||
CreditAdministrativeLicense::getTenantId,
|
||||
CreditAdministrativeLicense::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入行政许可
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@Operation(summary = "批量导入行政许可")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditAdministrativeLicenseImportParam param = list.get(i);
|
||||
try {
|
||||
CreditAdministrativeLicense item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:决定文书/许可证名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertByCodeOrName(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditAdministrativeLicenseService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditAdministrativeLicense existing = null;
|
||||
if (!ImportHelper.isBlank(rowItem.getCode())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
|
||||
.one();
|
||||
}
|
||||
if (existing == null) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
|
||||
.one();
|
||||
}
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditAdministrativeLicenseService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertByCodeOrName(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditAdministrativeLicenseService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditAdministrativeLicense existing = null;
|
||||
if (!ImportHelper.isBlank(rowItem.getCode())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
|
||||
.one();
|
||||
}
|
||||
if (existing == null) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
|
||||
.one();
|
||||
}
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditAdministrativeLicenseService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史行政许可(仅解析“历史行政许可”选项卡)
|
||||
* 规则:优先按编号(code)匹配;code 为空时按名称(name)匹配;匹配到则覆盖更新(recommend++ 记录更新次数)。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@Operation(summary = "批量导入历史行政许可")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史行政许可");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史行政许可”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");
|
||||
|
||||
LinkedHashMap<String, CreditAdministrativeLicense> latestByKey = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByKey = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditAdministrativeLicenseImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditAdministrativeLicense item = convertImportParamToEntity(param);
|
||||
if (item.getCode() != null) {
|
||||
item.setCode(item.getCode().trim());
|
||||
}
|
||||
if (item.getName() != null) {
|
||||
item.setName(item.getName().trim());
|
||||
}
|
||||
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:决定文书/许可证名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
String dedupKey = !ImportHelper.isBlank(item.getCode()) ? ("CODE:" + item.getCode()) : ("NAME:" + item.getName());
|
||||
latestByKey.put(dedupKey, item);
|
||||
latestRowByKey.put(dedupKey, excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByKey.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditAdministrativeLicense> entry : latestByKey.entrySet()) {
|
||||
String dedupKey = entry.getKey();
|
||||
CreditAdministrativeLicense item = entry.getValue();
|
||||
Integer rowNo = latestRowByKey.get(dedupKey);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getRecommend,
|
||||
CreditAdministrativeLicense::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditAdministrativeLicenseService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditAdministrativeLicense existing = null;
|
||||
if (!ImportHelper.isBlank(rowItem.getCode())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
|
||||
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
|
||||
.one();
|
||||
}
|
||||
if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
|
||||
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
|
||||
.one();
|
||||
}
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditAdministrativeLicenseService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getCode,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getRecommend,
|
||||
CreditAdministrativeLicense::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditAdministrativeLicenseService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditAdministrativeLicense existing = null;
|
||||
if (!ImportHelper.isBlank(rowItem.getCode())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
|
||||
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
|
||||
.one();
|
||||
}
|
||||
if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
|
||||
existing = creditAdministrativeLicenseService.lambdaQuery()
|
||||
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
|
||||
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
|
||||
.one();
|
||||
}
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditAdministrativeLicenseService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载行政许可导入模板
|
||||
*/
|
||||
@Operation(summary = "下载行政许可导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditAdministrativeLicenseImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditAdministrativeLicenseImportParam example = new CreditAdministrativeLicenseImportParam();
|
||||
example.setCode("(2024)示例许可编号");
|
||||
example.setName("示例行政许可名称");
|
||||
example.setStatusText("有效");
|
||||
example.setType("行政许可");
|
||||
example.setValidityStart("2024-01-01");
|
||||
example.setValidityEnd("2029-01-01");
|
||||
example.setLicensingAuthority("某某许可机关");
|
||||
example.setLicenseContent("许可内容示例");
|
||||
example.setDataSourceUnit("数据来源单位示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("行政许可导入模板", "行政许可", CreditAdministrativeLicenseImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_administrative_license_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditAdministrativeLicenseImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getStatusText());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditAdministrativeLicenseImportParam param) {
|
||||
return isHeaderValue(param.getCode(), "决定文书/许可编号")
|
||||
|| isHeaderValue(param.getName(), "决定文书/许可证名称")
|
||||
|| isHeaderValue(param.getStatusText(), "许可状态");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditAdministrativeLicense convertImportParamToEntity(CreditAdministrativeLicenseImportParam param) {
|
||||
CreditAdministrativeLicense entity = new CreditAdministrativeLicense();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setType(param.getType());
|
||||
entity.setValidityStart(param.getValidityStart());
|
||||
entity.setValidityEnd(param.getValidityEnd());
|
||||
entity.setLicensingAuthority(param.getLicensingAuthority());
|
||||
entity.setLicenseContent(param.getLicenseContent());
|
||||
entity.setDataSourceUnit(param.getDataSourceUnit());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,627 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditBankruptcy;
|
||||
import com.gxwebsoft.credit.param.CreditBankruptcyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBankruptcyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBankruptcyService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 破产重整控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "破产重整管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-bankruptcy")
|
||||
public class CreditBankruptcyController extends BaseController {
|
||||
@Resource
|
||||
private CreditBankruptcyService creditBankruptcyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询破产重整")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBankruptcy>> page(CreditBankruptcyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部破产重整")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBankruptcy>> list(CreditBankruptcyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询破产重整")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBankruptcy> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加破产重整")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBankruptcy creditBankruptcy) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditBankruptcy.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditBankruptcyService.save(creditBankruptcy)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改破产重整")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBankruptcy creditBankruptcy) {
|
||||
if (creditBankruptcyService.updateById(creditBankruptcy)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除破产重整")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditBankruptcyService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加破产重整")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBankruptcy> list) {
|
||||
if (creditBankruptcyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改破产重整")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBankruptcy> batchParam) {
|
||||
if (batchParam.update(creditBankruptcyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除破产重整")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditBankruptcyService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditBankruptcyService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getParty,
|
||||
CreditBankruptcy::getCompanyId,
|
||||
CreditBankruptcy::setCompanyId,
|
||||
CreditBankruptcy::getHasData,
|
||||
CreditBankruptcy::setHasData,
|
||||
CreditBankruptcy::getTenantId,
|
||||
CreditBankruptcy::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入破产重整
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@Operation(summary = "批量导入破产重整")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditBankruptcyImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditBankruptcyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBankruptcy> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBankruptcyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBankruptcy item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
String link = urlByCode.get(item.getCode().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCode())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getCode,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBankruptcyService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
|
||||
.eq(CreditBankruptcy::getCode, rowItem.getCode())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBankruptcyService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getCode,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBankruptcyService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
|
||||
.eq(CreditBankruptcy::getCode, rowItem.getCode())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBankruptcyService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BANKRUPTCY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史破产重整(仅解析“历史破产重整”选项卡)
|
||||
* 规则:案号/唯一标识相同则覆盖更新(recommend++ 记录更新次数);不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@Operation(summary = "批量导入历史破产重整")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史破产重整");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史破产重整”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBankruptcyImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBankruptcyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
LinkedHashMap<String, CreditBankruptcy> latestByCode = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCode = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBankruptcyImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditBankruptcy item = convertImportParamToEntity(param);
|
||||
if (item.getCode() != null) {
|
||||
item.setCode(item.getCode().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCode())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCode.get(item.getCode());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
latestByCode.put(item.getCode(), item);
|
||||
latestRowByCode.put(item.getCode(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCode.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBankruptcy> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditBankruptcy> entry : latestByCode.entrySet()) {
|
||||
String code = entry.getKey();
|
||||
CreditBankruptcy item = entry.getValue();
|
||||
Integer rowNo = latestRowByCode.get(code);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getRecommend,
|
||||
CreditBankruptcy::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditBankruptcyService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
|
||||
.eq(CreditBankruptcy::getCode, rowItem.getCode())
|
||||
.select(CreditBankruptcy::getId, CreditBankruptcy::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditBankruptcyService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getCode,
|
||||
CreditBankruptcy::getRecommend,
|
||||
CreditBankruptcy::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditBankruptcyService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
|
||||
.eq(CreditBankruptcy::getCode, rowItem.getCode())
|
||||
.select(CreditBankruptcy::getId, CreditBankruptcy::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditBankruptcyService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BANKRUPTCY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载破产重整导入模板
|
||||
*/
|
||||
@Operation(summary = "下载破产重整导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBankruptcyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBankruptcyImportParam example = new CreditBankruptcyImportParam();
|
||||
example.setCode("(2024)示例案号");
|
||||
example.setType("破产清算");
|
||||
example.setParty("某某公司");
|
||||
example.setCourt("某某人民法院");
|
||||
example.setPublicDate("2024-01-10");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("破产重整导入模板", "破产重整", CreditBankruptcyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_bankruptcy_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBankruptcyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getParty())
|
||||
&& ImportHelper.isBlank(param.getCourt());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditBankruptcyImportParam param) {
|
||||
return isHeaderValue(param.getCode(), "案号")
|
||||
|| isHeaderValue(param.getType(), "案件类型")
|
||||
|| isHeaderValue(param.getParty(), "当事人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditBankruptcy convertImportParamToEntity(CreditBankruptcyImportParam param) {
|
||||
CreditBankruptcy entity = new CreditBankruptcy();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setType(param.getType());
|
||||
entity.setParty(param.getParty());
|
||||
entity.setCourt(param.getCourt());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,420 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditBranch;
|
||||
import com.gxwebsoft.credit.param.CreditBranchImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBranchParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBranchService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 分支机构控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "分支机构管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-branch")
|
||||
public class CreditBranchController extends BaseController {
|
||||
@Resource
|
||||
private CreditBranchService creditBranchService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询分支机构")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBranch>> page(CreditBranchParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部分支机构")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBranch>> list(CreditBranchParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询分支机构")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBranch> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加分支机构")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBranch creditBranch) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditBranch.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditBranchService.save(creditBranch)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改分支机构")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBranch creditBranch) {
|
||||
if (creditBranchService.updateById(creditBranch)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除分支机构")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditBranchService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加分支机构")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBranch> list) {
|
||||
if (creditBranchService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改分支机构")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBranch> batchParam) {
|
||||
if (batchParam.update(creditBranchService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除分支机构")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditBranchService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditBranchService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBranch::getId,
|
||||
CreditBranch::setId,
|
||||
CreditBranch::getName,
|
||||
CreditBranch::getCompanyId,
|
||||
CreditBranch::setCompanyId,
|
||||
CreditBranch::getHasData,
|
||||
CreditBranch::setHasData,
|
||||
CreditBranch::getTenantId,
|
||||
CreditBranch::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入分支机构
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@Operation(summary = "批量导入分支机构")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditBranchImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditBranchImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditBranchImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "分支机构名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBranch> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBranchImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBranch item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:分支机构名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBranchService,
|
||||
chunkItems,
|
||||
CreditBranch::getId,
|
||||
CreditBranch::setId,
|
||||
CreditBranch::getName,
|
||||
CreditBranch::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBranchService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBranch existing = creditBranchService.lambdaQuery()
|
||||
.eq(CreditBranch::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBranchService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBranchService,
|
||||
chunkItems,
|
||||
CreditBranch::getId,
|
||||
CreditBranch::setId,
|
||||
CreditBranch::getName,
|
||||
CreditBranch::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBranchService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBranch existing = creditBranchService.lambdaQuery()
|
||||
.eq(CreditBranch::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBranchService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BRANCH, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载分支机构导入模板
|
||||
*/
|
||||
@Operation(summary = "下载分支机构导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBranchImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBranchImportParam example = new CreditBranchImportParam();
|
||||
example.setName("某某公司分支机构");
|
||||
example.setCurator("张三");
|
||||
example.setRegion("广西南宁");
|
||||
example.setEstablishDate("2020-06-01");
|
||||
example.setStatusText("存续");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("分支机构导入模板", "分支机构", CreditBranchImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_branch_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBranchImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getCurator())
|
||||
&& ImportHelper.isBlank(param.getRegion());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditBranchImportParam param) {
|
||||
return isHeaderValue(param.getName(), "分支机构名称")
|
||||
|| isHeaderValue(param.getCurator(), "负责人")
|
||||
|| isHeaderValue(param.getRegion(), "地区");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditBranch convertImportParamToEntity(CreditBranchImportParam param) {
|
||||
CreditBranch entity = new CreditBranch();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setCurator(param.getCurator());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,638 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditBreachOfTrust;
|
||||
import com.gxwebsoft.credit.param.CreditBreachOfTrustImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBreachOfTrustParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBreachOfTrustService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 失信被执行人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:46:14
|
||||
*/
|
||||
@Tag(name = "失信被执行人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-breach-of-trust")
|
||||
public class CreditBreachOfTrustController extends BaseController {
|
||||
@Resource
|
||||
private CreditBreachOfTrustService creditBreachOfTrustService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询失信被执行人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBreachOfTrust>> page(CreditBreachOfTrustParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部失信被执行人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBreachOfTrust>> list(CreditBreachOfTrustParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询失信被执行人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBreachOfTrust> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加失信被执行人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBreachOfTrust creditBreachOfTrust) {
|
||||
if (creditBreachOfTrustService.save(creditBreachOfTrust)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改失信被执行人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBreachOfTrust creditBreachOfTrust) {
|
||||
if (creditBreachOfTrustService.updateById(creditBreachOfTrust)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除失信被执行人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditBreachOfTrustService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加失信被执行人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBreachOfTrust> list) {
|
||||
if (creditBreachOfTrustService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改失信被执行人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBreachOfTrust> batchParam) {
|
||||
if (batchParam.update(creditBreachOfTrustService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除失信被执行人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditBreachOfTrustService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditBreachOfTrustService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getPlaintiffAppellant,
|
||||
CreditBreachOfTrust::getCompanyId,
|
||||
CreditBreachOfTrust::setCompanyId,
|
||||
CreditBreachOfTrust::getHasData,
|
||||
CreditBreachOfTrust::setHasData,
|
||||
CreditBreachOfTrust::getTenantId,
|
||||
CreditBreachOfTrust::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入失信被执行人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@Operation(summary = "批量导入失信被执行人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "失信被执行人", 0);
|
||||
ExcelImportSupport.ImportResult<CreditBreachOfTrustImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBreachOfTrustImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBreachOfTrustImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBreachOfTrust> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBreachOfTrustImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBreachOfTrust item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBreachOfTrustService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
|
||||
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBreachOfTrustService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditBreachOfTrustService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
|
||||
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditBreachOfTrustService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BREACH_OF_TRUST, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史失信被执行人(仅解析“历史失信被执行人”选项卡)
|
||||
* 规则:案号相同则覆盖更新(recommend++ 记录更新次数);案号不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@Operation(summary = "批量导入历史失信被执行人")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史失信被执行人");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史失信被执行人”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditBreachOfTrustImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBreachOfTrustImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBreachOfTrustImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
// 同案号多条:以导入文件中“最后一条”为准(视为最新)
|
||||
LinkedHashMap<String, CreditBreachOfTrust> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBreachOfTrustImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditBreachOfTrust item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBreachOfTrust> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditBreachOfTrust> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditBreachOfTrust item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getRecommend,
|
||||
CreditBreachOfTrust::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditBreachOfTrustService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
|
||||
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditBreachOfTrust::getId, CreditBreachOfTrust::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditBreachOfTrustService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
CreditBreachOfTrust::getRecommend,
|
||||
CreditBreachOfTrust::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditBreachOfTrustService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
|
||||
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditBreachOfTrust::getId, CreditBreachOfTrust::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditBreachOfTrustService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BREACH_OF_TRUST, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载失信被执行人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载失信被执行人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBreachOfTrustImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBreachOfTrustImportParam example = new CreditBreachOfTrustImportParam();
|
||||
example.setDataType("失信被执行人");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setInvolvedAmount("20,293.91");
|
||||
example.setDataStatus("正常");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCourtName("示例法院");
|
||||
example.setReleaseDate("2024-01-01");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("失信被执行人导入模板", "失信被执行人", CreditBreachOfTrustImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_breach_of_trust_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBreachOfTrustImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getAppellee2());
|
||||
}
|
||||
|
||||
private CreditBreachOfTrust convertImportParamToEntity(CreditBreachOfTrustImportParam param) {
|
||||
CreditBreachOfTrust entity = new CreditBreachOfTrust();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee2())
|
||||
? param.getAppellee2()
|
||||
: param.getAppellee();
|
||||
entity.setAppellee(appellee);
|
||||
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setInvolvedAmount(!ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount());
|
||||
entity.setOccurrenceTime(!ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime());
|
||||
entity.setCourtName(!ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,443 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCaseFiling;
|
||||
import com.gxwebsoft.credit.param.CreditCaseFilingImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCaseFilingParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCaseFilingService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:47:23
|
||||
*/
|
||||
@Tag(name = "司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-case-filing")
|
||||
public class CreditCaseFilingController extends BaseController {
|
||||
@Resource
|
||||
private CreditCaseFilingService creditCaseFilingService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCaseFiling>> page(CreditCaseFilingParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCaseFiling>> list(CreditCaseFilingParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCaseFiling> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCaseFiling creditCaseFiling) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCaseFiling.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCaseFilingService.save(creditCaseFiling)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCaseFiling creditCaseFiling) {
|
||||
if (creditCaseFilingService.updateById(creditCaseFiling)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCaseFilingService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCaseFiling> list) {
|
||||
if (creditCaseFilingService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCaseFiling> batchParam) {
|
||||
if (batchParam.update(creditCaseFilingService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCaseFilingService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCaseFilingService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCaseFiling::getId,
|
||||
CreditCaseFiling::setId,
|
||||
CreditCaseFiling::getAppellee,
|
||||
CreditCaseFiling::getCompanyId,
|
||||
CreditCaseFiling::setCompanyId,
|
||||
CreditCaseFiling::getHasData,
|
||||
CreditCaseFiling::setHasData,
|
||||
CreditCaseFiling::getTenantId,
|
||||
CreditCaseFiling::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入立案信息
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@Operation(summary = "批量导入立案信息")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "立案信息", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCaseFilingImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCaseFilingImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCaseFilingImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 通常挂在“案号”列的超链接中,需要额外读取回填。
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCaseFiling> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCaseFilingImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCaseFiling item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
CreditCaseFiling::getId,
|
||||
CreditCaseFiling::setId,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCaseFilingService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCaseFiling existing = creditCaseFilingService.lambdaQuery()
|
||||
.eq(CreditCaseFiling::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCaseFilingService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
CreditCaseFiling::getId,
|
||||
CreditCaseFiling::setId,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCaseFilingService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCaseFiling existing = creditCaseFilingService.lambdaQuery()
|
||||
.eq(CreditCaseFiling::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCaseFilingService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CASE_FILING, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载立案信息导入模板
|
||||
*/
|
||||
@Operation(summary = "下载立案信息导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCaseFilingImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCaseFilingImportParam example = new CreditCaseFilingImportParam();
|
||||
example.setDataType("立案信息");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("立案信息导入模板", "立案信息", CreditCaseFilingImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_case_filing_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCaseFilingImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
&& ImportHelper.isBlank(param.getCourtName())
|
||||
&& ImportHelper.isBlank(param.getCourtName2())
|
||||
&& ImportHelper.isBlank(param.getOccurrenceTime())
|
||||
&& ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
&& ImportHelper.isBlank(param.getDataStatus())
|
||||
&& ImportHelper.isBlank(param.getDataType())
|
||||
&& ImportHelper.isBlank(param.getComments());
|
||||
}
|
||||
|
||||
private CreditCaseFiling convertImportParamToEntity(CreditCaseFilingImportParam param) {
|
||||
CreditCaseFiling entity = new CreditCaseFiling();
|
||||
|
||||
// Template compatibility: prefer new columns when present.
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setCourtName(courtName);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,548 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.param.CreditCompanyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCompanyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 企业控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-17 08:28:03
|
||||
*/
|
||||
@Tag(name = "企业管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-company")
|
||||
public class CreditCompanyController extends BaseController {
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询企业")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCompany>> page(CreditCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部企业")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCompany>> list(CreditCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询企业")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCompany> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加企业")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCompany creditCompany) {
|
||||
if (creditCompanyService.save(creditCompany)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改企业")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCompany creditCompany) {
|
||||
if (creditCompanyService.updateById(creditCompany)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除企业")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCompanyService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加企业")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCompany> list) {
|
||||
if (creditCompanyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改企业")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCompany> batchParam) {
|
||||
if (batchParam.update(creditCompanyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除企业")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCompanyService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入企业
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@Operation(summary = "批量导入企业")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int insertedCount = 0;
|
||||
Set<String> touchedMatchNames = new HashSet<>();
|
||||
|
||||
try {
|
||||
List<CreditCompanyImportParam> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
list = filterEmptyRows(tryImport(file, config[0], config[1]));
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "原文件导入名称");
|
||||
Map<String, String> urlByMatchName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "系统匹配企业名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCompany> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCompanyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCompany item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (item.getName() != null) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && item.getMatchName() != null) {
|
||||
link = urlByMatchName.get(item.getMatchName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
if (item.getMatchName() == null || item.getMatchName().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
continue;
|
||||
}
|
||||
// if (item.getCode() == null || item.getCode().trim().isEmpty()) {
|
||||
// errorMessages.add("第" + excelRowNumber + "行:唯一标识不能为空");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
touchedMatchNames.add(item.getMatchName().trim());
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
insertedCount += batchImportSupport.persistChunkWithFallbackCount(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
int delta = countInsertedByMatchName(chunkItems);
|
||||
batchImportSupport.upsertBySingleKey(
|
||||
creditCompanyService,
|
||||
chunkItems,
|
||||
CreditCompany::getId,
|
||||
CreditCompany::setId,
|
||||
CreditCompany::getMatchName,
|
||||
CreditCompany::getMatchName,
|
||||
null,
|
||||
mpBatchSize
|
||||
);
|
||||
return delta;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompanyService.save(rowItem);
|
||||
if (saved) {
|
||||
return 1; // insert 入库
|
||||
}
|
||||
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompanyService.updateById(rowItem)) {
|
||||
return 0; // update 不计入“入库”条数
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("保存失败");
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
insertedCount += batchImportSupport.persistChunkWithFallbackCount(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
int delta = countInsertedByMatchName(chunkItems);
|
||||
batchImportSupport.upsertBySingleKey(
|
||||
creditCompanyService,
|
||||
chunkItems,
|
||||
CreditCompany::getId,
|
||||
CreditCompany::setId,
|
||||
CreditCompany::getMatchName,
|
||||
CreditCompany::getMatchName,
|
||||
null,
|
||||
mpBatchSize
|
||||
);
|
||||
return delta;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompanyService.save(rowItem);
|
||||
if (saved) {
|
||||
return 1; // insert 入库
|
||||
}
|
||||
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompanyService.updateById(rowItem)) {
|
||||
return 0; // update 不计入“入库”条数
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("保存失败");
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
// 导入完成后,按 matchName 定位本次涉及的企业并回填“关联记录数”字段(避免 companyId/自增 id 在导入对象里拿不到)。
|
||||
if (!touchedMatchNames.isEmpty()) {
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
List<String> allMatchNames = new ArrayList<>(touchedMatchNames);
|
||||
final int inChunkSize = 800;
|
||||
for (int i = 0; i < allMatchNames.size(); i += inChunkSize) {
|
||||
List<String> chunk = allMatchNames.subList(i, Math.min(allMatchNames.size(), i + inChunkSize));
|
||||
List<CreditCompany> dbRows = creditCompanyService.lambdaQuery()
|
||||
.select(CreditCompany::getId)
|
||||
.in(CreditCompany::getMatchName, chunk)
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(dbRows)) {
|
||||
for (CreditCompany row : dbRows) {
|
||||
if (row != null && row.getId() != null) {
|
||||
touchedCompanyIds.add(row.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
creditCompanyRecordCountService.refreshAll(touchedCompanyIds);
|
||||
}
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功入库" + insertedCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,入库" + insertedCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载企业导入模板
|
||||
*/
|
||||
@Operation(summary = "下载企业导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCompanyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCompanyImportParam example = new CreditCompanyImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setCode("C0001");
|
||||
example.setMatchName("匹配名称");
|
||||
example.setRegistrationStatus("登记状态");
|
||||
example.setLegalPerson("法定代表人");
|
||||
example.setRegisteredCapital("注册资本");
|
||||
example.setPaidinCapital("实缴资本");
|
||||
example.setEstablishDate("成立日期");
|
||||
example.setAddress("地址");
|
||||
example.setTel("电话");
|
||||
example.setMoreTel("更多电话");
|
||||
example.setEmail("邮箱");
|
||||
example.setMoreEmail("更多邮箱");
|
||||
example.setProvince("省");
|
||||
example.setCity("市");
|
||||
example.setRegion("区");
|
||||
example.setInstitutionType("机构类型");
|
||||
example.setTaxpayerCode("纳税人识别号");
|
||||
example.setRegistrationNumber("注册号");
|
||||
example.setOrganizationalCode("组织机构代码");
|
||||
example.setNumberOfInsuredPersons("参保人数");
|
||||
example.setAnnualReport("入库时间");
|
||||
example.setBusinessTerm("营业期限");
|
||||
example.setNationalStandardIndustryCategories("国标行业门类");
|
||||
example.setNationalStandardIndustryCategories2("国标行业大类");
|
||||
example.setNationalStandardIndustryCategories3("国标行业中类");
|
||||
example.setNationalStandardIndustryCategories4("国标行业小类");
|
||||
example.setNationalStandardIndustryCategories5("企查查行业门类");
|
||||
example.setNationalStandardIndustryCategories6("企查查行业大类");
|
||||
example.setNationalStandardIndustryCategories7("企查查行业中类");
|
||||
example.setNationalStandardIndustryCategories8("企查查行业小类");
|
||||
example.setCompanySize("企业规模");
|
||||
example.setFormerName("曾用名");
|
||||
example.setEnglishName("英文名");
|
||||
example.setDomain("官网");
|
||||
example.setMailingAddress("通信地址");
|
||||
example.setCompanyProfile("企业简介");
|
||||
example.setNatureOfBusiness("经营范围");
|
||||
example.setRegistrationAuthority("登记机关");
|
||||
example.setTaxpayerQualification("纳税人资质");
|
||||
example.setLatestAnnualReportYear("最新年报年份");
|
||||
example.setLatestAnnualReportOnOperatingRevenue("最新年报营业额");
|
||||
example.setEnterpriseScoreCheck("企查分");
|
||||
example.setCreditRating("信用等级");
|
||||
example.setCechnologyScore("科创分");
|
||||
example.setCechnologyLevel("科创等级");
|
||||
example.setSmallEnterprise("是否小微企业");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("一级企业主表导入模板", "企业");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditCompanyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_company_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private List<CreditCompanyImportParam> tryImport(MultipartFile file, int titleRows, int headRows) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(0);
|
||||
importParams.setSheetNum(1);
|
||||
return ExcelImportUtil.importExcel(file.getInputStream(), CreditCompanyImportParam.class, importParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉完全空白的导入行,避免空行导致导入失败
|
||||
*/
|
||||
private List<CreditCompanyImportParam> filterEmptyRows(List<CreditCompanyImportParam> rawList) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(this::isEmptyImportRow);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCompanyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库条数以 insert 为准:matchName 在数据库中不存在时计 1,否则计 0。
|
||||
*
|
||||
* <p>统计口径需与批量 upsert 的匹配字段保持一致(matchName)。</p>
|
||||
*/
|
||||
private int countInsertedByMatchName(List<CreditCompany> items) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
List<String> matchNames = new ArrayList<>(items.size());
|
||||
for (CreditCompany item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = item.getMatchName();
|
||||
if (!isBlank(key)) {
|
||||
matchNames.add(key.trim());
|
||||
}
|
||||
}
|
||||
if (matchNames.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set<String> existing = new HashSet<>();
|
||||
List<CreditCompany> dbRows = creditCompanyService.lambdaQuery()
|
||||
.select(CreditCompany::getMatchName)
|
||||
.in(CreditCompany::getMatchName, matchNames)
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(dbRows)) {
|
||||
for (CreditCompany row : dbRows) {
|
||||
String v = row != null ? row.getMatchName() : null;
|
||||
if (!isBlank(v)) {
|
||||
existing.add(v.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (CreditCompany item : items) {
|
||||
String key = item != null ? item.getMatchName() : null;
|
||||
if (!isBlank(key) && !existing.contains(key.trim())) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditCompanyImportParam转换为CreditCompany实体
|
||||
*/
|
||||
private CreditCompany convertImportParamToEntity(CreditCompanyImportParam param) {
|
||||
CreditCompany entity = new CreditCompany();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setMatchName(param.getMatchName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setPaidinCapital(param.getPaidinCapital());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setTel(param.getTel());
|
||||
entity.setMoreTel(param.getMoreTel());
|
||||
entity.setEmail(param.getEmail());
|
||||
entity.setMoreEmail(param.getMoreEmail());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setCity(param.getCity());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setInstitutionType(param.getInstitutionType());
|
||||
entity.setTaxpayerCode(param.getTaxpayerCode());
|
||||
entity.setRegistrationNumber(param.getRegistrationNumber());
|
||||
entity.setOrganizationalCode(param.getOrganizationalCode());
|
||||
entity.setNumberOfInsuredPersons(param.getNumberOfInsuredPersons());
|
||||
entity.setAnnualReport(param.getAnnualReport());
|
||||
entity.setBusinessTerm(param.getBusinessTerm());
|
||||
entity.setNationalStandardIndustryCategories(param.getNationalStandardIndustryCategories());
|
||||
entity.setNationalStandardIndustryCategories2(param.getNationalStandardIndustryCategories2());
|
||||
entity.setNationalStandardIndustryCategories3(param.getNationalStandardIndustryCategories3());
|
||||
entity.setNationalStandardIndustryCategories4(param.getNationalStandardIndustryCategories4());
|
||||
entity.setNationalStandardIndustryCategories5(param.getNationalStandardIndustryCategories5());
|
||||
entity.setNationalStandardIndustryCategories6(param.getNationalStandardIndustryCategories6());
|
||||
entity.setNationalStandardIndustryCategories7(param.getNationalStandardIndustryCategories7());
|
||||
entity.setNationalStandardIndustryCategories8(param.getNationalStandardIndustryCategories8());
|
||||
entity.setCompanySize(param.getCompanySize());
|
||||
entity.setFormerName(param.getFormerName());
|
||||
entity.setEnglishName(param.getEnglishName());
|
||||
entity.setDomain(param.getDomain());
|
||||
entity.setMailingAddress(param.getMailingAddress());
|
||||
entity.setCompanyProfile(param.getCompanyProfile());
|
||||
entity.setNatureOfBusiness(param.getNatureOfBusiness());
|
||||
entity.setRegistrationAuthority(param.getRegistrationAuthority());
|
||||
entity.setTaxpayerQualification(param.getTaxpayerQualification());
|
||||
entity.setLatestAnnualReportYear(param.getLatestAnnualReportYear());
|
||||
entity.setLatestAnnualReportOnOperatingRevenue(param.getLatestAnnualReportOnOperatingRevenue());
|
||||
entity.setEnterpriseScoreCheck(param.getEnterpriseScoreCheck());
|
||||
entity.setCreditRating(param.getCreditRating());
|
||||
entity.setCechnologyScore(param.getCechnologyScore());
|
||||
entity.setCechnologyLevel(param.getCechnologyLevel());
|
||||
entity.setSmallEnterprise(param.getSmallEnterprise());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,412 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompetitor;
|
||||
import com.gxwebsoft.credit.param.CreditCompetitorImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCompetitorParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCompetitorService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 竞争对手控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:05
|
||||
*/
|
||||
@Tag(name = "竞争对手管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-competitor")
|
||||
public class CreditCompetitorController extends BaseController {
|
||||
@Resource
|
||||
private CreditCompetitorService creditCompetitorService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询竞争对手")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCompetitor>> page(CreditCompetitorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部竞争对手")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCompetitor>> list(CreditCompetitorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询竞争对手")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCompetitor> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加竞争对手")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCompetitor creditCompetitor) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCompetitor.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCompetitorService.save(creditCompetitor)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改竞争对手")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCompetitor creditCompetitor) {
|
||||
if (creditCompetitorService.updateById(creditCompetitor)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除竞争对手")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCompetitorService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加竞争对手")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCompetitor> list) {
|
||||
if (creditCompetitorService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改竞争对手")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCompetitor> batchParam) {
|
||||
if (batchParam.update(creditCompetitorService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除竞争对手")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCompetitorService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCompetitorService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCompetitor::getId,
|
||||
CreditCompetitor::setId,
|
||||
CreditCompetitor::getName,
|
||||
CreditCompetitor::getCompanyId,
|
||||
CreditCompetitor::setCompanyId,
|
||||
CreditCompetitor::getHasData,
|
||||
CreditCompetitor::setHasData,
|
||||
CreditCompetitor::getTenantId,
|
||||
CreditCompetitor::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入竞争对手
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@Operation(summary = "批量导入竞争对手")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "竞争对手", 2);
|
||||
ExcelImportSupport.ImportResult<CreditCompetitorImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCompetitorImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCompetitorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCompetitor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCompetitorImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCompetitor item = convertImportParamToEntity(param);
|
||||
// name 才是持久化字段;companyName 为关联查询的临时字段(exist=false),导入时不应使用。
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCompetitorService,
|
||||
chunkItems,
|
||||
CreditCompetitor::getId,
|
||||
CreditCompetitor::setId,
|
||||
CreditCompetitor::getName,
|
||||
CreditCompetitor::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompetitorService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCompetitor existing = creditCompetitorService.lambdaQuery()
|
||||
.eq(CreditCompetitor::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompetitorService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCompetitorService,
|
||||
chunkItems,
|
||||
CreditCompetitor::getId,
|
||||
CreditCompetitor::setId,
|
||||
CreditCompetitor::getName,
|
||||
CreditCompetitor::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompetitorService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCompetitor existing = creditCompetitorService.lambdaQuery()
|
||||
.eq(CreditCompetitor::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompetitorService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COMPETITOR, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载竞争对手导入模板
|
||||
*/
|
||||
@Operation(summary = "下载竞争对手导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCompetitorImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCompetitorImportParam example = new CreditCompetitorImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setLegalRepresentative("张三");
|
||||
example.setRegisteredCapital("5000");
|
||||
example.setEstablishmentDate("2015-01-01");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setIndustry("软件和信息服务业");
|
||||
example.setProvince("广东省");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("竞争对手导入模板", "竞争对手", CreditCompetitorImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_competitor_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCompetitorImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getLegalRepresentative())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital())
|
||||
&& ImportHelper.isBlank(param.getEstablishmentDate());
|
||||
}
|
||||
|
||||
private CreditCompetitor convertImportParamToEntity(CreditCompetitorImportParam param) {
|
||||
CreditCompetitor entity = new CreditCompetitor();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setLegalRepresentative(param.getLegalRepresentative());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setEstablishmentDate(param.getEstablishmentDate());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setIndustry(param.getIndustry());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtAnnouncement;
|
||||
import com.gxwebsoft.credit.param.CreditCourtAnnouncementImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCourtAnnouncementParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCourtAnnouncementService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 法院公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:13
|
||||
*/
|
||||
@Tag(name = "法院公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-court-announcement")
|
||||
public class CreditCourtAnnouncementController extends BaseController {
|
||||
@Resource
|
||||
private CreditCourtAnnouncementService creditCourtAnnouncementService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询法院公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCourtAnnouncement>> page(CreditCourtAnnouncementParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部法院公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCourtAnnouncement>> list(CreditCourtAnnouncementParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询法院公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCourtAnnouncement> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加法院公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCourtAnnouncement creditCourtAnnouncement) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCourtAnnouncement.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCourtAnnouncementService.save(creditCourtAnnouncement)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改法院公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCourtAnnouncement creditCourtAnnouncement) {
|
||||
if (creditCourtAnnouncementService.updateById(creditCourtAnnouncement)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除法院公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCourtAnnouncementService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加法院公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCourtAnnouncement> list) {
|
||||
if (creditCourtAnnouncementService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改法院公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCourtAnnouncement> batchParam) {
|
||||
if (batchParam.update(creditCourtAnnouncementService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除法院公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCourtAnnouncementService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCourtAnnouncementService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCourtAnnouncement::getId,
|
||||
CreditCourtAnnouncement::setId,
|
||||
CreditCourtAnnouncement::getAppellee,
|
||||
CreditCourtAnnouncement::getCompanyId,
|
||||
CreditCourtAnnouncement::setCompanyId,
|
||||
CreditCourtAnnouncement::getHasData,
|
||||
CreditCourtAnnouncement::setHasData,
|
||||
CreditCourtAnnouncement::getTenantId,
|
||||
CreditCourtAnnouncement::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入法院公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@Operation(summary = "批量导入法院公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 兼容多 sheet 文件:优先定位“法院公告”sheet,否则默认第 0 个。
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "法院公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCourtAnnouncementImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtAnnouncementImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtAnnouncementImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtAnnouncement> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtAnnouncementImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCourtAnnouncement item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
CreditCourtAnnouncement::getId,
|
||||
CreditCourtAnnouncement::setId,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCourtAnnouncementService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtAnnouncement existing = creditCourtAnnouncementService.lambdaQuery()
|
||||
.eq(CreditCourtAnnouncement::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCourtAnnouncementService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
CreditCourtAnnouncement::getId,
|
||||
CreditCourtAnnouncement::setId,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCourtAnnouncementService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtAnnouncement existing = creditCourtAnnouncementService.lambdaQuery()
|
||||
.eq(CreditCourtAnnouncement::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCourtAnnouncementService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_ANNOUNCEMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载法院公告司法大数据导入模板
|
||||
*/
|
||||
@Operation(summary = "下载法院公告司法大数据导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCourtAnnouncementImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCourtAnnouncementImportParam example = new CreditCourtAnnouncementImportParam();
|
||||
example.setDataType("法院公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("法院公告导入模板", "法院公告", CreditCourtAnnouncementImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_court_announcement_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCourtAnnouncementImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditCourtAnnouncement convertImportParamToEntity(CreditCourtAnnouncementImportParam param) {
|
||||
CreditCourtAnnouncement entity = new CreditCourtAnnouncement();
|
||||
|
||||
String dataType = !ImportHelper.isBlank(param.getDataType2())
|
||||
? param.getDataType2()
|
||||
: param.getDataType();
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
|
||||
entity.setDataType(dataType);
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,636 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtSession;
|
||||
import com.gxwebsoft.credit.param.CreditCourtSessionImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCourtSessionParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCourtSessionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 开庭公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:33
|
||||
*/
|
||||
@Tag(name = "开庭公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-court-session")
|
||||
public class CreditCourtSessionController extends BaseController {
|
||||
@Resource
|
||||
private CreditCourtSessionService creditCourtSessionService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询开庭公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCourtSession>> page(CreditCourtSessionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部开庭公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCourtSession>> list(CreditCourtSessionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询开庭公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCourtSession> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加开庭公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCourtSession creditCourtSession) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCourtSession.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCourtSessionService.save(creditCourtSession)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改开庭公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCourtSession creditCourtSession) {
|
||||
if (creditCourtSessionService.updateById(creditCourtSession)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除开庭公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCourtSessionService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加开庭公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCourtSession> list) {
|
||||
if (creditCourtSessionService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改开庭公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCourtSession> batchParam) {
|
||||
if (batchParam.update(creditCourtSessionService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除开庭公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCourtSessionService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCourtSessionService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getAppellee,
|
||||
CreditCourtSession::getCompanyId,
|
||||
CreditCourtSession::setCompanyId,
|
||||
CreditCourtSession::getHasData,
|
||||
CreditCourtSession::setHasData,
|
||||
CreditCourtSession::getTenantId,
|
||||
CreditCourtSession::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入开庭公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@Operation(summary = "批量导入开庭公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 兼容多 sheet 文件:优先定位“开庭公告”sheet,否则默认第 0 个。
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "开庭公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCourtSessionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtSessionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtSessionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtSession> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtSessionImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCourtSession item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCourtSessionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
|
||||
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCourtSessionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCourtSessionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
|
||||
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCourtSessionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_SESSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史开庭公告(仅解析“历史开庭公告”选项卡)
|
||||
* 规则:案号相同则覆盖更新(recommend++ 记录更新次数);案号不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@Operation(summary = "批量导入历史开庭公告司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史开庭公告");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史开庭公告”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditCourtSessionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtSessionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtSessionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
LinkedHashMap<String, CreditCourtSession> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtSessionImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCourtSession item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtSession> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditCourtSession> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditCourtSession item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getRecommend,
|
||||
CreditCourtSession::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditCourtSessionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
|
||||
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditCourtSession::getId, CreditCourtSession::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditCourtSessionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
CreditCourtSession::getRecommend,
|
||||
CreditCourtSession::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditCourtSessionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
|
||||
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditCourtSession::getId, CreditCourtSession::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditCourtSessionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_SESSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载开庭公告司法大数据导入模板
|
||||
*/
|
||||
@Operation(summary = "下载开庭公告司法大数据导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCourtSessionImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCourtSessionImportParam example = new CreditCourtSessionImportParam();
|
||||
example.setDataType("开庭公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("开庭公告导入模板", "开庭公告", CreditCourtSessionImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_court_session_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCourtSessionImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditCourtSession convertImportParamToEntity(CreditCourtSessionImportParam param) {
|
||||
CreditCourtSession entity = new CreditCourtSession();
|
||||
|
||||
// Template compatibility: prefer new columns ("发生时间"/"其他当事人/第三人") when present.
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,572 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCustomer;
|
||||
import com.gxwebsoft.credit.param.CreditCustomerImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCustomerParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCustomerService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 客户控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-21 21:20:58
|
||||
*/
|
||||
@Tag(name = "客户管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-customer")
|
||||
public class CreditCustomerController extends BaseController {
|
||||
@Resource
|
||||
private CreditCustomerService creditCustomerService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询客户")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCustomer>> page(CreditCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部客户")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCustomer>> list(CreditCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询客户")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCustomer> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加客户")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCustomer creditCustomer) {
|
||||
if (creditCustomerService.save(creditCustomer)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改客户")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCustomer creditCustomer) {
|
||||
if (creditCustomerService.updateById(creditCustomer)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除客户")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditCustomerService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加客户")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCustomer> list) {
|
||||
if (creditCustomerService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改客户")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCustomer> batchParam) {
|
||||
if (batchParam.update(creditCustomerService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除客户")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditCustomerService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCustomerService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCustomer::getId,
|
||||
CreditCustomer::setId,
|
||||
CreditCustomer::getName,
|
||||
CreditCustomer::getCompanyId,
|
||||
CreditCustomer::setCompanyId,
|
||||
CreditCustomer::getHasData,
|
||||
CreditCustomer::setHasData,
|
||||
CreditCustomer::getTenantId,
|
||||
CreditCustomer::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入客户
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@Operation(summary = "批量导入客户")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "客户", 4);
|
||||
ExcelImportSupport.ImportResult<CreditCustomerImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCustomerImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCustomerImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "客户");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCustomer> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCustomerImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCustomer item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:客户不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
// 批内一次查库,避免逐行查/写导致数据库压力过大
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
for (CreditCustomer it : chunkItems) {
|
||||
if (it != null && !ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
}
|
||||
List<CreditCustomer> existingList = names.isEmpty()
|
||||
? new ArrayList<>()
|
||||
: creditCustomerService.lambdaQuery()
|
||||
.in(CreditCustomer::getName, names)
|
||||
.list();
|
||||
java.util.Map<String, CreditCustomer> existingByName = new java.util.HashMap<>();
|
||||
for (CreditCustomer existing : existingList) {
|
||||
if (existing != null && !ImportHelper.isBlank(existing.getName())) {
|
||||
existingByName.putIfAbsent(existing.getName().trim(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
java.util.Map<String, CreditCustomer> latestByName = new java.util.HashMap<>();
|
||||
int acceptedRows = 0;
|
||||
for (int idx = 0; idx < chunkItems.size(); idx++) {
|
||||
CreditCustomer it = chunkItems.get(idx);
|
||||
int rowNo = (idx < chunkRowNumbers.size()) ? chunkRowNumbers.get(idx) : -1;
|
||||
if (it == null || ImportHelper.isBlank(it.getName())) {
|
||||
continue;
|
||||
}
|
||||
String name = it.getName().trim();
|
||||
CreditCustomer existing = existingByName.get(name);
|
||||
if (existing != null) {
|
||||
Integer existingTenantId = existing.getTenantId();
|
||||
if (it.getTenantId() != null
|
||||
&& existingTenantId != null
|
||||
&& !it.getTenantId().equals(existingTenantId)) {
|
||||
errorMessages.add("第" + rowNo + "行:客户名称已存在且归属其他租户,无法导入");
|
||||
continue;
|
||||
}
|
||||
it.setId(existing.getId());
|
||||
if (existingTenantId != null) {
|
||||
it.setTenantId(existingTenantId);
|
||||
}
|
||||
}
|
||||
// 同名多行:保留最后一行的值(等价于“先插入/更新,再被后续行更新”)
|
||||
latestByName.put(name, it);
|
||||
acceptedRows++;
|
||||
}
|
||||
|
||||
List<CreditCustomer> updates = new ArrayList<>();
|
||||
List<CreditCustomer> inserts = new ArrayList<>();
|
||||
for (CreditCustomer it : latestByName.values()) {
|
||||
if (it.getId() != null) {
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditCustomerService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditCustomerService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return acceptedRows;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
CreditCustomer existing = creditCustomerService.lambdaQuery()
|
||||
.eq(CreditCustomer::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
Integer existingTenantId = existing.getTenantId();
|
||||
if (rowItem.getTenantId() != null
|
||||
&& existingTenantId != null
|
||||
&& !rowItem.getTenantId().equals(existingTenantId)) {
|
||||
errorMessages.add("第" + rowNumber + "行:客户名称已存在且归属其他租户,无法导入");
|
||||
return false;
|
||||
}
|
||||
rowItem.setId(existing.getId());
|
||||
if (existingTenantId != null) {
|
||||
rowItem.setTenantId(existingTenantId);
|
||||
}
|
||||
return creditCustomerService.updateById(rowItem);
|
||||
}
|
||||
|
||||
try {
|
||||
return creditCustomerService.save(rowItem);
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
if (!isDuplicateCustomerName(e)) {
|
||||
throw e;
|
||||
}
|
||||
CreditCustomer dbExisting = creditCustomerService.lambdaQuery()
|
||||
.eq(CreditCustomer::getName, rowItem.getName())
|
||||
.one();
|
||||
if (dbExisting != null) {
|
||||
Integer existingTenantId = dbExisting.getTenantId();
|
||||
rowItem.setId(dbExisting.getId());
|
||||
if (existingTenantId != null) {
|
||||
rowItem.setTenantId(existingTenantId);
|
||||
}
|
||||
return creditCustomerService.updateById(rowItem);
|
||||
}
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
for (CreditCustomer it : chunkItems) {
|
||||
if (it != null && !ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
}
|
||||
List<CreditCustomer> existingList = names.isEmpty()
|
||||
? new ArrayList<>()
|
||||
: creditCustomerService.lambdaQuery()
|
||||
.in(CreditCustomer::getName, names)
|
||||
.list();
|
||||
java.util.Map<String, CreditCustomer> existingByName = new java.util.HashMap<>();
|
||||
for (CreditCustomer existing : existingList) {
|
||||
if (existing != null && !ImportHelper.isBlank(existing.getName())) {
|
||||
existingByName.putIfAbsent(existing.getName().trim(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
java.util.Map<String, CreditCustomer> latestByName = new java.util.HashMap<>();
|
||||
int acceptedRows = 0;
|
||||
for (int idx = 0; idx < chunkItems.size(); idx++) {
|
||||
CreditCustomer it = chunkItems.get(idx);
|
||||
int rowNo = (idx < chunkRowNumbers.size()) ? chunkRowNumbers.get(idx) : -1;
|
||||
if (it == null || ImportHelper.isBlank(it.getName())) {
|
||||
continue;
|
||||
}
|
||||
String name = it.getName().trim();
|
||||
CreditCustomer existing = existingByName.get(name);
|
||||
if (existing != null) {
|
||||
Integer existingTenantId = existing.getTenantId();
|
||||
if (it.getTenantId() != null
|
||||
&& existingTenantId != null
|
||||
&& !it.getTenantId().equals(existingTenantId)) {
|
||||
errorMessages.add("第" + rowNo + "行:客户名称已存在且归属其他租户,无法导入");
|
||||
continue;
|
||||
}
|
||||
it.setId(existing.getId());
|
||||
if (existingTenantId != null) {
|
||||
it.setTenantId(existingTenantId);
|
||||
}
|
||||
}
|
||||
latestByName.put(name, it);
|
||||
acceptedRows++;
|
||||
}
|
||||
|
||||
List<CreditCustomer> updates = new ArrayList<>();
|
||||
List<CreditCustomer> inserts = new ArrayList<>();
|
||||
for (CreditCustomer it : latestByName.values()) {
|
||||
if (it.getId() != null) {
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditCustomerService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditCustomerService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return acceptedRows;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
CreditCustomer existing = creditCustomerService.lambdaQuery()
|
||||
.eq(CreditCustomer::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
Integer existingTenantId = existing.getTenantId();
|
||||
if (rowItem.getTenantId() != null
|
||||
&& existingTenantId != null
|
||||
&& !rowItem.getTenantId().equals(existingTenantId)) {
|
||||
errorMessages.add("第" + rowNumber + "行:客户名称已存在且归属其他租户,无法导入");
|
||||
return false;
|
||||
}
|
||||
rowItem.setId(existing.getId());
|
||||
if (existingTenantId != null) {
|
||||
rowItem.setTenantId(existingTenantId);
|
||||
}
|
||||
return creditCustomerService.updateById(rowItem);
|
||||
}
|
||||
|
||||
try {
|
||||
return creditCustomerService.save(rowItem);
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
if (!isDuplicateCustomerName(e)) {
|
||||
throw e;
|
||||
}
|
||||
CreditCustomer dbExisting = creditCustomerService.lambdaQuery()
|
||||
.eq(CreditCustomer::getName, rowItem.getName())
|
||||
.one();
|
||||
if (dbExisting != null) {
|
||||
Integer existingTenantId = dbExisting.getTenantId();
|
||||
rowItem.setId(dbExisting.getId());
|
||||
if (existingTenantId != null) {
|
||||
rowItem.setTenantId(existingTenantId);
|
||||
}
|
||||
return creditCustomerService.updateById(rowItem);
|
||||
}
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CUSTOMER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载客户导入模板
|
||||
*/
|
||||
@Operation(summary = "下载客户导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCustomerImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCustomerImportParam example = new CreditCustomerImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setStatusTxt("合作中");
|
||||
example.setPrice("88.8");
|
||||
example.setPublicDate("2024-01-01");
|
||||
example.setDataSource("公开渠道");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("客户导入模板", "客户", CreditCustomerImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_customer_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCustomerImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getStatusTxt())
|
||||
&& ImportHelper.isBlank(param.getPrice());
|
||||
}
|
||||
|
||||
private CreditCustomer convertImportParamToEntity(CreditCustomerImportParam param) {
|
||||
CreditCustomer entity = new CreditCustomer();
|
||||
|
||||
entity.setName(normalizeString(param.getName()));
|
||||
entity.setStatusTxt(normalizeString(param.getStatusTxt()));
|
||||
entity.setPrice(normalizeString(param.getPrice()));
|
||||
entity.setPublicDate(normalizeString(param.getPublicDate()));
|
||||
entity.setDataSource(normalizeString(param.getDataSource()));
|
||||
entity.setComments(normalizeString(param.getComments()));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private String normalizeString(String value) {
|
||||
if (ImportHelper.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
private boolean isDuplicateCustomerName(DataIntegrityViolationException e) {
|
||||
Throwable mostSpecificCause = e.getMostSpecificCause();
|
||||
String message = mostSpecificCause != null ? mostSpecificCause.getMessage() : e.getMessage();
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = message.toLowerCase();
|
||||
if (!lower.contains("duplicate")) {
|
||||
return false;
|
||||
}
|
||||
return lower.contains("credit_customer.name")
|
||||
|| lower.contains("for key 'name'")
|
||||
|| lower.contains("for key `name`");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,434 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditDeliveryNotice;
|
||||
import com.gxwebsoft.credit.param.CreditDeliveryNoticeImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditDeliveryNoticeParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditDeliveryNoticeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 送达公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:52
|
||||
*/
|
||||
@Tag(name = "送达公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-delivery-notice")
|
||||
public class CreditDeliveryNoticeController extends BaseController {
|
||||
@Resource
|
||||
private CreditDeliveryNoticeService creditDeliveryNoticeService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询送达公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditDeliveryNotice>> page(CreditDeliveryNoticeParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部送达公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditDeliveryNotice>> list(CreditDeliveryNoticeParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询送达公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditDeliveryNotice> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加送达公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditDeliveryNotice creditDeliveryNotice) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditDeliveryNotice.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditDeliveryNoticeService.save(creditDeliveryNotice)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改送达公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditDeliveryNotice creditDeliveryNotice) {
|
||||
if (creditDeliveryNoticeService.updateById(creditDeliveryNotice)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除送达公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditDeliveryNoticeService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加送达公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditDeliveryNotice> list) {
|
||||
if (creditDeliveryNoticeService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改送达公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditDeliveryNotice> batchParam) {
|
||||
if (batchParam.update(creditDeliveryNoticeService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除送达公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditDeliveryNoticeService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditDeliveryNoticeService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditDeliveryNotice::getId,
|
||||
CreditDeliveryNotice::setId,
|
||||
CreditDeliveryNotice::getOtherPartiesThirdParty,
|
||||
CreditDeliveryNotice::getCompanyId,
|
||||
CreditDeliveryNotice::setCompanyId,
|
||||
CreditDeliveryNotice::getHasData,
|
||||
CreditDeliveryNotice::setHasData,
|
||||
CreditDeliveryNotice::getTenantId,
|
||||
CreditDeliveryNotice::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入送达公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@Operation(summary = "批量导入送达公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "送达公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditDeliveryNoticeImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditDeliveryNoticeImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditDeliveryNoticeImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// URL 通常以超链接形式存在于“案号”列里
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditDeliveryNotice> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditDeliveryNoticeImportParam param = list.get(i);
|
||||
try {
|
||||
CreditDeliveryNotice item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
CreditDeliveryNotice::getId,
|
||||
CreditDeliveryNotice::setId,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditDeliveryNoticeService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditDeliveryNotice existing = creditDeliveryNoticeService.lambdaQuery()
|
||||
.eq(CreditDeliveryNotice::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditDeliveryNoticeService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
CreditDeliveryNotice::getId,
|
||||
CreditDeliveryNotice::setId,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditDeliveryNoticeService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditDeliveryNotice existing = creditDeliveryNoticeService.lambdaQuery()
|
||||
.eq(CreditDeliveryNotice::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditDeliveryNoticeService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.DELIVERY_NOTICE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载送达公告导入模板
|
||||
*/
|
||||
@Operation(summary = "下载送达公告导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditDeliveryNoticeImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditDeliveryNoticeImportParam example = new CreditDeliveryNoticeImportParam();
|
||||
example.setDataType("送达公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("送达公告导入模板", "送达公告", CreditDeliveryNoticeImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_delivery_notice_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditDeliveryNoticeImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getAppellee());
|
||||
}
|
||||
|
||||
private CreditDeliveryNotice convertImportParamToEntity(CreditDeliveryNoticeImportParam param) {
|
||||
CreditDeliveryNotice entity = new CreditDeliveryNotice();
|
||||
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(courtName);
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditExternal;
|
||||
import com.gxwebsoft.credit.param.CreditExternalImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditExternalParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditExternalService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 对外投资控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:12
|
||||
*/
|
||||
@Tag(name = "对外投资管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-external")
|
||||
public class CreditExternalController extends BaseController {
|
||||
@Resource
|
||||
private CreditExternalService creditExternalService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询对外投资")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditExternal>> page(CreditExternalParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部对外投资")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditExternal>> list(CreditExternalParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询对外投资")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditExternal> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加对外投资")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditExternal creditExternal) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditExternal.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditExternalService.save(creditExternal)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改对外投资")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditExternal creditExternal) {
|
||||
if (creditExternalService.updateById(creditExternal)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除对外投资")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditExternalService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加对外投资")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditExternal> list) {
|
||||
if (creditExternalService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改对外投资")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditExternal> batchParam) {
|
||||
if (batchParam.update(creditExternalService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除对外投资")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditExternalService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditExternalService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditExternal::getId,
|
||||
CreditExternal::setId,
|
||||
CreditExternal::getName,
|
||||
CreditExternal::getCompanyId,
|
||||
CreditExternal::setCompanyId,
|
||||
CreditExternal::getHasData,
|
||||
CreditExternal::setHasData,
|
||||
CreditExternal::getTenantId,
|
||||
CreditExternal::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入对外投资
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@Operation(summary = "批量导入对外投资")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "对外投资", 0);
|
||||
ExcelImportSupport.ImportResult<CreditExternalImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditExternalImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditExternalImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "被投资企业名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditExternal> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditExternalImportParam param = list.get(i);
|
||||
try {
|
||||
CreditExternal item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:被投资企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditExternalService,
|
||||
chunkItems,
|
||||
CreditExternal::getId,
|
||||
CreditExternal::setId,
|
||||
CreditExternal::getName,
|
||||
CreditExternal::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditExternalService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditExternal existing = creditExternalService.lambdaQuery()
|
||||
.eq(CreditExternal::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditExternalService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditExternalService,
|
||||
chunkItems,
|
||||
CreditExternal::getId,
|
||||
CreditExternal::setId,
|
||||
CreditExternal::getName,
|
||||
CreditExternal::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditExternalService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditExternal existing = creditExternalService.lambdaQuery()
|
||||
.eq(CreditExternal::getName, rowItem.getName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditExternalService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.EXTERNAL, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对外投资导入模板
|
||||
*/
|
||||
@Operation(summary = "下载对外投资导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditExternalImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditExternalImportParam example = new CreditExternalImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setStatusTxt("存续");
|
||||
example.setLegalRepresentative("李四");
|
||||
example.setRegisteredCapital("10000");
|
||||
example.setEstablishmentDate("2018-06-01");
|
||||
example.setShareholdingRatio("20");
|
||||
example.setSubscribedInvestmentAmount("2000");
|
||||
example.setSubscribedInvestmentDate("2019-01-01");
|
||||
example.setIndirectShareholdingRatio("5");
|
||||
example.setInvestmentDate("2019-06-01");
|
||||
example.setRegion("上海");
|
||||
example.setIndustry("信息技术");
|
||||
example.setInvestmentCount(1);
|
||||
example.setRelatedProductsInstitutions("关联产品示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("对外投资导入模板", "对外投资", CreditExternalImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_external_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditExternalImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getLegalRepresentative())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital())
|
||||
&& ImportHelper.isBlank(param.getEstablishmentDate());
|
||||
}
|
||||
|
||||
private CreditExternal convertImportParamToEntity(CreditExternalImportParam param) {
|
||||
CreditExternal entity = new CreditExternal();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusTxt(param.getStatusTxt());
|
||||
entity.setLegalRepresentative(param.getLegalRepresentative());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setEstablishmentDate(param.getEstablishmentDate());
|
||||
entity.setShareholdingRatio(param.getShareholdingRatio());
|
||||
entity.setSubscribedInvestmentAmount(param.getSubscribedInvestmentAmount());
|
||||
entity.setSubscribedInvestmentDate(param.getSubscribedInvestmentDate());
|
||||
entity.setIndirectShareholdingRatio(param.getIndirectShareholdingRatio());
|
||||
entity.setInvestmentDate(param.getInvestmentDate());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setIndustry(param.getIndustry());
|
||||
entity.setInvestmentCount(param.getInvestmentCount());
|
||||
entity.setRelatedProductsInstitutions(param.getRelatedProductsInstitutions());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,641 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditFinalVersion;
|
||||
import com.gxwebsoft.credit.param.CreditFinalVersionImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditFinalVersionParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditFinalVersionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 终本案件控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:19
|
||||
*/
|
||||
@Tag(name = "终本案件管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-final-version")
|
||||
public class CreditFinalVersionController extends BaseController {
|
||||
@Resource
|
||||
private CreditFinalVersionService creditFinalVersionService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询终本案件")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditFinalVersion>> page(CreditFinalVersionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部终本案件")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditFinalVersion>> list(CreditFinalVersionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询终本案件")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditFinalVersion> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加终本案件")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditFinalVersion creditFinalVersion) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditFinalVersion.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditFinalVersionService.save(creditFinalVersion)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改终本案件")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditFinalVersion creditFinalVersion) {
|
||||
if (creditFinalVersionService.updateById(creditFinalVersion)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除终本案件")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditFinalVersionService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加终本案件")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditFinalVersion> list) {
|
||||
if (creditFinalVersionService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改终本案件")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditFinalVersion> batchParam) {
|
||||
if (batchParam.update(creditFinalVersionService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除终本案件")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditFinalVersionService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditFinalVersionService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getAppellee,
|
||||
CreditFinalVersion::getCompanyId,
|
||||
CreditFinalVersion::setCompanyId,
|
||||
CreditFinalVersion::getHasData,
|
||||
CreditFinalVersion::setHasData,
|
||||
CreditFinalVersion::getTenantId,
|
||||
CreditFinalVersion::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入终本案件
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@Operation(summary = "批量导入终本案件")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 按选项卡名称读取(客户提供的文件可能不是把目标 sheet 放在第一个)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "终本案件", 0);
|
||||
ExcelImportSupport.ImportResult<CreditFinalVersionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditFinalVersionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditFinalVersionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditFinalVersion> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditFinalVersionImportParam param = list.get(i);
|
||||
try {
|
||||
CreditFinalVersion item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditFinalVersionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
|
||||
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditFinalVersionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditFinalVersionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
|
||||
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditFinalVersionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.FINAL_VERSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史终本案件(仅解析“历史终本案件”选项卡)
|
||||
* 规则:案号相同则覆盖更新(recommend++ 记录更新次数);案号不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@Operation(summary = "批量导入历史终本案件")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史终本案件");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史终本案件”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditFinalVersionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditFinalVersionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditFinalVersionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
LinkedHashMap<String, CreditFinalVersion> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditFinalVersionImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditFinalVersion item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditFinalVersion> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditFinalVersion> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditFinalVersion item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getRecommend,
|
||||
CreditFinalVersion::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditFinalVersionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
|
||||
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditFinalVersion::getId, CreditFinalVersion::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditFinalVersionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
CreditFinalVersion::getRecommend,
|
||||
CreditFinalVersion::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditFinalVersionService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
|
||||
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditFinalVersion::getId, CreditFinalVersion::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditFinalVersionService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.FINAL_VERSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载终本案件导入模板
|
||||
*/
|
||||
@Operation(summary = "下载终本案件导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditFinalVersionImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditFinalVersionImportParam example = new CreditFinalVersionImportParam();
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setInvolvedAmount("20,293.91");
|
||||
example.setDataStatus("正常");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setFinalDate("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("终本案件导入模板", "终本案件", CreditFinalVersionImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_final_version_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditFinalVersionImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditFinalVersion convertImportParamToEntity(CreditFinalVersionImportParam param) {
|
||||
CreditFinalVersion entity = new CreditFinalVersion();
|
||||
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee2())
|
||||
? param.getAppellee2()
|
||||
: param.getAppellee();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
? param.getOtherPartiesThirdParty()
|
||||
: param.getOtherPartiesThirdParty2();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setAppellee(appellee);
|
||||
entity.setUnfulfilledAmount(param.getUnfulfilledAmount());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setCourtName(courtName);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setFinalDate(param.getFinalDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,814 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditGqdj;
|
||||
import com.gxwebsoft.credit.param.CreditGqdjImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditGqdjParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditGqdjService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 股权冻结控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:37
|
||||
*/
|
||||
@Tag(name = "股权冻结管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-gqdj")
|
||||
public class CreditGqdjController extends BaseController {
|
||||
@Resource
|
||||
private CreditGqdjService creditGqdjService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询股权冻结")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditGqdj>> page(CreditGqdjParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部股权冻结")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditGqdj>> list(CreditGqdjParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询股权冻结")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditGqdj> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加股权冻结")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditGqdj creditGqdj) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditGqdj.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditGqdjService.save(creditGqdj)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改股权冻结")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditGqdj creditGqdj) {
|
||||
if (creditGqdjService.updateById(creditGqdj)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除股权冻结")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditGqdjService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加股权冻结")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditGqdj> list) {
|
||||
if (creditGqdjService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改股权冻结")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditGqdj> batchParam) {
|
||||
if (batchParam.update(creditGqdjService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除股权冻结")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditGqdjService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当事人/企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId 为空/0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Match companyId by any party/company-name column (e.g. plaintiff/appellant, defendant/appellee).
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNames(
|
||||
creditGqdjService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCompanyId,
|
||||
CreditGqdj::setCompanyId,
|
||||
CreditGqdj::getHasData,
|
||||
CreditGqdj::setHasData,
|
||||
CreditGqdj::getTenantId,
|
||||
CreditGqdj::new,
|
||||
CreditGqdj::getPlaintiffAppellant,
|
||||
CreditGqdj::getAppellee
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入股权冻结司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@Operation(summary = "批量导入股权冻结司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "股权冻结", 0);
|
||||
// Prefer the "best" header configuration; many upstream files have extra title rows or multi-row headers.
|
||||
ExcelImportSupport.ImportResult<CreditGqdjImportParam> importResult = ExcelImportSupport.readBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
// Score rows that look like real data (at least has a case number in either column).
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2())
|
||||
),
|
||||
sheetIndex
|
||||
);
|
||||
List<CreditGqdjImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
// Fallback: try other sheets if the named/default sheet doesn't match.
|
||||
importResult = ExcelImportSupport.readAnySheetBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2()))
|
||||
);
|
||||
list = importResult.getData();
|
||||
usedTitleRows = importResult.getTitleRows();
|
||||
usedHeadRows = importResult.getHeadRows();
|
||||
usedSheetIndex = importResult.getSheetIndex();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 通常挂在“案号/执行通知文书号”列的超链接中,需要额外读取回填。
|
||||
String caseNumberHeader = "执行通知文书号";
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
|
||||
// Some upstream sources use "案号" as the case number header.
|
||||
Map<String, String> urlByCaseNumberFromAh = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
urlByCaseNumberFromAh.forEach(urlByCaseNumber::putIfAbsent);
|
||||
// Some upstream sources use "暗号" as the case number header.
|
||||
Map<String, String> urlByCaseNumberFromAh2 = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号");
|
||||
urlByCaseNumberFromAh2.forEach(urlByCaseNumber::putIfAbsent);
|
||||
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
|
||||
Map<String, String> urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
// Try again with "案号" as the key column name.
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
// Try again with "暗号" as the key column name.
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "链接");
|
||||
}
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditGqdj> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditGqdjImportParam param = list.get(i);
|
||||
try {
|
||||
CreditGqdj item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String key = item.getCaseNumber().trim();
|
||||
String link = urlByCaseNumber.get(key);
|
||||
if (ImportHelper.isBlank(link)) {
|
||||
link = urlByCaseNumberFromUrlCol.get(key);
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditGqdjService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditGqdj existing = creditGqdjService.lambdaQuery()
|
||||
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditGqdjService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditGqdjService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditGqdj existing = creditGqdjService.lambdaQuery()
|
||||
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditGqdjService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.GQDJ, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史股权冻结(仅解析“历史股权冻结”选项卡)
|
||||
* 规则:执行通知文书号/案号相同则覆盖更新(recommend++ 记录更新次数);不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@Operation(summary = "批量导入历史股权冻结司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史股权冻结");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史股权冻结”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditGqdjImportParam> importResult = ExcelImportSupport.readBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2())),
|
||||
sheetIndex
|
||||
);
|
||||
List<CreditGqdjImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
String caseNumberHeader = "执行通知文书号";
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
|
||||
Map<String, String> urlByCaseNumberFromAh = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
urlByCaseNumberFromAh.forEach(urlByCaseNumber::putIfAbsent);
|
||||
Map<String, String> urlByCaseNumberFromAh2 = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号");
|
||||
urlByCaseNumberFromAh2.forEach(urlByCaseNumber::putIfAbsent);
|
||||
Map<String, String> urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "链接");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinkedHashMap<String, CreditGqdj> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditGqdjImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditGqdj item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = item.getCaseNumber();
|
||||
String link = urlByCaseNumber.get(key);
|
||||
if (ImportHelper.isBlank(link)) {
|
||||
link = urlByCaseNumberFromUrlCol.get(key);
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditGqdj> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditGqdj> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditGqdj item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getRecommend,
|
||||
CreditGqdj::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditGqdjService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditGqdj existing = creditGqdjService.lambdaQuery()
|
||||
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditGqdj::getId, CreditGqdj::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditGqdjService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getCaseNumber,
|
||||
CreditGqdj::getRecommend,
|
||||
CreditGqdj::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditGqdjService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditGqdj existing = creditGqdjService.lambdaQuery()
|
||||
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditGqdj::getId, CreditGqdj::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditGqdjService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.GQDJ, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载股权冻结导入模板
|
||||
*/
|
||||
@Operation(summary = "下载股权冻结导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditGqdjImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditGqdjImportParam example = new CreditGqdjImportParam();
|
||||
example.setDataType("股权冻结");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setCourtName("示例法院");
|
||||
example.setDataStatus("已公开");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("股权冻结导入模板", "股权冻结", CreditGqdjImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_gqdj_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditGqdjImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
// Don't over-filter here: if some columns are mapped but case number header differs,
|
||||
// we still want to read the row and report "案号不能为空" instead of "未读取到数据".
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCaseNumber2())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getAppellee2())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount())
|
||||
&& ImportHelper.isBlank(param.getCourtName())
|
||||
&& ImportHelper.isBlank(param.getDataType())
|
||||
&& ImportHelper.isBlank(param.getDataStatus())
|
||||
&& ImportHelper.isBlank(param.getDataStatus2())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateStart())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateEnd())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateStart2())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateEnd2())
|
||||
&& ImportHelper.isBlank(param.getPublicDate());
|
||||
}
|
||||
|
||||
private CreditGqdj convertImportParamToEntity(CreditGqdjImportParam param) {
|
||||
CreditGqdj entity = new CreditGqdj();
|
||||
|
||||
// Template compatibility: some sources use alternate headers for the same columns.
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee()) ? param.getAppellee() : param.getAppellee2();
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
? param.getPlaintiffAppellant()
|
||||
: param.getPlaintiffAppellant2();
|
||||
|
||||
if (!ImportHelper.isBlank(param.getCaseNumber2())) {
|
||||
entity.setCaseNumber(param.getCaseNumber2());
|
||||
} else {
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
}
|
||||
entity.setAppellee(appellee);
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setInvolvedAmount(param.getInvolvedAmount());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
if (!ImportHelper.isBlank(param.getDataStatus2())) {
|
||||
entity.setDataStatus(param.getDataStatus2());
|
||||
} else {
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
}
|
||||
entity.setDataType("股权冻结");
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
if (!ImportHelper.isBlank(param.getFreezeDateStart2())) {
|
||||
entity.setFreezeDateStart(param.getFreezeDateStart2());
|
||||
} else {
|
||||
entity.setFreezeDateStart(param.getFreezeDateStart());
|
||||
}
|
||||
if (!ImportHelper.isBlank(param.getFreezeDateEnd2())) {
|
||||
entity.setFreezeDateEnd(param.getFreezeDateEnd2());
|
||||
} else {
|
||||
entity.setFreezeDateEnd(param.getFreezeDateEnd());
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,511 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditHistoricalLegalPerson;
|
||||
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditHistoricalLegalPersonService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 历史法定代表人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "历史法定代表人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-historical-legal-person")
|
||||
public class CreditHistoricalLegalPersonController extends BaseController {
|
||||
@Resource
|
||||
private CreditHistoricalLegalPersonService creditHistoricalLegalPersonService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询历史法定代表人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditHistoricalLegalPerson>> page(CreditHistoricalLegalPersonParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部历史法定代表人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditHistoricalLegalPerson>> list(CreditHistoricalLegalPersonParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询历史法定代表人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditHistoricalLegalPerson> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加历史法定代表人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditHistoricalLegalPerson creditHistoricalLegalPerson) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditHistoricalLegalPerson.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditHistoricalLegalPersonService.save(creditHistoricalLegalPerson)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改历史法定代表人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditHistoricalLegalPerson creditHistoricalLegalPerson) {
|
||||
if (creditHistoricalLegalPersonService.updateById(creditHistoricalLegalPerson)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除历史法定代表人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditHistoricalLegalPersonService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加历史法定代表人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditHistoricalLegalPerson> list) {
|
||||
if (creditHistoricalLegalPersonService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改历史法定代表人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditHistoricalLegalPerson> batchParam) {
|
||||
if (batchParam.update(creditHistoricalLegalPersonService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除历史法定代表人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditHistoricalLegalPersonService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditHistoricalLegalPersonService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditHistoricalLegalPerson::getId,
|
||||
CreditHistoricalLegalPerson::setId,
|
||||
CreditHistoricalLegalPerson::getName,
|
||||
CreditHistoricalLegalPerson::getCompanyId,
|
||||
CreditHistoricalLegalPerson::setCompanyId,
|
||||
CreditHistoricalLegalPerson::getHasData,
|
||||
CreditHistoricalLegalPerson::setHasData,
|
||||
CreditHistoricalLegalPerson::getTenantId,
|
||||
CreditHistoricalLegalPerson::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史法定代表人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@Operation(summary = "批量导入历史法定代表人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditHistoricalLegalPersonImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditHistoricalLegalPersonImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditHistoricalLegalPersonImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditHistoricalLegalPerson> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditHistoricalLegalPersonImportParam param = list.get(i);
|
||||
try {
|
||||
CreditHistoricalLegalPerson item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
// 批内一次查库:按 name in (...) 拉取,再按 registerDate 做内存匹配
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
for (CreditHistoricalLegalPerson it : chunkItems) {
|
||||
if (it != null && !ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
}
|
||||
List<CreditHistoricalLegalPerson> existingList = names.isEmpty()
|
||||
? new ArrayList<>()
|
||||
: creditHistoricalLegalPersonService.lambdaQuery()
|
||||
.in(CreditHistoricalLegalPerson::getName, names)
|
||||
.list();
|
||||
|
||||
java.util.Map<String, CreditHistoricalLegalPerson> byName = new java.util.HashMap<>();
|
||||
java.util.Map<String, CreditHistoricalLegalPerson> byNameDate = new java.util.HashMap<>();
|
||||
for (CreditHistoricalLegalPerson existing : existingList) {
|
||||
if (existing == null || ImportHelper.isBlank(existing.getName())) {
|
||||
continue;
|
||||
}
|
||||
String n = existing.getName().trim();
|
||||
byName.putIfAbsent(n, existing);
|
||||
String d = ImportHelper.isBlank(existing.getRegisterDate()) ? null : existing.getRegisterDate().trim();
|
||||
if (d != null) {
|
||||
byNameDate.putIfAbsent(n + "|" + d, existing);
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditHistoricalLegalPerson> updates = new ArrayList<>();
|
||||
List<CreditHistoricalLegalPerson> inserts = new ArrayList<>();
|
||||
for (CreditHistoricalLegalPerson it : chunkItems) {
|
||||
if (it == null || ImportHelper.isBlank(it.getName())) {
|
||||
continue;
|
||||
}
|
||||
String n = it.getName().trim();
|
||||
CreditHistoricalLegalPerson existing;
|
||||
if (!ImportHelper.isBlank(it.getRegisterDate())) {
|
||||
String d = it.getRegisterDate().trim();
|
||||
existing = byNameDate.get(n + "|" + d);
|
||||
} else {
|
||||
existing = byName.get(n);
|
||||
}
|
||||
if (existing != null) {
|
||||
it.setId(existing.getId());
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditHistoricalLegalPersonService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditHistoricalLegalPersonService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditHistoricalLegalPersonService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditHistoricalLegalPerson existing = creditHistoricalLegalPersonService.lambdaQuery()
|
||||
.eq(CreditHistoricalLegalPerson::getName, rowItem.getName())
|
||||
.eq(!ImportHelper.isBlank(rowItem.getRegisterDate()), CreditHistoricalLegalPerson::getRegisterDate, rowItem.getRegisterDate())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditHistoricalLegalPersonService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
for (CreditHistoricalLegalPerson it : chunkItems) {
|
||||
if (it != null && !ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
}
|
||||
List<CreditHistoricalLegalPerson> existingList = names.isEmpty()
|
||||
? new ArrayList<>()
|
||||
: creditHistoricalLegalPersonService.lambdaQuery()
|
||||
.in(CreditHistoricalLegalPerson::getName, names)
|
||||
.list();
|
||||
|
||||
java.util.Map<String, CreditHistoricalLegalPerson> byName = new java.util.HashMap<>();
|
||||
java.util.Map<String, CreditHistoricalLegalPerson> byNameDate = new java.util.HashMap<>();
|
||||
for (CreditHistoricalLegalPerson existing : existingList) {
|
||||
if (existing == null || ImportHelper.isBlank(existing.getName())) {
|
||||
continue;
|
||||
}
|
||||
String n = existing.getName().trim();
|
||||
byName.putIfAbsent(n, existing);
|
||||
String d = ImportHelper.isBlank(existing.getRegisterDate()) ? null : existing.getRegisterDate().trim();
|
||||
if (d != null) {
|
||||
byNameDate.putIfAbsent(n + "|" + d, existing);
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditHistoricalLegalPerson> updates = new ArrayList<>();
|
||||
List<CreditHistoricalLegalPerson> inserts = new ArrayList<>();
|
||||
for (CreditHistoricalLegalPerson it : chunkItems) {
|
||||
if (it == null || ImportHelper.isBlank(it.getName())) {
|
||||
continue;
|
||||
}
|
||||
String n = it.getName().trim();
|
||||
CreditHistoricalLegalPerson existing;
|
||||
if (!ImportHelper.isBlank(it.getRegisterDate())) {
|
||||
String d = it.getRegisterDate().trim();
|
||||
existing = byNameDate.get(n + "|" + d);
|
||||
} else {
|
||||
existing = byName.get(n);
|
||||
}
|
||||
if (existing != null) {
|
||||
it.setId(existing.getId());
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditHistoricalLegalPersonService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditHistoricalLegalPersonService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditHistoricalLegalPersonService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditHistoricalLegalPerson existing = creditHistoricalLegalPersonService.lambdaQuery()
|
||||
.eq(CreditHistoricalLegalPerson::getName, rowItem.getName())
|
||||
.eq(!ImportHelper.isBlank(rowItem.getRegisterDate()), CreditHistoricalLegalPerson::getRegisterDate, rowItem.getRegisterDate())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditHistoricalLegalPersonService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.HISTORICAL_LEGAL_PERSON, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载历史法定代表人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载历史法定代表人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditHistoricalLegalPersonImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditHistoricalLegalPersonImportParam example = new CreditHistoricalLegalPersonImportParam();
|
||||
example.setName("张三");
|
||||
example.setRegisterDate("2020-01-01");
|
||||
example.setPublicDate("2023-06-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("历史法定代表人导入模板", "历史法定代表人", CreditHistoricalLegalPersonImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_historical_legal_person_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditHistoricalLegalPersonImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getRegisterDate())
|
||||
&& ImportHelper.isBlank(param.getPublicDate());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditHistoricalLegalPersonImportParam param) {
|
||||
return isHeaderValue(param.getName(), "名称")
|
||||
|| isHeaderValue(param.getRegisterDate(), "任职日期")
|
||||
|| isHeaderValue(param.getPublicDate(), "卸任日期");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditHistoricalLegalPerson convertImportParamToEntity(CreditHistoricalLegalPersonImportParam param) {
|
||||
CreditHistoricalLegalPerson entity = new CreditHistoricalLegalPerson();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setRegisterDate(param.getRegisterDate());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,969 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudgmentDebtor;
|
||||
import com.gxwebsoft.credit.param.CreditJudgmentDebtorImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudgmentDebtorParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudgmentDebtorService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Locale;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* 被执行人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:55
|
||||
*/
|
||||
@Tag(name = "被执行人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judgment-debtor")
|
||||
public class CreditJudgmentDebtorController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudgmentDebtorService creditJudgmentDebtorService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询被执行人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudgmentDebtor>> page(CreditJudgmentDebtorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部被执行人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudgmentDebtor>> list(CreditJudgmentDebtorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询被执行人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudgmentDebtor> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加被执行人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudgmentDebtor creditJudgmentDebtor) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditJudgmentDebtor.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditJudgmentDebtorService.save(creditJudgmentDebtor)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改被执行人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudgmentDebtor creditJudgmentDebtor) {
|
||||
if (creditJudgmentDebtorService.updateById(creditJudgmentDebtor)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除被执行人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditJudgmentDebtorService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加被执行人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudgmentDebtor> list) {
|
||||
if (creditJudgmentDebtorService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改被执行人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudgmentDebtor> batchParam) {
|
||||
if (batchParam.update(creditJudgmentDebtorService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除被执行人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditJudgmentDebtorService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditJudgmentDebtorService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudgmentDebtor::getId,
|
||||
CreditJudgmentDebtor::setId,
|
||||
CreditJudgmentDebtor::getName,
|
||||
CreditJudgmentDebtor::getCompanyId,
|
||||
CreditJudgmentDebtor::setCompanyId,
|
||||
CreditJudgmentDebtor::getHasData,
|
||||
CreditJudgmentDebtor::setHasData,
|
||||
CreditJudgmentDebtor::getTenantId,
|
||||
CreditJudgmentDebtor::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入被执行人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@Operation(summary = "批量导入被执行人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
try {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
ImportOutcome outcome;
|
||||
if (isZip(file)) {
|
||||
outcome = importFromZip(file, currentUserId, currentTenantId, companyId);
|
||||
} else {
|
||||
outcome = importFromExcel(file, safeFileLabel(file.getOriginalFilename()), currentUserId, currentTenantId, companyId, false);
|
||||
}
|
||||
|
||||
if (!outcome.anyDataRead) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDGMENT_DEBTOR, outcome.touchedCompanyIds);
|
||||
|
||||
if (outcome.errorMessages.isEmpty()) {
|
||||
return success("成功导入" + outcome.successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + outcome.successCount + "条,失败" + outcome.errorMessages.size() + "条", outcome.errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史被执行人(写入被执行人表 credit_judgment_debtor,仅解析“历史被执行人”选项卡)
|
||||
* 规则:案号相同则更新;案号不存在则插入;导入文件内案号重复时取最后一条覆盖。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@Operation(summary = "批量导入历史被执行人")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
try {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
ImportOutcome outcome;
|
||||
if (isZip(file)) {
|
||||
outcome = importHistoryFromZip(file, currentUserId, currentTenantId, companyId);
|
||||
} else {
|
||||
outcome = importHistoryFromExcel(file, safeFileLabel(file.getOriginalFilename()), currentUserId, currentTenantId, companyId);
|
||||
}
|
||||
|
||||
if (!outcome.anyDataRead) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史被执行人”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDGMENT_DEBTOR, outcome.touchedCompanyIds);
|
||||
|
||||
if (outcome.errorMessages.isEmpty()) {
|
||||
return success("成功导入" + outcome.successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + outcome.successCount + "条,失败" + outcome.errorMessages.size() + "条", outcome.errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载被执行人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载被执行人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudgmentDebtorImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudgmentDebtorImportParam example = new CreditJudgmentDebtorImportParam();
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setName("某某公司");
|
||||
example.setCode("1234567890");
|
||||
example.setOccurrenceTime("2024-01-10");
|
||||
example.setAmount("100000");
|
||||
example.setDataStatus("已公开");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("被执行人导入模板", "被执行人", CreditJudgmentDebtorImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judgment_debtor_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudgmentDebtorImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditJudgmentDebtorImportParam param) {
|
||||
return isHeaderValue(param.getName(), "序号")
|
||||
|| isHeaderValue(param.getName1(), "序号")
|
||||
|| isHeaderValue(param.getCaseNumber(), "案号")
|
||||
|| isHeaderValue(param.getName(), "被执行人名称")
|
||||
|| isHeaderValue(param.getName1(), "被执行人")
|
||||
|| isHeaderValue(param.getCode(), "证件号/组织机构代码")
|
||||
|| isHeaderValue(param.getOccurrenceTime(), "立案日期")
|
||||
|| isHeaderValue(param.getCourtName(), "法院")
|
||||
|| isHeaderValue(param.getAmount(), "执行标的(元)")
|
||||
|| isHeaderValue(param.getDataStatus(), "数据状态");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditJudgmentDebtor convertImportParamToEntity(CreditJudgmentDebtorImportParam param) {
|
||||
CreditJudgmentDebtor entity = new CreditJudgmentDebtor();
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setName1(param.getName1());
|
||||
String debtorName = ImportHelper.isBlank(param.getName()) ? param.getName1() : param.getName();
|
||||
entity.setName(debtorName);
|
||||
entity.setCode(param.getCode());
|
||||
entity.setOccurrenceTime(param.getOccurrenceTime());
|
||||
entity.setAmount(param.getAmount());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private static class ImportOutcome {
|
||||
private final boolean anyDataRead;
|
||||
private final int successCount;
|
||||
private final List<String> errorMessages;
|
||||
private final Set<Integer> touchedCompanyIds;
|
||||
|
||||
private ImportOutcome(boolean anyDataRead, int successCount, List<String> errorMessages, Set<Integer> touchedCompanyIds) {
|
||||
this.anyDataRead = anyDataRead;
|
||||
this.successCount = successCount;
|
||||
this.errorMessages = errorMessages;
|
||||
this.touchedCompanyIds = touchedCompanyIds != null ? touchedCompanyIds : new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId, boolean strictDebtorSheet) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = readDebtorImport(excelFile, strictDebtorSheet);
|
||||
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人名称");
|
||||
Map<String, String> urlByName1 = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人");
|
||||
|
||||
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudgmentDebtor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudgmentDebtorImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName1())) {
|
||||
link = urlByName1.get(item.getName1().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
}
|
||||
return new ImportOutcome(true, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
int historySheetIndex = ExcelImportSupport.findSheetIndex(excelFile, "历史被执行人");
|
||||
if (historySheetIndex < 0) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = ExcelImportSupport.readBest(
|
||||
excelFile,
|
||||
CreditJudgmentDebtorImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
this::isScoreImportRow,
|
||||
historySheetIndex
|
||||
);
|
||||
|
||||
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人名称");
|
||||
Map<String, String> urlByName1 = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人");
|
||||
|
||||
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
||||
|
||||
// 同案号多条:以导入文件中“最后一条”为准(视为最新),避免批处理中重复 upsert。
|
||||
LinkedHashMap<String, CreditJudgmentDebtor> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudgmentDebtorImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
||||
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName1())) {
|
||||
link = urlByName1.get(item.getName1().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
return new ImportOutcome(true, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudgmentDebtor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditJudgmentDebtor> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditJudgmentDebtor item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistHistoryImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistHistoryImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
}
|
||||
|
||||
return new ImportOutcome(true, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private int persistHistoryImportChunk(List<CreditJudgmentDebtor> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
String prefix,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
return batchImportSupport.runInNewTx(() -> {
|
||||
List<String> keys = new ArrayList<>(items.size());
|
||||
for (CreditJudgmentDebtor item : items) {
|
||||
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
continue;
|
||||
}
|
||||
keys.add(item.getCaseNumber().trim());
|
||||
}
|
||||
|
||||
Map<String, CreditJudgmentDebtor> existingByCaseNumber = new java.util.HashMap<>();
|
||||
if (!keys.isEmpty()) {
|
||||
List<CreditJudgmentDebtor> existingList = creditJudgmentDebtorService.lambdaQuery()
|
||||
.in(CreditJudgmentDebtor::getCaseNumber, keys)
|
||||
.select(CreditJudgmentDebtor::getId, CreditJudgmentDebtor::getCaseNumber, CreditJudgmentDebtor::getRecommend)
|
||||
.list();
|
||||
for (CreditJudgmentDebtor existing : existingList) {
|
||||
if (existing == null || ImportHelper.isBlank(existing.getCaseNumber())) {
|
||||
continue;
|
||||
}
|
||||
existingByCaseNumber.putIfAbsent(existing.getCaseNumber().trim(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditJudgmentDebtor> updates = new ArrayList<>();
|
||||
List<CreditJudgmentDebtor> inserts = new ArrayList<>();
|
||||
for (CreditJudgmentDebtor item : items) {
|
||||
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
continue;
|
||||
}
|
||||
String caseNumber = item.getCaseNumber().trim();
|
||||
CreditJudgmentDebtor existing = existingByCaseNumber.get(caseNumber);
|
||||
if (existing != null && existing.getId() != null) {
|
||||
// 覆盖更新:recommend 记录“被更新次数”,每次更新 +1
|
||||
item.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
item.setRecommend(old == null ? 1 : old + 1);
|
||||
updates.add(item);
|
||||
} else {
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
inserts.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updates.isEmpty()) {
|
||||
creditJudgmentDebtorService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditJudgmentDebtorService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
});
|
||||
} catch (Exception batchException) {
|
||||
int successCount = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
CreditJudgmentDebtor item = items.get(i);
|
||||
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
|
||||
try {
|
||||
int delta = batchImportSupport.runInNewTx(() -> {
|
||||
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
return 0;
|
||||
}
|
||||
String caseNumber = item.getCaseNumber().trim();
|
||||
CreditJudgmentDebtor existing = creditJudgmentDebtorService.lambdaQuery()
|
||||
.eq(CreditJudgmentDebtor::getCaseNumber, caseNumber)
|
||||
.select(CreditJudgmentDebtor::getId, CreditJudgmentDebtor::getRecommend)
|
||||
.one();
|
||||
if (existing != null && existing.getId() != null) {
|
||||
item.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
item.setRecommend(old == null ? 1 : old + 1);
|
||||
return creditJudgmentDebtorService.updateById(item) ? 1 : 0;
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
return creditJudgmentDebtorService.save(item) ? 1 : 0;
|
||||
});
|
||||
if (delta > 0) {
|
||||
successCount += delta;
|
||||
} else {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:保存失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
return successCount;
|
||||
}
|
||||
}
|
||||
|
||||
private int persistImportChunk(List<CreditJudgmentDebtor> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
String prefix,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return batchImportSupport.runInNewTx(() -> batchImportSupport.upsertBySingleKey(
|
||||
creditJudgmentDebtorService,
|
||||
items,
|
||||
CreditJudgmentDebtor::getId,
|
||||
CreditJudgmentDebtor::setId,
|
||||
CreditJudgmentDebtor::getCaseNumber,
|
||||
CreditJudgmentDebtor::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
));
|
||||
} catch (Exception batchException) {
|
||||
int successCount = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
CreditJudgmentDebtor item = items.get(i);
|
||||
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
|
||||
try {
|
||||
int delta = batchImportSupport.runInNewTx(() -> {
|
||||
boolean saved = creditJudgmentDebtorService.save(item);
|
||||
if (!saved) {
|
||||
CreditJudgmentDebtor existing = creditJudgmentDebtorService.lambdaQuery()
|
||||
.eq(CreditJudgmentDebtor::getCaseNumber, item.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
item.setId(existing.getId());
|
||||
if (creditJudgmentDebtorService.updateById(item)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
if (delta > 0) {
|
||||
successCount += delta;
|
||||
} else {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:保存失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
return successCount;
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
try {
|
||||
return importFromZip(zipFile, currentUserId, currentTenantId, companyId, StandardCharsets.UTF_8);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return importFromZip(zipFile, currentUserId, currentTenantId, companyId, Charset.forName("GBK"));
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId, Charset charset) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
boolean anyDataRead = false;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String entryName = entry.getName();
|
||||
if (!isExcelFileName(entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] bytes = readAllBytes(zis);
|
||||
String entryFileName = safeFileLabel(entryName);
|
||||
MultipartFile excelFile = new InMemoryMultipartFile(entryFileName, bytes);
|
||||
|
||||
try {
|
||||
ImportOutcome outcome = importFromExcel(excelFile, entryFileName, currentUserId, currentTenantId, companyId, true);
|
||||
if (outcome.anyDataRead) {
|
||||
anyDataRead = true;
|
||||
successCount += outcome.successCount;
|
||||
errorMessages.addAll(outcome.errorMessages);
|
||||
touchedCompanyIds.addAll(outcome.touchedCompanyIds);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("【" + entryFileName + "】解析失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ImportOutcome(anyDataRead, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
try {
|
||||
return importHistoryFromZip(zipFile, currentUserId, currentTenantId, companyId, StandardCharsets.UTF_8);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return importHistoryFromZip(zipFile, currentUserId, currentTenantId, companyId, Charset.forName("GBK"));
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId, Charset charset) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
boolean anyDataRead = false;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String entryName = entry.getName();
|
||||
if (!isExcelFileName(entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] bytes = readAllBytes(zis);
|
||||
String entryFileName = safeFileLabel(entryName);
|
||||
MultipartFile excelFile = new InMemoryMultipartFile(entryFileName, bytes);
|
||||
|
||||
try {
|
||||
ImportOutcome outcome = importHistoryFromExcel(excelFile, entryFileName, currentUserId, currentTenantId, companyId);
|
||||
if (outcome.anyDataRead) {
|
||||
anyDataRead = true;
|
||||
successCount += outcome.successCount;
|
||||
errorMessages.addAll(outcome.errorMessages);
|
||||
touchedCompanyIds.addAll(outcome.touchedCompanyIds);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("【" + entryFileName + "】解析失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ImportOutcome(anyDataRead, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private static boolean isZip(MultipartFile file) {
|
||||
String filename = file != null ? file.getOriginalFilename() : null;
|
||||
if (filename == null) {
|
||||
return false;
|
||||
}
|
||||
return filename.toLowerCase(Locale.ROOT).endsWith(".zip");
|
||||
}
|
||||
|
||||
private ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> readDebtorImport(MultipartFile excelFile, boolean strictDebtorSheet) throws Exception {
|
||||
List<Integer> debtorSheetIndices = findDebtorSheetIndices(excelFile);
|
||||
for (Integer sheetIndex : debtorSheetIndices) {
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> sheetResult = ExcelImportSupport.readBest(
|
||||
excelFile,
|
||||
CreditJudgmentDebtorImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
this::isScoreImportRow,
|
||||
sheetIndex
|
||||
);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
if (strictDebtorSheet) {
|
||||
return new ExcelImportSupport.ImportResult<>(new ArrayList<>(), 0, 0);
|
||||
}
|
||||
return ExcelImportSupport.readAnySheetBest(excelFile, CreditJudgmentDebtorImportParam.class, this::isEmptyImportRow, this::isScoreImportRow);
|
||||
}
|
||||
|
||||
private boolean isScoreImportRow(CreditJudgmentDebtorImportParam param) {
|
||||
if (param == null) {
|
||||
return false;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return false;
|
||||
}
|
||||
return !ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private List<Integer> findDebtorSheetIndices(MultipartFile excelFile) throws Exception {
|
||||
// Prefer an explicitly-named "被执行人" sheet when present.
|
||||
List<Integer> preferred = new ArrayList<>();
|
||||
List<Integer> indices = new ArrayList<>();
|
||||
try (InputStream is = excelFile.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
int sheetCount = workbook.getNumberOfSheets();
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String sheetName = workbook.getSheetName(i);
|
||||
if (!isDebtorSheetName(sheetName)) {
|
||||
continue;
|
||||
}
|
||||
String normalized = normalizeSheetName(sheetName);
|
||||
if ("被执行人".equals(normalized)) {
|
||||
preferred.add(i);
|
||||
} else {
|
||||
indices.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
preferred.addAll(indices);
|
||||
return preferred;
|
||||
}
|
||||
|
||||
private static boolean isDebtorSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return false;
|
||||
}
|
||||
String normalized = normalizeSheetName(sheetName);
|
||||
return normalized.contains("被执行人") && !normalized.contains("失信") && !normalized.contains("历史");
|
||||
}
|
||||
|
||||
private static String normalizeSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return "";
|
||||
}
|
||||
return sheetName.replace(" ", "").replace(" ", "").trim();
|
||||
}
|
||||
|
||||
private static boolean isExcelFileName(String name) {
|
||||
if (name == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = name.toLowerCase(Locale.ROOT);
|
||||
return lower.endsWith(".xlsx") || lower.endsWith(".xls") || lower.endsWith(".xlsm");
|
||||
}
|
||||
|
||||
private static String safeFileLabel(String name) {
|
||||
if (ImportHelper.isBlank(name)) {
|
||||
return "";
|
||||
}
|
||||
int lastSlash = name.lastIndexOf('/');
|
||||
if (lastSlash >= 0 && lastSlash + 1 < name.length()) {
|
||||
return name.substring(lastSlash + 1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private static byte[] readAllBytes(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[8192];
|
||||
int read;
|
||||
while ((read = inputStream.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private static class InMemoryMultipartFile implements MultipartFile {
|
||||
private final String originalFilename;
|
||||
private final byte[] bytes;
|
||||
|
||||
private InMemoryMultipartFile(String originalFilename, byte[] bytes) {
|
||||
this.originalFilename = originalFilename;
|
||||
this.bytes = bytes != null ? bytes : new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return bytes.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return new java.io.ByteArrayInputStream(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(java.io.File dest) throws IOException {
|
||||
Files.write(dest.toPath(), bytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,640 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudicialDocument;
|
||||
import com.gxwebsoft.credit.param.CreditJudicialDocumentImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudicialDocumentParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudicialDocumentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 裁判文书司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:03
|
||||
*/
|
||||
@Tag(name = "裁判文书司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judicial-document")
|
||||
public class CreditJudicialDocumentController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudicialDocumentService creditJudicialDocumentService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询裁判文书司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudicialDocument>> page(CreditJudicialDocumentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部裁判文书司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudicialDocument>> list(CreditJudicialDocumentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询裁判文书司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudicialDocument> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加裁判文书司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudicialDocument creditJudicialDocument) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditJudicialDocument.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditJudicialDocumentService.save(creditJudicialDocument)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改裁判文书司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudicialDocument creditJudicialDocument) {
|
||||
if (creditJudicialDocumentService.updateById(creditJudicialDocument)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除裁判文书司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditJudicialDocumentService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加裁判文书司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudicialDocument> list) {
|
||||
if (creditJudicialDocumentService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改裁判文书司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudicialDocument> batchParam) {
|
||||
if (batchParam.update(creditJudicialDocumentService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除裁判文书司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditJudicialDocumentService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditJudicialDocumentService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getAppellee,
|
||||
CreditJudicialDocument::getCompanyId,
|
||||
CreditJudicialDocument::setCompanyId,
|
||||
CreditJudicialDocument::getHasData,
|
||||
CreditJudicialDocument::setHasData,
|
||||
CreditJudicialDocument::getTenantId,
|
||||
CreditJudicialDocument::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入裁判文书司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@Operation(summary = "批量导入裁判文书司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 支持按选项卡名称导入:默认读取“裁判文书”sheet(不存在则回退到第 0 个sheet)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "裁判文书", 0);
|
||||
ExcelImportSupport.ImportResult<CreditJudicialDocumentImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditJudicialDocumentImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditJudicialDocumentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByTitle = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "文书标题");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudicialDocument> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudicialDocumentImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudicialDocument item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(link) && !ImportHelper.isBlank(item.getTitle())) {
|
||||
link = urlByTitle.get(item.getTitle().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditJudicialDocumentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
|
||||
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditJudicialDocumentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditJudicialDocumentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
|
||||
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditJudicialDocumentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIAL_DOCUMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史裁判文书(仅解析“历史裁判文书”选项卡)
|
||||
* 规则:案号相同则覆盖更新(recommend++ 记录更新次数);案号不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@Operation(summary = "批量导入历史裁判文书司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史裁判文书");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史裁判文书”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudicialDocumentImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditJudicialDocumentImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditJudicialDocumentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByTitle = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "文书标题");
|
||||
|
||||
LinkedHashMap<String, CreditJudicialDocument> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudicialDocumentImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditJudicialDocument item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
}
|
||||
if (ImportHelper.isBlank(link) && !ImportHelper.isBlank(item.getTitle())) {
|
||||
link = urlByTitle.get(item.getTitle().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudicialDocument> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditJudicialDocument> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditJudicialDocument item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getRecommend,
|
||||
CreditJudicialDocument::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditJudicialDocumentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
|
||||
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditJudicialDocument::getId, CreditJudicialDocument::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditJudicialDocumentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
CreditJudicialDocument::getRecommend,
|
||||
CreditJudicialDocument::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditJudicialDocumentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
|
||||
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditJudicialDocument::getId, CreditJudicialDocument::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditJudicialDocumentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIAL_DOCUMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载裁判文书导入模板
|
||||
*/
|
||||
@Operation(summary = "下载裁判文书导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudicialDocumentImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudicialDocumentImportParam example = new CreditJudicialDocumentImportParam();
|
||||
example.setTitle("裁判文书");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDefendantAppellee("裁判结果示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setReleaseDate("2024-01-02");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("裁判文书导入模板", "裁判文书", CreditJudicialDocumentImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judicial_document_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudicialDocumentImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditJudicialDocument convertImportParamToEntity(CreditJudicialDocumentImportParam param) {
|
||||
CreditJudicialDocument entity = new CreditJudicialDocument();
|
||||
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setTitle(param.getTitle());
|
||||
entity.setType(param.getType());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setOccurrenceTime(param.getOccurrenceTime());
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
// Excel导入字段映射补全:否则对应数据库字段(defendant_appellee/release_date)会一直为空
|
||||
entity.setDefendantAppellee(param.getDefendantAppellee());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
System.out.println("entity = " + entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,474 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudiciary;
|
||||
import com.gxwebsoft.credit.param.CreditJudiciaryImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudiciaryParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudiciaryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 司法案件控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-16 15:23:58
|
||||
*/
|
||||
@Tag(name = "司法案件管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judiciary")
|
||||
public class CreditJudiciaryController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudiciaryService creditJudiciaryService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询司法案件")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudiciary>> page(CreditJudiciaryParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部司法案件")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudiciary>> list(CreditJudiciaryParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询司法案件")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudiciary> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加司法案件")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudiciary creditJudiciary) {
|
||||
if (creditJudiciaryService.save(creditJudiciary)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改司法案件")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudiciary creditJudiciary) {
|
||||
if (creditJudiciaryService.updateById(creditJudiciary)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除司法案件")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditJudiciaryService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加司法案件")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudiciary> list) {
|
||||
if (creditJudiciaryService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改司法案件")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudiciary> batchParam) {
|
||||
if (batchParam.update(creditJudiciaryService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除司法案件")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditJudiciaryService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditJudiciaryService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudiciary::getId,
|
||||
CreditJudiciary::setId,
|
||||
CreditJudiciary::getName,
|
||||
CreditJudiciary::getCompanyId,
|
||||
CreditJudiciary::setCompanyId,
|
||||
CreditJudiciary::getHasData,
|
||||
CreditJudiciary::setHasData,
|
||||
CreditJudiciary::getTenantId,
|
||||
CreditJudiciary::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入司法案件
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@Operation(summary = "批量导入司法案件")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 支持按选项卡名称导入:默认读取“司法案件”sheet(不存在则回退到第 0 个sheet)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "司法案件", 0);
|
||||
|
||||
List<CreditJudiciaryImportParam> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
list = filterEmptyRows(tryImport(file, config[0], config[1], sheetIndex));
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 可能挂在“案号/案件名称”等列的超链接中,需要额外读取回填。
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, sheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, sheetIndex, usedTitleRows, usedHeadRows, "案件名称");
|
||||
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
|
||||
Map<String, String> urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudiciary> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudiciaryImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudiciary item = convertImportParamToEntity(param);
|
||||
if (!isBlank(item.getCode())) {
|
||||
String key = item.getCode().trim();
|
||||
String link = urlByCode.get(key);
|
||||
if (isBlank(link)) {
|
||||
link = urlByCodeFromUrlCol.get(key);
|
||||
}
|
||||
if (!isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
} else if (!isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getType() == null) {
|
||||
item.setType(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
// if (item.getName() == null || item.getName().trim().isEmpty()) {
|
||||
// errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
// continue;
|
||||
// }
|
||||
if (item.getCode() == null || item.getCode().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:唯一标识不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditJudiciaryService,
|
||||
chunkItems,
|
||||
CreditJudiciary::getId,
|
||||
CreditJudiciary::setId,
|
||||
CreditJudiciary::getName,
|
||||
CreditJudiciary::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditJudiciaryService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudiciary existing = creditJudiciaryService.getByName(rowItem.getName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditJudiciaryService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditJudiciaryService,
|
||||
chunkItems,
|
||||
CreditJudiciary::getId,
|
||||
CreditJudiciary::setId,
|
||||
CreditJudiciary::getName,
|
||||
CreditJudiciary::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditJudiciaryService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditJudiciary existing = creditJudiciaryService.getByName(rowItem.getName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditJudiciaryService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIARY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载司法案件导入模板
|
||||
*/
|
||||
@Operation(summary = "下载司法案件导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudiciaryImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudiciaryImportParam example = new CreditJudiciaryImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setCode("C0001");
|
||||
example.setInfoType("执行案件");
|
||||
example.setReason("买卖合同纠纷");
|
||||
example.setProcessDate("2025-08-27");
|
||||
example.setCaseProgress("首次执行");
|
||||
example.setCaseIdentity("被执行人");
|
||||
example.setCode("(2025)闽0103执5480号");
|
||||
example.setCourt("福建省福州市台江区人民法院");
|
||||
example.setCaseAmount("5134060.00");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("司法案件导入模板", "司法案件");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditJudiciaryImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judiciary_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private List<CreditJudiciaryImportParam> tryImport(MultipartFile file, int titleRows, int headRows, int sheetIndex) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(sheetIndex);
|
||||
importParams.setSheetNum(1);
|
||||
return ExcelImportUtil.importExcel(file.getInputStream(), CreditJudiciaryImportParam.class, importParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉完全空白的导入行,避免空行导致导入失败
|
||||
*/
|
||||
private List<CreditJudiciaryImportParam> filterEmptyRows(List<CreditJudiciaryImportParam> rawList) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(this::isEmptyImportRow);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudiciaryImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode())
|
||||
&& isBlank(param.getName())
|
||||
&& isBlank(param.getInfoType());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditJudiciaryImportParam转换为CreditJudiciary实体
|
||||
*/
|
||||
private CreditJudiciary convertImportParamToEntity(CreditJudiciaryImportParam param) {
|
||||
CreditJudiciary entity = new CreditJudiciary();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setInfoType(param.getInfoType());
|
||||
entity.setReason(param.getReason());
|
||||
entity.setProcessDate(param.getProcessDate());
|
||||
entity.setCaseProgress(param.getCaseProgress());
|
||||
entity.setCaseIdentity(param.getCaseIdentity());
|
||||
entity.setCourt(param.getCourt());
|
||||
entity.setCaseAmount(param.getCaseAmount());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,416 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditMediation;
|
||||
import com.gxwebsoft.credit.param.CreditMediationImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditMediationParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditMediationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 诉前调解司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:25
|
||||
*/
|
||||
@Tag(name = "诉前调解司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-mediation")
|
||||
public class CreditMediationController extends BaseController {
|
||||
@Resource
|
||||
private CreditMediationService creditMediationService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询诉前调解司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditMediation>> page(CreditMediationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部诉前调解司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditMediation>> list(CreditMediationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询诉前调解司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditMediation> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加诉前调解司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditMediation creditMediation) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditMediation.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditMediationService.save(creditMediation)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改诉前调解司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditMediation creditMediation) {
|
||||
if (creditMediationService.updateById(creditMediation)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除诉前调解司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditMediationService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加诉前调解司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditMediation> list) {
|
||||
if (creditMediationService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改诉前调解司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditMediation> batchParam) {
|
||||
if (batchParam.update(creditMediationService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除诉前调解司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditMediationService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditMediationService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditMediation::getId,
|
||||
CreditMediation::setId,
|
||||
CreditMediation::getAppellee,
|
||||
CreditMediation::getCompanyId,
|
||||
CreditMediation::setCompanyId,
|
||||
CreditMediation::getHasData,
|
||||
CreditMediation::setHasData,
|
||||
CreditMediation::getTenantId,
|
||||
CreditMediation::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入诉前调解司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@Operation(summary = "批量导入诉前调解司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "诉前调解", 0);
|
||||
ExcelImportSupport.ImportResult<CreditMediationImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditMediationImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditMediationImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditMediation> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditMediationImportParam param = list.get(i);
|
||||
try {
|
||||
CreditMediation item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
CreditMediation::getId,
|
||||
CreditMediation::setId,
|
||||
CreditMediation::getCaseNumber,
|
||||
CreditMediation::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditMediationService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditMediation existing = creditMediationService.lambdaQuery()
|
||||
.eq(CreditMediation::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditMediationService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
CreditMediation::getId,
|
||||
CreditMediation::setId,
|
||||
CreditMediation::getCaseNumber,
|
||||
CreditMediation::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditMediationService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditMediation existing = creditMediationService.lambdaQuery()
|
||||
.eq(CreditMediation::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditMediationService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.MEDIATION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载诉前调解导入模板
|
||||
*/
|
||||
@Operation(summary = "下载诉前调解导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditMediationImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditMediationImportParam example = new CreditMediationImportParam();
|
||||
example.setOtherPartiesThirdParty("当事人");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("诉前调解导入模板", "诉前调解", CreditMediationImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_mediation_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditMediationImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditMediation convertImportParamToEntity(CreditMediationImportParam param) {
|
||||
CreditMediation entity = new CreditMediation();
|
||||
|
||||
// Template compatibility: prefer new columns ("发生时间"/"其他当事人/第三人"), fallback to legacy ones ("立案日期"/"当事人").
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setInvolvedAmount(param.getInvolvedAmount());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,475 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditNearbyCompany;
|
||||
import com.gxwebsoft.credit.param.CreditNearbyCompanyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditNearbyCompanyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditNearbyCompanyService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 附近企业控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "附近企业管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-nearby-company")
|
||||
public class CreditNearbyCompanyController extends BaseController {
|
||||
@Resource
|
||||
private CreditNearbyCompanyService creditNearbyCompanyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询附近企业")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditNearbyCompany>> page(CreditNearbyCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部附近企业")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditNearbyCompany>> list(CreditNearbyCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询附近企业")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditNearbyCompany> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加附近企业")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditNearbyCompany creditNearbyCompany) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditNearbyCompany.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditNearbyCompanyService.save(creditNearbyCompany)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改附近企业")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditNearbyCompany creditNearbyCompany) {
|
||||
if (creditNearbyCompanyService.updateById(creditNearbyCompany)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除附近企业")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditNearbyCompanyService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加附近企业")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditNearbyCompany> list) {
|
||||
if (creditNearbyCompanyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改附近企业")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditNearbyCompany> batchParam) {
|
||||
if (batchParam.update(creditNearbyCompanyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除附近企业")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditNearbyCompanyService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditNearbyCompanyService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditNearbyCompany::getId,
|
||||
CreditNearbyCompany::setId,
|
||||
CreditNearbyCompany::getName,
|
||||
CreditNearbyCompany::getCompanyId,
|
||||
CreditNearbyCompany::setCompanyId,
|
||||
CreditNearbyCompany::getHasData,
|
||||
CreditNearbyCompany::setHasData,
|
||||
CreditNearbyCompany::getTenantId,
|
||||
CreditNearbyCompany::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入附近企业
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@Operation(summary = "批量导入附近企业")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId,
|
||||
@RequestParam(value = "parentId", required = false) Integer parentId,
|
||||
@RequestParam(value = "type", required = false) Integer type) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditNearbyCompanyImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditNearbyCompanyImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditNearbyCompanyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "统一社会信用代码");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
|
||||
// 避免逐行写库:按批处理,显著降低 SQL 次数与事务开销
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditNearbyCompany> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditNearbyCompanyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditNearbyCompany item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getParentId() == null && parentId != null) {
|
||||
item.setParentId(parentId);
|
||||
}
|
||||
if (item.getType() == null && type != null) {
|
||||
item.setType(type);
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.NEARBY_COMPANY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private int persistImportChunk(List<CreditNearbyCompany> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
Integer companyId,
|
||||
Integer parentId,
|
||||
Integer type,
|
||||
Integer tenantId,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
return batchImportSupport.persistChunkWithFallback(
|
||||
items,
|
||||
excelRowNumbers,
|
||||
() -> batchImportSupport.upsertByCodeOrName(
|
||||
creditNearbyCompanyService,
|
||||
items,
|
||||
CreditNearbyCompany::getId,
|
||||
CreditNearbyCompany::setId,
|
||||
CreditNearbyCompany::getCode,
|
||||
CreditNearbyCompany::getCode,
|
||||
CreditNearbyCompany::getName,
|
||||
CreditNearbyCompany::getName,
|
||||
wrapper -> {
|
||||
if (companyId != null) {
|
||||
wrapper.eq(CreditNearbyCompany::getCompanyId, companyId);
|
||||
}
|
||||
if (parentId != null) {
|
||||
wrapper.eq(CreditNearbyCompany::getParentId, parentId);
|
||||
}
|
||||
if (type != null) {
|
||||
wrapper.eq(CreditNearbyCompany::getType, type);
|
||||
}
|
||||
if (tenantId != null) {
|
||||
wrapper.eq(CreditNearbyCompany::getTenantId, tenantId);
|
||||
}
|
||||
},
|
||||
mpBatchSize
|
||||
),
|
||||
(item, excelRowNumber) -> {
|
||||
boolean saved = creditNearbyCompanyService.save(item);
|
||||
if (!saved) {
|
||||
CreditNearbyCompany existing = creditNearbyCompanyService.lambdaQuery()
|
||||
.eq(!ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getCode, item.getCode())
|
||||
.eq(ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getName, item.getName())
|
||||
.eq(item.getCompanyId() != null, CreditNearbyCompany::getCompanyId, item.getCompanyId())
|
||||
.eq(item.getParentId() != null, CreditNearbyCompany::getParentId, item.getParentId())
|
||||
.eq(item.getType() != null, CreditNearbyCompany::getType, item.getType())
|
||||
.eq(item.getTenantId() != null, CreditNearbyCompany::getTenantId, item.getTenantId())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
item.setId(existing.getId());
|
||||
if (creditNearbyCompanyService.updateById(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = excelRowNumber > 0 ? ("第" + excelRowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载附近企业导入模板
|
||||
*/
|
||||
@Operation(summary = "下载附近企业导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditNearbyCompanyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditNearbyCompanyImportParam example = new CreditNearbyCompanyImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setLegalPerson("李四");
|
||||
example.setRegisteredCapital("1000万人民币");
|
||||
example.setPaidinCapital("200万人民币");
|
||||
example.setEstablishDate("2018-06-01");
|
||||
example.setCode("91440101MA5XXXXXXX");
|
||||
example.setAddress("广西南宁市某某路1号");
|
||||
example.setPhone("13800000000");
|
||||
example.setEmail("demo@example.com");
|
||||
example.setProvince("广西");
|
||||
example.setCity("南宁");
|
||||
example.setRegion("青秀区");
|
||||
example.setDomain("https://example.com");
|
||||
example.setInstitutionType("有限责任公司");
|
||||
example.setCompanySize("小微企业");
|
||||
example.setRegistrationAuthority("南宁市市场监督管理局");
|
||||
example.setTaxpayerQualification("一般纳税人");
|
||||
example.setLatestAnnualReportYear("2023");
|
||||
example.setLatestAnnualReportOnOperatingRevenue("1000万");
|
||||
example.setEnterpriseScoreCheck("85");
|
||||
example.setCreditRating("A级");
|
||||
example.setCechnologyScore("70");
|
||||
example.setCechnologyLevel("良好");
|
||||
example.setSmallEnterprise("是");
|
||||
example.setCompanyProfile("企业简介示例");
|
||||
example.setNatureOfBusiness("经营范围示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("附近企业导入模板", "附近企业", CreditNearbyCompanyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_nearby_company_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditNearbyCompanyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getLegalPerson());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditNearbyCompanyImportParam param) {
|
||||
return isHeaderValue(param.getName(), "企业名称")
|
||||
|| isHeaderValue(param.getCode(), "统一社会信用代码")
|
||||
|| isHeaderValue(param.getLegalPerson(), "法定代表人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditNearbyCompany convertImportParamToEntity(CreditNearbyCompanyImportParam param) {
|
||||
CreditNearbyCompany entity = new CreditNearbyCompany();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setPaidinCapital(param.getPaidinCapital());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setCode(param.getCode());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setPhone(param.getPhone());
|
||||
entity.setEmail(param.getEmail());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setCity(param.getCity());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setDomain(param.getDomain());
|
||||
entity.setInstitutionType(param.getInstitutionType());
|
||||
entity.setCompanySize(param.getCompanySize());
|
||||
entity.setRegistrationAuthority(param.getRegistrationAuthority());
|
||||
entity.setTaxpayerQualification(param.getTaxpayerQualification());
|
||||
entity.setLatestAnnualReportYear(param.getLatestAnnualReportYear());
|
||||
entity.setLatestAnnualReportOnOperatingRevenue(param.getLatestAnnualReportOnOperatingRevenue());
|
||||
entity.setEnterpriseScoreCheck(param.getEnterpriseScoreCheck());
|
||||
entity.setCreditRating(param.getCreditRating());
|
||||
entity.setCechnologyScore(param.getCechnologyScore());
|
||||
entity.setCechnologyLevel(param.getCechnologyLevel());
|
||||
entity.setSmallEnterprise(param.getSmallEnterprise());
|
||||
entity.setCompanyProfile(param.getCompanyProfile());
|
||||
entity.setNatureOfBusiness(param.getNatureOfBusiness());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,431 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditPatent;
|
||||
import com.gxwebsoft.credit.param.CreditPatentImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditPatentParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditPatentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 专利控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "专利管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-patent")
|
||||
public class CreditPatentController extends BaseController {
|
||||
@Resource
|
||||
private CreditPatentService creditPatentService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询专利")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditPatent>> page(CreditPatentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部专利")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditPatent>> list(CreditPatentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询专利")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditPatent> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加专利")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditPatent creditPatent) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditPatent.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditPatentService.save(creditPatent)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改专利")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditPatent creditPatent) {
|
||||
if (creditPatentService.updateById(creditPatent)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除专利")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditPatentService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加专利")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditPatent> list) {
|
||||
if (creditPatentService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改专利")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditPatent> batchParam) {
|
||||
if (batchParam.update(creditPatentService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除专利")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditPatentService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditPatentService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditPatent::getId,
|
||||
CreditPatent::setId,
|
||||
CreditPatent::getPatentApplicant,
|
||||
CreditPatent::getCompanyId,
|
||||
CreditPatent::setCompanyId,
|
||||
CreditPatent::getHasData,
|
||||
CreditPatent::setHasData,
|
||||
CreditPatent::getTenantId,
|
||||
CreditPatent::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入专利
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@Operation(summary = "批量导入专利")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditPatentImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditPatentImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditPatentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByRegisterNo = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "申请号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "发明名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditPatent> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditPatentImportParam param = list.get(i);
|
||||
try {
|
||||
CreditPatent item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getRegisterNo())) {
|
||||
link = urlByRegisterNo.get(item.getRegisterNo().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getRegisterNo())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:申请号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditPatentService,
|
||||
chunkItems,
|
||||
CreditPatent::getId,
|
||||
CreditPatent::setId,
|
||||
CreditPatent::getRegisterNo,
|
||||
CreditPatent::getRegisterNo,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditPatentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditPatent existing = creditPatentService.lambdaQuery()
|
||||
.eq(CreditPatent::getRegisterNo, rowItem.getRegisterNo())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditPatentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditPatentService,
|
||||
chunkItems,
|
||||
CreditPatent::getId,
|
||||
CreditPatent::setId,
|
||||
CreditPatent::getRegisterNo,
|
||||
CreditPatent::getRegisterNo,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditPatentService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditPatent existing = creditPatentService.lambdaQuery()
|
||||
.eq(CreditPatent::getRegisterNo, rowItem.getRegisterNo())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditPatentService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.PATENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载专利导入模板
|
||||
*/
|
||||
@Operation(summary = "下载专利导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditPatentImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditPatentImportParam example = new CreditPatentImportParam();
|
||||
example.setName("一种示例装置及方法");
|
||||
example.setType("发明专利");
|
||||
example.setStatusText("有效");
|
||||
example.setRegisterNo("CN2024XXXXXXXX.X");
|
||||
example.setRegisterDate("2024-01-01");
|
||||
example.setPublicNo("CN1XXXXXXXXX");
|
||||
example.setPublicDate("2024-06-01");
|
||||
example.setInventor("张三;李四");
|
||||
example.setPatentApplicant("示例科技有限公司");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("专利导入模板", "专利", CreditPatentImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_patent_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditPatentImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getPublicNo());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditPatentImportParam param) {
|
||||
return isHeaderValue(param.getRegisterNo(), "申请号")
|
||||
|| isHeaderValue(param.getName(), "发明名称")
|
||||
|| isHeaderValue(param.getPatentApplicant(), "申请(专利权)人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditPatent convertImportParamToEntity(CreditPatentImportParam param) {
|
||||
CreditPatent entity = new CreditPatent();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setType(param.getType());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setRegisterNo(param.getRegisterNo());
|
||||
entity.setRegisterDate(param.getRegisterDate());
|
||||
entity.setPublicNo(param.getPublicNo());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setInventor(param.getInventor());
|
||||
entity.setPatentApplicant(param.getPatentApplicant());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,399 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditRiskRelation;
|
||||
import com.gxwebsoft.credit.param.CreditRiskRelationImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditRiskRelationParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditRiskRelationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 风险关系表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:41
|
||||
*/
|
||||
@Tag(name = "风险关系表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-risk-relation")
|
||||
public class CreditRiskRelationController extends BaseController {
|
||||
@Resource
|
||||
private CreditRiskRelationService creditRiskRelationService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询风险关系表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditRiskRelation>> page(CreditRiskRelationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部风险关系表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditRiskRelation>> list(CreditRiskRelationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询风险关系表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditRiskRelation> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加风险关系表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditRiskRelation creditRiskRelation) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditRiskRelation.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditRiskRelationService.save(creditRiskRelation)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改风险关系表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditRiskRelation creditRiskRelation) {
|
||||
if (creditRiskRelationService.updateById(creditRiskRelation)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除风险关系表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditRiskRelationService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加风险关系表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditRiskRelation> list) {
|
||||
if (creditRiskRelationService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改风险关系表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditRiskRelation> batchParam) {
|
||||
if (batchParam.update(creditRiskRelationService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除风险关系表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditRiskRelationService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditRiskRelationService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditRiskRelation::getId,
|
||||
CreditRiskRelation::setId,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
CreditRiskRelation::getCompanyId,
|
||||
CreditRiskRelation::setCompanyId,
|
||||
CreditRiskRelation::getHasData,
|
||||
CreditRiskRelation::setHasData,
|
||||
CreditRiskRelation::getTenantId,
|
||||
CreditRiskRelation::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入风险关系表
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@Operation(summary = "批量导入风险关系表")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "风险关系", 1);
|
||||
ExcelImportSupport.ImportResult<CreditRiskRelationImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditRiskRelationImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditRiskRelationImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditRiskRelation> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditRiskRelationImportParam param = list.get(i);
|
||||
try {
|
||||
CreditRiskRelation item = convertImportParamToEntity(param);
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getMainBodyName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:主体名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditRiskRelationService,
|
||||
chunkItems,
|
||||
CreditRiskRelation::getId,
|
||||
CreditRiskRelation::setId,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditRiskRelationService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditRiskRelation existing = creditRiskRelationService.lambdaQuery()
|
||||
.eq(CreditRiskRelation::getMainBodyName, rowItem.getMainBodyName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditRiskRelationService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditRiskRelationService,
|
||||
chunkItems,
|
||||
CreditRiskRelation::getId,
|
||||
CreditRiskRelation::setId,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditRiskRelationService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditRiskRelation existing = creditRiskRelationService.lambdaQuery()
|
||||
.eq(CreditRiskRelation::getMainBodyName, rowItem.getMainBodyName())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditRiskRelationService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.RISK_RELATION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载风险关系导入模板
|
||||
*/
|
||||
@Operation(summary = "下载风险关系导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditRiskRelationImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditRiskRelationImportParam example = new CreditRiskRelationImportParam();
|
||||
example.setMainBodyName("示例企业");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setRegisteredCapital("8000");
|
||||
example.setProvinceRegion("浙江");
|
||||
example.setAssociatedRelation("关联企业");
|
||||
example.setRiskRelation("存在风险关联");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("风险关系导入模板", "风险关系", CreditRiskRelationImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_risk_relation_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditRiskRelationImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getMainBodyName())
|
||||
&& ImportHelper.isBlank(param.getRegistrationStatus())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital());
|
||||
}
|
||||
|
||||
private CreditRiskRelation convertImportParamToEntity(CreditRiskRelationImportParam param) {
|
||||
CreditRiskRelation entity = new CreditRiskRelation();
|
||||
|
||||
entity.setMainBodyName(param.getMainBodyName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setProvinceRegion(param.getProvinceRegion());
|
||||
entity.setAssociatedRelation(param.getAssociatedRelation());
|
||||
entity.setRiskRelation(param.getRiskRelation());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditSupplier;
|
||||
import com.gxwebsoft.credit.param.CreditSupplierImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditSupplierParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditSupplierService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 供应商控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:47
|
||||
*/
|
||||
@Tag(name = "供应商管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-supplier")
|
||||
public class CreditSupplierController extends BaseController {
|
||||
@Resource
|
||||
private CreditSupplierService creditSupplierService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询供应商")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditSupplier>> page(CreditSupplierParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部供应商")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditSupplier>> list(CreditSupplierParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询供应商")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditSupplier> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加供应商")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditSupplier creditSupplier) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditSupplier.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditSupplierService.save(creditSupplier)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改供应商")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditSupplier creditSupplier) {
|
||||
if (creditSupplierService.updateById(creditSupplier)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除供应商")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditSupplierService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加供应商")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditSupplier> list) {
|
||||
if (creditSupplierService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改供应商")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditSupplier> batchParam) {
|
||||
if (batchParam.update(creditSupplierService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除供应商")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditSupplierService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditSupplierService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditSupplier::getId,
|
||||
CreditSupplier::setId,
|
||||
CreditSupplier::getSupplier,
|
||||
CreditSupplier::getCompanyId,
|
||||
CreditSupplier::setCompanyId,
|
||||
CreditSupplier::getHasData,
|
||||
CreditSupplier::setHasData,
|
||||
CreditSupplier::getTenantId,
|
||||
CreditSupplier::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入供应商
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@Operation(summary = "批量导入供应商")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "供应商", 3);
|
||||
ExcelImportSupport.ImportResult<CreditSupplierImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditSupplierImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditSupplierImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlBySupplier = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "供应商");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditSupplier> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditSupplierImportParam param = list.get(i);
|
||||
try {
|
||||
CreditSupplier item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getSupplier())) {
|
||||
String link = urlBySupplier.get(item.getSupplier().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getSupplier())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:供应商不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditSupplierService,
|
||||
chunkItems,
|
||||
CreditSupplier::getId,
|
||||
CreditSupplier::setId,
|
||||
CreditSupplier::getSupplier,
|
||||
CreditSupplier::getSupplier,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditSupplierService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditSupplier existing = creditSupplierService.lambdaQuery()
|
||||
.eq(CreditSupplier::getSupplier, rowItem.getSupplier())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditSupplierService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditSupplierService,
|
||||
chunkItems,
|
||||
CreditSupplier::getId,
|
||||
CreditSupplier::setId,
|
||||
CreditSupplier::getSupplier,
|
||||
CreditSupplier::getSupplier,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditSupplierService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditSupplier existing = creditSupplierService.lambdaQuery()
|
||||
.eq(CreditSupplier::getSupplier, rowItem.getSupplier())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditSupplierService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUPPLIER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载供应商导入模板
|
||||
*/
|
||||
@Operation(summary = "下载供应商导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditSupplierImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditSupplierImportParam example = new CreditSupplierImportParam();
|
||||
example.setSupplier("示例供应商");
|
||||
example.setStatusTxt("合作中");
|
||||
example.setPurchaseAmount("120");
|
||||
example.setPublicDate("2024-02-01");
|
||||
example.setDataSource("公开渠道");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("供应商导入模板", "供应商", CreditSupplierImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_supplier_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditSupplierImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getSupplier())
|
||||
&& ImportHelper.isBlank(param.getStatusTxt())
|
||||
&& ImportHelper.isBlank(param.getPurchaseAmount());
|
||||
}
|
||||
|
||||
private CreditSupplier convertImportParamToEntity(CreditSupplierImportParam param) {
|
||||
CreditSupplier entity = new CreditSupplier();
|
||||
|
||||
entity.setSupplier(param.getSupplier());
|
||||
entity.setStatusTxt(param.getStatusTxt());
|
||||
entity.setPurchaseAmount(param.getPurchaseAmount());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setDataSource(param.getDataSource());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,552 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditSuspectedRelationship;
|
||||
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditSuspectedRelationshipService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 疑似关系控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "疑似关系管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-suspected-relationship")
|
||||
public class CreditSuspectedRelationshipController extends BaseController {
|
||||
@Resource
|
||||
private CreditSuspectedRelationshipService creditSuspectedRelationshipService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询疑似关系")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditSuspectedRelationship>> page(CreditSuspectedRelationshipParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部疑似关系")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditSuspectedRelationship>> list(CreditSuspectedRelationshipParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询疑似关系")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditSuspectedRelationship> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加疑似关系")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditSuspectedRelationship creditSuspectedRelationship) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditSuspectedRelationship.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditSuspectedRelationshipService.save(creditSuspectedRelationship)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改疑似关系")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditSuspectedRelationship creditSuspectedRelationship) {
|
||||
if (creditSuspectedRelationshipService.updateById(creditSuspectedRelationship)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除疑似关系")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditSuspectedRelationshipService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加疑似关系")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditSuspectedRelationship> list) {
|
||||
if (creditSuspectedRelationshipService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改疑似关系")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditSuspectedRelationship> batchParam) {
|
||||
if (batchParam.update(creditSuspectedRelationshipService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除疑似关系")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditSuspectedRelationshipService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditSuspectedRelationshipService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditSuspectedRelationship::getId,
|
||||
CreditSuspectedRelationship::setId,
|
||||
CreditSuspectedRelationship::getName,
|
||||
CreditSuspectedRelationship::getCompanyId,
|
||||
CreditSuspectedRelationship::setCompanyId,
|
||||
CreditSuspectedRelationship::getHasData,
|
||||
CreditSuspectedRelationship::setHasData,
|
||||
CreditSuspectedRelationship::getTenantId,
|
||||
CreditSuspectedRelationship::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入疑似关系
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@Operation(summary = "批量导入疑似关系")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditSuspectedRelationshipImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditSuspectedRelationshipImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditSuspectedRelationshipImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditSuspectedRelationship> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditSuspectedRelationshipImportParam param = list.get(i);
|
||||
try {
|
||||
CreditSuspectedRelationship item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getRelatedParty())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:关联方不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
List<String> relatedParties = new ArrayList<>(chunkItems.size());
|
||||
for (CreditSuspectedRelationship it : chunkItems) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
if (!ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(it.getRelatedParty())) {
|
||||
relatedParties.add(it.getRelatedParty().trim());
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditSuspectedRelationship> existingList = (names.isEmpty() || relatedParties.isEmpty())
|
||||
? new ArrayList<>()
|
||||
: creditSuspectedRelationshipService.lambdaQuery()
|
||||
.in(CreditSuspectedRelationship::getName, names)
|
||||
.in(CreditSuspectedRelationship::getRelatedParty, relatedParties)
|
||||
.list();
|
||||
|
||||
java.util.Map<String, CreditSuspectedRelationship> byNameRelated = new java.util.HashMap<>();
|
||||
java.util.Map<String, CreditSuspectedRelationship> byNameRelatedType = new java.util.HashMap<>();
|
||||
for (CreditSuspectedRelationship existing : existingList) {
|
||||
if (existing == null
|
||||
|| ImportHelper.isBlank(existing.getName())
|
||||
|| ImportHelper.isBlank(existing.getRelatedParty())) {
|
||||
continue;
|
||||
}
|
||||
String n = existing.getName().trim();
|
||||
String r = existing.getRelatedParty().trim();
|
||||
byNameRelated.putIfAbsent(n + "|" + r, existing);
|
||||
if (!ImportHelper.isBlank(existing.getType())) {
|
||||
byNameRelatedType.putIfAbsent(n + "|" + r + "|" + existing.getType().trim(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditSuspectedRelationship> updates = new ArrayList<>();
|
||||
List<CreditSuspectedRelationship> inserts = new ArrayList<>();
|
||||
for (CreditSuspectedRelationship it : chunkItems) {
|
||||
if (it == null
|
||||
|| ImportHelper.isBlank(it.getName())
|
||||
|| ImportHelper.isBlank(it.getRelatedParty())) {
|
||||
continue;
|
||||
}
|
||||
String n = it.getName().trim();
|
||||
String r = it.getRelatedParty().trim();
|
||||
CreditSuspectedRelationship existing;
|
||||
if (!ImportHelper.isBlank(it.getType())) {
|
||||
existing = byNameRelatedType.get(n + "|" + r + "|" + it.getType().trim());
|
||||
} else {
|
||||
existing = byNameRelated.get(n + "|" + r);
|
||||
}
|
||||
if (existing != null) {
|
||||
it.setId(existing.getId());
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditSuspectedRelationshipService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditSuspectedRelationshipService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditSuspectedRelationshipService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditSuspectedRelationship existing = creditSuspectedRelationshipService.lambdaQuery()
|
||||
.eq(CreditSuspectedRelationship::getName, rowItem.getName())
|
||||
.eq(CreditSuspectedRelationship::getRelatedParty, rowItem.getRelatedParty())
|
||||
.eq(!ImportHelper.isBlank(rowItem.getType()), CreditSuspectedRelationship::getType, rowItem.getType())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditSuspectedRelationshipService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
List<String> names = new ArrayList<>(chunkItems.size());
|
||||
List<String> relatedParties = new ArrayList<>(chunkItems.size());
|
||||
for (CreditSuspectedRelationship it : chunkItems) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
if (!ImportHelper.isBlank(it.getName())) {
|
||||
names.add(it.getName().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(it.getRelatedParty())) {
|
||||
relatedParties.add(it.getRelatedParty().trim());
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditSuspectedRelationship> existingList = (names.isEmpty() || relatedParties.isEmpty())
|
||||
? new ArrayList<>()
|
||||
: creditSuspectedRelationshipService.lambdaQuery()
|
||||
.in(CreditSuspectedRelationship::getName, names)
|
||||
.in(CreditSuspectedRelationship::getRelatedParty, relatedParties)
|
||||
.list();
|
||||
|
||||
java.util.Map<String, CreditSuspectedRelationship> byNameRelated = new java.util.HashMap<>();
|
||||
java.util.Map<String, CreditSuspectedRelationship> byNameRelatedType = new java.util.HashMap<>();
|
||||
for (CreditSuspectedRelationship existing : existingList) {
|
||||
if (existing == null
|
||||
|| ImportHelper.isBlank(existing.getName())
|
||||
|| ImportHelper.isBlank(existing.getRelatedParty())) {
|
||||
continue;
|
||||
}
|
||||
String n = existing.getName().trim();
|
||||
String r = existing.getRelatedParty().trim();
|
||||
byNameRelated.putIfAbsent(n + "|" + r, existing);
|
||||
if (!ImportHelper.isBlank(existing.getType())) {
|
||||
byNameRelatedType.putIfAbsent(n + "|" + r + "|" + existing.getType().trim(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
List<CreditSuspectedRelationship> updates = new ArrayList<>();
|
||||
List<CreditSuspectedRelationship> inserts = new ArrayList<>();
|
||||
for (CreditSuspectedRelationship it : chunkItems) {
|
||||
if (it == null
|
||||
|| ImportHelper.isBlank(it.getName())
|
||||
|| ImportHelper.isBlank(it.getRelatedParty())) {
|
||||
continue;
|
||||
}
|
||||
String n = it.getName().trim();
|
||||
String r = it.getRelatedParty().trim();
|
||||
CreditSuspectedRelationship existing;
|
||||
if (!ImportHelper.isBlank(it.getType())) {
|
||||
existing = byNameRelatedType.get(n + "|" + r + "|" + it.getType().trim());
|
||||
} else {
|
||||
existing = byNameRelated.get(n + "|" + r);
|
||||
}
|
||||
if (existing != null) {
|
||||
it.setId(existing.getId());
|
||||
updates.add(it);
|
||||
} else {
|
||||
inserts.add(it);
|
||||
}
|
||||
}
|
||||
if (!updates.isEmpty()) {
|
||||
creditSuspectedRelationshipService.updateBatchById(updates, mpBatchSize);
|
||||
}
|
||||
if (!inserts.isEmpty()) {
|
||||
creditSuspectedRelationshipService.saveBatch(inserts, mpBatchSize);
|
||||
}
|
||||
return updates.size() + inserts.size();
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditSuspectedRelationshipService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditSuspectedRelationship existing = creditSuspectedRelationshipService.lambdaQuery()
|
||||
.eq(CreditSuspectedRelationship::getName, rowItem.getName())
|
||||
.eq(CreditSuspectedRelationship::getRelatedParty, rowItem.getRelatedParty())
|
||||
.eq(!ImportHelper.isBlank(rowItem.getType()), CreditSuspectedRelationship::getType, rowItem.getType())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditSuspectedRelationshipService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUSPECTED_RELATIONSHIP, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载疑似关系导入模板
|
||||
*/
|
||||
@Operation(summary = "下载疑似关系导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditSuspectedRelationshipImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditSuspectedRelationshipImportParam example = new CreditSuspectedRelationshipImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setStatusText("存续");
|
||||
example.setLegalPerson("李四");
|
||||
example.setRegisteredCapital("1000万人民币");
|
||||
example.setCreateDate("2018-06-01");
|
||||
example.setRelatedParty("关联方示例");
|
||||
example.setType("股权关联");
|
||||
example.setDetail("疑似关系详情示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("疑似关系导入模板", "疑似关系", CreditSuspectedRelationshipImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_suspected_relationship_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditSuspectedRelationshipImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getRelatedParty())
|
||||
&& ImportHelper.isBlank(param.getType());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditSuspectedRelationshipImportParam param) {
|
||||
return isHeaderValue(param.getName(), "企业名称")
|
||||
|| isHeaderValue(param.getRelatedParty(), "关联方")
|
||||
|| isHeaderValue(param.getType(), "疑似关系类型");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditSuspectedRelationship convertImportParamToEntity(CreditSuspectedRelationshipImportParam param) {
|
||||
CreditSuspectedRelationship entity = new CreditSuspectedRelationship();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setCreateDate(param.getCreateDate());
|
||||
entity.setRelatedParty(param.getRelatedParty());
|
||||
entity.setType(param.getType());
|
||||
entity.setDetail(param.getDetail());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,502 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditUser;
|
||||
import com.gxwebsoft.credit.param.CreditUserImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditUserParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 招投标信息表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-15 13:16:04
|
||||
*/
|
||||
@Tag(name = "招投标信息表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-user")
|
||||
public class CreditUserController extends BaseController {
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Resource
|
||||
private CreditUserService creditUserService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询招投标信息表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditUser>> page(CreditUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部招投标信息表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditUser>> list(CreditUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询招投标信息表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditUser> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加招投标信息表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditUser creditUser) {
|
||||
if (creditUserService.save(creditUser)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改招投标信息表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditUser creditUser) {
|
||||
if (creditUserService.updateById(creditUser)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除招投标信息表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditUserService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加招投标信息表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditUser> list) {
|
||||
if (creditUserService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改招投标信息表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditUser> batchParam) {
|
||||
if (batchParam.update(creditUserService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除招投标信息表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditUserService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditUserService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditUser::getId,
|
||||
CreditUser::setId,
|
||||
CreditUser::getWinningName,
|
||||
CreditUser::getCompanyId,
|
||||
CreditUser::setCompanyId,
|
||||
CreditUser::getHasData,
|
||||
CreditUser::setHasData,
|
||||
CreditUser::getTenantId,
|
||||
CreditUser::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入招投标信息
|
||||
* Excel表头格式:客户名称、唯一标识、类型、企业角色、上级ID、信息类型、所在国家、所在省份、所在城市、所在辖区、街道地址、招采单位名称、中标单位名称、中标金额、备注、是否推荐、到期时间、排序、状态、用户ID、租户ID
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@Operation(summary = "批量导入招投标信息")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "招投标", 0);
|
||||
List<CreditUserImportParam> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
list = filterEmptyRows(tryImport(file, config[0], config[1], sheetIndex));
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<Integer, String> urlMap = readNameHyperlinks(file, sheetIndex, usedTitleRows, usedHeadRows);
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditUser> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditUserImportParam param = list.get(i);
|
||||
try {
|
||||
CreditUser item = convertImportParamToEntity(param);
|
||||
|
||||
String link = urlMap.get(i);
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getType() == null) {
|
||||
item.setType(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
if (item.getName() == null || item.getName().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditUserService,
|
||||
chunkItems,
|
||||
CreditUser::getId,
|
||||
CreditUser::setId,
|
||||
CreditUser::getName,
|
||||
CreditUser::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditUserService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditUser existing = creditUserService.getByName(rowItem.getName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditUserService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditUserService,
|
||||
chunkItems,
|
||||
CreditUser::getId,
|
||||
CreditUser::setId,
|
||||
CreditUser::getName,
|
||||
CreditUser::getName,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditUserService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditUser existing = creditUserService.getByName(rowItem.getName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditUserService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.USER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载招投标信息导入模板
|
||||
*/
|
||||
@Operation(summary = "下载招投标信息导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditUserImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditUserImportParam example = new CreditUserImportParam();
|
||||
example.setCode("CUS001");
|
||||
example.setName("示例客户");
|
||||
example.setReleaseDate("2023-01-01");
|
||||
example.setType(0);
|
||||
example.setRole("采购方");
|
||||
example.setInfoType("企业");
|
||||
example.setAddress("广东省-广州市-南沙区");
|
||||
example.setProcurementName("示例招采单位");
|
||||
example.setWinningName("示例中标单位");
|
||||
example.setWinningPrice("100000");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("招投标信息导入模板", "招投标信息");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditUserImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_user_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private List<CreditUserImportParam> tryImport(MultipartFile file, int titleRows, int headRows, int sheetIndex) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(sheetIndex);
|
||||
importParams.setSheetNum(1);
|
||||
return ExcelImportUtil.importExcel(file.getInputStream(), CreditUserImportParam.class, importParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取“项目名称”列的超链接,按数据行顺序返回。
|
||||
*/
|
||||
private Map<Integer, String> readNameHyperlinks(MultipartFile file, int sheetIndex, int titleRows, int headRows) throws Exception {
|
||||
Map<Integer, String> result = new HashMap<>();
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return result;
|
||||
}
|
||||
int headerRowNum = titleRows + headRows - 1;
|
||||
Row headerRow = sheet.getRow(headerRowNum);
|
||||
int nameColIndex = 0;
|
||||
if (headerRow != null) {
|
||||
for (int c = headerRow.getFirstCellNum(); c < headerRow.getLastCellNum(); c++) {
|
||||
Cell cell = headerRow.getCell(c);
|
||||
if (cell != null && "项目名称".equals(cell.getStringCellValue())) {
|
||||
nameColIndex = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell cell = row.getCell(nameColIndex);
|
||||
if (cell != null && cell.getHyperlink() != null) {
|
||||
String address = cell.getHyperlink().getAddress();
|
||||
if (address != null && !address.isEmpty()) {
|
||||
result.put(r - dataStartRow, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉完全空白的导入行,避免空行导致导入失败
|
||||
*/
|
||||
private List<CreditUserImportParam> filterEmptyRows(List<CreditUserImportParam> rawList) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(this::isEmptyImportRow);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditUserImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode())
|
||||
&& isBlank(param.getRole())
|
||||
&& isBlank(param.getInfoType())
|
||||
&& isBlank(param.getAddress())
|
||||
&& isBlank(param.getProcurementName())
|
||||
&& isBlank(param.getWinningName())
|
||||
&& isBlank(param.getWinningPrice());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditUserImportParam转换为CreditUser实体
|
||||
*/
|
||||
private CreditUser convertImportParamToEntity(CreditUserImportParam param) {
|
||||
CreditUser entity = new CreditUser();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setType(param.getType());
|
||||
entity.setRole(param.getRole());
|
||||
entity.setInfoType(param.getInfoType());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setProcurementName(param.getProcurementName());
|
||||
entity.setWinningName(param.getWinningName());
|
||||
entity.setWinningPrice(param.getWinningPrice());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,632 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditXgxf;
|
||||
import com.gxwebsoft.credit.param.CreditXgxfImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditXgxfParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditXgxfService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 限制高消费控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:55
|
||||
*/
|
||||
@Tag(name = "限制高消费管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-xgxf")
|
||||
public class CreditXgxfController extends BaseController {
|
||||
@Resource
|
||||
private CreditXgxfService creditXgxfService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询限制高消费")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditXgxf>> page(CreditXgxfParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部限制高消费")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditXgxf>> list(CreditXgxfParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询限制高消费")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditXgxf> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加限制高消费")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditXgxf creditXgxf) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditXgxf.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditXgxfService.save(creditXgxf)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改限制高消费")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditXgxf creditXgxf) {
|
||||
if (creditXgxfService.updateById(creditXgxf)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除限制高消费")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditXgxfService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加限制高消费")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditXgxf> list) {
|
||||
if (creditXgxfService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改限制高消费")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditXgxf> batchParam) {
|
||||
if (batchParam.update(creditXgxfService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除限制高消费")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditXgxfService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditXgxfService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getDataType,
|
||||
CreditXgxf::getCompanyId,
|
||||
CreditXgxf::setCompanyId,
|
||||
CreditXgxf::getHasData,
|
||||
CreditXgxf::setHasData,
|
||||
CreditXgxf::getTenantId,
|
||||
CreditXgxf::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入限制高消费司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@Operation(summary = "批量导入限制高消费司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "限制高消费", 0);
|
||||
ExcelImportSupport.ImportResult<CreditXgxfImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditXgxfImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditXgxfImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 可能挂在“案号”等列的超链接中,或单独提供 url/网址/链接 列。
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditXgxf> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditXgxfImportParam param = list.get(i);
|
||||
try {
|
||||
CreditXgxf item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditXgxfService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditXgxf existing = creditXgxfService.lambdaQuery()
|
||||
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditXgxfService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKey(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getCaseNumber,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditXgxfService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditXgxf existing = creditXgxfService.lambdaQuery()
|
||||
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditXgxfService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.XGXF, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史限制高消费(仅解析“历史限制高消费”选项卡)
|
||||
* 规则:案号相同则覆盖更新(recommend++ 记录更新次数);案号不存在则插入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@Operation(summary = "批量导入历史限制高消费司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史限制高消费");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史限制高消费”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditXgxfImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditXgxfImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditXgxfImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
LinkedHashMap<String, CreditXgxf> latestByCaseNumber = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditXgxfImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditXgxf item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
latestByCaseNumber.put(item.getCaseNumber(), item);
|
||||
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (latestByCaseNumber.isEmpty()) {
|
||||
if (errorMessages.isEmpty()) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
return success("导入完成,成功0条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditXgxf> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (Map.Entry<String, CreditXgxf> entry : latestByCaseNumber.entrySet()) {
|
||||
String caseNumber = entry.getKey();
|
||||
CreditXgxf item = entry.getValue();
|
||||
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getRecommend,
|
||||
CreditXgxf::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditXgxfService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditXgxf existing = creditXgxfService.lambdaQuery()
|
||||
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditXgxf::getId, CreditXgxf::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditXgxfService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistChunkWithFallback(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getCaseNumber,
|
||||
CreditXgxf::getRecommend,
|
||||
CreditXgxf::setRecommend,
|
||||
null,
|
||||
mpBatchSize
|
||||
),
|
||||
(rowItem, rowNumber) -> {
|
||||
if (rowItem.getRecommend() == null) {
|
||||
rowItem.setRecommend(0);
|
||||
}
|
||||
boolean saved = creditXgxfService.save(rowItem);
|
||||
if (!saved) {
|
||||
CreditXgxf existing = creditXgxfService.lambdaQuery()
|
||||
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
|
||||
.select(CreditXgxf::getId, CreditXgxf::getRecommend)
|
||||
.one();
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
Integer old = existing.getRecommend();
|
||||
rowItem.setRecommend(old == null ? 1 : old + 1);
|
||||
if (creditXgxfService.updateById(rowItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
String prefix = rowNumber > 0 ? ("第" + rowNumber + "行:") : "";
|
||||
errorMessages.add(prefix + "保存失败");
|
||||
return false;
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.XGXF, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载限制高消费导入模板
|
||||
*/
|
||||
@Operation(summary = "下载限制高消费导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditXgxfImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditXgxfImportParam example = new CreditXgxfImportParam();
|
||||
example.setDataType("限制高消费");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setCourtName("示例法院");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("限制高消费导入模板", "限制高消费", CreditXgxfImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_xgxf_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditXgxfImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditXgxf convertImportParamToEntity(CreditXgxfImportParam param) {
|
||||
CreditXgxf entity = new CreditXgxf();
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setType(param.getType());
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffUser(param.getPlaintiffUser());
|
||||
entity.setDefendantUser(param.getDefendantUser());
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
|
||||
// 兼容不同模板字段:如果 *2 有值则以 *2 为准写入主字段
|
||||
entity.setInvolvedAmount(!ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount());
|
||||
entity.setOccurrenceTime(!ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime());
|
||||
entity.setCourtName(!ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName());
|
||||
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,609 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Excel 导入导出通用支持
|
||||
*/
|
||||
public class ExcelImportSupport {
|
||||
|
||||
public static class ImportResult<T> {
|
||||
private final List<T> data;
|
||||
private final int titleRows;
|
||||
private final int headRows;
|
||||
private final int sheetIndex;
|
||||
|
||||
public ImportResult(List<T> data, int titleRows, int headRows) {
|
||||
this(data, titleRows, headRows, 0);
|
||||
}
|
||||
|
||||
public ImportResult(List<T> data, int titleRows, int headRows, int sheetIndex) {
|
||||
this.data = data;
|
||||
this.titleRows = titleRows;
|
||||
this.headRows = headRows;
|
||||
this.sheetIndex = sheetIndex;
|
||||
}
|
||||
|
||||
public List<T> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getTitleRows() {
|
||||
return titleRows;
|
||||
}
|
||||
|
||||
public int getHeadRows() {
|
||||
return headRows;
|
||||
}
|
||||
|
||||
public int getSheetIndex() {
|
||||
return sheetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
||||
return read(file, clazz, emptyRowPredicate, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动尝试所有 sheet(从第 0 个开始),直到读取到非空数据。
|
||||
*/
|
||||
public static <T> ImportResult<T> readAnySheet(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
||||
ImportResult<T> result = read(file, clazz, emptyRowPredicate, 0);
|
||||
if (!CollectionUtils.isEmpty(result.getData())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int sheetCount = getSheetCount(file);
|
||||
for (int i = 1; i < sheetCount; i++) {
|
||||
ImportResult<T> sheetResult = read(file, clazz, emptyRowPredicate, i);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动尝试所有 sheet(从第 0 个开始),并在每个 sheet 内选择“得分”最高的表头配置。
|
||||
*/
|
||||
public static <T> ImportResult<T> readAnySheetBest(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, Predicate<T> scoreRowPredicate) throws Exception {
|
||||
ImportResult<T> result = readBest(file, clazz, emptyRowPredicate, scoreRowPredicate, 0);
|
||||
if (!CollectionUtils.isEmpty(result.getData())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int sheetCount = getSheetCount(file);
|
||||
for (int i = 1; i < sheetCount; i++) {
|
||||
ImportResult<T> sheetResult = readBest(file, clazz, emptyRowPredicate, scoreRowPredicate, i);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定 sheet 的 Excel。
|
||||
*
|
||||
* @param sheetIndex 目标 sheet 下标,从 0 开始。第二个选项卡传 1。
|
||||
*/
|
||||
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, int sheetIndex) throws Exception {
|
||||
List<T> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {2, 1}, {3, 1}, {0, 2}, {0, 3}, {0, 4}};
|
||||
Exception lastFailure = null;
|
||||
boolean anyImported = false;
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, config[0], config[1], sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
// Some source files can trigger easypoi/POI runtime exceptions for certain title/head row combinations.
|
||||
// Keep trying other configurations instead of failing the whole import.
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for upstream files with extra banner/title rows or wider multi-row headers.
|
||||
// Keep the default fast path above for common templates.
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
final int maxTitleRows = 10;
|
||||
final int maxHeadRows = 6;
|
||||
outer:
|
||||
for (int titleRows = 0; titleRows <= maxTitleRows; titleRows++) {
|
||||
for (int headRows = 1; headRows <= maxHeadRows; headRows++) {
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, titleRows, headRows, sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = titleRows;
|
||||
usedHeadRows = headRows;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list == null) {
|
||||
if (!anyImported && lastFailure != null) {
|
||||
throw lastFailure;
|
||||
}
|
||||
list = Collections.emptyList();
|
||||
}
|
||||
return new ImportResult<>(list, usedTitleRows, usedHeadRows, sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定 sheet 的 Excel,并从多组表头配置中挑选“得分”最高的结果。
|
||||
*/
|
||||
public static <T> ImportResult<T> readBest(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, Predicate<T> scoreRowPredicate, int sheetIndex) throws Exception {
|
||||
List<T> bestList = null;
|
||||
int bestTitleRows = 0;
|
||||
int bestHeadRows = 0;
|
||||
int bestScore = -1;
|
||||
int bestSize = -1;
|
||||
Exception lastFailure = null;
|
||||
boolean anyImported = false;
|
||||
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {2, 1}, {3, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 2}, {1, 3}, {1, 4}, {2, 2}, {2, 3}, {2, 4}, {3, 2}, {3, 3}, {3, 4}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
List<T> list;
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, config[0], config[1], sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
if (scoreRowPredicate != null) {
|
||||
for (T row : list) {
|
||||
if (scoreRowPredicate.test(row)) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = list.size();
|
||||
if (score > bestScore || (score == bestScore && size > bestSize)) {
|
||||
bestList = list;
|
||||
bestTitleRows = config[0];
|
||||
bestHeadRows = config[1];
|
||||
bestScore = score;
|
||||
bestSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback scan: broaden the search space for messy source files (extra title rows, multi-row headers).
|
||||
if (bestList == null) {
|
||||
final int maxTitleRows = 10;
|
||||
final int maxHeadRows = 6;
|
||||
for (int titleRows = 0; titleRows <= maxTitleRows; titleRows++) {
|
||||
for (int headRows = 1; headRows <= maxHeadRows; headRows++) {
|
||||
List<T> list;
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, titleRows, headRows, sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
if (scoreRowPredicate != null) {
|
||||
for (T row : list) {
|
||||
if (scoreRowPredicate.test(row)) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = list.size();
|
||||
if (score > bestScore || (score == bestScore && size > bestSize)) {
|
||||
bestList = list;
|
||||
bestTitleRows = titleRows;
|
||||
bestHeadRows = headRows;
|
||||
bestScore = score;
|
||||
bestSize = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestList != null) {
|
||||
return new ImportResult<>(bestList, bestTitleRows, bestHeadRows, sheetIndex);
|
||||
}
|
||||
|
||||
if (!anyImported && lastFailure != null) {
|
||||
throw lastFailure;
|
||||
}
|
||||
return read(file, clazz, emptyRowPredicate, sheetIndex);
|
||||
}
|
||||
|
||||
private static <T> List<T> importSheet(MultipartFile file, Class<T> clazz, int titleRows, int headRows, int sheetIndex) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(sheetIndex);
|
||||
importParams.setSheetNum(1);
|
||||
|
||||
// Easypoi matches headers by exact string. Some upstream files contain extra spaces/tabs/newlines in header cells
|
||||
// (e.g. "原告 / 上诉人" or "原告/上诉人\t"), which makes specific columns silently not mapped.
|
||||
// Normalize header cells first to make imports robust.
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() > sheetIndex) {
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet != null) {
|
||||
normalizeHeaderCells(sheet, titleRows, headRows);
|
||||
}
|
||||
}
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
workbook.write(bos);
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())) {
|
||||
return ExcelImportUtil.importExcel(bis, clazz, importParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void normalizeHeaderCells(Sheet sheet, int titleRows, int headRows) {
|
||||
if (sheet == null || headRows <= 0) {
|
||||
return;
|
||||
}
|
||||
int headerStart = Math.max(titleRows, 0);
|
||||
int headerEnd = headerStart + headRows - 1;
|
||||
for (int r = headerStart; r <= headerEnd; r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
short last = row.getLastCellNum();
|
||||
for (int c = 0; c < last; c++) {
|
||||
Cell cell = row.getCell(c);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String text = null;
|
||||
CellType type = cell.getCellType();
|
||||
if (type == CellType.STRING) {
|
||||
text = cell.getStringCellValue();
|
||||
} else if (type == CellType.FORMULA && cell.getCachedFormulaResultType() == CellType.STRING) {
|
||||
text = cell.getStringCellValue();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
String normalized = normalizeHeaderText(text);
|
||||
if (normalized != null && !normalized.equals(text)) {
|
||||
cell.setCellValue(normalized);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String normalizeHeaderText(String text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
// Remove common invisible whitespace characters, including full-width space.
|
||||
return text
|
||||
.replace("/", "/")
|
||||
.replace(" ", "")
|
||||
.replace("\t", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
.replace("\u00A0", "")
|
||||
.replace(" ", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
private static <T> List<T> filterEmptyRows(List<T> rawList, Predicate<T> emptyRowPredicate) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(emptyRowPredicate);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private static int getSheetCount(MultipartFile file) throws Exception {
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
return workbook.getNumberOfSheets();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 sheet 名称查找下标(优先精确匹配,其次前缀匹配/包含匹配)。
|
||||
*
|
||||
* @return 找不到返回 -1
|
||||
*/
|
||||
public static int findSheetIndex(MultipartFile file, String sheetName) throws Exception {
|
||||
if (file == null || sheetName == null || sheetName.trim().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
String target = normalizeSheetName(sheetName);
|
||||
if (target.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
int sheetCount = workbook.getNumberOfSheets();
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String candidate = normalizeSheetName(workbook.getSheetName(i));
|
||||
if (Objects.equals(candidate, target)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String candidate = normalizeSheetName(workbook.getSheetName(i));
|
||||
if (candidate.startsWith(target) || candidate.contains(target) || target.startsWith(candidate)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int findSheetIndex(MultipartFile file, String sheetName, int defaultIndex) throws Exception {
|
||||
int idx = findSheetIndex(file, sheetName);
|
||||
return idx >= 0 ? idx : defaultIndex;
|
||||
}
|
||||
|
||||
private static String normalizeSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return "";
|
||||
}
|
||||
return sheetName.replace(" ", "").replace(" ", "").trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定列(由表头名定位)的超链接,返回:单元格显示值 -> 超链接地址。
|
||||
*
|
||||
* <p>适用于:导入对象没有 url 字段,但 Excel 把链接放在某个“名称/案号”等列的超链接里。</p>
|
||||
*/
|
||||
public static Map<String, String> readHyperlinksByHeaderKey(MultipartFile file, int sheetIndex, int titleRows, int headRows, String headerName) throws Exception {
|
||||
if (file == null || headerName == null || headerName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() <= sheetIndex) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
int colIndex = findColumnIndexByHeader(sheet, titleRows, headRows, headerName);
|
||||
if (colIndex < 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell cell = row.getCell(colIndex);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
String address = extractHyperlinkAddress(cell);
|
||||
if (address == null || address.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = formatter.formatCellValue(cell);
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
result.put(key.trim(), address);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取两列(由表头名定位)的文本/超链接,返回:key列显示值 -> value列(优先超链接地址,其次单元格文本)。
|
||||
*
|
||||
* <p>适用于:Excel 把 url 放在单独一列(可能是纯文本,也可能是超链接)。</p>
|
||||
*/
|
||||
public static Map<String, String> readKeyValueByHeaders(MultipartFile file,
|
||||
int sheetIndex,
|
||||
int titleRows,
|
||||
int headRows,
|
||||
String keyHeaderName,
|
||||
String valueHeaderName) throws Exception {
|
||||
if (file == null
|
||||
|| keyHeaderName == null || keyHeaderName.trim().isEmpty()
|
||||
|| valueHeaderName == null || valueHeaderName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() <= sheetIndex) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
int keyCol = findColumnIndexByHeader(sheet, titleRows, headRows, keyHeaderName);
|
||||
int valCol = findColumnIndexByHeader(sheet, titleRows, headRows, valueHeaderName);
|
||||
if (keyCol < 0 || valCol < 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell keyCell = row.getCell(keyCol);
|
||||
if (keyCell == null) {
|
||||
continue;
|
||||
}
|
||||
String key = formatter.formatCellValue(keyCell);
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cell valCell = row.getCell(valCol);
|
||||
if (valCell == null) {
|
||||
continue;
|
||||
}
|
||||
String value = extractHyperlinkAddress(valCell);
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
value = formatter.formatCellValue(valCell);
|
||||
}
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
result.put(key.trim(), value.trim());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取“key列 -> url”的映射:
|
||||
* - 优先读取 key 列自身的超链接(url 常挂在名称/案号等列的超链接里)
|
||||
* - 如果源文件提供独立的 url/URL/网址/链接/链接地址 等列,则读取该列(支持文本或超链接)
|
||||
*/
|
||||
public static Map<String, String> readUrlByKey(MultipartFile file,
|
||||
int sheetIndex,
|
||||
int titleRows,
|
||||
int headRows,
|
||||
String keyHeaderName) throws Exception {
|
||||
if (file == null || keyHeaderName == null || keyHeaderName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
// 1) url 挂在 key 列超链接里(最常见)
|
||||
Map<String, String> fromKeyHyperlinks = readHyperlinksByHeaderKey(file, sheetIndex, titleRows, headRows, keyHeaderName);
|
||||
if (!fromKeyHyperlinks.isEmpty()) {
|
||||
result.putAll(fromKeyHyperlinks);
|
||||
}
|
||||
|
||||
// 2) url 作为单独一列(多种表头命名)
|
||||
String[] urlHeaders = new String[]{"url", "URL", "网址", "链接", "链接地址"};
|
||||
for (String urlHeader : urlHeaders) {
|
||||
Map<String, String> fromUrlCol = readKeyValueByHeaders(file, sheetIndex, titleRows, headRows, keyHeaderName, urlHeader);
|
||||
if (fromUrlCol.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : fromUrlCol.entrySet()) {
|
||||
// 不覆盖已从 key 超链接读取到的地址
|
||||
result.putIfAbsent(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int findColumnIndexByHeader(Sheet sheet, int titleRows, int headRows, String headerName) {
|
||||
int firstHeaderRow = Math.max(0, titleRows);
|
||||
int lastHeaderRow = Math.max(0, titleRows + headRows - 1);
|
||||
for (int r = firstHeaderRow; r <= lastHeaderRow; r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
|
||||
Cell cell = row.getCell(c);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
if (cell.getCellType() == CellType.STRING) {
|
||||
String value = cell.getStringCellValue();
|
||||
if (headerName.equals(value != null ? value.trim() : null)) {
|
||||
return c;
|
||||
}
|
||||
} else {
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
String value = formatter.formatCellValue(cell);
|
||||
if (headerName.equals(value != null ? value.trim() : null)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String extractHyperlinkAddress(Cell cell) {
|
||||
Hyperlink hyperlink = cell.getHyperlink();
|
||||
if (hyperlink != null && hyperlink.getAddress() != null && !hyperlink.getAddress().isEmpty()) {
|
||||
return hyperlink.getAddress();
|
||||
}
|
||||
if (cell.getCellType() == CellType.FORMULA) {
|
||||
String formula = cell.getCellFormula();
|
||||
if (formula != null && formula.toUpperCase().startsWith("HYPERLINK(")) {
|
||||
int firstQuote = formula.indexOf('\"');
|
||||
if (firstQuote >= 0) {
|
||||
int secondQuote = formula.indexOf('\"', firstQuote + 1);
|
||||
if (secondQuote > firstQuote) {
|
||||
return formula.substring(firstQuote + 1, secondQuote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> Workbook buildTemplate(String title, String sheetName, Class<T> clazz, List<T> examples) {
|
||||
ExportParams exportParams = new ExportParams(title, sheetName);
|
||||
return ExcelExportUtil.exportExcel(exportParams, clazz, examples);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 导入解析辅助工具
|
||||
*/
|
||||
public final class ImportHelper {
|
||||
|
||||
private ImportHelper() {
|
||||
}
|
||||
|
||||
public static boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
public static BigDecimal parseBigDecimal(String value, String fieldLabel) {
|
||||
if (isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(value.trim());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(fieldLabel + "格式不正确");
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalDate parseLocalDate(String value, String fieldLabel) {
|
||||
if (isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return LocalDate.parse(value.trim());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(fieldLabel + "日期格式应为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 行政许可
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditAdministrativeLicense对象", description = "行政许可")
|
||||
public class CreditAdministrativeLicense implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "决定文书/许可编号")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "决定文书/许可证名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "许可状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "许可类别")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "有效期自")
|
||||
private String validityStart;
|
||||
|
||||
@Schema(description = "有效期至")
|
||||
private String validityEnd;
|
||||
|
||||
@Schema(description = "许可机关")
|
||||
private String licensingAuthority;
|
||||
|
||||
@Schema(description = "许可内容")
|
||||
@TableField("License_content")
|
||||
private String licenseContent;
|
||||
|
||||
@Schema(description = "数据来源单位")
|
||||
private String dataSourceUnit;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 破产重整
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBankruptcy对象", description = "破产重整")
|
||||
public class CreditBankruptcy implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "案件类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "当事人")
|
||||
private String party;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "经办法院")
|
||||
private String court;
|
||||
|
||||
@Schema(description = "公开日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分支机构
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBranch对象", description = "分支机构")
|
||||
public class CreditBranch implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "分支机构名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "负责人")
|
||||
private String curator;
|
||||
|
||||
@Schema(description = "地区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishDate;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "主题企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 失信被执行人
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:46:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBreachOfTrust对象", description = "失信被执行人")
|
||||
public class CreditBreachOfTrust implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "失信被执行人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "疑似申请执行人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "涉案金额(元)")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "执行法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "立案日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String releaseDate;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user