diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/AcdrConfigController.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/AcdrConfigController.java new file mode 100644 index 00000000..7b3bf1f6 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/AcdrConfigController.java @@ -0,0 +1,95 @@ +package cn.yskj.linghe.module.acdr.controller.admin.config; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.yskj.linghe.framework.common.pojo.PageParam; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.pojo.CommonResult; +import cn.yskj.linghe.framework.common.util.object.BeanUtils; +import static cn.yskj.linghe.framework.common.pojo.CommonResult.success; + +import cn.yskj.linghe.framework.excel.core.util.ExcelUtils; + +import cn.yskj.linghe.framework.apilog.core.annotation.ApiAccessLog; +import static cn.yskj.linghe.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.yskj.linghe.module.acdr.controller.admin.config.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.config.AcdrConfigDO; +import cn.yskj.linghe.module.acdr.service.config.AcdrConfigService; + +@Tag(name = "管理后台 - 宠物配置文件") +@RestController +@RequestMapping("/acdr/config") +@Validated +public class AcdrConfigController { + + @Resource + private AcdrConfigService configService; + + @PostMapping("/create") + @Operation(summary = "创建宠物配置文件") + @PreAuthorize("@ss.hasPermission('acdr:config:create')") + public CommonResult createConfig(@Valid @RequestBody AcdrConfigSaveReqVO createReqVO) { + return success(configService.createConfig(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新宠物配置文件") + @PreAuthorize("@ss.hasPermission('acdr:config:update')") + public CommonResult updateConfig(@Valid @RequestBody AcdrConfigSaveReqVO updateReqVO) { + configService.updateConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除宠物配置文件") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('acdr:config:delete')") + public CommonResult deleteConfig(@RequestParam("id") Long id) { + configService.deleteConfig(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得宠物配置文件") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('acdr:config:query')") + public CommonResult getConfig(@RequestParam("id") Long id) { + AcdrConfigDO config = configService.getConfig(id); + return success(BeanUtils.toBean(config, AcdrConfigRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得宠物配置文件分页") + @PreAuthorize("@ss.hasPermission('acdr:config:query')") + public CommonResult> getConfigPage(@Valid AcdrConfigPageReqVO pageReqVO) { + PageResult pageResult = configService.getConfigPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AcdrConfigRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出宠物配置文件 Excel") + @PreAuthorize("@ss.hasPermission('acdr:config:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportConfigExcel(@Valid AcdrConfigPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = configService.getConfigPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "宠物配置文件.xls", "数据", AcdrConfigRespVO.class, + BeanUtils.toBean(list, AcdrConfigRespVO.class)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigPageReqVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigPageReqVO.java new file mode 100644 index 00000000..b50ea16c --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigPageReqVO.java @@ -0,0 +1,28 @@ +package cn.yskj.linghe.module.acdr.controller.admin.config.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.yskj.linghe.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.yskj.linghe.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 宠物配置文件分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AcdrConfigPageReqVO extends PageParam { + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "配置表key") + private String key; + + @Schema(description = "配置表value(有可能储存的是json数据 )") + private String value; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigRespVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigRespVO.java new file mode 100644 index 00000000..e1a13682 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigRespVO.java @@ -0,0 +1,31 @@ +package cn.yskj.linghe.module.acdr.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 宠物配置文件 Response VO") +@Data +@ExcelIgnoreUnannotated +public class AcdrConfigRespVO { + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7483") + @ExcelProperty("id") + private Long id; + + @Schema(description = "配置表key", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("配置表key") + private String key; + + @Schema(description = "配置表value(有可能储存的是json数据 )", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("配置表value(有可能储存的是json数据 )") + private String value; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigSaveReqVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigSaveReqVO.java new file mode 100644 index 00000000..0bc6d1af --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/config/vo/AcdrConfigSaveReqVO.java @@ -0,0 +1,23 @@ +package cn.yskj.linghe.module.acdr.controller.admin.config.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 宠物配置文件新增/修改 Request VO") +@Data +public class AcdrConfigSaveReqVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7483") + private Long id; + + @Schema(description = "配置表key", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "配置表key不能为空") + private String key; + + @Schema(description = "配置表value(有可能储存的是json数据 )", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "配置表value(有可能储存的是json数据 )不能为空") + private String value; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/PetExpertCertificationController.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/PetExpertCertificationController.java new file mode 100644 index 00000000..5d63bbd2 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/PetExpertCertificationController.java @@ -0,0 +1,95 @@ +package cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.yskj.linghe.framework.common.pojo.PageParam; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.pojo.CommonResult; +import cn.yskj.linghe.framework.common.util.object.BeanUtils; +import static cn.yskj.linghe.framework.common.pojo.CommonResult.success; + +import cn.yskj.linghe.framework.excel.core.util.ExcelUtils; + +import cn.yskj.linghe.framework.apilog.core.annotation.ApiAccessLog; +import static cn.yskj.linghe.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification.PetExpertCertificationDO; +import cn.yskj.linghe.module.acdr.service.petexpertcertification.PetExpertCertificationService; + +@Tag(name = "管理后台 - 宠托师审核") +@RestController +@RequestMapping("/acdr/pet-expert-certification") +@Validated +public class PetExpertCertificationController { + + @Resource + private PetExpertCertificationService petExpertCertificationService; + + @PostMapping("/create") + @Operation(summary = "创建宠托师审核") + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:create')") + public CommonResult createPetExpertCertification(@Valid @RequestBody PetExpertCertificationSaveReqVO createReqVO) { + return success(petExpertCertificationService.createPetExpertCertification(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新宠托师审核") + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:update')") + public CommonResult updatePetExpertCertification(@Valid @RequestBody PetExpertCertificationSaveReqVO updateReqVO) { + petExpertCertificationService.updatePetExpertCertification(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除宠托师审核") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:delete')") + public CommonResult deletePetExpertCertification(@RequestParam("id") Long id) { + petExpertCertificationService.deletePetExpertCertification(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得宠托师审核") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:query')") + public CommonResult getPetExpertCertification(@RequestParam("id") Long id) { + PetExpertCertificationDO petExpertCertification = petExpertCertificationService.getPetExpertCertification(id); + return success(BeanUtils.toBean(petExpertCertification, PetExpertCertificationRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得宠托师审核分页") + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:query')") + public CommonResult> getPetExpertCertificationPage(@Valid PetExpertCertificationPageReqVO pageReqVO) { + PageResult pageResult = petExpertCertificationService.getPetExpertCertificationPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, PetExpertCertificationRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出宠托师审核 Excel") + @PreAuthorize("@ss.hasPermission('acdr:pet-expert-certification:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportPetExpertCertificationExcel(@Valid PetExpertCertificationPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = petExpertCertificationService.getPetExpertCertificationPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "宠托师审核.xls", "数据", PetExpertCertificationRespVO.class, + BeanUtils.toBean(list, PetExpertCertificationRespVO.class)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationPageReqVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationPageReqVO.java new file mode 100644 index 00000000..66981e10 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationPageReqVO.java @@ -0,0 +1,40 @@ +package cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.yskj.linghe.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.yskj.linghe.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 宠托师审核分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PetExpertCertificationPageReqVO extends PageParam { + + @Schema(description = "审核内容") + private String content; + + @Schema(description = "申请职务", example = "2") + private String type; + + @Schema(description = "审核材料") + private String imageUrls; + + @Schema(description = "审核状态") + private Integer state; + + @Schema(description = "审核管理员", example = "7048") + private Long verifyAdminId; + + @Schema(description = "创建人", example = "21626") + private Long userId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationRespVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationRespVO.java new file mode 100644 index 00000000..868f26bd --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationRespVO.java @@ -0,0 +1,47 @@ +package cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 宠托师审核 Response VO") +@Data +@ExcelIgnoreUnannotated +public class PetExpertCertificationRespVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19647") + @ExcelProperty("ID") + private Long id; + + @Schema(description = "审核内容") + @ExcelProperty("审核内容") + private String content; + + @Schema(description = "申请职务", example = "2") + @ExcelProperty("申请职务") + private String type; + + @Schema(description = "审核材料") + @ExcelProperty("审核材料") + private String imageUrls; + + @Schema(description = "审核状态") + @ExcelProperty("审核状态") + private Integer state; + + @Schema(description = "审核管理员", example = "7048") + @ExcelProperty("审核管理员") + private Long verifyAdminId; + + @Schema(description = "创建人", example = "21626") + @ExcelProperty("创建人") + private Long userId; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationSaveReqVO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationSaveReqVO.java new file mode 100644 index 00000000..9a68b427 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/controller/admin/petexpertcertification/vo/PetExpertCertificationSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 宠托师审核新增/修改 Request VO") +@Data +public class PetExpertCertificationSaveReqVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19647") + private Long id; + + @Schema(description = "审核内容") + private String content; + + @Schema(description = "申请职务", example = "2") + private String type; + + @Schema(description = "审核材料") + private String imageUrls; + + @Schema(description = "审核状态") + private Integer state; + + @Schema(description = "审核管理员", example = "7048") + private Long verifyAdminId; + + @Schema(description = "创建人", example = "21626") + private Long userId; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/config/AcdrConfigDO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/config/AcdrConfigDO.java new file mode 100644 index 00000000..b97493e0 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/config/AcdrConfigDO.java @@ -0,0 +1,39 @@ +package cn.yskj.linghe.module.acdr.dal.dataobject.config; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.yskj.linghe.framework.mybatis.core.dataobject.BaseDO; + +/** + * 宠物配置文件 DO + * + * @author 林河 + */ +@TableName("acdr_config") +@KeySequence("acdr_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AcdrConfigDO extends BaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 配置表key + */ + private String key; + /** + * 配置表value(有可能储存的是json数据 ) + */ + private String value; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/petexpertcertification/PetExpertCertificationDO.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/petexpertcertification/PetExpertCertificationDO.java new file mode 100644 index 00000000..026a3308 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/dataobject/petexpertcertification/PetExpertCertificationDO.java @@ -0,0 +1,55 @@ +package cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.yskj.linghe.framework.mybatis.core.dataobject.BaseDO; + +/** + * 宠托师审核 DO + * + * @author 林河 + */ +@TableName("acdr_pet_expert_certification") +@KeySequence("acdr_pet_expert_certification_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PetExpertCertificationDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + /** + * 审核内容 + */ + private String content; + /** + * 申请职务 + */ + private String type; + /** + * 审核材料 + */ + private String imageUrls; + /** + * 审核状态 + */ + private Integer state; + /** + * 审核管理员 + */ + private Long verifyAdminId; + /** + * 创建人 + */ + private Long userId; + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/config/AcdrConfigMapper.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/config/AcdrConfigMapper.java new file mode 100644 index 00000000..3029916c --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/config/AcdrConfigMapper.java @@ -0,0 +1,28 @@ +package cn.yskj.linghe.module.acdr.dal.mysql.config; + +import java.util.*; + +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.yskj.linghe.framework.mybatis.core.mapper.BaseMapperX; +import cn.yskj.linghe.module.acdr.dal.dataobject.config.AcdrConfigDO; +import org.apache.ibatis.annotations.Mapper; +import cn.yskj.linghe.module.acdr.controller.admin.config.vo.*; + +/** + * 宠物配置文件 Mapper + * + * @author 林河 + */ +@Mapper +public interface AcdrConfigMapper extends BaseMapperX { + + default PageResult selectPage(AcdrConfigPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .betweenIfPresent(AcdrConfigDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(AcdrConfigDO::getKey, reqVO.getKey()) + .eqIfPresent(AcdrConfigDO::getValue, reqVO.getValue()) + .orderByDesc(AcdrConfigDO::getId)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/petexpertcertification/PetExpertCertificationMapper.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/petexpertcertification/PetExpertCertificationMapper.java new file mode 100644 index 00000000..52abb0b5 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/dal/mysql/petexpertcertification/PetExpertCertificationMapper.java @@ -0,0 +1,32 @@ +package cn.yskj.linghe.module.acdr.dal.mysql.petexpertcertification; + +import java.util.*; + +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.yskj.linghe.framework.mybatis.core.mapper.BaseMapperX; +import cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification.PetExpertCertificationDO; +import org.apache.ibatis.annotations.Mapper; +import cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo.*; + +/** + * 宠托师审核 Mapper + * + * @author 林河 + */ +@Mapper +public interface PetExpertCertificationMapper extends BaseMapperX { + + default PageResult selectPage(PetExpertCertificationPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(PetExpertCertificationDO::getContent, reqVO.getContent()) + .eqIfPresent(PetExpertCertificationDO::getType, reqVO.getType()) + .eqIfPresent(PetExpertCertificationDO::getImageUrls, reqVO.getImageUrls()) + .eqIfPresent(PetExpertCertificationDO::getState, reqVO.getState()) + .eqIfPresent(PetExpertCertificationDO::getVerifyAdminId, reqVO.getVerifyAdminId()) + .eqIfPresent(PetExpertCertificationDO::getUserId, reqVO.getUserId()) + .betweenIfPresent(PetExpertCertificationDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(PetExpertCertificationDO::getId)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigService.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigService.java new file mode 100644 index 00000000..a4225454 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigService.java @@ -0,0 +1,55 @@ +package cn.yskj.linghe.module.acdr.service.config; + +import java.util.*; +import jakarta.validation.*; +import cn.yskj.linghe.module.acdr.controller.admin.config.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.config.AcdrConfigDO; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.pojo.PageParam; + +/** + * 宠物配置文件 Service 接口 + * + * @author 林河 + */ +public interface AcdrConfigService { + + /** + * 创建宠物配置文件 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createConfig(@Valid AcdrConfigSaveReqVO createReqVO); + + /** + * 更新宠物配置文件 + * + * @param updateReqVO 更新信息 + */ + void updateConfig(@Valid AcdrConfigSaveReqVO updateReqVO); + + /** + * 删除宠物配置文件 + * + * @param id 编号 + */ + void deleteConfig(Long id); + + /** + * 获得宠物配置文件 + * + * @param id 编号 + * @return 宠物配置文件 + */ + AcdrConfigDO getConfig(Long id); + + /** + * 获得宠物配置文件分页 + * + * @param pageReqVO 分页查询 + * @return 宠物配置文件分页 + */ + PageResult getConfigPage(AcdrConfigPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImpl.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImpl.java new file mode 100644 index 00000000..6844134f --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImpl.java @@ -0,0 +1,71 @@ +package cn.yskj.linghe.module.acdr.service.config; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import cn.yskj.linghe.module.acdr.controller.admin.config.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.config.AcdrConfigDO; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.util.object.BeanUtils; + +import cn.yskj.linghe.module.acdr.dal.mysql.config.AcdrConfigMapper; + +import static cn.yskj.linghe.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.yskj.linghe.module.acdr.enums.ErrorCodeConstants.*; + +/** + * 宠物配置文件 Service 实现类 + * + * @author 林河 + */ +@Service +@Validated +public class AcdrConfigServiceImpl implements AcdrConfigService { + + @Resource + private AcdrConfigMapper acdrConfigMapper; + + @Override + public Long createConfig(AcdrConfigSaveReqVO createReqVO) { + // 插入 + AcdrConfigDO config = BeanUtils.toBean(createReqVO, AcdrConfigDO.class); + acdrConfigMapper.insert(config); + // 返回 + return config.getId(); + } + + @Override + public void updateConfig(AcdrConfigSaveReqVO updateReqVO) { + // 校验存在 + validateConfigExists(updateReqVO.getId()); + // 更新 + AcdrConfigDO updateObj = BeanUtils.toBean(updateReqVO, AcdrConfigDO.class); + acdrConfigMapper.updateById(updateObj); + } + + @Override + public void deleteConfig(Long id) { + // 校验存在 + validateConfigExists(id); + // 删除 + acdrConfigMapper.deleteById(id); + } + + private void validateConfigExists(Long id) { + if (acdrConfigMapper.selectById(id) == null) { + throw exception(CONFIG_NOT_EXISTS); + } + } + + @Override + public AcdrConfigDO getConfig(Long id) { + return acdrConfigMapper.selectById(id); + } + + @Override + public PageResult getConfigPage(AcdrConfigPageReqVO pageReqVO) { + return acdrConfigMapper.selectPage(pageReqVO); + } + +} diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationService.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationService.java new file mode 100644 index 00000000..7e21c340 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationService.java @@ -0,0 +1,55 @@ +package cn.yskj.linghe.module.acdr.service.petexpertcertification; + +import java.util.*; +import jakarta.validation.*; +import cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification.PetExpertCertificationDO; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.pojo.PageParam; + +/** + * 宠托师审核 Service 接口 + * + * @author 林河 + */ +public interface PetExpertCertificationService { + + /** + * 创建宠托师审核 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPetExpertCertification(@Valid PetExpertCertificationSaveReqVO createReqVO); + + /** + * 更新宠托师审核 + * + * @param updateReqVO 更新信息 + */ + void updatePetExpertCertification(@Valid PetExpertCertificationSaveReqVO updateReqVO); + + /** + * 删除宠托师审核 + * + * @param id 编号 + */ + void deletePetExpertCertification(Long id); + + /** + * 获得宠托师审核 + * + * @param id 编号 + * @return 宠托师审核 + */ + PetExpertCertificationDO getPetExpertCertification(Long id); + + /** + * 获得宠托师审核分页 + * + * @param pageReqVO 分页查询 + * @return 宠托师审核分页 + */ + PageResult getPetExpertCertificationPage(PetExpertCertificationPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImpl.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImpl.java new file mode 100644 index 00000000..51a6c458 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImpl.java @@ -0,0 +1,74 @@ +package cn.yskj.linghe.module.acdr.service.petexpertcertification; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification.PetExpertCertificationDO; +import cn.yskj.linghe.framework.common.pojo.PageResult; +import cn.yskj.linghe.framework.common.pojo.PageParam; +import cn.yskj.linghe.framework.common.util.object.BeanUtils; + +import cn.yskj.linghe.module.acdr.dal.mysql.petexpertcertification.PetExpertCertificationMapper; + +import static cn.yskj.linghe.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.yskj.linghe.module.acdr.enums.ErrorCodeConstants.*; + +/** + * 宠托师审核 Service 实现类 + * + * @author 林河 + */ +@Service +@Validated +public class PetExpertCertificationServiceImpl implements PetExpertCertificationService { + + @Resource + private PetExpertCertificationMapper petExpertCertificationMapper; + + @Override + public Long createPetExpertCertification(PetExpertCertificationSaveReqVO createReqVO) { + // 插入 + PetExpertCertificationDO petExpertCertification = BeanUtils.toBean(createReqVO, PetExpertCertificationDO.class); + petExpertCertificationMapper.insert(petExpertCertification); + // 返回 + return petExpertCertification.getId(); + } + + @Override + public void updatePetExpertCertification(PetExpertCertificationSaveReqVO updateReqVO) { + // 校验存在 + validatePetExpertCertificationExists(updateReqVO.getId()); + // 更新 + PetExpertCertificationDO updateObj = BeanUtils.toBean(updateReqVO, PetExpertCertificationDO.class); + petExpertCertificationMapper.updateById(updateObj); + } + + @Override + public void deletePetExpertCertification(Long id) { + // 校验存在 + validatePetExpertCertificationExists(id); + // 删除 + petExpertCertificationMapper.deleteById(id); + } + + private void validatePetExpertCertificationExists(Long id) { + if (petExpertCertificationMapper.selectById(id) == null) { + throw exception(PET_EXPERT_CERTIFICATION_NOT_EXISTS); + } + } + + @Override + public PetExpertCertificationDO getPetExpertCertification(Long id) { + return petExpertCertificationMapper.selectById(id); + } + + @Override + public PageResult getPetExpertCertificationPage(PetExpertCertificationPageReqVO pageReqVO) { + return petExpertCertificationMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/config/AcdrConfigMapper.xml b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/config/AcdrConfigMapper.xml new file mode 100644 index 00000000..4ca0bca8 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/config/AcdrConfigMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/petexpertcertification/PetExpertCertificationMapper.xml b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/petexpertcertification/PetExpertCertificationMapper.xml new file mode 100644 index 00000000..dc11c5e2 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/main/resources/mapper/petexpertcertification/PetExpertCertificationMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImplTest.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImplTest.java new file mode 100644 index 00000000..3e6f4249 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/config/AcdrConfigServiceImplTest.java @@ -0,0 +1,138 @@ +package cn.yskj.linghe.module.acdr.service.config; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import jakarta.annotation.Resource; + +import cn.yskj.linghe.framework.test.core.ut.BaseDbUnitTest; + +import cn.yskj.linghe.module.acdr.controller.admin.config.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.config.AcdrConfigDO; +import cn.yskj.linghe.module.acdr.dal.mysql.config.AcdrConfigMapper; +import cn.yskj.linghe.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.yskj.linghe.module.acdr.enums.ErrorCodeConstants.*; +import static cn.yskj.linghe.framework.test.core.util.AssertUtils.*; +import static cn.yskj.linghe.framework.test.core.util.RandomUtils.*; +import static cn.yskj.linghe.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.yskj.linghe.framework.common.util.object.ObjectUtils.*; +import static cn.yskj.linghe.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link AcdrConfigServiceImpl} 的单元测试类 + * + * @author 林河 + */ +@Import(AcdrConfigServiceImpl.class) +public class AcdrConfigServiceImplTest extends BaseDbUnitTest { + + @Resource + private AcdrConfigServiceImpl configService; + + @Resource + private AcdrConfigMapper configMapper; + + @Test + public void testCreateConfig_success() { + // 准备参数 + AcdrConfigSaveReqVO createReqVO = randomPojo(AcdrConfigSaveReqVO.class).setId(null); + + // 调用 + Long configId = configService.createConfig(createReqVO); + // 断言 + assertNotNull(configId); + // 校验记录的属性是否正确 + AcdrConfigDO config = configMapper.selectById(configId); + assertPojoEquals(createReqVO, config, "id"); + } + + @Test + public void testUpdateConfig_success() { + // mock 数据 + AcdrConfigDO dbConfig = randomPojo(AcdrConfigDO.class); + configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + AcdrConfigSaveReqVO updateReqVO = randomPojo(AcdrConfigSaveReqVO.class, o -> { + o.setId(dbConfig.getId()); // 设置更新的 ID + }); + + // 调用 + configService.updateConfig(updateReqVO); + // 校验是否更新正确 + AcdrConfigDO config = configMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, config); + } + + @Test + public void testUpdateConfig_notExists() { + // 准备参数 + AcdrConfigSaveReqVO updateReqVO = randomPojo(AcdrConfigSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> configService.updateConfig(updateReqVO), CONFIG_NOT_EXISTS); + } + + @Test + public void testDeleteConfig_success() { + // mock 数据 + AcdrConfigDO dbConfig = randomPojo(AcdrConfigDO.class); + configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbConfig.getId(); + + // 调用 + configService.deleteConfig(id); + // 校验数据不存在了 + assertNull(configMapper.selectById(id)); + } + + @Test + public void testDeleteConfig_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> configService.deleteConfig(id), CONFIG_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetConfigPage() { + // mock 数据 + AcdrConfigDO dbConfig = randomPojo(AcdrConfigDO.class, o -> { // 等会查询到 + o.setCreateTime(null); + o.setKey(null); + o.setValue(null); + }); + configMapper.insert(dbConfig); + // 测试 createTime 不匹配 + configMapper.insert(cloneIgnoreId(dbConfig, o -> o.setCreateTime(null))); + // 测试 key 不匹配 + configMapper.insert(cloneIgnoreId(dbConfig, o -> o.setKey(null))); + // 测试 value 不匹配 + configMapper.insert(cloneIgnoreId(dbConfig, o -> o.setValue(null))); + // 准备参数 + AcdrConfigPageReqVO reqVO = new AcdrConfigPageReqVO(); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setKey(null); + reqVO.setValue(null); + + // 调用 + PageResult pageResult = configService.getConfigPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbConfig, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImplTest.java b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImplTest.java new file mode 100644 index 00000000..68d97c77 --- /dev/null +++ b/acdr-admin/yskj-module-acdr/yskj-module-acdr-biz/src/test/java/cn/yskj/linghe/module/acdr/service/petexpertcertification/PetExpertCertificationServiceImplTest.java @@ -0,0 +1,154 @@ +package cn.yskj.linghe.module.acdr.service.petexpertcertification; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import jakarta.annotation.Resource; + +import cn.yskj.linghe.framework.test.core.ut.BaseDbUnitTest; + +import cn.yskj.linghe.module.acdr.controller.admin.petexpertcertification.vo.*; +import cn.yskj.linghe.module.acdr.dal.dataobject.petexpertcertification.PetExpertCertificationDO; +import cn.yskj.linghe.module.acdr.dal.mysql.petexpertcertification.PetExpertCertificationMapper; +import cn.yskj.linghe.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.yskj.linghe.module.acdr.enums.ErrorCodeConstants.*; +import static cn.yskj.linghe.framework.test.core.util.AssertUtils.*; +import static cn.yskj.linghe.framework.test.core.util.RandomUtils.*; +import static cn.yskj.linghe.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.yskj.linghe.framework.common.util.object.ObjectUtils.*; +import static cn.yskj.linghe.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link PetExpertCertificationServiceImpl} 的单元测试类 + * + * @author 林河 + */ +@Import(PetExpertCertificationServiceImpl.class) +public class PetExpertCertificationServiceImplTest extends BaseDbUnitTest { + + @Resource + private PetExpertCertificationServiceImpl petExpertCertificationService; + + @Resource + private PetExpertCertificationMapper petExpertCertificationMapper; + + @Test + public void testCreatePetExpertCertification_success() { + // 准备参数 + PetExpertCertificationSaveReqVO createReqVO = randomPojo(PetExpertCertificationSaveReqVO.class).setId(null); + + // 调用 + Long petExpertCertificationId = petExpertCertificationService.createPetExpertCertification(createReqVO); + // 断言 + assertNotNull(petExpertCertificationId); + // 校验记录的属性是否正确 + PetExpertCertificationDO petExpertCertification = petExpertCertificationMapper.selectById(petExpertCertificationId); + assertPojoEquals(createReqVO, petExpertCertification, "id"); + } + + @Test + public void testUpdatePetExpertCertification_success() { + // mock 数据 + PetExpertCertificationDO dbPetExpertCertification = randomPojo(PetExpertCertificationDO.class); + petExpertCertificationMapper.insert(dbPetExpertCertification);// @Sql: 先插入出一条存在的数据 + // 准备参数 + PetExpertCertificationSaveReqVO updateReqVO = randomPojo(PetExpertCertificationSaveReqVO.class, o -> { + o.setId(dbPetExpertCertification.getId()); // 设置更新的 ID + }); + + // 调用 + petExpertCertificationService.updatePetExpertCertification(updateReqVO); + // 校验是否更新正确 + PetExpertCertificationDO petExpertCertification = petExpertCertificationMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, petExpertCertification); + } + + @Test + public void testUpdatePetExpertCertification_notExists() { + // 准备参数 + PetExpertCertificationSaveReqVO updateReqVO = randomPojo(PetExpertCertificationSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> petExpertCertificationService.updatePetExpertCertification(updateReqVO), PET_EXPERT_CERTIFICATION_NOT_EXISTS); + } + + @Test + public void testDeletePetExpertCertification_success() { + // mock 数据 + PetExpertCertificationDO dbPetExpertCertification = randomPojo(PetExpertCertificationDO.class); + petExpertCertificationMapper.insert(dbPetExpertCertification);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbPetExpertCertification.getId(); + + // 调用 + petExpertCertificationService.deletePetExpertCertification(id); + // 校验数据不存在了 + assertNull(petExpertCertificationMapper.selectById(id)); + } + + @Test + public void testDeletePetExpertCertification_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> petExpertCertificationService.deletePetExpertCertification(id), PET_EXPERT_CERTIFICATION_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetPetExpertCertificationPage() { + // mock 数据 + PetExpertCertificationDO dbPetExpertCertification = randomPojo(PetExpertCertificationDO.class, o -> { // 等会查询到 + o.setContent(null); + o.setType(null); + o.setImageUrls(null); + o.setState(null); + o.setVerifyAdminId(null); + o.setUserId(null); + o.setCreateTime(null); + }); + petExpertCertificationMapper.insert(dbPetExpertCertification); + // 测试 content 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setContent(null))); + // 测试 type 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setType(null))); + // 测试 imageUrls 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setImageUrls(null))); + // 测试 state 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setState(null))); + // 测试 verifyAdminId 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setVerifyAdminId(null))); + // 测试 userId 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setUserId(null))); + // 测试 createTime 不匹配 + petExpertCertificationMapper.insert(cloneIgnoreId(dbPetExpertCertification, o -> o.setCreateTime(null))); + // 准备参数 + PetExpertCertificationPageReqVO reqVO = new PetExpertCertificationPageReqVO(); + reqVO.setContent(null); + reqVO.setType(null); + reqVO.setImageUrls(null); + reqVO.setState(null); + reqVO.setVerifyAdminId(null); + reqVO.setUserId(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = petExpertCertificationService.getPetExpertCertificationPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbPetExpertCertification, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/api/acdr/config/index.ts b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/api/acdr/config/index.ts new file mode 100644 index 00000000..dedd2621 --- /dev/null +++ b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/api/acdr/config/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// 宠物配置文件 VO +export interface ConfigVO { + id: number // id + key: string // 配置表key + value: string // 配置表value(有可能储存的是json数据 ) +} + +// 宠物配置文件 API +export const ConfigApi = { + // 查询宠物配置文件分页 + getConfigPage: async (params: any) => { + return await request.get({ url: `/acdr/config/page`, params }) + }, + + // 查询宠物配置文件详情 + getConfig: async (id: number) => { + return await request.get({ url: `/acdr/config/get?id=` + id }) + }, + + // 新增宠物配置文件 + createConfig: async (data: ConfigVO) => { + return await request.post({ url: `/acdr/config/create`, data }) + }, + + // 修改宠物配置文件 + updateConfig: async (data: ConfigVO) => { + return await request.put({ url: `/acdr/config/update`, data }) + }, + + // 删除宠物配置文件 + deleteConfig: async (id: number) => { + return await request.delete({ url: `/acdr/config/delete?id=` + id }) + }, + + // 导出宠物配置文件 Excel + exportConfig: async (params) => { + return await request.download({ url: `/acdr/config/export-excel`, params }) + }, +} \ No newline at end of file diff --git a/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/ConfigForm.vue b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/ConfigForm.vue new file mode 100644 index 00000000..6ae5d30b --- /dev/null +++ b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/ConfigForm.vue @@ -0,0 +1,98 @@ + + \ No newline at end of file diff --git a/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/index.vue b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/index.vue new file mode 100644 index 00000000..4843fd02 --- /dev/null +++ b/acdr-admin/yskj-ui/yskj-ui-admin-vue3/src/views/acdr/config/index.vue @@ -0,0 +1,198 @@ + + + \ No newline at end of file diff --git a/acdr-ui/tootls/social-auto-upload b/acdr-ui/tootls/social-auto-upload new file mode 160000 index 00000000..f5b96d24 --- /dev/null +++ b/acdr-ui/tootls/social-auto-upload @@ -0,0 +1 @@ +Subproject commit f5b96d24c7119ac7402d94e37600e47f4319475d diff --git a/acdr-ui/tootls/代码生成工具.py b/acdr-ui/tootls/代码生成工具.py new file mode 100644 index 00000000..c9ea7650 --- /dev/null +++ b/acdr-ui/tootls/代码生成工具.py @@ -0,0 +1,140 @@ +import os +import shutil +import pymysql +import tkinter as tk +from tkinter import filedialog, messagebox, StringVar + +# 执行 SQL 文件 +def execute_sql_file(sql_file_path, db_config): + try: + # 连接 MySQL 数据库 + connection = pymysql.connect( + host=db_config['host'], + user=db_config['user'], + password=db_config['password'], + database=db_config['database'], + port=int(db_config['port']) + ) + cursor = connection.cursor() + with open(sql_file_path, 'r', encoding='utf-8') as file: + sql_script = file.read() + cursor.execute(sql_script) + connection.commit() + messagebox.showinfo("SQL执行成功", f"SQL文件 {sql_file_path} 已成功执行") + except Exception as e: + messagebox.showerror("SQL执行失败", f"执行SQL文件时出错: {e}") + finally: + cursor.close() + connection.close() + +# 处理解压后的文件 +def handle_extracted_files(temp_extract_dir, output_dir, ui_dir, db_config): + for root_dir, dirs, files in os.walk(temp_extract_dir): + for file in files: + src_file_path = os.path.join(root_dir, file) + relative_path = os.path.relpath(root_dir, temp_extract_dir) + top_level_dir = relative_path.split(os.sep)[0] # 获取一级目录名 + + if "module" in top_level_dir: + dest_file_path = os.path.join(output_dir, relative_path, file) + os.makedirs(os.path.dirname(dest_file_path), exist_ok=True) + shutil.copy2(src_file_path, dest_file_path) + print(f"复制文件 {src_file_path} 到 {dest_file_path}") + + elif "sql" in top_level_dir and file == "sql.sql": + execute_sql_file(src_file_path, db_config) + print(f"执行SQL文件: {src_file_path}") + + elif "vue" in top_level_dir: + dest_file_path = os.path.join(ui_dir, relative_path, file) + os.makedirs(os.path.dirname(dest_file_path), exist_ok=True) + shutil.copy2(src_file_path, dest_file_path) + print(f"复制文件 {src_file_path} 到 {dest_file_path}") + +# 选择zip文件 +def select_zip_file(): + zip_file_path.set(filedialog.askopenfilename(filetypes=[("ZIP files", "*.zip")])) + +# 选择输出目录 +def select_output_dir(): + output_dir.set(filedialog.askdirectory()) + +# 选择UI目录 +def select_ui_dir(): + ui_dir.set(filedialog.askdirectory()) + +# 解压并处理文件 +def extract_and_process_files(): + if not zip_file_path.get() or not output_dir.get() or not ui_dir.get(): + messagebox.showwarning("警告", "请确保选择了ZIP文件和目标目录") + return + + # 设置数据库连接参数 + db_config = { + 'host': host_var.get() or 'localhost', + 'user': user_var.get() or 'root', + 'password': password_var.get() or 'root', + 'database': db_var.get() or 'cwet', + 'port': port_var.get() or 3306 + } + + # 解压ZIP文件 + temp_extract_dir = os.path.join(output_dir.get(), "temp_extracted") + shutil.unpack_archive(zip_file_path.get(), temp_extract_dir) + + # 处理解压后的文件 + handle_extracted_files(temp_extract_dir, output_dir.get(), ui_dir.get(), db_config) + + # 清理临时文件夹 + shutil.rmtree(temp_extract_dir) + messagebox.showinfo("完成", "文件处理完成!") + +# 创建主窗口 +root = tk.Tk() +root.title("代码生成工具") + +# 创建变量 +zip_file_path = StringVar() +output_dir = StringVar() +ui_dir = StringVar() + +# 数据库连接参数 +host_var = StringVar(value='localhost') +user_var = StringVar(value='root') +password_var = StringVar(value='root') +db_var = StringVar(value='cwet') +port_var = StringVar(value='3306') + +# GUI布局 +tk.Label(root, text="选择ZIP文件:").grid(row=0, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=zip_file_path, width=50).grid(row=0, column=1, padx=10, pady=5) +tk.Button(root, text="选择ZIP文件", command=select_zip_file).grid(row=0, column=2, padx=10, pady=5) + +tk.Label(root, text="选择输出目录:").grid(row=1, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=output_dir, width=50).grid(row=1, column=1, padx=10, pady=5) +tk.Button(root, text="选择输出目录", command=select_output_dir).grid(row=1, column=2, padx=10, pady=5) + +tk.Label(root, text="选择UI目录:").grid(row=2, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=ui_dir, width=50).grid(row=2, column=1, padx=10, pady=5) +tk.Button(root, text="选择UI目录", command=select_ui_dir).grid(row=2, column=2, padx=10, pady=5) + +# 数据库设置 +tk.Label(root, text="数据库主机:").grid(row=3, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=host_var).grid(row=3, column=1, padx=10, pady=5) + +tk.Label(root, text="用户名:").grid(row=4, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=user_var).grid(row=4, column=1, padx=10, pady=5) + +tk.Label(root, text="密码:").grid(row=5, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=password_var).grid(row=5, column=1, padx=10, pady=5) + +tk.Label(root, text="数据库名:").grid(row=6, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=db_var).grid(row=6, column=1, padx=10, pady=5) + +tk.Label(root, text="端口:").grid(row=7, column=0, padx=10, pady=5) +tk.Entry(root, textvariable=port_var).grid(row=7, column=1, padx=10, pady=5) + +tk.Button(root, text="开始处理", command=extract_and_process_files).grid(row=8, column=1, padx=10, pady=20) + +# 运行应用 +root.mainloop() diff --git a/acdr-ui/tootls/图形工具.py b/acdr-ui/tootls/图形工具.py new file mode 100644 index 00000000..5c004d54 --- /dev/null +++ b/acdr-ui/tootls/图形工具.py @@ -0,0 +1,150 @@ +import os +import cv2 +import numpy as np +import re +from tkinter import * +from tkinter import filedialog, messagebox, colorchooser +from PIL import Image +import tkinter as tk + +# 主应用类 +class ImageSplitterApp: + def __init__(self, root): + self.root = root + self.root.title("图像分割工具") + self.root.geometry("500x450") + + # 文件或文件夹路径 + self.file_path = None + self.folder_path = None + self.selected_color = (0, 0, 0) # 默认黑色 + + # 创建选择文件按钮 + Button(self.root, text="选择单个文件", command=self.select_file).pack(pady=10) + Button(self.root, text="选择文件夹", command=self.select_folder).pack(pady=10) + + # 选择颜色按钮 + Label(self.root, text="选择分割线颜色:").pack(pady=10) + Button(self.root, text="打开取色器", command=self.pick_color).pack(pady=5) + + # 当前选择的颜色显示 + self.color_label = Label(self.root, text=f"当前颜色: {self.selected_color}") + self.color_label.pack(pady=5) + + # 命名规则 + Label(self.root, text="请输入保存图片的命名规则(支持正则):").pack(pady=10) + self.naming_entry = Entry(self.root) + self.naming_entry.insert(0, r"sub_image_{idx}") # 默认命名规则 + self.naming_entry.pack(pady=5) + + # 分割按钮 + Button(self.root, text="开始分割", command=self.split_image).pack(pady=20) + + # 选择保存文件夹 + self.save_folder_path = None + Button(self.root, text="选择保存文件夹", command=self.select_save_folder).pack(pady=10) + + def select_file(self): + self.file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png *.jpg *.jpeg")]) + if self.file_path: + messagebox.showinfo("文件选择", f"已选择文件: {self.file_path}") + + def select_folder(self): + self.folder_path = filedialog.askdirectory() + if self.folder_path: + messagebox.showinfo("文件夹选择", f"已选择文件夹: {self.folder_path}") + + def select_save_folder(self): + self.save_folder_path = filedialog.askdirectory() + if self.save_folder_path: + messagebox.showinfo("保存文件夹选择", f"已选择保存文件夹: {self.save_folder_path}") + + # 颜色取色器 + def pick_color(self): + color = colorchooser.askcolor(title="选择分割线颜色") + if color: + self.selected_color = tuple(map(int, color[0])) # 颜色转换为整数的 (r, g, b) + self.color_label.config(text=f"当前颜色: {self.selected_color}") + + # 查找分割线的位置 (通过指定颜色) + def find_dividing_lines(self, image, line_color): + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度图 + _, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV) # 进行二值化 + + # 查找水平和垂直线条 + horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 1)) + vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 25)) + + # 水平线 + horizontal_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) + + # 垂直线 + vertical_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, vertical_kernel, iterations=2) + + return horizontal_lines, vertical_lines + + # 分割图像 + def split_image(self): + # 提取颜色 + line_color = self.selected_color + + # 读取命名规则 + naming_rule = self.naming_entry.get() + + # 处理单个文件 + if self.file_path: + self.process_file(self.file_path, line_color, naming_rule) + + # 处理文件夹中的所有文件 + if self.folder_path: + for file_name in os.listdir(self.folder_path): + if file_name.endswith(('.png', '.jpg', '.jpeg')): + file_path = os.path.join(self.folder_path, file_name) + self.process_file(file_path, line_color, naming_rule) + + # 处理单个文件的分割 + def process_file(self, file_path, line_color, naming_rule): + image = cv2.imread(file_path) + if image is None: + messagebox.showerror("错误", f"无法加载图像: {file_path}") + return + + horizontal_lines, vertical_lines = self.find_dividing_lines(image, line_color) + sub_images = self.split_image_by_lines(image, horizontal_lines, vertical_lines) + + # 保存分割后的图像 + self.save_sub_images(sub_images, naming_rule) + + # 根据分割线分割图像 + def split_image_by_lines(self, image, horizontal_lines, vertical_lines): + horizontal_coords = np.where(np.any(horizontal_lines > 0, axis=1))[0] + vertical_coords = np.where(np.any(vertical_lines > 0, axis=0))[0] + + sub_images = [] + for i in range(len(horizontal_coords) - 1): + for j in range(len(vertical_coords) - 1): + x1, x2 = vertical_coords[j], vertical_coords[j + 1] + y1, y2 = horizontal_coords[i], horizontal_coords[i + 1] + sub_image = image[y1:y2, x1:x2] + sub_images.append(sub_image) + + return sub_images + + # 保存分割后的图像,支持正则命名规则 + def save_sub_images(self, sub_images, naming_rule): + if not self.save_folder_path: + messagebox.showerror("错误", "请先选择保存文件夹") + return + + for idx, img in enumerate(sub_images): + filename = re.sub(r'{idx}', str(idx), naming_rule) # 使用正则表达式进行命名 + save_path = os.path.join(self.save_folder_path, f"{filename}.png") + cv2.imwrite(save_path, img) + + messagebox.showinfo("完成", f"图像已分割并保存到 {self.save_folder_path}") + +# 运行图形界面应用 +if __name__ == "__main__": + root = tk.Tk() + app = ImageSplitterApp(root) + root.mainloop() diff --git a/acdr-ui/tootls/文件处理工具.py b/acdr-ui/tootls/文件处理工具.py new file mode 100644 index 00000000..511ea7ef --- /dev/null +++ b/acdr-ui/tootls/文件处理工具.py @@ -0,0 +1,202 @@ +import os +import tkinter as tk +from tkinter import filedialog, scrolledtext, ttk +from tkinter import Menu +from PIL import Image + +# 搜索指定关键字的函数 +def search_keyword_in_files(directory, keyword, output_text): + if not keyword: + output_text.insert(tk.END, "请输入要搜索的关键字。\n") + return + + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(('.js', '.json', '.vue', '.ts', '.py', '.java', '.cpp')): + file_path = os.path.join(root, file) + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + count = content.count(keyword) + if count > 0: + output_text.insert(tk.END, f"在 {file_path} 中找到 '{keyword}',共 {count} 次\n") + except Exception as e: + output_text.insert(tk.END, f"读取文件 {file_path} 出错: {e}\n") + output_text.insert(tk.END, "搜索完成。\n") + +# 找出不包含指定关键字的文件 +def find_files_without_keyword(directory, keyword, output_text): + if not keyword: + output_text.insert(tk.END, "请输入要搜索的关键字。\n") + return + + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(('.js', '.json', '.vue', '.ts', '.py', '.java', '.cpp')): + file_path = os.path.join(root, file) + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + if keyword not in content: + output_text.insert(tk.END, f"'{keyword}' 未在文件 {file_path} 中找到。\n") + except Exception as e: + output_text.insert(tk.END, f"读取文件 {file_path} 出错: {e}\n") + output_text.insert(tk.END, "查找未包含关键字的文件完成。\n") + +# 替换文件内容中的指定字符串 +def replace_in_files(directory, search_text, replace_text, output_text): + if not search_text or not replace_text: + output_text.insert(tk.END, "请输入要替换的文本和新文本。\n") + return + + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(('.js', '.json', '.vue', '.ts', '.py', '.java', '.cpp')): + file_path = os.path.join(root, file) + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + if search_text in content: + new_content = content.replace(search_text, replace_text) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + output_text.insert(tk.END, f"在 {file_path} 中替换 '{search_text}' 为 '{replace_text}'\n") + except Exception as e: + output_text.insert(tk.END, f"处理文件 {file_path} 时出错: {e}\n") + output_text.insert(tk.END, "替换完成。\n") + +# 转换指定颜色为透明色的功能 +def convert_color_to_transparent(image_path, color, output_text): + img = Image.open(image_path) + img = img.convert("RGBA") + datas = img.getdata() + + newData = [] + for item in datas: + if item[0:3] == color: + newData.append((255, 255, 255, 0)) # 将指定颜色变为透明 + else: + newData.append(item) + + img.putdata(newData) + new_path = os.path.splitext(image_path)[0] + "_transparent.png" + img.save(new_path) + output_text.insert(tk.END, f"处理后的图片保存为 '{new_path}'\n") + +# 清空输出框的函数 +def clear_output(output_text): + output_text.delete(1.0, tk.END) + +# 添加右键菜单 +def add_right_click_menu(output_text): + menu = Menu(output_text, tearoff=0) + menu.add_command(label="清空输出", command=lambda: clear_output(output_text)) + + def show_menu(event): + menu.post(event.x_root, event.y_root) + + output_text.bind("", show_menu) + +# 创建GUI界面 +def create_gui(): + root = tk.Tk() + root.title("文件和图片处理工具") + root.geometry("800x500") + + notebook = ttk.Notebook(root) + notebook.pack(fill='both', expand=True) + + search_frame = ttk.Frame(notebook) + notebook.add(search_frame, text="搜索和替换") + image_frame = ttk.Frame(notebook) + notebook.add(image_frame, text="图片透明化") + note_frame = ttk.Frame(notebook) + notebook.add(note_frame, text="记事本") + + # 搜索和替换界面 + left_frame_search = ttk.Frame(search_frame) + left_frame_search.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10) + + keyword_entry = ttk.Entry(left_frame_search) + keyword_entry.pack(pady=5) + ttk.Label(left_frame_search, text="请输入要搜索的关键字:").pack(pady=5) + + search_button = ttk.Button(left_frame_search, text="搜索文件夹", + command=lambda: browse_directory_for_search(keyword_entry.get(), output_text_search)) + search_button.pack(pady=5) + + search_text_entry = ttk.Entry(left_frame_search) + search_text_entry.pack(pady=5) + ttk.Label(left_frame_search, text="请输入要替换的文本:").pack(pady=5) + + replace_text_entry = ttk.Entry(left_frame_search) + replace_text_entry.pack(pady=5) + ttk.Label(left_frame_search, text="请输入新文本:").pack(pady=5) + + replace_button = ttk.Button(left_frame_search, text="替换文件夹中的内容", + command=lambda: browse_directory_for_replace(search_text_entry.get(), replace_text_entry.get(), output_text_search)) + replace_button.pack(pady=5) + + search_missing_button = ttk.Button(left_frame_search, text="查找不包含关键字的文件", + command=lambda: browse_directory_for_missing(keyword_entry.get(), output_text_search)) + search_missing_button.pack(pady=5) + + output_text_search = scrolledtext.ScrolledText(search_frame, width=70) + output_text_search.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) + add_right_click_menu(output_text_search) # 为搜索输出框添加右键菜单 + + # 图像透明化界面 + color_entry = ttk.Entry(image_frame) + color_entry.pack(pady=5) + ttk.Label(image_frame, text="请输入要透明化的颜色 (r,g,b):").pack(pady=5) + + trans_button = ttk.Button(image_frame, text="使图片透明", + command=lambda: browse_image_for_transparency(tuple(map(int, color_entry.get().split(','))), output_text_image)) + trans_button.pack(pady=5) + + output_text_image = scrolledtext.ScrolledText(image_frame, width=70) + output_text_image.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) + add_right_click_menu(output_text_image) # 为图片处理输出框添加右键菜单 + + # 记事本界面 + note_text = scrolledtext.ScrolledText(note_frame, width=70) + note_text.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) + + save_button = ttk.Button(note_frame, text="保存记事本", command=lambda: save_notes(note_text)) + save_button.pack(pady=10) + + root.mainloop() + +# 辅助函数 +def browse_directory_for_search(keyword, output_text): + directory = filedialog.askdirectory() + if directory: + output_text.insert(tk.END, f"正在 {directory} 中搜索关键字: '{keyword}'\n") + search_keyword_in_files(directory, keyword, output_text) + +def browse_directory_for_replace(search_text, replace_text, output_text): + directory = filedialog.askdirectory() + if directory: + output_text.insert(tk.END, f"在 {directory} 中将 '{search_text}' 替换为 '{replace_text}'\n") + replace_in_files(directory, search_text, replace_text, output_text) + +def browse_directory_for_missing(keyword, output_text): + directory = filedialog.askdirectory() + if directory: + output_text.insert(tk.END, f"正在 {directory} 中查找未包含关键字 '{keyword}' 的文件。\n") + find_files_without_keyword(directory, keyword, output_text) + +def browse_image_for_transparency(color, output_text): + image_path = filedialog.askopenfilename() + if image_path: + convert_color_to_transparent(image_path, color, output_text) + +def save_notes(note_text): + file_path = filedialog.asksaveasfilename(defaultextension=".txt") + if file_path: + with open(file_path, 'w') as file: + file.write(note_text.get(1.0, tk.END)) + note_text.insert(tk.END, f"记事本已保存到 {file_path}\n") + +if __name__ == "__main__": + create_gui()