diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java index 31be045..21e8a8c 100644 --- a/src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsArticleController.java @@ -143,6 +143,20 @@ public class CmsArticleController extends BaseController { return fail("删除失败"); } + @PreAuthorize("hasAuthority('cms:cmsArticle:update')") + @Operation(summary = "修改文章状态(发布/下线/草稿)") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody CmsArticle article) { + CmsArticle entity = new CmsArticle(); + entity.setArticleId(article.getArticleId()); + entity.setStatus(article.getStatus()); + if (cmsArticleService.updateById(entity)) { + redisUtil.delete(CACHE_KEY_ARTICLE + article.getArticleId()); + return success("修改成功"); + } + return fail("修改失败"); + } + @PreAuthorize("hasAuthority('cms:cmsArticle:save')") @Operation(summary = "批量添加文章") @PostMapping("/batch") diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsBannerController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsBannerController.java new file mode 100644 index 0000000..ecf901b --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsBannerController.java @@ -0,0 +1,85 @@ +package com.gxwebsoft.cms.controller; + +import com.gxwebsoft.cms.entity.CmsBanner; +import com.gxwebsoft.cms.param.CmsBannerParam; +import com.gxwebsoft.cms.service.CmsBannerService; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.PageResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 轮播图控制器 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Tag(name = "轮播图管理") +@RestController +@RequestMapping("/api/cms/cms-banner") +public class CmsBannerController extends BaseController { + @Resource + private CmsBannerService cmsBannerService; + + @Operation(summary = "分页查询轮播图") + @GetMapping("/page") + public ApiResult> page(CmsBannerParam param) { + return success(cmsBannerService.pageRel(param)); + } + + @Operation(summary = "查询全部轮播图") + @GetMapping() + public ApiResult> list(CmsBannerParam param) { + return success(cmsBannerService.listRel(param)); + } + + @Operation(summary = "根据id查询轮播图") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(cmsBannerService.getByIdRel(id)); + } + + @Operation(summary = "添加轮播图") + @PostMapping() + public ApiResult save(@RequestBody CmsBanner cmsBanner) { + if (cmsBannerService.save(cmsBanner)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @Operation(summary = "修改轮播图") + @PutMapping() + public ApiResult update(@RequestBody CmsBanner cmsBanner) { + if (cmsBannerService.updateById(cmsBanner)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @Operation(summary = "删除轮播图") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (cmsBannerService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @Operation(summary = "修改轮播图状态(启用/停用)") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody CmsBanner cmsBanner) { + CmsBanner entity = new CmsBanner(); + entity.setBannerId(cmsBanner.getBannerId()); + entity.setStatus(cmsBanner.getStatus()); + if (cmsBannerService.updateById(entity)) { + return success("修改成功"); + } + return fail("修改失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsMessageController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsMessageController.java new file mode 100644 index 0000000..9c6b3fa --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsMessageController.java @@ -0,0 +1,82 @@ +package com.gxwebsoft.cms.controller; + +import com.gxwebsoft.cms.entity.CmsMessage; +import com.gxwebsoft.cms.param.CmsMessageParam; +import com.gxwebsoft.cms.service.CmsMessageService; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.PageResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 留言咨询控制器 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Tag(name = "留言咨询管理") +@RestController +@RequestMapping("/api/cms/cms-message") +public class CmsMessageController extends BaseController { + @Resource + private CmsMessageService cmsMessageService; + + @Operation(summary = "分页查询留言咨询") + @GetMapping("/page") + public ApiResult> page(CmsMessageParam param) { + return success(cmsMessageService.pageRel(param)); + } + + @Operation(summary = "查询全部留言咨询") + @GetMapping() + public ApiResult> list(CmsMessageParam param) { + return success(cmsMessageService.listRel(param)); + } + + @Operation(summary = "根据id查询留言咨询") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(cmsMessageService.getByIdRel(id)); + } + + @Operation(summary = "删除留言咨询") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (cmsMessageService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @Operation(summary = "修改留言状态(完成/归档)") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody CmsMessage message) { + CmsMessage entity = new CmsMessage(); + entity.setMessageId(message.getMessageId()); + entity.setStatus(message.getStatus()); + if (cmsMessageService.updateById(entity)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @Operation(summary = "回复留言") + @PutMapping("/reply") + public ApiResult reply(@RequestBody CmsMessage message) { + CmsMessage entity = new CmsMessage(); + entity.setMessageId(message.getMessageId()); + entity.setReply(message.getReply()); + entity.setReplyTime(LocalDateTime.now()); + entity.setStatus(1); + if (cmsMessageService.updateById(entity)) { + return success("回复成功"); + } + return fail("回复失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java index a415b17..276f9e0 100644 --- a/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsNavigationController.java @@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.Operation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import java.util.Map; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -135,6 +136,27 @@ public class CmsNavigationController extends BaseController { return fail("删除失败"); } + @PreAuthorize("hasAuthority('cms:cmsNavigation:update')") + @Operation(summary = "修改栏目状态") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody Map body) { + Object menuIdObj = body.get("menuId"); + Object statusObj = body.get("status"); + if (menuIdObj == null) { + return fail("缺少 menuId"); + } + CmsNavigation entity = new CmsNavigation(); + entity.setNavigationId(((Number) menuIdObj).intValue()); + if (statusObj != null) { + entity.setStatus(((Number) statusObj).intValue()); + } + if (cmsNavigationService.updateById(entity)) { + redisUtil.delete(SITE_INFO_KEY_PREFIX.concat(getTenantId().toString())); + return success("修改成功"); + } + return fail("修改失败"); + } + @PreAuthorize("hasAuthority('cms:cmsNavigation:save')") @Operation(summary = "批量添加网站导航记录表") @PostMapping("/batch") diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsProductCategoryController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsProductCategoryController.java new file mode 100644 index 0000000..b384540 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsProductCategoryController.java @@ -0,0 +1,85 @@ +package com.gxwebsoft.cms.controller; + +import com.gxwebsoft.cms.entity.CmsProductCategory; +import com.gxwebsoft.cms.param.CmsProductCategoryParam; +import com.gxwebsoft.cms.service.CmsProductCategoryService; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.PageResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 产品分类控制器 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Tag(name = "产品分类管理") +@RestController +@RequestMapping("/api/cms/cms-product-category") +public class CmsProductCategoryController extends BaseController { + @Resource + private CmsProductCategoryService cmsProductCategoryService; + + @Operation(summary = "分页查询产品分类") + @GetMapping("/page") + public ApiResult> page(CmsProductCategoryParam param) { + return success(cmsProductCategoryService.pageRel(param)); + } + + @Operation(summary = "查询全部产品分类") + @GetMapping() + public ApiResult> list(CmsProductCategoryParam param) { + return success(cmsProductCategoryService.listRel(param)); + } + + @Operation(summary = "根据id查询产品分类") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(cmsProductCategoryService.getByIdRel(id)); + } + + @Operation(summary = "添加产品分类") + @PostMapping() + public ApiResult save(@RequestBody CmsProductCategory category) { + if (cmsProductCategoryService.save(category)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @Operation(summary = "修改产品分类") + @PutMapping() + public ApiResult update(@RequestBody CmsProductCategory category) { + if (cmsProductCategoryService.updateById(category)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @Operation(summary = "删除产品分类") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (cmsProductCategoryService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @Operation(summary = "修改分类状态(启用/禁用)") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody CmsProductCategory category) { + CmsProductCategory entity = new CmsProductCategory(); + entity.setCategoryId(category.getCategoryId()); + entity.setStatus(category.getStatus()); + if (cmsProductCategoryService.updateById(entity)) { + return success("修改成功"); + } + return fail("修改失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/controller/CmsProductController.java b/src/main/java/com/gxwebsoft/cms/controller/CmsProductController.java new file mode 100644 index 0000000..f91800c --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/controller/CmsProductController.java @@ -0,0 +1,90 @@ +package com.gxwebsoft.cms.controller; + +import com.gxwebsoft.cms.entity.CmsProduct; +import com.gxwebsoft.cms.param.CmsProductParam; +import com.gxwebsoft.cms.service.CmsProductService; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.system.entity.User; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 产品控制器 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Tag(name = "产品管理") +@RestController +@RequestMapping("/api/cms/cms-product") +public class CmsProductController extends BaseController { + @Resource + private CmsProductService cmsProductService; + + @Operation(summary = "分页查询产品") + @GetMapping("/page") + public ApiResult> page(CmsProductParam param) { + return success(cmsProductService.pageRel(param)); + } + + @Operation(summary = "查询全部产品") + @GetMapping() + public ApiResult> list(CmsProductParam param) { + return success(cmsProductService.listRel(param)); + } + + @Operation(summary = "根据id查询产品") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(cmsProductService.getByIdRel(id)); + } + + @Operation(summary = "添加产品") + @PostMapping() + public ApiResult save(@RequestBody CmsProduct cmsProduct) { + User loginUser = getLoginUser(); + if (loginUser != null) { + cmsProduct.setUserId(loginUser.getUserId()); + } + if (cmsProductService.save(cmsProduct)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @Operation(summary = "修改产品") + @PutMapping() + public ApiResult update(@RequestBody CmsProduct cmsProduct) { + if (cmsProductService.updateById(cmsProduct)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @Operation(summary = "删除产品") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (cmsProductService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @Operation(summary = "修改产品状态(在售/下架)") + @PutMapping("/status") + public ApiResult updateStatus(@RequestBody CmsProduct cmsProduct) { + CmsProduct entity = new CmsProduct(); + entity.setProductId(cmsProduct.getProductId()); + entity.setStatus(cmsProduct.getStatus()); + if (cmsProductService.updateById(entity)) { + return success("修改成功"); + } + return fail("修改失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsBanner.java b/src/main/java/com/gxwebsoft/cms/entity/CmsBanner.java new file mode 100644 index 0000000..5bd4e87 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsBanner.java @@ -0,0 +1,82 @@ +package com.gxwebsoft.cms.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 轮播图 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("cms_banner") +@Schema(name = "CmsBanner对象", description = "轮播图") +public class CmsBanner implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "轮播图ID") + @TableId(value = "banner_id", type = IdType.AUTO) + private Integer bannerId; + + @Schema(description = "标题") + private String title; + + @Schema(description = "图片地址") + private String image; + + @Schema(description = "跳转类型: 0无 1外链 2文章 3产品") + private Integer linkType; + + @Schema(description = "外链地址") + private String linkUrl; + + @Schema(description = "跳转目标ID(文章/产品)") + private Integer linkTargetId; + + @Schema(description = "状态: 1启用 0停用") + private Integer status; + + @Schema(description = "排序(数字越小越靠前)") + @JsonProperty("sortNum") + @JSONField(name = "sortNum") + private Integer sortNumber; + + @Schema(description = "生效开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime startTime; + + @Schema(description = "生效结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime endTime; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "是否删除: 0否 1是") + @TableLogic + private Integer deleted; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsMessage.java b/src/main/java/com/gxwebsoft/cms/entity/CmsMessage.java new file mode 100644 index 0000000..704d215 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsMessage.java @@ -0,0 +1,74 @@ +package com.gxwebsoft.cms.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 留言咨询 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("cms_message") +@Schema(name = "CmsMessage对象", description = "留言咨询") +public class CmsMessage implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "留言ID") + @TableId(value = "message_id", type = IdType.AUTO) + private Integer messageId; + + @Schema(description = "联系人姓名") + private String name; + + @Schema(description = "手机号") + private String phone; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "公司名称") + private String company; + + @Schema(description = "类型: 1产品咨询 2意见反馈 3商务合作") + private Integer type; + + @Schema(description = "留言内容") + private String content; + + @Schema(description = "回复内容") + private String reply; + + @Schema(description = "回复时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime replyTime; + + @Schema(description = "状态: 0待处理 1已回复 2已完成 3已归档") + private Integer status; + + @Schema(description = "是否删除: 0否 1是") + @TableLogic + private Integer deleted; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java b/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java new file mode 100644 index 0000000..1e06be3 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java @@ -0,0 +1,93 @@ +package com.gxwebsoft.cms.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 产品 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("cms_product") +@Schema(name = "CmsProduct对象", description = "产品") +public class CmsProduct implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "产品ID") + @TableId(value = "product_id", type = IdType.AUTO) + private Integer productId; + + @Schema(description = "产品名称") + private String productName; + + @Schema(description = "封面图") + private String cover; + + @Schema(description = "简介") + private String summary; + + @Schema(description = "详情描述") + private String description; + + @Schema(description = "分类ID") + private Integer categoryId; + + @Schema(description = "分类名称(冗余存储)") + private String categoryName; + + @Schema(description = "价格") + private BigDecimal price; + + @Schema(description = "原价") + private BigDecimal originalPrice; + + @Schema(description = "计价单位") + private String unit; + + @Schema(description = "计费方式: 1包月 2包年 3一次性 4按量") + private Integer chargeType; + + @Schema(description = "状态: 1在售 0下架") + private Integer status; + + @Schema(description = "排序(数字越小越靠前)") + @JsonProperty("sortNum") + @JSONField(name = "sortNum") + private Integer sortNumber; + + @Schema(description = "标签, 逗号分隔") + private String tags; + + @Schema(description = "创建人ID") + private Integer userId; + + @Schema(description = "是否删除: 0否 1是") + @TableLogic + private Integer deleted; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsProductCategory.java b/src/main/java/com/gxwebsoft/cms/entity/CmsProductCategory.java new file mode 100644 index 0000000..5006a96 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsProductCategory.java @@ -0,0 +1,59 @@ +package com.gxwebsoft.cms.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 产品分类 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("cms_product_category") +@Schema(name = "CmsProductCategory对象", description = "产品分类") +public class CmsProductCategory implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "分类ID") + @TableId(value = "category_id", type = IdType.AUTO) + private Integer categoryId; + + @Schema(description = "分类名称") + private String categoryName; + + @Schema(description = "状态: 1启用 0禁用") + private Integer status; + + @Schema(description = "排序(数字越小越靠前)") + @JsonProperty("sortNum") + @JSONField(name = "sortNum") + private Integer sortNumber; + + @Schema(description = "是否删除: 0否 1是") + @TableLogic + private Integer deleted; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/gxwebsoft/cms/mapper/CmsBannerMapper.java b/src/main/java/com/gxwebsoft/cms/mapper/CmsBannerMapper.java new file mode 100644 index 0000000..539900b --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/mapper/CmsBannerMapper.java @@ -0,0 +1,16 @@ +package com.gxwebsoft.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gxwebsoft.cms.entity.CmsBanner; +import org.apache.ibatis.annotations.Mapper; + +/** + * 轮播图Mapper + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Mapper +public interface CmsBannerMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gxwebsoft/cms/mapper/CmsMessageMapper.java b/src/main/java/com/gxwebsoft/cms/mapper/CmsMessageMapper.java new file mode 100644 index 0000000..b17fc45 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/mapper/CmsMessageMapper.java @@ -0,0 +1,16 @@ +package com.gxwebsoft.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gxwebsoft.cms.entity.CmsMessage; +import org.apache.ibatis.annotations.Mapper; + +/** + * 留言咨询Mapper + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Mapper +public interface CmsMessageMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gxwebsoft/cms/mapper/CmsProductCategoryMapper.java b/src/main/java/com/gxwebsoft/cms/mapper/CmsProductCategoryMapper.java new file mode 100644 index 0000000..89968fe --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/mapper/CmsProductCategoryMapper.java @@ -0,0 +1,16 @@ +package com.gxwebsoft.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gxwebsoft.cms.entity.CmsProductCategory; +import org.apache.ibatis.annotations.Mapper; + +/** + * 产品分类Mapper + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Mapper +public interface CmsProductCategoryMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gxwebsoft/cms/mapper/CmsProductMapper.java b/src/main/java/com/gxwebsoft/cms/mapper/CmsProductMapper.java new file mode 100644 index 0000000..cf6bfef --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/mapper/CmsProductMapper.java @@ -0,0 +1,16 @@ +package com.gxwebsoft.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gxwebsoft.cms.entity.CmsProduct; +import org.apache.ibatis.annotations.Mapper; + +/** + * 产品Mapper + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Mapper +public interface CmsProductMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gxwebsoft/cms/param/CmsBannerParam.java b/src/main/java/com/gxwebsoft/cms/param/CmsBannerParam.java new file mode 100644 index 0000000..ad4081b --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/param/CmsBannerParam.java @@ -0,0 +1,37 @@ +package com.gxwebsoft.cms.param; + +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 轮播图查询参数 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(name = "CmsBannerParam对象", description = "轮播图查询参数") +public class CmsBannerParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @Schema(description = "轮播图ID") + @QueryField(type = QueryType.EQ) + private Integer bannerId; + + @Schema(description = "标题") + @QueryField(type = QueryType.LIKE) + private String title; + + @Schema(description = "跳转类型: 0无 1外链 2文章 3产品") + @QueryField(type = QueryType.EQ) + private Integer linkType; + + @Schema(description = "状态: 1启用 0停用") + @QueryField(type = QueryType.EQ) + private Integer status; +} diff --git a/src/main/java/com/gxwebsoft/cms/param/CmsMessageParam.java b/src/main/java/com/gxwebsoft/cms/param/CmsMessageParam.java new file mode 100644 index 0000000..f724726 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/param/CmsMessageParam.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.param; + +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 留言咨询查询参数 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(name = "CmsMessageParam对象", description = "留言咨询查询参数") +public class CmsMessageParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @Schema(description = "留言ID") + @QueryField(type = QueryType.EQ) + private Integer messageId; + + @Schema(description = "联系人姓名") + @QueryField(type = QueryType.LIKE) + private String name; + + @Schema(description = "手机号") + @QueryField(type = QueryType.EQ) + private String phone; + + @Schema(description = "类型: 1产品咨询 2意见反馈 3商务合作") + @QueryField(type = QueryType.EQ) + private Integer type; + + @Schema(description = "状态: 0待处理 1已回复 2已完成 3已归档") + @QueryField(type = QueryType.EQ) + private Integer status; +} diff --git a/src/main/java/com/gxwebsoft/cms/param/CmsProductCategoryParam.java b/src/main/java/com/gxwebsoft/cms/param/CmsProductCategoryParam.java new file mode 100644 index 0000000..5130866 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/param/CmsProductCategoryParam.java @@ -0,0 +1,33 @@ +package com.gxwebsoft.cms.param; + +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 产品分类查询参数 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(name = "CmsProductCategoryParam对象", description = "产品分类查询参数") +public class CmsProductCategoryParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @Schema(description = "分类ID") + @QueryField(type = QueryType.EQ) + private Integer categoryId; + + @Schema(description = "分类名称") + @QueryField(type = QueryType.LIKE) + private String categoryName; + + @Schema(description = "状态: 1启用 0禁用") + @QueryField(type = QueryType.EQ) + private Integer status; +} diff --git a/src/main/java/com/gxwebsoft/cms/param/CmsProductParam.java b/src/main/java/com/gxwebsoft/cms/param/CmsProductParam.java new file mode 100644 index 0000000..0cecf65 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/param/CmsProductParam.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.param; + +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 产品查询参数 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(name = "CmsProductParam对象", description = "产品查询参数") +public class CmsProductParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @Schema(description = "产品ID") + @QueryField(type = QueryType.EQ) + private Integer productId; + + @Schema(description = "产品名称") + @QueryField(type = QueryType.LIKE) + private String productName; + + @Schema(description = "分类ID") + @QueryField(type = QueryType.EQ) + private Integer categoryId; + + @Schema(description = "状态: 1在售 0下架") + @QueryField(type = QueryType.EQ) + private Integer status; + + @Schema(description = "计费方式: 1包月 2包年 3一次性 4按量") + @QueryField(type = QueryType.EQ) + private Integer chargeType; +} diff --git a/src/main/java/com/gxwebsoft/cms/service/CmsBannerService.java b/src/main/java/com/gxwebsoft/cms/service/CmsBannerService.java new file mode 100644 index 0000000..4f10e11 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/CmsBannerService.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.cms.entity.CmsBanner; +import com.gxwebsoft.cms.param.CmsBannerParam; +import com.gxwebsoft.common.core.web.PageResult; + +import java.util.List; + +/** + * 轮播图Service接口 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +public interface CmsBannerService extends IService { + + /** + * 分页查询 + * + * @param param 查询参数 + * @return 分页结果 + */ + PageResult pageRel(CmsBannerParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return 列表 + */ + List listRel(CmsBannerParam param); + + /** + * 根据id查询 + * + * @param bannerId 轮播图ID + * @return 轮播图 + */ + CmsBanner getByIdRel(Integer bannerId); +} diff --git a/src/main/java/com/gxwebsoft/cms/service/CmsMessageService.java b/src/main/java/com/gxwebsoft/cms/service/CmsMessageService.java new file mode 100644 index 0000000..cc7c4f6 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/CmsMessageService.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.cms.entity.CmsMessage; +import com.gxwebsoft.cms.param.CmsMessageParam; +import com.gxwebsoft.common.core.web.PageResult; + +import java.util.List; + +/** + * 留言咨询Service接口 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +public interface CmsMessageService extends IService { + + /** + * 分页查询 + * + * @param param 查询参数 + * @return 分页结果 + */ + PageResult pageRel(CmsMessageParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return 列表 + */ + List listRel(CmsMessageParam param); + + /** + * 根据id查询 + * + * @param messageId 留言ID + * @return 留言 + */ + CmsMessage getByIdRel(Integer messageId); +} diff --git a/src/main/java/com/gxwebsoft/cms/service/CmsProductCategoryService.java b/src/main/java/com/gxwebsoft/cms/service/CmsProductCategoryService.java new file mode 100644 index 0000000..78a2509 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/CmsProductCategoryService.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.cms.entity.CmsProductCategory; +import com.gxwebsoft.cms.param.CmsProductCategoryParam; +import com.gxwebsoft.common.core.web.PageResult; + +import java.util.List; + +/** + * 产品分类Service接口 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +public interface CmsProductCategoryService extends IService { + + /** + * 分页查询 + * + * @param param 查询参数 + * @return 分页结果 + */ + PageResult pageRel(CmsProductCategoryParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return 列表 + */ + List listRel(CmsProductCategoryParam param); + + /** + * 根据id查询 + * + * @param categoryId 分类ID + * @return 分类 + */ + CmsProductCategory getByIdRel(Integer categoryId); +} diff --git a/src/main/java/com/gxwebsoft/cms/service/CmsProductService.java b/src/main/java/com/gxwebsoft/cms/service/CmsProductService.java new file mode 100644 index 0000000..b94e1ba --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/CmsProductService.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.cms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.cms.entity.CmsProduct; +import com.gxwebsoft.cms.param.CmsProductParam; +import com.gxwebsoft.common.core.web.PageResult; + +import java.util.List; + +/** + * 产品Service接口 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +public interface CmsProductService extends IService { + + /** + * 分页查询 + * + * @param param 查询参数 + * @return 分页结果 + */ + PageResult pageRel(CmsProductParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return 列表 + */ + List listRel(CmsProductParam param); + + /** + * 根据id查询 + * + * @param productId 产品ID + * @return 产品 + */ + CmsProduct getByIdRel(Integer productId); +} diff --git a/src/main/java/com/gxwebsoft/cms/service/impl/CmsBannerServiceImpl.java b/src/main/java/com/gxwebsoft/cms/service/impl/CmsBannerServiceImpl.java new file mode 100644 index 0000000..bfbde96 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/impl/CmsBannerServiceImpl.java @@ -0,0 +1,44 @@ +package com.gxwebsoft.cms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.cms.entity.CmsBanner; +import com.gxwebsoft.cms.mapper.CmsBannerMapper; +import com.gxwebsoft.cms.param.CmsBannerParam; +import com.gxwebsoft.cms.service.CmsBannerService; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 轮播图Service实现 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Service +public class CmsBannerServiceImpl extends ServiceImpl implements CmsBannerService { + + @Override + public PageResult pageRel(CmsBannerParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + IPage result = page(page, page.getOrderWrapper()); + return new PageResult<>(result.getRecords(), result.getTotal()); + } + + @Override + public List listRel(CmsBannerParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + return list(page.getOrderWrapper()); + } + + @Override + public CmsBanner getByIdRel(Integer bannerId) { + return getById(bannerId); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/service/impl/CmsMessageServiceImpl.java b/src/main/java/com/gxwebsoft/cms/service/impl/CmsMessageServiceImpl.java new file mode 100644 index 0000000..b59b570 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/impl/CmsMessageServiceImpl.java @@ -0,0 +1,57 @@ +package com.gxwebsoft.cms.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.cms.entity.CmsMessage; +import com.gxwebsoft.cms.mapper.CmsMessageMapper; +import com.gxwebsoft.cms.param.CmsMessageParam; +import com.gxwebsoft.cms.service.CmsMessageService; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 留言咨询Service实现 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Service +public class CmsMessageServiceImpl extends ServiceImpl implements CmsMessageService { + + @Override + public PageResult pageRel(CmsMessageParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + QueryWrapper wrapper = page.getWrapper(); + if (StrUtil.isNotBlank(param.getKeywords())) { + wrapper.and(w -> w.like("name", param.getKeywords()) + .or().like("content", param.getKeywords()) + .or().like("company", param.getKeywords())); + } + IPage result = page(page, page.getOrderWrapper(wrapper)); + return new PageResult<>(result.getRecords(), result.getTotal()); + } + + @Override + public List listRel(CmsMessageParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + QueryWrapper wrapper = page.getWrapper(); + if (StrUtil.isNotBlank(param.getKeywords())) { + wrapper.and(w -> w.like("name", param.getKeywords()) + .or().like("content", param.getKeywords()) + .or().like("company", param.getKeywords())); + } + return list(page.getOrderWrapper(wrapper)); + } + + @Override + public CmsMessage getByIdRel(Integer messageId) { + return getById(messageId); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductCategoryServiceImpl.java b/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductCategoryServiceImpl.java new file mode 100644 index 0000000..d839388 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductCategoryServiceImpl.java @@ -0,0 +1,44 @@ +package com.gxwebsoft.cms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.cms.entity.CmsProductCategory; +import com.gxwebsoft.cms.mapper.CmsProductCategoryMapper; +import com.gxwebsoft.cms.param.CmsProductCategoryParam; +import com.gxwebsoft.cms.service.CmsProductCategoryService; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 产品分类Service实现 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Service +public class CmsProductCategoryServiceImpl extends ServiceImpl implements CmsProductCategoryService { + + @Override + public PageResult pageRel(CmsProductCategoryParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + IPage result = page(page, page.getOrderWrapper()); + return new PageResult<>(result.getRecords(), result.getTotal()); + } + + @Override + public List listRel(CmsProductCategoryParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + return list(page.getOrderWrapper()); + } + + @Override + public CmsProductCategory getByIdRel(Integer categoryId) { + return getById(categoryId); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductServiceImpl.java b/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductServiceImpl.java new file mode 100644 index 0000000..a110001 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/service/impl/CmsProductServiceImpl.java @@ -0,0 +1,55 @@ +package com.gxwebsoft.cms.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.cms.entity.CmsProduct; +import com.gxwebsoft.cms.mapper.CmsProductMapper; +import com.gxwebsoft.cms.param.CmsProductParam; +import com.gxwebsoft.cms.service.CmsProductService; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 产品Service实现 + * + * @author WorkBuddy + * @since 2026-07-17 + */ +@Service +public class CmsProductServiceImpl extends ServiceImpl implements CmsProductService { + + @Override + public PageResult pageRel(CmsProductParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + QueryWrapper wrapper = page.getWrapper(); + if (StrUtil.isNotBlank(param.getKeywords())) { + wrapper.and(w -> w.like("product_name", param.getKeywords()) + .or().like("summary", param.getKeywords())); + } + IPage result = page(page, page.getOrderWrapper(wrapper)); + return new PageResult<>(result.getRecords(), result.getTotal()); + } + + @Override + public List listRel(CmsProductParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + QueryWrapper wrapper = page.getWrapper(); + if (StrUtil.isNotBlank(param.getKeywords())) { + wrapper.and(w -> w.like("product_name", param.getKeywords()) + .or().like("summary", param.getKeywords())); + } + return list(page.getOrderWrapper(wrapper)); + } + + @Override + public CmsProduct getByIdRel(Integer productId) { + return getById(productId); + } +} diff --git a/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql b/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql new file mode 100644 index 0000000..765d13e --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql @@ -0,0 +1,123 @@ +-- ---------------------------- +-- 产品分类表 +-- 官网产品模块的分类 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `cms_product_category` ( + `category_id` INT NOT NULL AUTO_INCREMENT COMMENT '分类ID', + `category_name` VARCHAR(100) NOT NULL COMMENT '分类名称', + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1启用 0禁用', + `sort_number` INT NOT NULL DEFAULT 0 COMMENT '排序(数字越小越靠前)', + `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', + `tenant_id` INT DEFAULT NULL COMMENT '租户ID', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`category_id`), + KEY `idx_tenant_id` (`tenant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品分类'; + +-- ---------------------------- +-- 产品表 +-- 官网展示的云产品 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `cms_product` ( + `product_id` INT NOT NULL AUTO_INCREMENT COMMENT '产品ID', + `product_name` VARCHAR(200) NOT NULL COMMENT '产品名称', + `cover` VARCHAR(500) DEFAULT NULL COMMENT '封面图', + `summary` VARCHAR(500) DEFAULT NULL COMMENT '简介', + `description` TEXT DEFAULT NULL COMMENT '详情描述', + `category_id` INT DEFAULT NULL COMMENT '分类ID', + `category_name` VARCHAR(100) DEFAULT NULL COMMENT '分类名称(冗余存储, 便于列表展示)', + `price` DECIMAL(10,2) DEFAULT NULL COMMENT '价格', + `original_price` DECIMAL(10,2) DEFAULT NULL COMMENT '原价', + `unit` VARCHAR(20) DEFAULT NULL COMMENT '计价单位', + `charge_type` TINYINT DEFAULT 1 COMMENT '计费方式: 1包月 2包年 3一次性 4按量', + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1在售 0下架', + `sort_number` INT NOT NULL DEFAULT 0 COMMENT '排序(数字越小越靠前)', + `tags` VARCHAR(255) DEFAULT NULL COMMENT '标签, 逗号分隔', + `user_id` INT DEFAULT NULL COMMENT '创建人ID', + `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', + `tenant_id` INT DEFAULT NULL COMMENT '租户ID', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`product_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_category_id` (`category_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品'; + +-- ---------------------------- +-- 案例表 +-- 官网客户案例展示 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `cms_case` ( + `case_id` INT NOT NULL AUTO_INCREMENT COMMENT '案例ID', + `case_name` VARCHAR(200) NOT NULL COMMENT '案例名称', + `cover` VARCHAR(500) DEFAULT NULL COMMENT '封面图', + `summary` VARCHAR(500) DEFAULT NULL COMMENT '简介', + `content` TEXT DEFAULT NULL COMMENT '案例详情', + `industry` VARCHAR(100) DEFAULT NULL COMMENT '所属行业', + `customer` VARCHAR(200) DEFAULT NULL COMMENT '客户名称', + `product_used` VARCHAR(255) DEFAULT NULL COMMENT '使用产品', + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1已发布 0已下线', + `sort_number` INT NOT NULL DEFAULT 0 COMMENT '排序(数字越小越靠前)', + `views` INT NOT NULL DEFAULT 0 COMMENT '浏览量', + `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', + `tenant_id` INT DEFAULT NULL COMMENT '租户ID', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`case_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_industry` (`industry`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='案例'; + +-- ---------------------------- +-- 轮播图表 +-- 官网首页轮播图 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `cms_banner` ( + `banner_id` INT NOT NULL AUTO_INCREMENT COMMENT '轮播图ID', + `title` VARCHAR(200) DEFAULT NULL COMMENT '标题', + `image` VARCHAR(500) NOT NULL COMMENT '图片地址', + `link_type` TINYINT NOT NULL DEFAULT 0 COMMENT '跳转类型: 0无 1外链 2文章 3产品', + `link_url` VARCHAR(500) DEFAULT NULL COMMENT '外链地址', + `link_target_id` INT DEFAULT NULL COMMENT '跳转目标ID(文章/产品)', + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1启用 0停用', + `sort_number` INT NOT NULL DEFAULT 0 COMMENT '排序(数字越小越靠前)', + `start_time` DATETIME DEFAULT NULL COMMENT '生效开始时间', + `end_time` DATETIME DEFAULT NULL COMMENT '生效结束时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', + `tenant_id` INT DEFAULT NULL COMMENT '租户ID', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`banner_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='轮播图'; + +-- ---------------------------- +-- 留言咨询表 +-- 官网留言/咨询 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `cms_message` ( + `message_id` INT NOT NULL AUTO_INCREMENT COMMENT '留言ID', + `name` VARCHAR(50) NOT NULL COMMENT '联系人姓名', + `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号', + `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱', + `company` VARCHAR(100) DEFAULT NULL COMMENT '公司名称', + `type` TINYINT NOT NULL DEFAULT 1 COMMENT '类型: 1产品咨询 2意见反馈 3商务合作', + `content` TEXT NOT NULL COMMENT '留言内容', + `reply` TEXT DEFAULT NULL COMMENT '回复内容', + `reply_time` DATETIME DEFAULT NULL COMMENT '回复时间', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态: 0待处理 1已回复 2已完成 3已归档', + `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', + `tenant_id` INT DEFAULT NULL COMMENT '租户ID', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`message_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_phone` (`phone`), + KEY `idx_status` (`status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='留言咨询'; diff --git a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java index c9d1463..9d83370 100644 --- a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java @@ -39,6 +39,7 @@ public class SecurityConfig { .permitAll() .antMatchers( "/api/login", + "/api/loginBySms", "/api/qr-login/**", "/api/register", "/api/cms/website/createWebsite", @@ -81,7 +82,9 @@ public class SecurityConfig { "/api/shop/shop-order/test", "/api/qr-code/**", "/api/shop/order-delivery/notify", - "/api/cms/cms-contact-lead/submit" + "/api/cms/cms-contact-lead/submit", + "/api/led/bme/stop-replace", + "/api/led/bme/number-sources" ) .permitAll() .anyRequest() diff --git a/src/main/java/com/gxwebsoft/led/.workbuddy/memory/2026-06-24.md b/src/main/java/com/gxwebsoft/led/.workbuddy/memory/2026-06-24.md new file mode 100644 index 0000000..586759f --- /dev/null +++ b/src/main/java/com/gxwebsoft/led/.workbuddy/memory/2026-06-24.md @@ -0,0 +1,25 @@ +# 2026-06-24 工作日志 + +## LED大屏项目前后端分析与静态化部署方案评估 + +### 项目概况 +- 后端: Spring Boot 2.7.18 + MyBatis-Plus + Redis,13个业务模块的大型单体应用 +- LED模块只是其中一个,只有2个API接口(停替诊查询/号源查询),本质是医院BME中台的代理 +- 前端: Vue 3 + TypeScript + Vite + Ant Design Vue + ele-admin-pro +- LED页面(/views/led/index.vue): 医院大厅大屏展示,两个表格每10秒自动翻页轮播 + +### 关键发现 +- LED后端核心逻辑: Token获取/刷新(Redis缓存5天) + MD5签名 + HTTP转发BME + 响应扁平化 +- BME中台地址: http://16.1.4.201:7979,需要appid/secret-key认证 +- 前端日期硬编码为2025-12-23,应改为动态获取 +- /led路由未加入WHITE_LIST白名单,大屏需登录才能访问 +- 前端API基地址: localStorage ApiUrl > 环境变量 VITE_API_URL + +### 部署方案建议 +客户内网无法部署面板环境,推荐方案A: Nginx(静态前端) + Go轻量后端 +- Go后端只需实现2个接口 + 内存缓存Token + MD5签名,无需MySQL/Redis +- 替代方案: Python(Flask/FastAPI) / OpenResty(Nginx+Lua) / 保留Java JAR(需Java+Redis) +- 纯静态不可行: BME API需要secret-key认证,不能暴露到前端 + +### 状态 +- 仅分析,未改动任何代码 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index dd1a48e..4d507ba 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -2,7 +2,8 @@ # 服务器配置 server: - port: 9200 + # 9500 与 website-admin 本地开发代理(server/api/_* 的 dev 目标 127.0.0.1:9500)一致 + port: 9500 # 数据源配置 spring: diff --git a/src/main/resources/application-ykd-local-dev.yml b/src/main/resources/application-ykd-local-dev.yml new file mode 100644 index 0000000..b16a9a2 --- /dev/null +++ b/src/main/resources/application-ykd-local-dev.yml @@ -0,0 +1,85 @@ +# 生产环境配置 + +# 数据源配置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/led?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: nnws112233 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + remove-abandoned: true + + # redis + redis: + database: 0 + host: 127.0.0.1 + port: 6379 + password: + +# 日志配置 +logging: + file: + name: websoft-modules.log + level: + root: DEBUG + com.gxwebsoft: DEBUG + com.baomidou.mybatisplus: DEBUG + +socketio: + host: 0.0.0.0 #IP地址 + +# MQTT配置 +mqtt: + enabled: true # 启用MQTT服务 + host: tcp://132.232.214.96:1883 + username: swdev + password: Sw20250523 + client-id-prefix: hjm_car_ + topic: /SW_GPS/# + qos: 2 + connection-timeout: 10 + keep-alive-interval: 20 + auto-reconnect: true + +# 框架配置 +config: + # 文件服务器 + file-server: https://file-s209.shoplnk.cn + # 基础模块接口 + server-url: https://server.websoft.top/api + # 业务模块接口 + api-url: https://cms-api.websoft.top/api + upload-path: /www/wwwroot/file.ws + + # 阿里云OSS云存储 + endpoint: https://oss-cn-shenzhen.aliyuncs.com + accessKeyId: LTAI4GKGZ9Z2Z8JZ77c3GNZP + accessKeySecret: BiDkpS7UXj72HWwDWaFZxiXjNFBNCM + bucketName: oss-gxwebsoft + bucketDomain: https://oss.wsdns.cn + aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com + +# 生产环境证书配置 +certificate: + load-mode: VOLUME # 生产环境从Docker挂载卷加载 + cert-root-path: /www/wwwroot/file.ws + +# 支付配置缓存 +payment: + cache: + # 支付配置缓存键前缀,生产环境使用 Payment:1* 格式 + key-prefix: "Payment:1" + # 缓存过期时间(小时) + expire-hours: 24 +# 阿里云翻译配置 +aliyun: + translate: + access-key-id: LTAI5tEsyhW4GCKbds1qsopg + access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO + endpoint: mt.cn-hangzhou.aliyuncs.com +wechatpay: + transfer: + scene-id: 1005 + scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"配送员"},{"info_type":"报酬说明","info_content":"12月份配送费"}]' diff --git a/src/main/resources/application-ykd-local.yml b/src/main/resources/application-ykd-local.yml new file mode 100644 index 0000000..7e66bd9 --- /dev/null +++ b/src/main/resources/application-ykd-local.yml @@ -0,0 +1,85 @@ +# 生产环境配置 + +# 数据源配置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/led?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: nnws112233 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + remove-abandoned: true + + # redis + redis: + database: 0 + host: 127.0.0.1 + port: 6379 + password: + +# 日志配置 +logging: + file: + name: websoft-modules.log + level: + root: WARN + com.gxwebsoft: ERROR + com.baomidou.mybatisplus: ERROR + +socketio: + host: 0.0.0.0 #IP地址 + +# MQTT配置 +mqtt: + enabled: true # 启用MQTT服务 + host: tcp://132.232.214.96:1883 + username: swdev + password: Sw20250523 + client-id-prefix: hjm_car_ + topic: /SW_GPS/# + qos: 2 + connection-timeout: 10 + keep-alive-interval: 20 + auto-reconnect: true + +# 框架配置 +config: + # 文件服务器 + file-server: https://file-s209.shoplnk.cn + # 基础模块接口 + server-url: https://server.websoft.top/api + # 业务模块接口 + api-url: https://cms-api.websoft.top/api + upload-path: /www/wwwroot/file.ws + + # 阿里云OSS云存储 + endpoint: https://oss-cn-shenzhen.aliyuncs.com + accessKeyId: LTAI4GKGZ9Z2Z8JZ77c3GNZP + accessKeySecret: BiDkpS7UXj72HWwDWaFZxiXjNFBNCM + bucketName: oss-gxwebsoft + bucketDomain: https://oss.wsdns.cn + aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com + +# 生产环境证书配置 +certificate: + load-mode: VOLUME # 生产环境从Docker挂载卷加载 + cert-root-path: /www/wwwroot/file.ws + +# 支付配置缓存 +payment: + cache: + # 支付配置缓存键前缀,生产环境使用 Payment:1* 格式 + key-prefix: "Payment:1" + # 缓存过期时间(小时) + expire-hours: 24 +# 阿里云翻译配置 +aliyun: + translate: + access-key-id: LTAI5tEsyhW4GCKbds1qsopg + access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO + endpoint: mt.cn-hangzhou.aliyuncs.com +wechatpay: + transfer: + scene-id: 1005 + scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"配送员"},{"info_type":"报酬说明","info_content":"12月份配送费"}]'