feat(企业微信): 新增企业小程序二维码管理功能

添加企业小程序二维码相关功能模块,包括:
- 创建二维码命令和更新命令
- 二维码实体类和服务层
- 二维码模型工厂和模型
- 二维码查询条件和DTO
- 二维码应用服务层
- 数据库表结构和Mapper接口
This commit is contained in:
dzq 2025-12-03 09:23:29 +08:00
parent 5bd95c20da
commit 61b53dfb67
12 changed files with 515 additions and 0 deletions

View File

@ -0,0 +1,79 @@
package com.agileboot.domain.qywx.mpQrcode;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.qywx.mpQrcode.command.AddMpQrcodeCommand;
import com.agileboot.domain.qywx.mpQrcode.command.UpdateMpQrcodeCommand;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeEntity;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeService;
import com.agileboot.domain.qywx.mpQrcode.dto.QyMpQrcodeDTO;
import com.agileboot.domain.qywx.mpQrcode.model.MpQrcodeModel;
import com.agileboot.domain.qywx.mpQrcode.model.MpQrcodeModelFactory;
import com.agileboot.domain.qywx.mpQrcode.query.SearchMpQrcodeQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* <p>
* 小程序二维码应用服务层
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@Service
@RequiredArgsConstructor
public class MpQrcodeApplicationService {
private final QyMpQrcodeService qrcodeService;
private final MpQrcodeModelFactory qrcodeModelFactory;
/**
* 分页查询二维码列表
*/
public PageDTO<QyMpQrcodeDTO> getQrcodeList(SearchMpQrcodeQuery<QyMpQrcodeEntity> query) {
Page<QyMpQrcodeEntity> page = qrcodeService.getQrcodeList(query);
List<QyMpQrcodeDTO> dtoList = page.getRecords().stream()
.map(QyMpQrcodeDTO::new)
.collect(Collectors.toList());
return new PageDTO<>(dtoList, page.getTotal());
}
/**
* 添加二维码
*/
public void addQrcode(AddMpQrcodeCommand command) {
MpQrcodeModel model = qrcodeModelFactory.create();
model.loadAddCommand(command);
model.insert();
}
/**
* 更新二维码
*/
public void updateQrcode(UpdateMpQrcodeCommand command) {
MpQrcodeModel model = qrcodeModelFactory.loadById(command.getQrcodeId());
model.loadUpdateCommand(command);
model.updateById();
}
/**
* 批量删除二维码
*/
public void deleteQrcode(BulkOperationCommand<Long> command) {
for (Long id : command.getIds()) {
MpQrcodeModel model = qrcodeModelFactory.loadById(id);
model.deleteById();
}
}
/**
* 根据企业ID查询二维码列表
*/
public List<QyMpQrcodeEntity> getQrcodeListByCorpid(String corpid) {
return qrcodeService.selectByCorpid(corpid);
}
}

View File

@ -0,0 +1,19 @@
package com.agileboot.domain.qywx.mpQrcode.command;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 添加小程序二维码命令
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class AddMpQrcodeCommand extends QyMpQrcodeEntity {
}

View File

@ -0,0 +1,24 @@
package com.agileboot.domain.qywx.mpQrcode.command;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 更新小程序二维码命令
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class UpdateMpQrcodeCommand extends AddMpQrcodeCommand {
@NotNull
@PositiveOrZero
private Long qrcodeId;
}

View File

@ -0,0 +1,55 @@
package com.agileboot.domain.qywx.mpQrcode.db;
import com.agileboot.common.core.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 企业小程序二维码表
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("qy_mp_qrcode")
@ApiModel(value = "QyMpQrcodeEntity对象", description = "企业小程序二维码表")
public class QyMpQrcodeEntity extends BaseEntity<QyMpQrcodeEntity> {
@ApiModelProperty("二维码唯一ID")
@TableId(value = "qrcode_id", type = IdType.AUTO)
private Long qrcodeId;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("二维码名称")
@TableField("name")
private String name;
@ApiModelProperty("小程序码参数最大32个可见字符")
@TableField("scene")
private String scene;
@ApiModelProperty("小程序页面路径")
@TableField("page")
private String page;
@ApiModelProperty("二维码链接")
@TableField("qrcode_url")
private String qrcodeUrl;
@Override
public Long pkVal() {
return this.qrcodeId;
}
}

