Showing
32 changed files
with
2129 additions
and
9 deletions
This diff is collapsed. Click to expand it.
| 1 | +package com.apple.erp.controller; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.DealerAddReq; | ||
| 4 | +import com.apple.erp.dto.DealerQueryReq; | ||
| 5 | +import com.apple.erp.dto.DealerUpdateReq; | ||
| 6 | +import com.apple.erp.entity.DealerInfo; | ||
| 7 | +import com.apple.erp.service.DealerInfoService; | ||
| 8 | +import com.apple.erp.dto.response.ApiRes; | ||
| 9 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 10 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 11 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 12 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 13 | +import javax.validation.Valid; | ||
| 14 | +import lombok.RequiredArgsConstructor; | ||
| 15 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 16 | +import org.springframework.web.bind.annotation.*; | ||
| 17 | + | ||
| 18 | +import java.util.List; | ||
| 19 | + | ||
| 20 | +@Tag(name = "经销商管理", description = "经销商信息管理接口") | ||
| 21 | +@RestController | ||
| 22 | +@RequestMapping("/api/dealer") | ||
| 23 | +@RequiredArgsConstructor | ||
| 24 | +public class DealerInfoController { | ||
| 25 | + | ||
| 26 | + private final DealerInfoService dealerInfoService; | ||
| 27 | + | ||
| 28 | + @Operation(summary = "获取经销商列表", description = "分页查询经销商信息列表") | ||
| 29 | + @GetMapping("/list") | ||
| 30 | + @PreAuthorize("hasAuthority('dealer:list')") | ||
| 31 | + public ApiRes<IPage<DealerInfo>> getDealerList(@Valid DealerQueryReq queryReq) { | ||
| 32 | + IPage<DealerInfo> page = dealerInfoService.getDealerList(queryReq); | ||
| 33 | + return ApiRes.success(page); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + @Operation(summary = "获取经销商详情", description = "根据经销商ID获取经销商详细信息") | ||
| 37 | + @GetMapping("/{dealerId}") | ||
| 38 | + @PreAuthorize("hasAuthority('dealer:detail')") | ||
| 39 | + public ApiRes<DealerInfo> getDealerDetail(@Parameter(description = "经销商ID") @PathVariable Long dealerId) { | ||
| 40 | + DealerInfo dealerInfo = dealerInfoService.getDealerDetail(dealerId); | ||
| 41 | + if (dealerInfo != null) { | ||
| 42 | + return ApiRes.success(dealerInfo); | ||
| 43 | + } else { | ||
| 44 | + return ApiRes.error("经销商不存在"); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Operation(summary = "新增经销商", description = "新增一个经销商信息") | ||
| 49 | + @PostMapping | ||
| 50 | + @PreAuthorize("hasAuthority('dealer:add')") | ||
| 51 | + public ApiRes<String> addDealer(@Parameter(description = "经销商新增请求") @Valid @RequestBody DealerAddReq addReq) { | ||
| 52 | + try { | ||
| 53 | + boolean success = dealerInfoService.addDealer(addReq); | ||
| 54 | + return success ? ApiRes.success("经销商新增成功", null) : ApiRes.error("经销商新增失败"); | ||
| 55 | + } catch (IllegalArgumentException e) { | ||
| 56 | + return ApiRes.error(e.getMessage()); | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + @Operation(summary = "修改经销商", description = "修改一个经销商信息") | ||
| 61 | + @PostMapping("/update") | ||
| 62 | + @PreAuthorize("hasAuthority('dealer:update')") | ||
| 63 | + public ApiRes<String> updateDealer(@Parameter(description = "经销商修改请求") @Valid @RequestBody DealerUpdateReq updateReq) { | ||
| 64 | + try { | ||
| 65 | + boolean success = dealerInfoService.updateDealer(updateReq); | ||
| 66 | + return success ? ApiRes.success("经销商修改成功", null) : ApiRes.error("经销商修改失败"); | ||
| 67 | + } catch (IllegalArgumentException e) { | ||
| 68 | + return ApiRes.error(e.getMessage()); | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @Operation(summary = "删除经销商", description = "根据经销商ID删除经销商信息(软删除)") | ||
| 73 | + @DeleteMapping("/{dealerId}") | ||
| 74 | + @PreAuthorize("hasAuthority('dealer:delete')") | ||
| 75 | + public ApiRes<String> deleteDealer(@Parameter(description = "经销商ID") @PathVariable Long dealerId) { | ||
| 76 | + try { | ||
| 77 | + boolean success = dealerInfoService.deleteDealer(dealerId); | ||
| 78 | + return success ? ApiRes.success("经销商删除成功", null) : ApiRes.error("经销商删除失败"); | ||
| 79 | + } catch (IllegalArgumentException e) { | ||
| 80 | + return ApiRes.error(e.getMessage()); | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @Operation(summary = "批量删除经销商", description = "根据经销商ID列表批量删除经销商信息(软删除)") | ||
| 85 | + @DeleteMapping("/batch") | ||
| 86 | + @PreAuthorize("hasAuthority('dealer:batchDelete')") | ||
| 87 | + public ApiRes<String> batchDeleteDealers(@Parameter(description = "经销商ID列表") @RequestBody List<Long> dealerIds) { | ||
| 88 | + boolean success = dealerInfoService.batchDeleteDealers(dealerIds); | ||
| 89 | + return success ? ApiRes.success("经销商批量删除成功", null) : ApiRes.error("经销商批量删除失败"); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @Operation(summary = "修改经销商合作状态", description = "修改经销商的合作状态") | ||
| 93 | + @PostMapping("/{dealerId}/cooperateStatus/{cooperateStatus}") | ||
| 94 | + @PreAuthorize("hasAuthority('dealer:updateStatus')") | ||
| 95 | + public ApiRes<String> updateDealerCooperateStatus( | ||
| 96 | + @Parameter(description = "经销商ID") @PathVariable Long dealerId, | ||
| 97 | + @Parameter(description = "合作状态(1-正常合作/2-暂停合作/3-终止合作)") @PathVariable Integer cooperateStatus) { | ||
| 98 | + try { | ||
| 99 | + boolean success = dealerInfoService.updateDealerCooperateStatus(dealerId, cooperateStatus); | ||
| 100 | + return success ? ApiRes.success("经销商合作状态修改成功", null) : ApiRes.error("经销商合作状态修改失败"); | ||
| 101 | + } catch (IllegalArgumentException e) { | ||
| 102 | + return ApiRes.error(e.getMessage()); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @Operation(summary = "修改经销商资质审核状态", description = "修改经销商的资质审核状态") | ||
| 107 | + @PostMapping("/{dealerId}/auditStatus") | ||
| 108 | + @PreAuthorize("hasAuthority('dealer:audit')") | ||
| 109 | + public ApiRes<String> updateDealerAuditStatus( | ||
| 110 | + @Parameter(description = "经销商ID") @PathVariable Long dealerId, | ||
| 111 | + @Parameter(description = "资质审核状态(1-待审核/2-审核通过/3-审核不通过)") @RequestParam Integer qualificationAuditStatus, | ||
| 112 | + @Parameter(description = "审核意见") @RequestParam(required = false) String auditOpinion) { | ||
| 113 | + try { | ||
| 114 | + boolean success = dealerInfoService.updateDealerAuditStatus(dealerId, qualificationAuditStatus, auditOpinion); | ||
| 115 | + return success ? ApiRes.success("经销商资质审核状态修改成功", null) : ApiRes.error("经销商资质审核状态修改失败"); | ||
| 116 | + } catch (IllegalArgumentException e) { | ||
| 117 | + return ApiRes.error(e.getMessage()); | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | +} |
| 1 | +package com.apple.erp.controller; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.ProductAddReq; | ||
| 4 | +import com.apple.erp.dto.ProductQueryReq; | ||
| 5 | +import com.apple.erp.dto.ProductUpdateReq; | ||
| 6 | +import com.apple.erp.entity.ProductInfo; | ||
| 7 | +import com.apple.erp.service.ProductInfoService; | ||
| 8 | +import com.apple.erp.dto.response.ApiRes; | ||
| 9 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 10 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 11 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 12 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 13 | +import lombok.RequiredArgsConstructor; | ||
| 14 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | +import org.springframework.web.bind.annotation.*; | ||
| 17 | + | ||
| 18 | +import javax.validation.Valid; | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * 产品信息管理控制器 | ||
| 23 | + * | ||
| 24 | + * @author Apple ERP Team | ||
| 25 | + * @since 2025-01-27 | ||
| 26 | + */ | ||
| 27 | +@Tag(name = "产品信息管理", description = "产品信息的增删改查等操作") | ||
| 28 | +@RestController | ||
| 29 | +@RequestMapping("/api/product") | ||
| 30 | +@RequiredArgsConstructor | ||
| 31 | +@Validated | ||
| 32 | +public class ProductInfoController { | ||
| 33 | + | ||
| 34 | + private final ProductInfoService productInfoService; | ||
| 35 | + | ||
| 36 | + @Operation(summary = "分页查询产品列表", description = "根据条件分页查询产品列表") | ||
| 37 | + @GetMapping("/list") | ||
| 38 | + @PreAuthorize("hasAuthority('product:list')") | ||
| 39 | + public ApiRes<IPage<ProductInfo>> getProductList(@Valid ProductQueryReq queryReq) { | ||
| 40 | + try { | ||
| 41 | + IPage<ProductInfo> result = productInfoService.getProductPage(queryReq); | ||
| 42 | + return ApiRes.success(result); | ||
| 43 | + } catch (Exception e) { | ||
| 44 | + return ApiRes.error("查询产品列表失败:" + e.getMessage()); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Operation(summary = "获取产品详情", description = "根据产品ID获取产品详情") | ||
| 49 | + @GetMapping("/{productId}") | ||
| 50 | + @PreAuthorize("hasAuthority('product:detail')") | ||
| 51 | + public ApiRes<ProductInfo> getProductDetail( | ||
| 52 | + @Parameter(description = "产品ID", required = true) | ||
| 53 | + @PathVariable Long productId) { | ||
| 54 | + try { | ||
| 55 | + ProductInfo productInfo = productInfoService.getProductById(productId); | ||
| 56 | + if (productInfo == null) { | ||
| 57 | + return ApiRes.error("产品不存在"); | ||
| 58 | + } | ||
| 59 | + return ApiRes.success(productInfo); | ||
| 60 | + } catch (Exception e) { | ||
| 61 | + return ApiRes.error("获取产品详情失败:" + e.getMessage()); | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Operation(summary = "新增产品", description = "新增产品信息") | ||
| 66 | + @PostMapping | ||
| 67 | + @PreAuthorize("hasAuthority('product:add')") | ||
| 68 | + public ApiRes<String> addProduct(@Valid @RequestBody ProductAddReq addReq) { | ||
| 69 | + try { | ||
| 70 | + boolean success = productInfoService.addProduct(addReq); | ||
| 71 | + if (success) { | ||
| 72 | + return ApiRes.success("新增产品成功"); | ||
| 73 | + } else { | ||
| 74 | + return ApiRes.error("新增产品失败"); | ||
| 75 | + } | ||
| 76 | + } catch (RuntimeException e) { | ||
| 77 | + return ApiRes.error(e.getMessage()); | ||
| 78 | + } catch (Exception e) { | ||
| 79 | + return ApiRes.error("新增产品失败:" + e.getMessage()); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @Operation(summary = "修改产品", description = "修改产品信息") | ||
| 84 | + @PostMapping("/update") | ||
| 85 | + @PreAuthorize("hasAuthority('product:edit')") | ||
| 86 | + public ApiRes<String> updateProduct(@Valid @RequestBody ProductUpdateReq updateReq) { | ||
| 87 | + try { | ||
| 88 | + boolean success = productInfoService.updateProduct(updateReq); | ||
| 89 | + if (success) { | ||
| 90 | + return ApiRes.success("修改产品成功"); | ||
| 91 | + } else { | ||
| 92 | + return ApiRes.error("修改产品失败"); | ||
| 93 | + } | ||
| 94 | + } catch (RuntimeException e) { | ||
| 95 | + return ApiRes.error(e.getMessage()); | ||
| 96 | + } catch (Exception e) { | ||
| 97 | + return ApiRes.error("修改产品失败:" + e.getMessage()); | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @Operation(summary = "删除产品", description = "根据产品ID删除产品") | ||
| 102 | + @DeleteMapping("/{productId}") | ||
| 103 | + @PreAuthorize("hasAuthority('product:delete')") | ||
| 104 | + public ApiRes<String> deleteProduct( | ||
| 105 | + @Parameter(description = "产品ID", required = true) | ||
| 106 | + @PathVariable Long productId) { | ||
| 107 | + try { | ||
| 108 | + boolean success = productInfoService.deleteProduct(productId); | ||
| 109 | + if (success) { | ||
| 110 | + return ApiRes.success("删除产品成功"); | ||
| 111 | + } else { | ||
| 112 | + return ApiRes.error("删除产品失败"); | ||
| 113 | + } | ||
| 114 | + } catch (Exception e) { | ||
| 115 | + return ApiRes.error("删除产品失败:" + e.getMessage()); | ||
| 116 | + } | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + @Operation(summary = "批量删除产品", description = "批量删除产品") | ||
| 120 | + @PostMapping("/batchDelete") | ||
| 121 | + @PreAuthorize("hasAuthority('product:delete')") | ||
| 122 | + public ApiRes<String> batchDeleteProducts(@RequestBody List<Long> productIds) { | ||
| 123 | + try { | ||
| 124 | + if (productIds == null || productIds.isEmpty()) { | ||
| 125 | + return ApiRes.error("请选择要删除的产品"); | ||
| 126 | + } | ||
| 127 | + boolean success = productInfoService.batchDeleteProducts(productIds); | ||
| 128 | + if (success) { | ||
| 129 | + return ApiRes.success("批量删除产品成功"); | ||
| 130 | + } else { | ||
| 131 | + return ApiRes.error("批量删除产品失败"); | ||
| 132 | + } | ||
| 133 | + } catch (Exception e) { | ||
| 134 | + return ApiRes.error("批量删除产品失败:" + e.getMessage()); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Operation(summary = "修改产品状态", description = "修改产品销售状态") | ||
| 139 | + @PostMapping("/{productId}/status") | ||
| 140 | + @PreAuthorize("hasAuthority('product:edit')") | ||
| 141 | + public ApiRes<String> updateProductStatus( | ||
| 142 | + @Parameter(description = "产品ID", required = true) | ||
| 143 | + @PathVariable Long productId, | ||
| 144 | + @Parameter(description = "销售状态", required = true) | ||
| 145 | + @RequestParam Integer saleStatus) { | ||
| 146 | + try { | ||
| 147 | + boolean success = productInfoService.updateProductStatus(productId, saleStatus); | ||
| 148 | + if (success) { | ||
| 149 | + return ApiRes.success("修改产品状态成功"); | ||
| 150 | + } else { | ||
| 151 | + return ApiRes.error("修改产品状态失败"); | ||
| 152 | + } | ||
| 153 | + } catch (Exception e) { | ||
| 154 | + return ApiRes.error("修改产品状态失败:" + e.getMessage()); | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + @Operation(summary = "修改返利标识", description = "修改产品返利标识") | ||
| 159 | + @PostMapping("/{productId}/rebate") | ||
| 160 | + @PreAuthorize("hasAuthority('product:edit')") | ||
| 161 | + public ApiRes<String> updateRebateFlag( | ||
| 162 | + @Parameter(description = "产品ID", required = true) | ||
| 163 | + @PathVariable Long productId, | ||
| 164 | + @Parameter(description = "返利标识", required = true) | ||
| 165 | + @RequestParam Integer rebateFlag) { | ||
| 166 | + try { | ||
| 167 | + boolean success = productInfoService.updateRebateFlag(productId, rebateFlag); | ||
| 168 | + if (success) { | ||
| 169 | + return ApiRes.success("修改返利标识成功"); | ||
| 170 | + } else { | ||
| 171 | + return ApiRes.error("修改返利标识失败"); | ||
| 172 | + } | ||
| 173 | + } catch (Exception e) { | ||
| 174 | + return ApiRes.error("修改返利标识失败:" + e.getMessage()); | ||
| 175 | + } | ||
| 176 | + } | ||
| 177 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import javax.validation.constraints.NotBlank; | ||
| 5 | +import javax.validation.constraints.NotNull; | ||
| 6 | +import javax.validation.constraints.Pattern; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDate; | ||
| 11 | + | ||
| 12 | +@Data | ||
| 13 | +@Schema(description = "经销商新增请求DTO") | ||
| 14 | +public class DealerAddReq { | ||
| 15 | + | ||
| 16 | + @NotBlank(message = "经销商编码不能为空") | ||
| 17 | + @Pattern(regexp = "^[A-Z0-9]{6,20}$", message = "经销商编码格式不正确,应为6-20位大写字母和数字") | ||
| 18 | + @Schema(description = "经销商编码", required = true) | ||
| 19 | + private String dealerCode; | ||
| 20 | + | ||
| 21 | + @NotBlank(message = "经销商名称不能为空") | ||
| 22 | + @Schema(description = "经销商名称", required = true) | ||
| 23 | + private String dealerName; | ||
| 24 | + | ||
| 25 | + @NotBlank(message = "统一社会信用代码不能为空") | ||
| 26 | + @Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}[0-9]{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "统一社会信用代码格式不正确") | ||
| 27 | + @Schema(description = "统一社会信用代码", required = true) | ||
| 28 | + private String creditCode; | ||
| 29 | + | ||
| 30 | + @NotNull(message = "经销商等级不能为空") | ||
| 31 | + @Schema(description = "经销商等级(1-一级经销商/2-二级经销商)", required = true) | ||
| 32 | + private Integer dealerLevel; | ||
| 33 | + | ||
| 34 | + @NotBlank(message = "所在区域不能为空") | ||
| 35 | + @Schema(description = "所在区域", required = true) | ||
| 36 | + private String region; | ||
| 37 | + | ||
| 38 | + @Schema(description = "联系人") | ||
| 39 | + private String contactPerson; | ||
| 40 | + | ||
| 41 | + @Schema(description = "联系电话") | ||
| 42 | + private String contactPhone; | ||
| 43 | + | ||
| 44 | + @NotNull(message = "合作起始日期不能为空") | ||
| 45 | + @Schema(description = "合作起始日期", required = true) | ||
| 46 | + @DateTimeFormat(pattern = "yyyy-MM-dd") | ||
| 47 | + private LocalDate cooperateStartDate; | ||
| 48 | + | ||
| 49 | + @Schema(description = "合作状态(1-正常合作/2-暂停合作/3-终止合作)") | ||
| 50 | + private Integer cooperateStatus = 1; | ||
| 51 | + | ||
| 52 | + @Schema(description = "营业执照URL") | ||
| 53 | + private String businessLicenseUrl; | ||
| 54 | + | ||
| 55 | + @Schema(description = "合作协议URL") | ||
| 56 | + private String cooperationAgreementUrl; | ||
| 57 | + | ||
| 58 | + @Schema(description = "资质审核状态(1-待审核/2-审核通过/3-审核不通过)") | ||
| 59 | + private Integer qualificationAuditStatus = 1; | ||
| 60 | + | ||
| 61 | + @Schema(description = "审核意见") | ||
| 62 | + private String auditOpinion; | ||
| 63 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 6 | + | ||
| 7 | +import java.time.LocalDate; | ||
| 8 | + | ||
| 9 | +@Data | ||
| 10 | +@Schema(description = "经销商查询请求DTO") | ||
| 11 | +public class DealerQueryReq { | ||
| 12 | + | ||
| 13 | + @Schema(description = "经销商编码") | ||
| 14 | + private String dealerCode; | ||
| 15 | + | ||
| 16 | + @Schema(description = "经销商名称") | ||
| 17 | + private String dealerName; | ||
| 18 | + | ||
| 19 | + @Schema(description = "统一社会信用代码") | ||
| 20 | + private String creditCode; | ||
| 21 | + | ||
| 22 | + @Schema(description = "经销商等级(1-一级经销商/2-二级经销商)") | ||
| 23 | + private Integer dealerLevel; | ||
| 24 | + | ||
| 25 | + @Schema(description = "所在区域") | ||
| 26 | + private String region; | ||
| 27 | + | ||
| 28 | + @Schema(description = "联系人") | ||
| 29 | + private String contactPerson; | ||
| 30 | + | ||
| 31 | + @Schema(description = "联系电话") | ||
| 32 | + private String contactPhone; | ||
| 33 | + | ||
| 34 | + @Schema(description = "合作状态(1-正常合作/2-暂停合作/3-终止合作)") | ||
| 35 | + private Integer cooperateStatus; | ||
| 36 | + | ||
| 37 | + @Schema(description = "资质审核状态(1-待审核/2-审核通过/3-审核不通过)") | ||
| 38 | + private Integer qualificationAuditStatus; | ||
| 39 | + | ||
| 40 | + @Schema(description = "合作起始日期开始") | ||
| 41 | + @DateTimeFormat(pattern = "yyyy-MM-dd") | ||
| 42 | + private LocalDate cooperateStartDateStart; | ||
| 43 | + | ||
| 44 | + @Schema(description = "合作起始日期结束") | ||
| 45 | + @DateTimeFormat(pattern = "yyyy-MM-dd") | ||
| 46 | + private LocalDate cooperateStartDateEnd; | ||
| 47 | + | ||
| 48 | + @Schema(description = "当前页码") | ||
| 49 | + private Long pageNum = 1L; | ||
| 50 | + | ||
| 51 | + @Schema(description = "每页大小") | ||
| 52 | + private Long pageSize = 10L; | ||
| 53 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import javax.validation.constraints.NotBlank; | ||
| 5 | +import javax.validation.constraints.NotNull; | ||
| 6 | +import javax.validation.constraints.Pattern; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDate; | ||
| 11 | + | ||
| 12 | +@Data | ||
| 13 | +@Schema(description = "经销商修改请求DTO") | ||
| 14 | +public class DealerUpdateReq { | ||
| 15 | + | ||
| 16 | + @NotNull(message = "经销商ID不能为空") | ||
| 17 | + @Schema(description = "经销商ID", required = true) | ||
| 18 | + private Long dealerId; | ||
| 19 | + | ||
| 20 | + @NotBlank(message = "经销商编码不能为空") | ||
| 21 | + @Pattern(regexp = "^[A-Z0-9]{6,20}$", message = "经销商编码格式不正确,应为6-20位大写字母和数字") | ||
| 22 | + @Schema(description = "经销商编码", required = true) | ||
| 23 | + private String dealerCode; | ||
| 24 | + | ||
| 25 | + @NotBlank(message = "经销商名称不能为空") | ||
| 26 | + @Schema(description = "经销商名称", required = true) | ||
| 27 | + private String dealerName; | ||
| 28 | + | ||
| 29 | + @NotBlank(message = "统一社会信用代码不能为空") | ||
| 30 | + @Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}[0-9]{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "统一社会信用代码格式不正确") | ||
| 31 | + @Schema(description = "统一社会信用代码", required = true) | ||
| 32 | + private String creditCode; | ||
| 33 | + | ||
| 34 | + @NotNull(message = "经销商等级不能为空") | ||
| 35 | + @Schema(description = "经销商等级(1-一级经销商/2-二级经销商)", required = true) | ||
| 36 | + private Integer dealerLevel; | ||
| 37 | + | ||
| 38 | + @NotBlank(message = "所在区域不能为空") | ||
| 39 | + @Schema(description = "所在区域", required = true) | ||
| 40 | + private String region; | ||
| 41 | + | ||
| 42 | + @Schema(description = "联系人") | ||
| 43 | + private String contactPerson; | ||
| 44 | + | ||
| 45 | + @Schema(description = "联系电话") | ||
| 46 | + private String contactPhone; | ||
| 47 | + | ||
| 48 | + @NotNull(message = "合作起始日期不能为空") | ||
| 49 | + @Schema(description = "合作起始日期", required = true) | ||
| 50 | + @DateTimeFormat(pattern = "yyyy-MM-dd") | ||
| 51 | + private LocalDate cooperateStartDate; | ||
| 52 | + | ||
| 53 | + @Schema(description = "合作状态(1-正常合作/2-暂停合作/3-终止合作)") | ||
| 54 | + private Integer cooperateStatus; | ||
| 55 | + | ||
| 56 | + @Schema(description = "营业执照URL") | ||
| 57 | + private String businessLicenseUrl; | ||
| 58 | + | ||
| 59 | + @Schema(description = "合作协议URL") | ||
| 60 | + private String cooperationAgreementUrl; | ||
| 61 | + | ||
| 62 | + @Schema(description = "资质审核状态(1-待审核/2-审核通过/3-审核不通过)") | ||
| 63 | + private Integer qualificationAuditStatus; | ||
| 64 | + | ||
| 65 | + @Schema(description = "审核意见") | ||
| 66 | + private String auditOpinion; | ||
| 67 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotBlank; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | +import java.math.BigDecimal; | ||
| 10 | +import java.time.LocalDate; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 产品新增请求DTO | ||
| 14 | + * | ||
| 15 | + * @author Apple ERP Team | ||
| 16 | + * @since 2025-01-27 | ||
| 17 | + */ | ||
| 18 | +@Data | ||
| 19 | +@Schema(description = "产品新增请求") | ||
| 20 | +public class ProductAddReq { | ||
| 21 | + | ||
| 22 | + @Schema(description = "产品编码", required = true) | ||
| 23 | + @NotBlank(message = "产品编码不能为空") | ||
| 24 | + private String productCode; | ||
| 25 | + | ||
| 26 | + @Schema(description = "产品名称", required = true) | ||
| 27 | + @NotBlank(message = "产品名称不能为空") | ||
| 28 | + private String productName; | ||
| 29 | + | ||
| 30 | + @Schema(description = "产品型号", required = true) | ||
| 31 | + @NotBlank(message = "产品型号不能为空") | ||
| 32 | + private String productModel; | ||
| 33 | + | ||
| 34 | + @Schema(description = "产品类别", required = true) | ||
| 35 | + @NotBlank(message = "产品类别不能为空") | ||
| 36 | + private String productType; | ||
| 37 | + | ||
| 38 | + @Schema(description = "存储容量") | ||
| 39 | + private String storageCapacity; | ||
| 40 | + | ||
| 41 | + @Schema(description = "产品颜色") | ||
| 42 | + private String color; | ||
| 43 | + | ||
| 44 | + @Schema(description = "产品图片URL") | ||
| 45 | + private String productImgUrl; | ||
| 46 | + | ||
| 47 | + @Schema(description = "官方指导价") | ||
| 48 | + private BigDecimal officialPrice; | ||
| 49 | + | ||
| 50 | + @Schema(description = "销售状态(0-下架/1-在售/2-预售)", required = true) | ||
| 51 | + @NotNull(message = "销售状态不能为空") | ||
| 52 | + private Integer saleStatus; | ||
| 53 | + | ||
| 54 | + @Schema(description = "是否参与返利(0-否/1-是)", required = true) | ||
| 55 | + @NotNull(message = "返利标识不能为空") | ||
| 56 | + private Integer rebateFlag; | ||
| 57 | + | ||
| 58 | + @Schema(description = "销售起始日期") | ||
| 59 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 60 | + private LocalDate saleStartDate; | ||
| 61 | + | ||
| 62 | + @Schema(description = "销售终止日期") | ||
| 63 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 64 | + private LocalDate saleEndDate; | ||
| 65 | + | ||
| 66 | + @Schema(description = "产品备注") | ||
| 67 | + private String remark; | ||
| 68 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import java.math.BigDecimal; | ||
| 8 | +import java.time.LocalDate; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 产品查询请求DTO | ||
| 12 | + * | ||
| 13 | + * @author Apple ERP Team | ||
| 14 | + * @since 2025-01-27 | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +@Schema(description = "产品查询请求") | ||
| 18 | +public class ProductQueryReq { | ||
| 19 | + | ||
| 20 | + @Schema(description = "产品编码") | ||
| 21 | + private String productCode; | ||
| 22 | + | ||
| 23 | + @Schema(description = "产品名称") | ||
| 24 | + private String productName; | ||
| 25 | + | ||
| 26 | + @Schema(description = "产品型号") | ||
| 27 | + private String productModel; | ||
| 28 | + | ||
| 29 | + @Schema(description = "产品类别") | ||
| 30 | + private String productType; | ||
| 31 | + | ||
| 32 | + @Schema(description = "存储容量") | ||
| 33 | + private String storageCapacity; | ||
| 34 | + | ||
| 35 | + @Schema(description = "产品颜色") | ||
| 36 | + private String color; | ||
| 37 | + | ||
| 38 | + @Schema(description = "销售状态(0-下架/1-在售/2-预售)") | ||
| 39 | + private Integer saleStatus; | ||
| 40 | + | ||
| 41 | + @Schema(description = "是否参与返利(0-否/1-是)") | ||
| 42 | + private Integer rebateFlag; | ||
| 43 | + | ||
| 44 | + @Schema(description = "最低价格") | ||
| 45 | + private BigDecimal minPrice; | ||
| 46 | + | ||
| 47 | + @Schema(description = "最高价格") | ||
| 48 | + private BigDecimal maxPrice; | ||
| 49 | + | ||
| 50 | + @Schema(description = "销售起始日期开始") | ||
| 51 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 52 | + private LocalDate saleStartDateBegin; | ||
| 53 | + | ||
| 54 | + @Schema(description = "销售起始日期结束") | ||
| 55 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 56 | + private LocalDate saleStartDateEnd; | ||
| 57 | + | ||
| 58 | + @Schema(description = "销售终止日期开始") | ||
| 59 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 60 | + private LocalDate saleEndDateBegin; | ||
| 61 | + | ||
| 62 | + @Schema(description = "销售终止日期结束") | ||
| 63 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 64 | + private LocalDate saleEndDateEnd; | ||
| 65 | + | ||
| 66 | + @Schema(description = "页码", example = "1") | ||
| 67 | + private Integer pageNum = 1; | ||
| 68 | + | ||
| 69 | + @Schema(description = "每页大小", example = "10") | ||
| 70 | + private Integer pageSize = 10; | ||
| 71 | +} |
| 1 | +package com.apple.erp.dto; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotBlank; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | +import java.math.BigDecimal; | ||
| 10 | +import java.time.LocalDate; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 产品修改请求DTO | ||
| 14 | + * | ||
| 15 | + * @author Apple ERP Team | ||
| 16 | + * @since 2025-01-27 | ||
| 17 | + */ | ||
| 18 | +@Data | ||
| 19 | +@Schema(description = "产品修改请求") | ||
| 20 | +public class ProductUpdateReq { | ||
| 21 | + | ||
| 22 | + @Schema(description = "产品ID", required = true) | ||
| 23 | + @NotNull(message = "产品ID不能为空") | ||
| 24 | + private Long productId; | ||
| 25 | + | ||
| 26 | + @Schema(description = "产品编码", required = true) | ||
| 27 | + @NotBlank(message = "产品编码不能为空") | ||
| 28 | + private String productCode; | ||
| 29 | + | ||
| 30 | + @Schema(description = "产品名称", required = true) | ||
| 31 | + @NotBlank(message = "产品名称不能为空") | ||
| 32 | + private String productName; | ||
| 33 | + | ||
| 34 | + @Schema(description = "产品型号", required = true) | ||
| 35 | + @NotBlank(message = "产品型号不能为空") | ||
| 36 | + private String productModel; | ||
| 37 | + | ||
| 38 | + @Schema(description = "产品类别", required = true) | ||
| 39 | + @NotBlank(message = "产品类别不能为空") | ||
| 40 | + private String productType; | ||
| 41 | + | ||
| 42 | + @Schema(description = "存储容量") | ||
| 43 | + private String storageCapacity; | ||
| 44 | + | ||
| 45 | + @Schema(description = "产品颜色") | ||
| 46 | + private String color; | ||
| 47 | + | ||
| 48 | + @Schema(description = "产品图片URL") | ||
| 49 | + private String productImgUrl; | ||
| 50 | + | ||
| 51 | + @Schema(description = "官方指导价") | ||
| 52 | + private BigDecimal officialPrice; | ||
| 53 | + | ||
| 54 | + @Schema(description = "销售状态(0-下架/1-在售/2-预售)", required = true) | ||
| 55 | + @NotNull(message = "销售状态不能为空") | ||
| 56 | + private Integer saleStatus; | ||
| 57 | + | ||
| 58 | + @Schema(description = "是否参与返利(0-否/1-是)", required = true) | ||
| 59 | + @NotNull(message = "返利标识不能为空") | ||
| 60 | + private Integer rebateFlag; | ||
| 61 | + | ||
| 62 | + @Schema(description = "销售起始日期") | ||
| 63 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 64 | + private LocalDate saleStartDate; | ||
| 65 | + | ||
| 66 | + @Schema(description = "销售终止日期") | ||
| 67 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 68 | + private LocalDate saleEndDate; | ||
| 69 | + | ||
| 70 | + @Schema(description = "产品备注") | ||
| 71 | + private String remark; | ||
| 72 | +} |
| 1 | +package com.apple.erp.entity; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.annotation.IdType; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +import java.math.BigDecimal; | ||
| 10 | +import java.time.LocalDate; | ||
| 11 | +import java.time.LocalDateTime; | ||
| 12 | + | ||
| 13 | +@Data | ||
| 14 | +@TableName("t_dealer_info") | ||
| 15 | +@Schema(description = "经销商信息实体") | ||
| 16 | +public class DealerInfo { | ||
| 17 | + | ||
| 18 | + @TableId(type = IdType.AUTO) | ||
| 19 | + @Schema(description = "经销商ID") | ||
| 20 | + private Long dealerId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "经销商编码") | ||
| 23 | + private String dealerCode; | ||
| 24 | + | ||
| 25 | + @Schema(description = "经销商名称") | ||
| 26 | + private String dealerName; | ||
| 27 | + | ||
| 28 | + @Schema(description = "统一社会信用代码") | ||
| 29 | + private String creditCode; | ||
| 30 | + | ||
| 31 | + @Schema(description = "经销商等级(1-一级经销商/2-二级经销商)") | ||
| 32 | + private Integer dealerLevel; | ||
| 33 | + | ||
| 34 | + @Schema(description = "所在区域") | ||
| 35 | + private String region; | ||
| 36 | + | ||
| 37 | + @Schema(description = "联系人") | ||
| 38 | + private String contactPerson; | ||
| 39 | + | ||
| 40 | + @Schema(description = "联系电话") | ||
| 41 | + private String contactPhone; | ||
| 42 | + | ||
| 43 | + @Schema(description = "合作起始日期") | ||
| 44 | + private LocalDate cooperateStartDate; | ||
| 45 | + | ||
| 46 | + @Schema(description = "合作状态(1-正常合作/2-暂停合作/3-终止合作)") | ||
| 47 | + private Integer cooperateStatus; | ||
| 48 | + | ||
| 49 | + @Schema(description = "营业执照URL") | ||
| 50 | + private String businessLicenseUrl; | ||
| 51 | + | ||
| 52 | + @Schema(description = "合作协议URL") | ||
| 53 | + private String cooperationAgreementUrl; | ||
| 54 | + | ||
| 55 | + @Schema(description = "资质审核状态(1-待审核/2-审核通过/3-审核不通过)") | ||
| 56 | + private Integer qualificationAuditStatus; | ||
| 57 | + | ||
| 58 | + @Schema(description = "审核意见") | ||
| 59 | + private String auditOpinion; | ||
| 60 | + | ||
| 61 | + @Schema(description = "累计应返金额") | ||
| 62 | + private BigDecimal totalRebateAmount; | ||
| 63 | + | ||
| 64 | + @Schema(description = "累计已返金额") | ||
| 65 | + private BigDecimal usedRebateAmount; | ||
| 66 | + | ||
| 67 | + @Schema(description = "待返利总金额") | ||
| 68 | + private BigDecimal pendingRebateAmount; | ||
| 69 | + | ||
| 70 | + @Schema(description = "最后返利更新时间") | ||
| 71 | + private LocalDateTime lastRebateUpdateTime; | ||
| 72 | + | ||
| 73 | + @Schema(description = "创建者") | ||
| 74 | + private String createBy; | ||
| 75 | + | ||
| 76 | + @Schema(description = "创建时间") | ||
| 77 | + private LocalDateTime createTime; | ||
| 78 | + | ||
| 79 | + @Schema(description = "更新者") | ||
| 80 | + private String updateBy; | ||
| 81 | + | ||
| 82 | + @Schema(description = "更新时间") | ||
| 83 | + private LocalDateTime updateTime; | ||
| 84 | + | ||
| 85 | + @Schema(description = "删除标志(0代表存在 2代表删除)") | ||
| 86 | + private String delFlag; | ||
| 87 | +} |
| 1 | +package com.apple.erp.entity; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.annotation.IdType; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | + | ||
| 10 | +import java.io.Serializable; | ||
| 11 | +import java.math.BigDecimal; | ||
| 12 | +import java.time.LocalDate; | ||
| 13 | +import java.time.LocalDateTime; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 产品信息表 | ||
| 17 | + * | ||
| 18 | + * @author Apple ERP Team | ||
| 19 | + * @since 2025-01-27 | ||
| 20 | + */ | ||
| 21 | +@Data | ||
| 22 | +@EqualsAndHashCode(callSuper = false) | ||
| 23 | +@TableName("t_product_info") | ||
| 24 | +public class ProductInfo implements Serializable { | ||
| 25 | + | ||
| 26 | + private static final long serialVersionUID = 1L; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 产品ID | ||
| 30 | + */ | ||
| 31 | + @TableId(value = "product_id", type = IdType.AUTO) | ||
| 32 | + private Long productId; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 产品编码 | ||
| 36 | + */ | ||
| 37 | + private String productCode; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 产品名称 | ||
| 41 | + */ | ||
| 42 | + private String productName; | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 产品型号 | ||
| 46 | + */ | ||
| 47 | + private String productModel; | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 产品类别 | ||
| 51 | + */ | ||
| 52 | + private String productType; | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 存储容量 | ||
| 56 | + */ | ||
| 57 | + private String storageCapacity; | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * 产品颜色 | ||
| 61 | + */ | ||
| 62 | + private String color; | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 产品图片URL | ||
| 66 | + */ | ||
| 67 | + private String productImgUrl; | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * 官方指导价 | ||
| 71 | + */ | ||
| 72 | + private BigDecimal officialPrice; | ||
| 73 | + | ||
| 74 | + /** | ||
| 75 | + * 销售状态(0-下架/1-在售/2-预售) | ||
| 76 | + */ | ||
| 77 | + private Integer saleStatus; | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 是否参与返利(0-否/1-是) | ||
| 81 | + */ | ||
| 82 | + private Integer rebateFlag; | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 销售起始日期 | ||
| 86 | + */ | ||
| 87 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 88 | + private LocalDate saleStartDate; | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 销售终止日期 | ||
| 92 | + */ | ||
| 93 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 94 | + private LocalDate saleEndDate; | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * 产品备注 | ||
| 98 | + */ | ||
| 99 | + private String remark; | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 创建者 | ||
| 103 | + */ | ||
| 104 | + private String createBy; | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 创建时间 | ||
| 108 | + */ | ||
| 109 | + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||
| 110 | + private LocalDateTime createTime; | ||
| 111 | + | ||
| 112 | + /** | ||
| 113 | + * 更新者 | ||
| 114 | + */ | ||
| 115 | + private String updateBy; | ||
| 116 | + | ||
| 117 | + /** | ||
| 118 | + * 更新时间 | ||
| 119 | + */ | ||
| 120 | + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||
| 121 | + private LocalDateTime updateTime; | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * 删除标志(0代表存在 2代表删除) | ||
| 125 | + */ | ||
| 126 | + private String delFlag; | ||
| 127 | +} |
| 1 | +package com.apple.erp.mapper; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.entity.ProductInfo; | ||
| 4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 5 | +import org.apache.ibatis.annotations.Mapper; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 产品信息表 Mapper 接口 | ||
| 9 | + * | ||
| 10 | + * @author Apple ERP Team | ||
| 11 | + * @since 2025-01-27 | ||
| 12 | + */ | ||
| 13 | +@Mapper | ||
| 14 | +public interface ProductInfoMapper extends BaseMapper<ProductInfo> { | ||
| 15 | + | ||
| 16 | +} |
| 1 | +package com.apple.erp.service; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.DealerAddReq; | ||
| 4 | +import com.apple.erp.dto.DealerQueryReq; | ||
| 5 | +import com.apple.erp.dto.DealerUpdateReq; | ||
| 6 | +import com.apple.erp.entity.DealerInfo; | ||
| 7 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 8 | +import com.baomidou.mybatisplus.extension.service.IService; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +public interface DealerInfoService extends IService<DealerInfo> { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 分页查询经销商列表 | ||
| 16 | + * @param queryReq 查询条件 | ||
| 17 | + * @return 经销商分页数据 | ||
| 18 | + */ | ||
| 19 | + IPage<DealerInfo> getDealerList(DealerQueryReq queryReq); | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 根据ID获取经销商详情 | ||
| 23 | + * @param dealerId 经销商ID | ||
| 24 | + * @return 经销商详情 | ||
| 25 | + */ | ||
| 26 | + DealerInfo getDealerDetail(Long dealerId); | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 新增经销商 | ||
| 30 | + * @param addReq 新增请求 | ||
| 31 | + * @return 是否成功 | ||
| 32 | + */ | ||
| 33 | + boolean addDealer(DealerAddReq addReq); | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 修改经销商 | ||
| 37 | + * @param updateReq 修改请求 | ||
| 38 | + * @return 是否成功 | ||
| 39 | + */ | ||
| 40 | + boolean updateDealer(DealerUpdateReq updateReq); | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 删除经销商 | ||
| 44 | + * @param dealerId 经销商ID | ||
| 45 | + * @return 是否成功 | ||
| 46 | + */ | ||
| 47 | + boolean deleteDealer(Long dealerId); | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 批量删除经销商 | ||
| 51 | + * @param dealerIds 经销商ID列表 | ||
| 52 | + * @return 是否成功 | ||
| 53 | + */ | ||
| 54 | + boolean batchDeleteDealers(List<Long> dealerIds); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 修改经销商合作状态 | ||
| 58 | + * @param dealerId 经销商ID | ||
| 59 | + * @param cooperateStatus 合作状态 | ||
| 60 | + * @return 是否成功 | ||
| 61 | + */ | ||
| 62 | + boolean updateDealerCooperateStatus(Long dealerId, Integer cooperateStatus); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 修改经销商资质审核状态 | ||
| 66 | + * @param dealerId 经销商ID | ||
| 67 | + * @param qualificationAuditStatus 资质审核状态 | ||
| 68 | + * @param auditOpinion 审核意见 | ||
| 69 | + * @return 是否成功 | ||
| 70 | + */ | ||
| 71 | + boolean updateDealerAuditStatus(Long dealerId, Integer qualificationAuditStatus, String auditOpinion); | ||
| 72 | +} |
| 1 | +package com.apple.erp.service; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.ProductAddReq; | ||
| 4 | +import com.apple.erp.dto.ProductQueryReq; | ||
| 5 | +import com.apple.erp.dto.ProductUpdateReq; | ||
| 6 | +import com.apple.erp.entity.ProductInfo; | ||
| 7 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 8 | +import com.baomidou.mybatisplus.extension.service.IService; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 产品信息表 服务类 | ||
| 14 | + * | ||
| 15 | + * @author Apple ERP Team | ||
| 16 | + * @since 2025-01-27 | ||
| 17 | + */ | ||
| 18 | +public interface ProductInfoService extends IService<ProductInfo> { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 分页查询产品列表 | ||
| 22 | + * | ||
| 23 | + * @param queryReq 查询条件 | ||
| 24 | + * @return 产品分页列表 | ||
| 25 | + */ | ||
| 26 | + IPage<ProductInfo> getProductPage(ProductQueryReq queryReq); | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 根据产品ID获取产品详情 | ||
| 30 | + * | ||
| 31 | + * @param productId 产品ID | ||
| 32 | + * @return 产品详情 | ||
| 33 | + */ | ||
| 34 | + ProductInfo getProductById(Long productId); | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 新增产品 | ||
| 38 | + * | ||
| 39 | + * @param addReq 新增请求 | ||
| 40 | + * @return 是否成功 | ||
| 41 | + */ | ||
| 42 | + boolean addProduct(ProductAddReq addReq); | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 修改产品 | ||
| 46 | + * | ||
| 47 | + * @param updateReq 修改请求 | ||
| 48 | + * @return 是否成功 | ||
| 49 | + */ | ||
| 50 | + boolean updateProduct(ProductUpdateReq updateReq); | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * 删除产品 | ||
| 54 | + * | ||
| 55 | + * @param productId 产品ID | ||
| 56 | + * @return 是否成功 | ||
| 57 | + */ | ||
| 58 | + boolean deleteProduct(Long productId); | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 批量删除产品 | ||
| 62 | + * | ||
| 63 | + * @param productIds 产品ID列表 | ||
| 64 | + * @return 是否成功 | ||
| 65 | + */ | ||
| 66 | + boolean batchDeleteProducts(List<Long> productIds); | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * 修改产品状态 | ||
| 70 | + * | ||
| 71 | + * @param productId 产品ID | ||
| 72 | + * @param saleStatus 销售状态 | ||
| 73 | + * @return 是否成功 | ||
| 74 | + */ | ||
| 75 | + boolean updateProductStatus(Long productId, Integer saleStatus); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 修改返利标识 | ||
| 79 | + * | ||
| 80 | + * @param productId 产品ID | ||
| 81 | + * @param rebateFlag 返利标识 | ||
| 82 | + * @return 是否成功 | ||
| 83 | + */ | ||
| 84 | + boolean updateRebateFlag(Long productId, Integer rebateFlag); | ||
| 85 | + | ||
| 86 | + /** | ||
| 87 | + * 检查产品编码是否存在 | ||
| 88 | + * | ||
| 89 | + * @param productCode 产品编码 | ||
| 90 | + * @param productId 产品ID(修改时排除自己) | ||
| 91 | + * @return 是否存在 | ||
| 92 | + */ | ||
| 93 | + boolean checkProductCodeExists(String productCode, Long productId); | ||
| 94 | +} |
This diff is collapsed. Click to expand it.
| 1 | +package com.apple.erp.service.impl; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.ProductAddReq; | ||
| 4 | +import com.apple.erp.dto.ProductQueryReq; | ||
| 5 | +import com.apple.erp.dto.ProductUpdateReq; | ||
| 6 | +import com.apple.erp.entity.ProductInfo; | ||
| 7 | +import com.apple.erp.mapper.ProductInfoMapper; | ||
| 8 | +import com.apple.erp.service.ProductInfoService; | ||
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 10 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 11 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||
| 12 | +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||
| 13 | +import org.springframework.beans.BeanUtils; | ||
| 14 | +import org.springframework.stereotype.Service; | ||
| 15 | +import org.springframework.util.StringUtils; | ||
| 16 | + | ||
| 17 | +import java.time.LocalDateTime; | ||
| 18 | +import java.util.List; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * 产品信息表 服务实现类 | ||
| 22 | + * | ||
| 23 | + * @author Apple ERP Team | ||
| 24 | + * @since 2025-01-27 | ||
| 25 | + */ | ||
| 26 | +@Service | ||
| 27 | +public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, ProductInfo> implements ProductInfoService { | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + public IPage<ProductInfo> getProductPage(ProductQueryReq queryReq) { | ||
| 31 | + Page<ProductInfo> page = new Page<>(queryReq.getPageNum(), queryReq.getPageSize()); | ||
| 32 | + LambdaQueryWrapper<ProductInfo> queryWrapper = getQueryWrapper(queryReq); | ||
| 33 | + return this.page(page, queryWrapper); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public ProductInfo getProductById(Long productId) { | ||
| 38 | + return this.getById(productId); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public boolean addProduct(ProductAddReq addReq) { | ||
| 43 | + // 检查产品编码是否已存在 | ||
| 44 | + if (checkProductCodeExists(addReq.getProductCode(), null)) { | ||
| 45 | + throw new RuntimeException("产品编码已存在"); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + ProductInfo productInfo = new ProductInfo(); | ||
| 49 | + BeanUtils.copyProperties(addReq, productInfo); | ||
| 50 | + productInfo.setCreateTime(LocalDateTime.now()); | ||
| 51 | + productInfo.setDelFlag("0"); | ||
| 52 | + return this.save(productInfo); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + public boolean updateProduct(ProductUpdateReq updateReq) { | ||
| 57 | + // 检查产品编码是否已存在(排除自己) | ||
| 58 | + if (checkProductCodeExists(updateReq.getProductCode(), updateReq.getProductId())) { | ||
| 59 | + throw new RuntimeException("产品编码已存在"); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + ProductInfo productInfo = new ProductInfo(); | ||
| 63 | + BeanUtils.copyProperties(updateReq, productInfo); | ||
| 64 | + productInfo.setUpdateTime(LocalDateTime.now()); | ||
| 65 | + return this.updateById(productInfo); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @Override | ||
| 69 | + public boolean deleteProduct(Long productId) { | ||
| 70 | + ProductInfo productInfo = new ProductInfo(); | ||
| 71 | + productInfo.setProductId(productId); | ||
| 72 | + productInfo.setDelFlag("2"); | ||
| 73 | + productInfo.setUpdateTime(LocalDateTime.now()); | ||
| 74 | + return this.updateById(productInfo); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public boolean batchDeleteProducts(List<Long> productIds) { | ||
| 79 | + for (Long productId : productIds) { | ||
| 80 | + deleteProduct(productId); | ||
| 81 | + } | ||
| 82 | + return true; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @Override | ||
| 86 | + public boolean updateProductStatus(Long productId, Integer saleStatus) { | ||
| 87 | + ProductInfo productInfo = new ProductInfo(); | ||
| 88 | + productInfo.setProductId(productId); | ||
| 89 | + productInfo.setSaleStatus(saleStatus); | ||
| 90 | + productInfo.setUpdateTime(LocalDateTime.now()); | ||
| 91 | + return this.updateById(productInfo); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + public boolean updateRebateFlag(Long productId, Integer rebateFlag) { | ||
| 96 | + ProductInfo productInfo = new ProductInfo(); | ||
| 97 | + productInfo.setProductId(productId); | ||
| 98 | + productInfo.setRebateFlag(rebateFlag); | ||
| 99 | + productInfo.setUpdateTime(LocalDateTime.now()); | ||
| 100 | + return this.updateById(productInfo); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @Override | ||
| 104 | + public boolean checkProductCodeExists(String productCode, Long productId) { | ||
| 105 | + LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>(); | ||
| 106 | + queryWrapper.eq(ProductInfo::getProductCode, productCode) | ||
| 107 | + .eq(ProductInfo::getDelFlag, "0"); | ||
| 108 | + if (productId != null) { | ||
| 109 | + queryWrapper.ne(ProductInfo::getProductId, productId); | ||
| 110 | + } | ||
| 111 | + return this.count(queryWrapper) > 0; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * 构建查询条件 | ||
| 116 | + * | ||
| 117 | + * @param queryReq 查询请求 | ||
| 118 | + * @return 查询条件 | ||
| 119 | + */ | ||
| 120 | + private LambdaQueryWrapper<ProductInfo> getQueryWrapper(ProductQueryReq queryReq) { | ||
| 121 | + LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>(); | ||
| 122 | + | ||
| 123 | + // 基础查询条件 | ||
| 124 | + queryWrapper.eq(ProductInfo::getDelFlag, "0"); | ||
| 125 | + | ||
| 126 | + // 产品编码 | ||
| 127 | + if (StringUtils.hasText(queryReq.getProductCode())) { | ||
| 128 | + queryWrapper.like(ProductInfo::getProductCode, queryReq.getProductCode()); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + // 产品名称 | ||
| 132 | + if (StringUtils.hasText(queryReq.getProductName())) { | ||
| 133 | + queryWrapper.like(ProductInfo::getProductName, queryReq.getProductName()); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // 产品型号 | ||
| 137 | + if (StringUtils.hasText(queryReq.getProductModel())) { | ||
| 138 | + queryWrapper.like(ProductInfo::getProductModel, queryReq.getProductModel()); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + // 产品类别 | ||
| 142 | + if (StringUtils.hasText(queryReq.getProductType())) { | ||
| 143 | + queryWrapper.eq(ProductInfo::getProductType, queryReq.getProductType()); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + // 存储容量 | ||
| 147 | + if (StringUtils.hasText(queryReq.getStorageCapacity())) { | ||
| 148 | + queryWrapper.eq(ProductInfo::getStorageCapacity, queryReq.getStorageCapacity()); | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + // 产品颜色 | ||
| 152 | + if (StringUtils.hasText(queryReq.getColor())) { | ||
| 153 | + queryWrapper.eq(ProductInfo::getColor, queryReq.getColor()); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + // 销售状态 | ||
| 157 | + if (queryReq.getSaleStatus() != null) { | ||
| 158 | + queryWrapper.eq(ProductInfo::getSaleStatus, queryReq.getSaleStatus()); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + // 返利标识 | ||
| 162 | + if (queryReq.getRebateFlag() != null) { | ||
| 163 | + queryWrapper.eq(ProductInfo::getRebateFlag, queryReq.getRebateFlag()); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + // 价格范围 | ||
| 167 | + if (queryReq.getMinPrice() != null) { | ||
| 168 | + queryWrapper.ge(ProductInfo::getOfficialPrice, queryReq.getMinPrice()); | ||
| 169 | + } | ||
| 170 | + if (queryReq.getMaxPrice() != null) { | ||
| 171 | + queryWrapper.le(ProductInfo::getOfficialPrice, queryReq.getMaxPrice()); | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + // 销售起始日期范围 | ||
| 175 | + if (queryReq.getSaleStartDateBegin() != null) { | ||
| 176 | + queryWrapper.ge(ProductInfo::getSaleStartDate, queryReq.getSaleStartDateBegin()); | ||
| 177 | + } | ||
| 178 | + if (queryReq.getSaleStartDateEnd() != null) { | ||
| 179 | + queryWrapper.le(ProductInfo::getSaleStartDate, queryReq.getSaleStartDateEnd()); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + // 销售终止日期范围 | ||
| 183 | + if (queryReq.getSaleEndDateBegin() != null) { | ||
| 184 | + queryWrapper.ge(ProductInfo::getSaleEndDate, queryReq.getSaleEndDateBegin()); | ||
| 185 | + } | ||
| 186 | + if (queryReq.getSaleEndDateEnd() != null) { | ||
| 187 | + queryWrapper.le(ProductInfo::getSaleEndDate, queryReq.getSaleEndDateEnd()); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + // 排序 | ||
| 191 | + queryWrapper.orderByDesc(ProductInfo::getCreateTime); | ||
| 192 | + | ||
| 193 | + return queryWrapper; | ||
| 194 | + } | ||
| 195 | +} |
| 1 | +-- Apple经销商ERP系统 - 业务数据库初始化脚本 | ||
| 2 | +-- 按顺序执行所有业务数据库脚本 | ||
| 3 | + | ||
| 4 | +-- 1. 创建业务表 | ||
| 5 | +SOURCE 01_create_business_tables.sql; | ||
| 6 | + | ||
| 7 | +-- 2. 创建业务索引 | ||
| 8 | +SOURCE 02_create_business_indexes.sql; | ||
| 9 | + | ||
| 10 | +-- 3. 插入业务测试数据 | ||
| 11 | +SOURCE 03_insert_business_data.sql; | ||
| 12 | + | ||
| 13 | +-- 4. 插入产品管理和经销商管理权限 | ||
| 14 | +SOURCE 06_insert_product_dealer_permissions.sql; | ||
| 15 | + | ||
| 16 | +-- 完成业务数据库初始化 | ||
| 17 | +SELECT 'Apple经销商ERP系统业务数据库初始化完成!' AS message; |
This diff is collapsed. Click to expand it.
| 1 | + |
| 1 | +-- Apple经销商ERP系统 - 业务表索引创建脚本 | ||
| 2 | +-- 按照数据库设计文档创建索引 | ||
| 3 | + | ||
| 4 | +-- ============================================= | ||
| 5 | +-- 订单主表索引 | ||
| 6 | +-- ============================================= | ||
| 7 | + | ||
| 8 | +-- 业务唯一索引 | ||
| 9 | +CREATE UNIQUE INDEX uk_order_no ON t_order_main(order_no); | ||
| 10 | + | ||
| 11 | +-- 查询优化索引 | ||
| 12 | +CREATE INDEX idx_order_dealer_code ON t_order_main(dealer_code); | ||
| 13 | +CREATE INDEX idx_order_date ON t_order_main(order_date); | ||
| 14 | +CREATE INDEX idx_order_status ON t_order_main(delivery_status, invoice_status); | ||
| 15 | +CREATE INDEX idx_order_verify ON t_order_main(verify_status); | ||
| 16 | +CREATE INDEX idx_order_upload_time ON t_order_main(upload_time); | ||
| 17 | + | ||
| 18 | +-- ============================================= | ||
| 19 | +-- 订单商品明细表索引 | ||
| 20 | +-- ============================================= | ||
| 21 | + | ||
| 22 | +-- 外键索引 | ||
| 23 | +CREATE INDEX idx_item_order_id ON t_order_item(order_id); | ||
| 24 | +CREATE INDEX idx_item_order_no ON t_order_item(order_no); | ||
| 25 | +CREATE INDEX idx_item_product_code ON t_order_item(product_code); | ||
| 26 | + | ||
| 27 | +-- ============================================= | ||
| 28 | +-- 出库主表索引 | ||
| 29 | +-- ============================================= | ||
| 30 | + | ||
| 31 | +-- 业务唯一索引 | ||
| 32 | +CREATE UNIQUE INDEX uk_delivery_no ON t_delivery_main(delivery_no); | ||
| 33 | + | ||
| 34 | +-- 查询优化索引 | ||
| 35 | +CREATE INDEX idx_delivery_dealer_code ON t_delivery_main(dealer_code); | ||
| 36 | +CREATE INDEX idx_delivery_order_no ON t_delivery_main(order_no); | ||
| 37 | +CREATE INDEX idx_delivery_date ON t_delivery_main(delivery_date); | ||
| 38 | +CREATE INDEX idx_delivery_status ON t_delivery_main(delivery_status); | ||
| 39 | + | ||
| 40 | +-- ============================================= | ||
| 41 | +-- 出库商品明细表索引 | ||
| 42 | +-- ============================================= | ||
| 43 | + | ||
| 44 | +-- 外键索引 | ||
| 45 | +CREATE INDEX idx_delivery_item_delivery_id ON t_delivery_item(delivery_id); | ||
| 46 | +CREATE INDEX idx_delivery_item_delivery_no ON t_delivery_item(delivery_no); | ||
| 47 | +CREATE INDEX idx_delivery_item_order_no ON t_delivery_item(order_no); | ||
| 48 | +CREATE INDEX idx_delivery_item_product_code ON t_delivery_item(product_code); | ||
| 49 | + | ||
| 50 | +-- ============================================= | ||
| 51 | +-- 发票主表索引 | ||
| 52 | +-- ============================================= | ||
| 53 | + | ||
| 54 | +-- 业务唯一索引 | ||
| 55 | +CREATE UNIQUE INDEX uk_invoice_no ON t_invoice_main(invoice_no); | ||
| 56 | + | ||
| 57 | +-- 查询优化索引 | ||
| 58 | +CREATE INDEX idx_invoice_dealer_code ON t_invoice_main(dealer_code); | ||
| 59 | +CREATE INDEX idx_invoice_order_no ON t_invoice_main(order_no); | ||
| 60 | +CREATE INDEX idx_invoice_delivery_no ON t_invoice_main(delivery_no); | ||
| 61 | +CREATE INDEX idx_invoice_date ON t_invoice_main(invoice_date); | ||
| 62 | +CREATE INDEX idx_invoice_status ON t_invoice_main(invoice_status); | ||
| 63 | + | ||
| 64 | +-- ============================================= | ||
| 65 | +-- 发票商品明细表索引 | ||
| 66 | +-- ============================================= | ||
| 67 | + | ||
| 68 | +-- 外键索引 | ||
| 69 | +CREATE INDEX idx_invoice_item_invoice_id ON t_invoice_item(invoice_id); | ||
| 70 | +CREATE INDEX idx_invoice_item_invoice_no ON t_invoice_item(invoice_no); | ||
| 71 | +CREATE INDEX idx_invoice_item_order_no ON t_invoice_item(order_no); | ||
| 72 | +CREATE INDEX idx_invoice_item_product_code ON t_invoice_item(product_code); | ||
| 73 | + | ||
| 74 | +-- ============================================= | ||
| 75 | +-- 返利台账明细表索引 | ||
| 76 | +-- ============================================= | ||
| 77 | + | ||
| 78 | +-- 业务唯一索引 | ||
| 79 | +CREATE UNIQUE INDEX uk_rebate_no ON t_rebate_detail(rebate_no); | ||
| 80 | + | ||
| 81 | +-- 查询优化索引 | ||
| 82 | +CREATE INDEX idx_rebate_dealer_code ON t_rebate_detail(dealer_code); | ||
| 83 | +CREATE INDEX idx_rebate_order_no ON t_rebate_detail(order_no); | ||
| 84 | +CREATE INDEX idx_rebate_product_code ON t_rebate_detail(product_code); | ||
| 85 | +CREATE INDEX idx_rebate_date ON t_rebate_detail(rebate_date); | ||
| 86 | +CREATE INDEX idx_rebate_operate_type ON t_rebate_detail(operate_type); | ||
| 87 | +CREATE INDEX idx_rebate_calc_flag ON t_rebate_detail(calc_flag); | ||
| 88 | + | ||
| 89 | +-- ============================================= | ||
| 90 | +-- 异常工单表索引 | ||
| 91 | +-- ============================================= | ||
| 92 | + | ||
| 93 | +-- 业务唯一索引 | ||
| 94 | +CREATE UNIQUE INDEX uk_workorder_no ON t_exception_workorder(workorder_no); | ||
| 95 | + | ||
| 96 | +-- 查询优化索引 | ||
| 97 | +CREATE INDEX idx_workorder_dealer_code ON t_exception_workorder(dealer_code); | ||
| 98 | +CREATE INDEX idx_workorder_order_no ON t_exception_workorder(order_no); | ||
| 99 | +CREATE INDEX idx_workorder_exception_type ON t_exception_workorder(exception_type); | ||
| 100 | +CREATE INDEX idx_workorder_severity_level ON t_exception_workorder(severity_level); | ||
| 101 | +CREATE INDEX idx_workorder_status ON t_exception_workorder(workorder_status); | ||
| 102 | +CREATE INDEX idx_workorder_create_time ON t_exception_workorder(create_time); | ||
| 103 | +CREATE INDEX idx_workorder_handler_user ON t_exception_workorder(handler_user); | ||
| 104 | + | ||
| 105 | +-- ============================================= | ||
| 106 | +-- 异常工单处理日志表索引 | ||
| 107 | +-- ============================================= | ||
| 108 | + | ||
| 109 | +-- 外键索引 | ||
| 110 | +CREATE INDEX idx_workorder_log_workorder_id ON t_exception_workorder_log(workorder_id); | ||
| 111 | +CREATE INDEX idx_workorder_log_workorder_no ON t_exception_workorder_log(workorder_no); | ||
| 112 | +CREATE INDEX idx_workorder_log_handle_user ON t_exception_workorder_log(handle_user); | ||
| 113 | +CREATE INDEX idx_workorder_log_handle_time ON t_exception_workorder_log(handle_time); | ||
| 114 | + | ||
| 115 | +-- ============================================= | ||
| 116 | +-- 经销商信息表索引 | ||
| 117 | +-- ============================================= | ||
| 118 | + | ||
| 119 | +-- 业务唯一索引(已在表定义中创建) | ||
| 120 | +-- UNIQUE INDEX uk_dealer_code ON t_dealer_info(dealer_code); | ||
| 121 | +-- UNIQUE INDEX uk_credit_code ON t_dealer_info(credit_code); | ||
| 122 | + | ||
| 123 | +-- 查询优化索引 | ||
| 124 | +CREATE INDEX idx_dealer_name ON t_dealer_info(dealer_name); | ||
| 125 | +CREATE INDEX idx_dealer_level ON t_dealer_info(dealer_level); | ||
| 126 | +CREATE INDEX idx_dealer_region ON t_dealer_info(region); | ||
| 127 | +CREATE INDEX idx_dealer_cooperate_status ON t_dealer_info(cooperate_status); | ||
| 128 | +CREATE INDEX idx_dealer_qualification_audit_status ON t_dealer_info(qualification_audit_status); | ||
| 129 | +CREATE INDEX idx_dealer_cooperate_start_date ON t_dealer_info(cooperate_start_date); | ||
| 130 | + | ||
| 131 | +-- ============================================= | ||
| 132 | +-- 产品信息表索引 | ||
| 133 | +-- ============================================= | ||
| 134 | + | ||
| 135 | +-- 业务唯一索引(已在表定义中创建) | ||
| 136 | +-- UNIQUE INDEX uk_product_code ON t_product_info(product_code); | ||
| 137 | + | ||
| 138 | +-- 查询优化索引 | ||
| 139 | +CREATE INDEX idx_product_name ON t_product_info(product_name); | ||
| 140 | +CREATE INDEX idx_product_model ON t_product_info(product_model); | ||
| 141 | +CREATE INDEX idx_product_type ON t_product_info(product_type); | ||
| 142 | +CREATE INDEX idx_product_sale_status ON t_product_info(sale_status); | ||
| 143 | +CREATE INDEX idx_product_rebate_flag ON t_product_info(rebate_flag); | ||
| 144 | +CREATE INDEX idx_product_sale_start_date ON t_product_info(sale_start_date); | ||
| 145 | +CREATE INDEX idx_product_sale_end_date ON t_product_info(sale_end_date); | ||
| 146 | + | ||
| 147 | +-- ============================================= | ||
| 148 | +-- 复合索引优化查询性能 | ||
| 149 | +-- ============================================= | ||
| 150 | + | ||
| 151 | +-- 订单查询优化 | ||
| 152 | +CREATE INDEX idx_order_complex_query ON t_order_main(dealer_code, order_date, delivery_status, invoice_status); | ||
| 153 | + | ||
| 154 | +-- 出库查询优化 | ||
| 155 | +CREATE INDEX idx_delivery_complex_query ON t_delivery_main(dealer_code, delivery_date, delivery_status); | ||
| 156 | + | ||
| 157 | +-- 发票查询优化 | ||
| 158 | +CREATE INDEX idx_invoice_complex_query ON t_invoice_main(dealer_code, invoice_date, invoice_status); | ||
| 159 | + | ||
| 160 | +-- 返利查询优化 | ||
| 161 | +CREATE INDEX idx_rebate_complex_query ON t_rebate_detail(dealer_code, rebate_date, operate_type); | ||
| 162 | + | ||
| 163 | +-- 异常工单查询优化 | ||
| 164 | +CREATE INDEX idx_workorder_complex_query ON t_exception_workorder(workorder_status, severity_level, create_time); | ||
| 165 | + | ||
| 166 | +-- 经销商查询优化 | ||
| 167 | +CREATE INDEX idx_dealer_complex_query ON t_dealer_info(dealer_level, cooperate_status, region); | ||
| 168 | + | ||
| 169 | +-- 产品查询优化 | ||
| 170 | +CREATE INDEX idx_product_complex_query ON t_product_info(product_type, sale_status, rebate_flag); |
database/scripts/03_insert_business_data.sql
0 → 100644
This diff is collapsed. Click to expand it.
| 1 | +-- Apple经销商ERP系统对接项目 - 产品管理和经销商管理权限配置脚本 | ||
| 2 | +-- 创建时间: 2025-01-27 | ||
| 3 | +-- 版本: v1.0 | ||
| 4 | + | ||
| 5 | +-- 设置数据库和字符集 | ||
| 6 | +SET NAMES utf8mb4; | ||
| 7 | +SET FOREIGN_KEY_CHECKS = 0; | ||
| 8 | + | ||
| 9 | +-- 使用数据库 | ||
| 10 | +USE apple_erp; | ||
| 11 | + | ||
| 12 | +-- ========================================= | ||
| 13 | +-- 1. 插入产品管理相关按钮权限 | ||
| 14 | +-- ========================================= | ||
| 15 | + | ||
| 16 | +-- 获取产品管理主菜单ID(menu_id = 8) | ||
| 17 | +SET @product_menu_id = (SELECT menu_id FROM t_sys_menu WHERE menu_name = '产品管理' AND del_flag = '0' LIMIT 1); | ||
| 18 | + | ||
| 19 | +-- 产品管理按钮权限 | ||
| 20 | +INSERT INTO t_sys_menu (parent_id, menu_name, menu_type, path, icon, sort, status, perms, create_by, create_time, update_by, update_time, del_flag) | ||
| 21 | +VALUES | ||
| 22 | +(@product_menu_id, '产品查询', '2', '', '', 1, '1', 'product:list', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 23 | +(@product_menu_id, '产品新增', '2', '', '', 2, '1', 'product:add', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 24 | +(@product_menu_id, '产品修改', '2', '', '', 3, '1', 'product:edit', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 25 | +(@product_menu_id, '产品删除', '2', '', '', 4, '1', 'product:delete', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 26 | +(@product_menu_id, '产品详情', '2', '', '', 5, '1', 'product:detail', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 27 | +(@product_menu_id, '产品批量删除', '2', '', '', 6, '1', 'product:batchDelete', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 28 | +(@product_menu_id, '产品状态修改', '2', '', '', 7, '1', 'product:updateStatus', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 29 | +(@product_menu_id, '产品返利标识修改', '2', '', '', 8, '1', 'product:updateRebateFlag', 'admin', NOW(), 'admin', NOW(), '0'); | ||
| 30 | + | ||
| 31 | +-- ========================================= | ||
| 32 | +-- 2. 插入经销商管理相关按钮权限 | ||
| 33 | +-- ========================================= | ||
| 34 | + | ||
| 35 | +-- 获取经销商管理主菜单ID(menu_id = 9) | ||
| 36 | +SET @dealer_menu_id = (SELECT menu_id FROM t_sys_menu WHERE menu_name = '经销商管理' AND del_flag = '0' LIMIT 1); | ||
| 37 | + | ||
| 38 | +-- 经销商管理按钮权限 | ||
| 39 | +INSERT INTO t_sys_menu (parent_id, menu_name, menu_type, path, icon, sort, status, perms, create_by, create_time, update_by, update_time, del_flag) | ||
| 40 | +VALUES | ||
| 41 | +(@dealer_menu_id, '经销商查询', '2', '', '', 1, '1', 'dealer:list', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 42 | +(@dealer_menu_id, '经销商新增', '2', '', '', 2, '1', 'dealer:add', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 43 | +(@dealer_menu_id, '经销商修改', '2', '', '', 3, '1', 'dealer:update', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 44 | +(@dealer_menu_id, '经销商删除', '2', '', '', 4, '1', 'dealer:delete', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 45 | +(@dealer_menu_id, '经销商详情', '2', '', '', 5, '1', 'dealer:detail', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 46 | +(@dealer_menu_id, '经销商批量删除', '2', '', '', 6, '1', 'dealer:batchDelete', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 47 | +(@dealer_menu_id, '经销商合作状态修改', '2', '', '', 7, '1', 'dealer:updateStatus', 'admin', NOW(), 'admin', NOW(), '0'), | ||
| 48 | +(@dealer_menu_id, '经销商资质审核', '2', '', '', 8, '1', 'dealer:audit', 'admin', NOW(), 'admin', NOW(), '0'); | ||
| 49 | + | ||
| 50 | +SET FOREIGN_KEY_CHECKS = 1; | ||
| 51 | +SELECT 'Apple经销商ERP系统产品管理和经销商管理权限配置完成!' AS message; |
This diff is collapsed. Click to expand it.
| 1 | -import { request } from '@/utils/request' | 1 | +import axios from 'axios' |
| 2 | import type { LoginForm, LoginResponse, User } from '@/types' | 2 | import type { LoginForm, LoginResponse, User } from '@/types' |
| 3 | 3 | ||
| 4 | +// 创建axios实例 | ||
| 5 | +const api = axios.create({ | ||
| 6 | + baseURL: 'http://localhost:8083/api', | ||
| 7 | + timeout: 10000 | ||
| 8 | +}) | ||
| 9 | + | ||
| 10 | +// 请求拦截器 | ||
| 11 | +api.interceptors.request.use( | ||
| 12 | + config => { | ||
| 13 | + const token = localStorage.getItem('token') | ||
| 14 | + if (token) { | ||
| 15 | + config.headers.Authorization = `Bearer ${token}` | ||
| 16 | + } | ||
| 17 | + return config | ||
| 18 | + }, | ||
| 19 | + error => { | ||
| 20 | + return Promise.reject(error) | ||
| 21 | + } | ||
| 22 | +) | ||
| 23 | + | ||
| 24 | +// 响应拦截器 | ||
| 25 | +api.interceptors.response.use( | ||
| 26 | + response => { | ||
| 27 | + return response.data | ||
| 28 | + }, | ||
| 29 | + error => { | ||
| 30 | + if (error.response?.status === 401) { | ||
| 31 | + localStorage.removeItem('token') | ||
| 32 | + localStorage.removeItem('userInfo') | ||
| 33 | + window.location.href = '/login' | ||
| 34 | + } | ||
| 35 | + return Promise.reject(error) | ||
| 36 | + } | ||
| 37 | +) | ||
| 38 | + | ||
| 4 | // 登录 | 39 | // 登录 |
| 5 | export function loginApi(data: LoginForm): Promise<LoginResponse> { | 40 | export function loginApi(data: LoginForm): Promise<LoginResponse> { |
| 6 | - return request.post('/api/auth/login', data) | 41 | + return api.post('/auth/login', data) |
| 7 | } | 42 | } |
| 8 | 43 | ||
| 9 | // 登出 | 44 | // 登出 |
| 10 | export function logoutApi(): Promise<void> { | 45 | export function logoutApi(): Promise<void> { |
| 11 | - return request.post('/api/auth/logout') | 46 | + return api.post('/auth/logout') |
| 12 | } | 47 | } |
| 13 | 48 | ||
| 14 | // 获取用户信息 | 49 | // 获取用户信息 |
| 15 | export function getUserInfoApi(): Promise<User> { | 50 | export function getUserInfoApi(): Promise<User> { |
| 16 | - return request.get('/api/auth/userInfo') | 51 | + return api.get('/auth/userInfo') |
| 17 | } | 52 | } |
| 18 | 53 | ||
| 19 | // 刷新Token | 54 | // 刷新Token |
| 20 | export function refreshTokenApi(): Promise<{ token: string }> { | 55 | export function refreshTokenApi(): Promise<{ token: string }> { |
| 21 | - return request.post('/api/auth/refresh') | 56 | + return api.post('/auth/refresh') |
| 22 | } | 57 | } |
| 23 | 58 | ||
| 24 | // 修改密码 | 59 | // 修改密码 |
| ... | @@ -26,10 +61,10 @@ export function changePasswordApi(data: { | ... | @@ -26,10 +61,10 @@ export function changePasswordApi(data: { |
| 26 | oldPassword: string | 61 | oldPassword: string |
| 27 | newPassword: string | 62 | newPassword: string |
| 28 | }): Promise<void> { | 63 | }): Promise<void> { |
| 29 | - return request.post('/api/auth/changePassword', data) | 64 | + return api.post('/auth/changePassword', data) |
| 30 | } | 65 | } |
| 31 | 66 | ||
| 32 | // 获取验证码 | 67 | // 获取验证码 |
| 33 | export function getCaptchaApi(): Promise<{ captchaId: string; captchaImage: string }> { | 68 | export function getCaptchaApi(): Promise<{ captchaId: string; captchaImage: string }> { |
| 34 | - return request.get('/api/auth/captcha') | 69 | + return api.get('/auth/captcha') |
| 35 | } | 70 | } | ... | ... |
frontend/src/api/dealer.ts
0 → 100644
| 1 | +import axios from 'axios' | ||
| 2 | + | ||
| 3 | +// 创建axios实例 | ||
| 4 | +const api = axios.create({ | ||
| 5 | + baseURL: 'http://localhost:8083/api', | ||
| 6 | + timeout: 10000 | ||
| 7 | +}) | ||
| 8 | + | ||
| 9 | +// 请求拦截器 | ||
| 10 | +api.interceptors.request.use( | ||
| 11 | + (config) => { | ||
| 12 | + const token = localStorage.getItem('token') | ||
| 13 | + if (token) { | ||
| 14 | + config.headers.Authorization = `Bearer ${token}` | ||
| 15 | + } | ||
| 16 | + return config | ||
| 17 | + }, | ||
| 18 | + (error) => { | ||
| 19 | + return Promise.reject(error) | ||
| 20 | + } | ||
| 21 | +) | ||
| 22 | + | ||
| 23 | +// 响应拦截器 | ||
| 24 | +api.interceptors.response.use( | ||
| 25 | + (response) => { | ||
| 26 | + return response.data | ||
| 27 | + }, | ||
| 28 | + (error) => { | ||
| 29 | + if (error.response?.status === 401) { | ||
| 30 | + localStorage.removeItem('token') | ||
| 31 | + localStorage.removeItem('userInfo') | ||
| 32 | + window.location.href = '/login' | ||
| 33 | + } | ||
| 34 | + return Promise.reject(error) | ||
| 35 | + } | ||
| 36 | +) | ||
| 37 | + | ||
| 38 | +// 经销商信息接口 | ||
| 39 | +export interface DealerInfo { | ||
| 40 | + dealerId: number | ||
| 41 | + dealerCode: string | ||
| 42 | + dealerName: string | ||
| 43 | + creditCode: string | ||
| 44 | + dealerLevel: number | ||
| 45 | + region: string | ||
| 46 | + contactPerson: string | ||
| 47 | + contactPhone: string | ||
| 48 | + cooperateStartDate: string | ||
| 49 | + cooperateStatus: number | ||
| 50 | + businessLicenseUrl: string | ||
| 51 | + cooperationAgreementUrl: string | ||
| 52 | + qualificationAuditStatus: number | ||
| 53 | + auditOpinion: string | ||
| 54 | + createTime: string | ||
| 55 | + updateTime: string | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +// 经销商查询请求参数 | ||
| 59 | +export interface DealerQueryReq { | ||
| 60 | + dealerCode?: string | ||
| 61 | + dealerName?: string | ||
| 62 | + creditCode?: string | ||
| 63 | + dealerLevel?: number | ||
| 64 | + region?: string | ||
| 65 | + contactPerson?: string | ||
| 66 | + contactPhone?: string | ||
| 67 | + cooperateStatus?: number | ||
| 68 | + qualificationAuditStatus?: number | ||
| 69 | + pageNum: number | ||
| 70 | + pageSize: number | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +// 经销商新增请求参数 | ||
| 74 | +export interface DealerAddReq { | ||
| 75 | + dealerCode: string | ||
| 76 | + dealerName: string | ||
| 77 | + creditCode: string | ||
| 78 | + dealerLevel: number | ||
| 79 | + region: string | ||
| 80 | + contactPerson?: string | ||
| 81 | + contactPhone?: string | ||
| 82 | + cooperateStartDate: string | ||
| 83 | + cooperateStatus?: number | ||
| 84 | + businessLicenseUrl?: string | ||
| 85 | + cooperationAgreementUrl?: string | ||
| 86 | + qualificationAuditStatus?: number | ||
| 87 | + auditOpinion?: string | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +// 经销商修改请求参数 | ||
| 91 | +export interface DealerUpdateReq { | ||
| 92 | + dealerId: number | ||
| 93 | + dealerCode: string | ||
| 94 | + dealerName: string | ||
| 95 | + creditCode: string | ||
| 96 | + dealerLevel: number | ||
| 97 | + region: string | ||
| 98 | + contactPerson?: string | ||
| 99 | + contactPhone?: string | ||
| 100 | + cooperateStartDate: string | ||
| 101 | + cooperateStatus?: number | ||
| 102 | + businessLicenseUrl?: string | ||
| 103 | + cooperationAgreementUrl?: string | ||
| 104 | + qualificationAuditStatus?: number | ||
| 105 | + auditOpinion?: string | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +// 分页数据接口 | ||
| 109 | +export interface PageData<T> { | ||
| 110 | + records: T[] | ||
| 111 | + total: number | ||
| 112 | + pageNum: number | ||
| 113 | + pageSize: number | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +// API响应接口 | ||
| 117 | +export interface ApiResponse<T = any> { | ||
| 118 | + code: number | ||
| 119 | + message: string | ||
| 120 | + data: T | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +// 经销商管理API | ||
| 124 | +export const dealerApi = { | ||
| 125 | + // 分页查询经销商列表 | ||
| 126 | + getDealerList: (params: DealerQueryReq) => { | ||
| 127 | + return api.get<ApiResponse<PageData<DealerInfo>>>('/dealer/list', { params }) | ||
| 128 | + }, | ||
| 129 | + | ||
| 130 | + // 获取经销商详情 | ||
| 131 | + getDealerDetail: (dealerId: number) => { | ||
| 132 | + return api.get<ApiResponse<DealerInfo>>(`/dealer/${dealerId}`) | ||
| 133 | + }, | ||
| 134 | + | ||
| 135 | + // 新增经销商 | ||
| 136 | + addDealer: (data: DealerAddReq) => { | ||
| 137 | + return api.post<ApiResponse>('/dealer', data) | ||
| 138 | + }, | ||
| 139 | + | ||
| 140 | + // 修改经销商 | ||
| 141 | + updateDealer: (data: DealerUpdateReq) => { | ||
| 142 | + return api.post<ApiResponse>('/dealer/update', data) | ||
| 143 | + }, | ||
| 144 | + | ||
| 145 | + // 删除经销商 | ||
| 146 | + deleteDealer: (dealerId: number) => { | ||
| 147 | + return api.delete<ApiResponse>(`/dealer/${dealerId}`) | ||
| 148 | + }, | ||
| 149 | + | ||
| 150 | + // 批量删除经销商 | ||
| 151 | + batchDeleteDealer: (dealerIds: number[]) => { | ||
| 152 | + return api.delete<ApiResponse>('/dealer/batch', { data: dealerIds }) | ||
| 153 | + }, | ||
| 154 | + | ||
| 155 | + // 修改经销商合作状态 | ||
| 156 | + updateCooperateStatus: (dealerId: number, cooperateStatus: number) => { | ||
| 157 | + return api.post<ApiResponse>(`/dealer/${dealerId}/cooperateStatus/${cooperateStatus}`) | ||
| 158 | + }, | ||
| 159 | + | ||
| 160 | + // 修改经销商资质审核状态 | ||
| 161 | + updateAuditStatus: (dealerId: number, qualificationAuditStatus: number, auditOpinion?: string) => { | ||
| 162 | + return api.post<ApiResponse>(`/dealer/${dealerId}/auditStatus`, null, { | ||
| 163 | + params: { qualificationAuditStatus, auditOpinion } | ||
| 164 | + }) | ||
| 165 | + } | ||
| 166 | +} |
frontend/src/api/product.ts
0 → 100644
| 1 | +import axios from 'axios' | ||
| 2 | + | ||
| 3 | +// 创建axios实例 | ||
| 4 | +const api = axios.create({ | ||
| 5 | + baseURL: 'http://localhost:8083/api', | ||
| 6 | + timeout: 10000 | ||
| 7 | +}) | ||
| 8 | + | ||
| 9 | +// 请求拦截器 | ||
| 10 | +api.interceptors.request.use( | ||
| 11 | + config => { | ||
| 12 | + const token = localStorage.getItem('token') | ||
| 13 | + if (token) { | ||
| 14 | + config.headers.Authorization = `Bearer ${token}` | ||
| 15 | + } | ||
| 16 | + return config | ||
| 17 | + }, | ||
| 18 | + error => { | ||
| 19 | + return Promise.reject(error) | ||
| 20 | + } | ||
| 21 | +) | ||
| 22 | + | ||
| 23 | +// 响应拦截器 | ||
| 24 | +api.interceptors.response.use( | ||
| 25 | + response => { | ||
| 26 | + return response.data | ||
| 27 | + }, | ||
| 28 | + error => { | ||
| 29 | + if (error.response?.status === 401) { | ||
| 30 | + localStorage.removeItem('token') | ||
| 31 | + localStorage.removeItem('userInfo') | ||
| 32 | + window.location.href = '/login' | ||
| 33 | + } | ||
| 34 | + return Promise.reject(error) | ||
| 35 | + } | ||
| 36 | +) | ||
| 37 | + | ||
| 38 | +// 产品信息接口 | ||
| 39 | +export interface ProductInfo { | ||
| 40 | + productId: number | ||
| 41 | + productCode: string | ||
| 42 | + productName: string | ||
| 43 | + productModel: string | ||
| 44 | + productType: string | ||
| 45 | + storageCapacity: string | ||
| 46 | + color: string | ||
| 47 | + officialPrice: number | ||
| 48 | + saleStatus: number | ||
| 49 | + rebateFlag: number | ||
| 50 | + saleStartDate: string | ||
| 51 | + saleEndDate: string | ||
| 52 | + imageUrl: string | ||
| 53 | + remark: string | ||
| 54 | + createTime: string | ||
| 55 | + updateTime: string | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +// 产品查询请求参数 | ||
| 59 | +export interface ProductQueryReq { | ||
| 60 | + productCode?: string | ||
| 61 | + productName?: string | ||
| 62 | + productModel?: string | ||
| 63 | + saleStatus?: number | ||
| 64 | + rebateFlag?: number | ||
| 65 | + pageNum: number | ||
| 66 | + pageSize: number | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +// 产品新增请求参数 | ||
| 70 | +export interface ProductAddReq { | ||
| 71 | + productCode: string | ||
| 72 | + productName: string | ||
| 73 | + productModel: string | ||
| 74 | + productType: string | ||
| 75 | + storageCapacity: string | ||
| 76 | + color: string | ||
| 77 | + officialPrice: number | ||
| 78 | + saleStatus: number | ||
| 79 | + rebateFlag: number | ||
| 80 | + saleStartDate: string | ||
| 81 | + saleEndDate: string | ||
| 82 | + imageUrl?: string | ||
| 83 | + remark?: string | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +// 产品修改请求参数 | ||
| 87 | +export interface ProductUpdateReq { | ||
| 88 | + productId: number | ||
| 89 | + productCode: string | ||
| 90 | + productName: string | ||
| 91 | + productModel: string | ||
| 92 | + productType: string | ||
| 93 | + storageCapacity: string | ||
| 94 | + color: string | ||
| 95 | + officialPrice: number | ||
| 96 | + saleStatus: number | ||
| 97 | + rebateFlag: number | ||
| 98 | + saleStartDate: string | ||
| 99 | + saleEndDate: string | ||
| 100 | + imageUrl?: string | ||
| 101 | + remark?: string | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +// 分页数据接口 | ||
| 105 | +export interface PageData<T> { | ||
| 106 | + records: T[] | ||
| 107 | + total: number | ||
| 108 | + current: number | ||
| 109 | + size: number | ||
| 110 | + pages: number | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +// API响应接口 | ||
| 114 | +export interface ApiResponse<T> { | ||
| 115 | + code: number | ||
| 116 | + message: string | ||
| 117 | + data: T | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +// API接口 | ||
| 121 | +export const productApi = { | ||
| 122 | + // 获取产品列表 | ||
| 123 | + getProductList: (params: ProductQueryReq) => { | ||
| 124 | + return api.get<ApiResponse<PageData<ProductInfo>>>('/product/list', { params }) | ||
| 125 | + }, | ||
| 126 | + | ||
| 127 | + // 获取产品详情 | ||
| 128 | + getProductDetail: (productId: number) => { | ||
| 129 | + return api.get<ProductInfo>(`/product/${productId}`) | ||
| 130 | + }, | ||
| 131 | + | ||
| 132 | + // 新增产品 | ||
| 133 | + addProduct: (data: ProductAddReq) => { | ||
| 134 | + return api.post('/product', data) | ||
| 135 | + }, | ||
| 136 | + | ||
| 137 | + // 修改产品 | ||
| 138 | + updateProduct: (data: ProductUpdateReq) => { | ||
| 139 | + return api.post('/product/update', data) | ||
| 140 | + }, | ||
| 141 | + | ||
| 142 | + // 删除产品 | ||
| 143 | + deleteProduct: (productId: number) => { | ||
| 144 | + return api.delete(`/product/${productId}`) | ||
| 145 | + }, | ||
| 146 | + | ||
| 147 | + // 批量删除产品 | ||
| 148 | + batchDeleteProduct: (productIds: number[]) => { | ||
| 149 | + return api.post('/product/batchDelete', productIds) | ||
| 150 | + }, | ||
| 151 | + | ||
| 152 | + // 修改销售状态 | ||
| 153 | + updateSaleStatus: (productId: number, saleStatus: number) => { | ||
| 154 | + return api.post(`/product/${productId}/status`, null, { params: { saleStatus } }) | ||
| 155 | + }, | ||
| 156 | + | ||
| 157 | + // 修改返利标识 | ||
| 158 | + updateRebateFlag: (productId: number, rebateFlag: number) => { | ||
| 159 | + return api.post(`/product/${productId}/rebate`, null, { params: { rebateFlag } }) | ||
| 160 | + } | ||
| 161 | +} |
| ... | @@ -124,6 +124,7 @@ | ... | @@ -124,6 +124,7 @@ |
| 124 | <script setup lang="ts"> | 124 | <script setup lang="ts"> |
| 125 | import { ref, computed, onMounted, watch, nextTick } from 'vue' | 125 | import { ref, computed, onMounted, watch, nextTick } from 'vue' |
| 126 | import { useRouter, useRoute } from 'vue-router' | 126 | import { useRouter, useRoute } from 'vue-router' |
| 127 | +import { logoutApi } from '../api/auth' | ||
| 127 | 128 | ||
| 128 | const router = useRouter() | 129 | const router = useRouter() |
| 129 | const route = useRoute() | 130 | const route = useRoute() |
| ... | @@ -140,6 +141,8 @@ const tabContainer = ref<HTMLElement>() | ... | @@ -140,6 +141,8 @@ const tabContainer = ref<HTMLElement>() |
| 140 | // 菜单项配置 | 141 | // 菜单项配置 |
| 141 | const menuItems = ref([ | 142 | const menuItems = ref([ |
| 142 | { name: '首页', path: '/main/dashboard', icon: '🏠' }, | 143 | { name: '首页', path: '/main/dashboard', icon: '🏠' }, |
| 144 | + { name: '产品管理', path: '/main/product', icon: '📦' }, | ||
| 145 | + { name: '经销商管理', path: '/main/dealer', icon: '🏢' }, | ||
| 143 | { | 146 | { |
| 144 | name: '系统设置', | 147 | name: '系统设置', |
| 145 | icon: '⚙️', | 148 | icon: '⚙️', |
| ... | @@ -314,15 +317,22 @@ const toggleSidebar = () => { | ... | @@ -314,15 +317,22 @@ const toggleSidebar = () => { |
| 314 | } | 317 | } |
| 315 | 318 | ||
| 316 | // 退出登录 | 319 | // 退出登录 |
| 317 | -const handleLogout = () => { | 320 | +const handleLogout = async () => { |
| 318 | if (confirm('确定要退出登录吗?')) { | 321 | if (confirm('确定要退出登录吗?')) { |
| 319 | - // 清除本地存储 | 322 | + try { |
| 323 | + // 调用后端退出登录接口 | ||
| 324 | + await logoutApi() | ||
| 325 | + } catch (error) { | ||
| 326 | + console.error('退出登录接口调用失败:', error) | ||
| 327 | + } finally { | ||
| 328 | + // 无论接口调用成功与否,都清除本地存储 | ||
| 320 | localStorage.removeItem('token') | 329 | localStorage.removeItem('token') |
| 321 | localStorage.removeItem('userInfo') | 330 | localStorage.removeItem('userInfo') |
| 322 | 331 | ||
| 323 | // 跳转到登录页 | 332 | // 跳转到登录页 |
| 324 | router.push('/') | 333 | router.push('/') |
| 325 | } | 334 | } |
| 335 | + } | ||
| 326 | } | 336 | } |
| 327 | 337 | ||
| 328 | // 监听路由变化,自动管理标签页 | 338 | // 监听路由变化,自动管理标签页 | ... | ... |
| ... | @@ -45,6 +45,15 @@ const staticRoutes: RouteRecordRaw[] = [ | ... | @@ -45,6 +45,15 @@ const staticRoutes: RouteRecordRaw[] = [ |
| 45 | } | 45 | } |
| 46 | }, | 46 | }, |
| 47 | { | 47 | { |
| 48 | + path: 'product', | ||
| 49 | + name: 'Product', | ||
| 50 | + component: () => import('@/views/product/index.vue'), | ||
| 51 | + meta: { | ||
| 52 | + title: '产品管理', | ||
| 53 | + requiresAuth: true | ||
| 54 | + } | ||
| 55 | + }, | ||
| 56 | + { | ||
| 48 | path: 'sys/role', | 57 | path: 'sys/role', |
| 49 | name: 'Role', | 58 | name: 'Role', |
| 50 | component: () => import('@/views/sys/role/index.vue'), | 59 | component: () => import('@/views/sys/role/index.vue'), |
| ... | @@ -108,6 +117,24 @@ const staticRoutes: RouteRecordRaw[] = [ | ... | @@ -108,6 +117,24 @@ const staticRoutes: RouteRecordRaw[] = [ |
| 108 | } | 117 | } |
| 109 | }, | 118 | }, |
| 110 | { | 119 | { |
| 120 | + path: 'product', | ||
| 121 | + name: 'Product', | ||
| 122 | + component: () => import('@/views/product/index.vue'), | ||
| 123 | + meta: { | ||
| 124 | + title: '产品管理', | ||
| 125 | + requiresAuth: true | ||
| 126 | + } | ||
| 127 | + }, | ||
| 128 | + { | ||
| 129 | + path: 'dealer', | ||
| 130 | + name: 'Dealer', | ||
| 131 | + component: () => import('@/views/dealer/index.vue'), | ||
| 132 | + meta: { | ||
| 133 | + title: '经销商管理', | ||
| 134 | + requiresAuth: true | ||
| 135 | + } | ||
| 136 | + }, | ||
| 137 | + { | ||
| 111 | path: 'settings', | 138 | path: 'settings', |
| 112 | name: 'Settings', | 139 | name: 'Settings', |
| 113 | component: () => import('@/views/settings/index.vue'), | 140 | component: () => import('@/views/settings/index.vue'), | ... | ... |
frontend/src/views/dealer/index.vue
0 → 100644
This diff is collapsed. Click to expand it.
frontend/src/views/product/index.vue
0 → 100644
This diff is collapsed. Click to expand it.
frontend/前端布局代码模板.md
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="users-container"> | ||
| 3 | + <!-- 搜索筛选区域 --> | ||
| 4 | + <div class="search-section"> | ||
| 5 | + <div class="search-row"> | ||
| 6 | + <div class="search-item"> | ||
| 7 | + <label>登录名称:</label> | ||
| 8 | + <input | ||
| 9 | + v-model="searchForm.username" | ||
| 10 | + type="text" | ||
| 11 | + class="search-input" | ||
| 12 | + placeholder="请输入登录名称" | ||
| 13 | + /> | ||
| 14 | + </div> | ||
| 15 | + <div class="search-item"> | ||
| 16 | + <label>用户状态:</label> | ||
| 17 | + <select v-model="searchForm.status" class="search-select"> | ||
| 18 | + <option value="">所有</option> | ||
| 19 | + <option value="1">正常</option> | ||
| 20 | + <option value="0">停用</option> | ||
| 21 | + </select> | ||
| 22 | + </div> | ||
| 23 | + <div class="search-item"> | ||
| 24 | + <label>创建时间:</label> | ||
| 25 | + <div class="date-range"> | ||
| 26 | + <div class="date-picker-container"> | ||
| 27 | + <input | ||
| 28 | + v-model="searchForm.startTime" | ||
| 29 | + type="text" | ||
| 30 | + class="date-input" | ||
| 31 | + placeholder="开始时间" | ||
| 32 | + readonly | ||
| 33 | + @click="toggleStartDatePicker" | ||
| 34 | + @mouseenter="showStartDateOptions = true" | ||
| 35 | + @mouseleave="hideStartDateOptions" | ||
| 36 | + /> | ||
| 37 | + <div v-if="showStartDateOptions" class="date-options" @mouseenter="showStartDateOptions = true" @mouseleave="hideStartDateOptions"> | ||
| 38 | + <div class="date-option" @click="selectStartDate('today')">今天</div> | ||
| 39 | + <div class="date-option" @click="selectStartDate('yesterday')">昨天</div> | ||
| 40 | + <div class="date-option" @click="selectStartDate('thisWeek')">本周</div> | ||
| 41 | + <div class="date-option" @click="selectStartDate('lastWeek')">上周</div> | ||
| 42 | + <div class="date-option" @click="selectStartDate('thisMonth')">本月</div> | ||
| 43 | + <div class="date-option" @click="selectStartDate('lastMonth')">上月</div> | ||
| 44 | + <div class="date-option" @click="selectStartDate('custom')">自定义</div> | ||
| 45 | + </div> | ||
| 46 | + <!-- 自定义日期选择器 --> | ||
| 47 | + <div v-if="showStartDatePicker" class="custom-date-picker"> | ||
| 48 | + <input | ||
| 49 | + type="date" | ||
| 50 | + v-model="searchForm.startTime" | ||
| 51 | + @change="showStartDatePicker = false" | ||
| 52 | + class="date-input" | ||
| 53 | + /> | ||
| 54 | + </div> | ||
| 55 | + </div> | ||
| 56 | + <span class="date-separator">-</span> | ||
| 57 | + <div class="date-picker-container"> | ||
| 58 | + <input | ||
| 59 | + v-model="searchForm.endTime" | ||
| 60 | + type="text" | ||
| 61 | + class="date-input" | ||
| 62 | + placeholder="结束时间" | ||
| 63 | + readonly | ||
| 64 | + @click="toggleEndDatePicker" | ||
| 65 | + @mouseenter="showEndDateOptions = true" | ||
| 66 | + @mouseleave="hideEndDateOptions" | ||
| 67 | + /> | ||
| 68 | + <div v-if="showEndDateOptions" class="date-options" @mouseenter="showEndDateOptions = true" @mouseleave="hideEndDateOptions"> | ||
| 69 | + <div class="date-option" @click="selectEndDate('today')">今天</div> | ||
| 70 | + <div class="date-option" @click="selectEndDate('yesterday')">昨天</div> | ||
| 71 | + <div class="date-option" @click="selectEndDate('thisWeek')">本周</div> | ||
| 72 | + <div class="date-option" @click="selectEndDate('lastWeek')">上周</div> | ||
| 73 | + <div class="date-option" @click="selectEndDate('thisMonth')">本月</div> | ||
| 74 | + <div class="date-option" @click="selectEndDate('lastMonth')">上月</div> | ||
| 75 | + <div class="date-option" @click="selectEndDate('custom')">自定义</div> | ||
| 76 | + </div> | ||
| 77 | + <!-- 自定义日期选择器 --> | ||
| 78 | + <div v-if="showEndDatePicker" class="custom-date-picker"> | ||
| 79 | + <input | ||
| 80 | + type="date" | ||
| 81 | + v-model="searchForm.endTime" | ||
| 82 | + @change="showEndDatePicker = false" | ||
| 83 | + class="date-input" | ||
| 84 | + /> | ||
| 85 | + </div> | ||
| 86 | + </div> | ||
| 87 | + </div> | ||
| 88 | + </div> | ||
| 89 | + <div class="search-actions"> | ||
| 90 | + <button @click="handleSearch" class="search-btn">🔍 搜索</button> | ||
| 91 | + <button @click="handleReset" class="reset-btn">🔄 重置</button> | ||
| 92 | + </div> | ||
| 93 | + </div> | ||
| 94 | + </div> | ||
| 95 | + | ||
| 96 | + <!-- 操作按钮区域 --> | ||
| 97 | + <div class="action-section"> | ||
| 98 | + <div class="action-buttons"> | ||
| 99 | + <button @click="handleAdd" class="action-btn primary">✨ 新增</button> | ||
| 100 | + <button @click="handleBatchDelete" class="action-btn danger">🗑️ 删除</button> | ||
| 101 | + </div> | ||
| 102 | + </div> | ||
| 103 | + | ||
| 104 | + <!-- 数据表格 --> | ||
| 105 | + <div class="table-section"> | ||
| 106 | + <div class="table-header"> | ||
| 107 | + <div class="table-controls"> | ||
| 108 | + <button @click="handleTableSearch" class="control-btn" title="搜索">🔍</button> | ||
| 109 | + <button @click="handleTableRefresh" class="control-btn" title="刷新">🔄</button> | ||
| 110 | + <button @click="handleTableExport" class="control-btn" title="导出">📋</button> | ||
| 111 | + <button @click="handleTableViewToggle" class="control-btn" title="视图切换">⊞</button> | ||
| 112 | + </div> | ||
| 113 | + </div> | ||
| 114 | + | ||
| 115 | + <div class="table-container"> | ||
| 116 | + <div v-if="loading" class="loading-overlay"> | ||
| 117 | + <div class="loading-spinner">加载中...</div> | ||
| 118 | + </div> | ||
| 119 | + <table class="data-table"> | ||
| 120 | + <thead> | ||
| 121 | + <tr> | ||
| 122 | + <th> | ||
| 123 | + <input | ||
| 124 | + type="checkbox" | ||
| 125 | + class="select-all" | ||
| 126 | + v-model="selectAll" | ||
| 127 | + @change="handleSelectAll" | ||
| 128 | + /> | ||
| 129 | + <th>操作</th> | ||
| 130 | + </tr> | ||
| 131 | + </thead> | ||
| 132 | + <tbody> | ||
| 133 | + <tr v-for="user in users" :key="user.userId"> | ||
| 134 | + <td> | ||
| 135 | + <button @click="handleEdit(user)" class="table-btn edit">✏️ 编辑</button> | ||
| 136 | + <button @click="handleDelete(user)" class="table-btn delete">🗑️ 删除</button> | ||
| 137 | + </td> | ||
| 138 | + </tr> | ||
| 139 | + </tbody> | ||
| 140 | + </table> | ||
| 141 | + </div> | ||
| 142 | + | ||
| 143 | + <!-- 分页信息 --> | ||
| 144 | + <div class="table-footer"> | ||
| 145 | + <div class="pagination-left"> | ||
| 146 | + <div class="pagination-info"> | ||
| 147 | + 共 {{ total }} 条记录,第 {{ currentPage }} / {{ totalPages }} 页 | ||
| 148 | + </div> | ||
| 149 | + <div class="page-size-selector"> | ||
| 150 | + <label>每页显示:</label> | ||
| 151 | + <select v-model="pageSize" @change="handlePageSizeChange" class="page-size-select"> | ||
| 152 | + <option value="10">10条</option> | ||
| 153 | + <option value="20">20条</option> | ||
| 154 | + <option value="50">50条</option> | ||
| 155 | + <option value="100">100条</option> | ||
| 156 | + </select> | ||
| 157 | + </div> | ||
| 158 | + </div> | ||
| 159 | + <div class="pagination-container"> | ||
| 160 | + <button | ||
| 161 | + @click="handlePageChange(currentPage - 1)" | ||
| 162 | + :disabled="currentPage <= 1" | ||
| 163 | + class="pagination-btn prev-btn" | ||
| 164 | + > | ||
| 165 | + 上一页 | ||
| 166 | + </button> | ||
| 167 | + <div class="pagination-pages"> | ||
| 168 | + <button | ||
| 169 | + v-for="page in getPageNumbers()" | ||
| 170 | + :key="page" | ||
| 171 | + @click="handlePageChange(page)" | ||
| 172 | + :class="['page-number', { active: page === currentPage }]" | ||
| 173 | + > | ||
| 174 | + {{ page }} | ||
| 175 | + </button> | ||
| 176 | + </div> | ||
| 177 | + <button | ||
| 178 | + @click="handlePageChange(currentPage + 1)" | ||
| 179 | + :disabled="currentPage >= totalPages" | ||
| 180 | + class="pagination-btn next-btn" | ||
| 181 | + > | ||
| 182 | + 下一页 | ||
| 183 | + </button> | ||
| 184 | + </div> | ||
| 185 | + </div> | ||
| 186 | + </div> | ||
| 187 | + | ||
| 188 | + </div> | ||
| 189 | + </div> | ||
| 190 | + </div> | ||
| 191 | +</template> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment