zhouhui.jiang

update 基础数据添加

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.DealerInfo;
4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 +import org.apache.ibatis.annotations.Mapper;
6 +
7 +@Mapper
8 +public interface DealerInfoMapper extends BaseMapper<DealerInfo> {
9 +}
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 +}
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 +-- 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);
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 }
......
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 +}
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'),
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
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