View File

@ -0,0 +1,49 @@
package com.agileboot.domain.qywx.mpQrcode.db;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* <p>
* 企业小程序二维码表 Mapper 接口
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
public interface QyMpQrcodeMapper extends BaseMapper<QyMpQrcodeEntity> {
/**
* 分页查询二维码列表
*/
@Select("SELECT qrcode_id, corpid, name, scene, page, qrcode_url, creator_id, create_time, updater_id, update_time, deleted " +
"FROM qy_mp_qrcode " +
"${ew.customSqlSegment}")
Page<QyMpQrcodeEntity> getQrcodeList(
Page<QyMpQrcodeEntity> page,
@Param(Constants.WRAPPER) Wrapper<QyMpQrcodeEntity> queryWrapper
);
/**
* 查询所有二维码按创建时间降序
*/
@Select("SELECT * " +
"FROM qy_mp_qrcode " +
"WHERE deleted = 0 " +
"ORDER BY create_time DESC")
List<QyMpQrcodeEntity> selectAll();
/**
* 根据企业ID查询二维码列表
*/
@Select("SELECT * " +
"FROM qy_mp_qrcode " +
"WHERE corpid = #{corpid} AND deleted = 0 " +
"ORDER BY create_time DESC")
List<QyMpQrcodeEntity> selectByCorpid(@Param("corpid") String corpid);
}

View File

@ -0,0 +1,32 @@
package com.agileboot.domain.qywx.mpQrcode.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 企业小程序二维码表 服务类
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
public interface QyMpQrcodeService extends IService<QyMpQrcodeEntity> {
/**
* 分页查询二维码列表
*/
Page<QyMpQrcodeEntity> getQrcodeList(AbstractPageQuery<QyMpQrcodeEntity> query);
/**
* 查询所有二维码按创建时间降序
*/
List<QyMpQrcodeEntity> selectAll();
/**
* 根据企业ID查询二维码列表
*/
List<QyMpQrcodeEntity> selectByCorpid(String corpid);
}

View File

@ -0,0 +1,36 @@
package com.agileboot.domain.qywx.mpQrcode.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* <p>
* 企业小程序二维码表 服务类
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@Service
@RequiredArgsConstructor
public class QyMpQrcodeServiceImpl extends ServiceImpl<QyMpQrcodeMapper, QyMpQrcodeEntity> implements QyMpQrcodeService {
@Override
public Page<QyMpQrcodeEntity> getQrcodeList(AbstractPageQuery<QyMpQrcodeEntity> query) {
return baseMapper.getQrcodeList(query.toPage(), query.addQueryCondition());
}
@Override
public List<QyMpQrcodeEntity> selectAll() {
return baseMapper.selectAll();
}
@Override
public List<QyMpQrcodeEntity> selectByCorpid(String corpid) {
return baseMapper.selectByCorpid(corpid);
}
}

View File

@ -0,0 +1,80 @@
package com.agileboot.domain.qywx.mpQrcode.dto;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeEntity;
import lombok.Data;
/**
* <p>
* 企业小程序二维码 DTO
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@ExcelSheet(name = "企业小程序二维码列表")
@Data
public class QyMpQrcodeDTO {
public QyMpQrcodeDTO(QyMpQrcodeEntity entity) {
if (entity != null) {
BeanUtil.copyProperties(entity, this);
/* // 设置创建者信息
SysUserEntity creator = CacheCenter.userCache.get(entity.getCreatorId() + "");
if (creator != null) {
this.creatorName = creator.getUsername();
}
// 设置更新者信息
SysUserEntity updater = CacheCenter.userCache.get(entity.getUpdaterId() + "");
if (updater != null) {
this.updaterName = updater.getUsername();
}*/
// 格式化时间
if (entity.getCreateTime() != null) {
this.createTimeStr = DateUtil.formatDateTime(entity.getCreateTime());
}
if (entity.getUpdateTime() != null) {
this.updateTimeStr = DateUtil.formatDateTime(entity.getUpdateTime());
}
}
}
@ExcelColumn(name = "二维码ID")
private Long qrcodeId;
@ExcelColumn(name = "企业微信ID")
private String corpid;
@ExcelColumn(name = "二维码名称")
private String name;
@ExcelColumn(name = "小程序码参数")
private String scene;
@ExcelColumn(name = "小程序页面路径")
private String page;
@ExcelColumn(name = "二维码链接")
private String qrcodeUrl;
@ExcelColumn(name = "创建者")
private String creatorName;
@ExcelColumn(name = "创建时间")
private String createTimeStr;
@ExcelColumn(name = "更新者")
private String updaterName;
@ExcelColumn(name = "更新时间")
private String updateTimeStr;
@ExcelColumn(name = "删除标志")
private Boolean deleted;
}

View File

@ -0,0 +1,48 @@
package com.agileboot.domain.qywx.mpQrcode.model;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.domain.qywx.mpQrcode.command.AddMpQrcodeCommand;
import com.agileboot.domain.qywx.mpQrcode.command.UpdateMpQrcodeCommand;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeEntity;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeService;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 小程序二维码模型
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MpQrcodeModel extends QyMpQrcodeEntity {
private QyMpQrcodeService qrcodeService;
public MpQrcodeModel(QyMpQrcodeEntity entity, QyMpQrcodeService qrcodeService) {
this(qrcodeService);
if (entity != null) {
BeanUtil.copyProperties(entity, this);
}
}
public MpQrcodeModel(QyMpQrcodeService qrcodeService) {
this.qrcodeService = qrcodeService;
}
public void loadAddCommand(AddMpQrcodeCommand command) {
if (command != null) {
BeanUtil.copyProperties(command, this, "qrcodeId");
}
}
public void loadUpdateCommand(UpdateMpQrcodeCommand command) {
if (command != null) {
loadAddCommand(command);
this.setQrcodeId(command.getQrcodeId());
}
}
}

View File

@ -0,0 +1,35 @@
package com.agileboot.domain.qywx.mpQrcode.model;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeEntity;
import com.agileboot.domain.qywx.mpQrcode.db.QyMpQrcodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* <p>
* 小程序二维码模型工厂
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@Component
@RequiredArgsConstructor
public class MpQrcodeModelFactory {
private final QyMpQrcodeService qrcodeService;
public MpQrcodeModel loadById(Long qrcodeId) {
QyMpQrcodeEntity entity = qrcodeService.getById(qrcodeId);
if (entity == null) {
throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, qrcodeId, "二维码");
}
return new MpQrcodeModel(entity, qrcodeService);
}
public MpQrcodeModel create() {
return new MpQrcodeModel(qrcodeService);
}
}

View File

@ -0,0 +1,42 @@
package com.agileboot.domain.qywx.mpQrcode.query;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 查询小程序二维码
* </p>
*
* @author AgileBoot
* @since 2025-12-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SearchMpQrcodeQuery<T> extends AbstractPageQuery<T> {
private String corpid;
private String name;
private String scene;
private Date createStartTime;
private Date createEndTime;
@Override
public QueryWrapper<T> addQueryCondition() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(StrUtil.isNotEmpty(corpid), "corpid", corpid)
.eq(StrUtil.isNotEmpty(name), "name", name)
.eq(StrUtil.isNotEmpty(scene), "scene", scene)
.between(createStartTime != null && createEndTime != null, "create_time", createStartTime, createEndTime);
this.timeRangeColumn = "create_time";
return queryWrapper;
}
}

16
doc/sql/qy_mp_qrcode.sql Normal file
View File

@ -0,0 +1,16 @@
CREATE TABLE `qy_mp_qrcode` (
`qrcode_id` bigint NOT NULL AUTO_INCREMENT COMMENT '二维码唯一ID',
`corpid` varchar(50) NOT NULL COMMENT '企业微信id',
`name` varchar(255) NOT NULL COMMENT '二维码名称',
`scene` varchar(64) DEFAULT NULL COMMENT '小程序码参数最大32个可见字符',
`page` varchar(255) DEFAULT NULL COMMENT '小程序页面路径',
`qrcode_url` text DEFAULT NULL COMMENT '二维码链接',
`creator_id` bigint NOT NULL DEFAULT 0 COMMENT '创建者ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater_id` bigint NOT NULL DEFAULT 0 COMMENT '更新者ID',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志0存在 1删除',
PRIMARY KEY (`qrcode_id`),
UNIQUE KEY `uk_corpid_name` (`corpid`, `name`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业小程序二维码表';