mp:menu 前端接入菜单的保存、清空操作
This commit is contained in:
parent
c0b950257f
commit
2173cf0364
|
@ -52,6 +52,7 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode DRAFT_DELETE_FAIL = new ErrorCode(1006007002, "删除草稿失败,原因:{}");
|
ErrorCode DRAFT_DELETE_FAIL = new ErrorCode(1006007002, "删除草稿失败,原因:{}");
|
||||||
|
|
||||||
// ========== 公众号菜单 1006008000============
|
// ========== 公众号菜单 1006008000============
|
||||||
ErrorCode MENU_NOT_EXISTS = new ErrorCode(1006008000, "菜单不存在");
|
ErrorCode MENU_SAVE_FAIL = new ErrorCode(1006008000, "创建菜单失败,原因:{}");
|
||||||
|
ErrorCode MENU_DELETE_FAIL = new ErrorCode(1006008001, "删除菜单失败,原因:{}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,24 +6,24 @@ tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
{
|
{
|
||||||
"accountId": "1",
|
"accountId": "1",
|
||||||
"buttons": [
|
"menus": [
|
||||||
{
|
{
|
||||||
"type":"click",
|
"type":"click",
|
||||||
"name":"今日歌曲",
|
"name":"今日歌曲",
|
||||||
"key":"V1001_TODAY_MUSIC"
|
"menuKey":"V1001_TODAY_MUSIC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"搜索",
|
"name":"搜索",
|
||||||
"type":"view",
|
"type":"view",
|
||||||
"url":"http://www.soso.com/"
|
"url":"https://www.soso.com/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "父按钮",
|
"name": "父按钮",
|
||||||
"subButtons": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type":"click",
|
"type":"click",
|
||||||
"name":"归去来兮",
|
"name":"归去来兮",
|
||||||
"key":"MUSIC"
|
"menuKey":"MUSIC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"不说",
|
"name":"不说",
|
||||||
|
@ -33,6 +33,17 @@ tenant-id: {{adminTenentId}}
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### 请求 /mp/menu/save 接口 => 成功(清空)
|
||||||
|
POST {{baseUrl}}/mp/menu/save
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"accountId": "1",
|
||||||
|
"menus": []
|
||||||
|
}
|
||||||
|
|
||||||
### 请求 /mp/menu/list 接口 => 成功
|
### 请求 /mp/menu/list 接口 => 成功
|
||||||
GET {{baseUrl}}/mp/menu/list?accountId=1
|
GET {{baseUrl}}/mp/menu/list?accountId=1
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
@ -32,28 +31,20 @@ public class MpMenuController {
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
@ApiOperation("保存公众号菜单")
|
@ApiOperation("保存公众号菜单")
|
||||||
@PreAuthorize("@ss.hasPermission('mp:menu:save')")
|
@PreAuthorize("@ss.hasPermission('mp:menu:save')")
|
||||||
public CommonResult<Long> saveMenu(@Valid @RequestBody MpMenuSaveReqVO createReqVO) {
|
public CommonResult<Boolean> saveMenu(@Valid @RequestBody MpMenuSaveReqVO createReqVO) {
|
||||||
return success(mpMenuService.saveMenu(createReqVO));
|
mpMenuService.saveMenu(createReqVO);
|
||||||
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@ApiOperation("删除公众号菜单")
|
@ApiOperation("删除公众号菜单")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('mp:menu:delete')")
|
@PreAuthorize("@ss.hasPermission('mp:menu:delete')")
|
||||||
public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteMenu(@RequestParam("accountId") Long accountId) {
|
||||||
mpMenuService.deleteMenu(id);
|
mpMenuService.deleteMenuByAccountId(accountId);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
|
||||||
@ApiOperation("获得公众号菜单")
|
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
|
||||||
@PreAuthorize("@ss.hasPermission('mp:menu:query')")
|
|
||||||
public CommonResult<MpMenuRespVO> getMenu(@RequestParam("id") Long id) {
|
|
||||||
MpMenuDO menu = mpMenuService.getMenu(id);
|
|
||||||
return success(MpMenuConvert.INSTANCE.convert(menu));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperation("获得公众号菜单列表")
|
@ApiOperation("获得公众号菜单列表")
|
||||||
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import me.chanjar.weixin.common.api.WxConsts;
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
// TODO 芋艿:完善 swagger 注解
|
// TODO 芋艿:完善 swagger 注解
|
||||||
|
@ -17,17 +14,6 @@ import java.util.List;
|
||||||
@Data
|
@Data
|
||||||
public class MpMenuBaseVO {
|
public class MpMenuBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
|
||||||
@NotNull(message = "公众号账号的编号不能为空")
|
|
||||||
private Long accountId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信公众号 appid
|
|
||||||
*
|
|
||||||
* 冗余 {@link MpAccountDO#getAppId()}
|
|
||||||
*/
|
|
||||||
private String appId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单名称
|
* 菜单名称
|
||||||
*/
|
*/
|
||||||
|
@ -42,10 +28,6 @@ public class MpMenuBaseVO {
|
||||||
* 父菜单编号
|
* 父菜单编号
|
||||||
*/
|
*/
|
||||||
private Long parentId;
|
private Long parentId;
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
// ========== 按钮操作 ==========
|
// ========== 按钮操作 ==========
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
||||||
|
|
||||||
import lombok.*;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.util.*;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Date;
|
||||||
import io.swagger.annotations.*;
|
|
||||||
|
|
||||||
|
// TODO swagger 文档
|
||||||
@ApiModel("管理后台 - 微信菜单 Response VO")
|
@ApiModel("管理后台 - 微信菜单 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ -15,6 +20,17 @@ public class MpMenuRespVO extends MpMenuBaseVO {
|
||||||
@ApiModelProperty(value = "主键", required = true)
|
@ApiModelProperty(value = "主键", required = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||||
|
@NotNull(message = "公众号账号的编号不能为空")
|
||||||
|
private Long accountId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信公众号 appid
|
||||||
|
*
|
||||||
|
* 冗余 {@link MpAccountDO#getAppId()}
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间", required = true)
|
@ApiModelProperty(value = "创建时间", required = true)
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,32 @@
|
||||||
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
|
||||||
|
|
||||||
import lombok.*;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 微信菜单保存 Request VO")
|
// TODO 芋艿:swagger 文档
|
||||||
|
@ApiModel("管理后台 - 公众号菜单保存 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
public class MpMenuSaveReqVO {
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class MpMenuSaveReqVO extends MpMenuBaseVO {
|
|
||||||
|
|
||||||
@NotNull(message = "按钮不能为空")
|
@ApiModelProperty(value = "公众号账号的编号", required = true, example = "2048")
|
||||||
private List<WxMenuButton> buttons;
|
@NotNull(message = "公众号账号的编号不能为空")
|
||||||
|
private Long accountId;
|
||||||
|
|
||||||
|
@NotEmpty(message = "菜单不能为空")
|
||||||
|
@Valid
|
||||||
|
private List<Menu> menus;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Menu extends MpMenuBaseVO {
|
||||||
|
|
||||||
|
private List<Menu> children;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuRespVO;
|
||||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||||
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
||||||
|
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mapping;
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
|
@ -16,8 +17,6 @@ public interface MpMenuConvert {
|
||||||
|
|
||||||
MpMenuConvert INSTANCE = Mappers.getMapper(MpMenuConvert.class);
|
MpMenuConvert INSTANCE = Mappers.getMapper(MpMenuConvert.class);
|
||||||
|
|
||||||
MpMenuDO convert(MpMenuSaveReqVO bean);
|
|
||||||
|
|
||||||
MpMenuRespVO convert(MpMenuDO bean);
|
MpMenuRespVO convert(MpMenuDO bean);
|
||||||
|
|
||||||
List<MpMenuRespVO> convertList(List<MpMenuDO> list);
|
List<MpMenuRespVO> convertList(List<MpMenuDO> list);
|
||||||
|
@ -27,11 +26,20 @@ public interface MpMenuConvert {
|
||||||
@Mapping(source = "menu.replyMessageType", target = "type"),
|
@Mapping(source = "menu.replyMessageType", target = "type"),
|
||||||
@Mapping(source = "menu.replyContent", target = "content"),
|
@Mapping(source = "menu.replyContent", target = "content"),
|
||||||
@Mapping(source = "menu.replyMediaId", target = "mediaId"),
|
@Mapping(source = "menu.replyMediaId", target = "mediaId"),
|
||||||
@Mapping(source = "menu.replyMediaUrl", target = "mediaUrl"),
|
|
||||||
@Mapping(source = "menu.replyTitle", target = "title"),
|
@Mapping(source = "menu.replyTitle", target = "title"),
|
||||||
@Mapping(source = "menu.replyDescription", target = "description"),
|
@Mapping(source = "menu.replyDescription", target = "description"),
|
||||||
@Mapping(source = "menu.replyArticles", target = "articles"),
|
@Mapping(source = "menu.replyArticles", target = "articles"),
|
||||||
})
|
})
|
||||||
MpMessageSendOutReqBO convert(String openid, MpMenuDO menu);
|
MpMessageSendOutReqBO convert(String openid, MpMenuDO menu);
|
||||||
|
|
||||||
|
List<WxMenuButton> convert(List<MpMenuSaveReqVO.Menu> list);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "menuKey", target = "key"),
|
||||||
|
@Mapping(source = "children", target = "subButtons"),
|
||||||
|
})
|
||||||
|
WxMenuButton convert(MpMenuSaveReqVO.Menu bean);
|
||||||
|
|
||||||
|
MpMenuDO convert02(MpMenuSaveReqVO.Menu menu);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,6 @@ public class MpMenuDO extends BaseDO {
|
||||||
* 父菜单编号
|
* 父菜单编号
|
||||||
*/
|
*/
|
||||||
private Long parentId;
|
private Long parentId;
|
||||||
/**
|
|
||||||
* 排序
|
|
||||||
*/
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
// ========== 按钮操作 ==========
|
// ========== 按钮操作 ==========
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.mp.dal.mysql.menu;
|
package cn.iocoder.yudao.module.mp.dal.mysql.menu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@ -18,4 +19,7 @@ public interface MpMenuMapper extends BaseMapperX<MpMenuDO> {
|
||||||
return selectList(MpMenuDO::getAccountId, accountId);
|
return selectList(MpMenuDO::getAccountId, accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void deleteByAccountId(Long accountId) {
|
||||||
|
delete(new LambdaQueryWrapperX<MpMenuDO>().eq(MpMenuDO::getAccountId, accountId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,24 +18,15 @@ public interface MpMenuService {
|
||||||
* 保存公众号菜单
|
* 保存公众号菜单
|
||||||
*
|
*
|
||||||
* @param createReqVO 创建信息
|
* @param createReqVO 创建信息
|
||||||
* @return 编号
|
|
||||||
*/
|
*/
|
||||||
Long saveMenu(@Valid MpMenuSaveReqVO createReqVO);
|
void saveMenu(@Valid MpMenuSaveReqVO createReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除公众号菜单
|
* 删除公众号菜单
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param accountId 公众号账号的编号
|
||||||
*/
|
*/
|
||||||
void deleteMenu(Long id);
|
void deleteMenuByAccountId(Long accountId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得公众号菜单
|
|
||||||
*
|
|
||||||
* @param id 编号
|
|
||||||
* @return 公众号菜单
|
|
||||||
*/
|
|
||||||
MpMenuDO getMenu(Long id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户点击菜单按钮时,回复对应的消息
|
* 用户点击菜单按钮时,回复对应的消息
|
||||||
|
@ -50,7 +41,7 @@ public interface MpMenuService {
|
||||||
/**
|
/**
|
||||||
* 获得公众号菜单列表
|
* 获得公众号菜单列表
|
||||||
*
|
*
|
||||||
* @param accountId 公众号编号
|
* @param accountId 公众号账号的编号
|
||||||
* @return 公众号菜单列表
|
* @return 公众号菜单列表
|
||||||
*/
|
*/
|
||||||
List<MpMenuDO> getMenuListByAccountId(Long accountId);
|
List<MpMenuDO> getMenuListByAccountId(Long accountId);
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package cn.iocoder.yudao.module.mp.service.menu;
|
package cn.iocoder.yudao.module.mp.service.menu;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.mp.convert.menu.MpMenuConvert;
|
import cn.iocoder.yudao.module.mp.convert.menu.MpMenuConvert;
|
||||||
|
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
|
||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
|
||||||
import cn.iocoder.yudao.module.mp.dal.mysql.menu.MpMenuMapper;
|
import cn.iocoder.yudao.module.mp.dal.mysql.menu.MpMenuMapper;
|
||||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
|
||||||
|
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
|
||||||
import cn.iocoder.yudao.module.mp.service.message.MpMessageService;
|
import cn.iocoder.yudao.module.mp.service.message.MpMessageService;
|
||||||
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -15,13 +18,15 @@ import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.MENU_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.MENU_DELETE_FAIL;
|
||||||
|
import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.MENU_SAVE_FAIL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公众号菜单 Service 实现类
|
* 公众号菜单 Service 实现类
|
||||||
|
@ -35,6 +40,9 @@ public class MpMenuServiceImpl implements MpMenuService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private MpMessageService mpMessageService;
|
private MpMessageService mpMessageService;
|
||||||
|
@Resource
|
||||||
|
@Lazy // 延迟加载,避免循环引用报错
|
||||||
|
private MpAccountService mpAccountService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Lazy // 延迟加载,避免循环引用报错
|
@Lazy // 延迟加载,避免循环引用报错
|
||||||
|
@ -44,43 +52,64 @@ public class MpMenuServiceImpl implements MpMenuService {
|
||||||
private MpMenuMapper mpMenuMapper;
|
private MpMenuMapper mpMenuMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long saveMenu(MpMenuSaveReqVO createReqVO) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
String appId = "wx5b23ba7a5589ecbb";
|
public void saveMenu(MpMenuSaveReqVO createReqVO) {
|
||||||
// 插入
|
MpAccountDO account = mpAccountService.getRequiredAccount(createReqVO.getAccountId());
|
||||||
MpMenuDO menu = MpMenuConvert.INSTANCE.convert(createReqVO);
|
WxMpService mpService = mpServiceFactory.getRequiredMpService(createReqVO.getAccountId());
|
||||||
// mpMenuMapper.insert(menu);
|
|
||||||
|
|
||||||
// TODO 同步菜单
|
// 第一步,同步公众号
|
||||||
WxMpService mpService = mpServiceFactory.getRequiredMpService(appId);
|
|
||||||
WxMenu wxMenu = new WxMenu();
|
WxMenu wxMenu = new WxMenu();
|
||||||
wxMenu.setButtons(createReqVO.getButtons());
|
wxMenu.setButtons(MpMenuConvert.INSTANCE.convert(createReqVO.getMenus()));
|
||||||
try {
|
try {
|
||||||
mpService.getMenuService().menuCreate(wxMenu);
|
mpService.getMenuService().menuCreate(wxMenu);
|
||||||
} catch (WxErrorException e) {
|
} catch (WxErrorException e) {
|
||||||
throw new RuntimeException(e);
|
throw exception(MENU_SAVE_FAIL, e.getError().getErrorMsg());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回
|
// 第二步,存储到数据库
|
||||||
return menu.getId();
|
mpMenuMapper.deleteByAccountId(createReqVO.getAccountId());
|
||||||
|
createReqVO.getMenus().forEach(menu -> {
|
||||||
|
// 先保存顶级菜单
|
||||||
|
MpMenuDO menuDO = createMenu(menu, null, account);
|
||||||
|
// 再保存子菜单
|
||||||
|
if (CollUtil.isEmpty(menu.getChildren())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menu.getChildren().forEach(childMenu -> createMenu(childMenu, menuDO, account));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteMenu(Long id) {
|
public void deleteMenuByAccountId(Long accountId) {
|
||||||
// 校验存在
|
WxMpService mpService = mpServiceFactory.getRequiredMpService(accountId);
|
||||||
validateMenuExists(id);
|
// 第一步,同步公众号
|
||||||
// 删除
|
try {
|
||||||
mpMenuMapper.deleteById(id);
|
mpService.getMenuService().menuDelete();
|
||||||
}
|
} catch (WxErrorException e) {
|
||||||
|
throw exception(MENU_DELETE_FAIL, e.getError().getErrorMsg());
|
||||||
private void validateMenuExists(Long id) {
|
|
||||||
if (mpMenuMapper.selectById(id) == null) {
|
|
||||||
throw exception(MENU_NOT_EXISTS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 第二步,存储到数据库
|
||||||
|
mpMenuMapper.deleteByAccountId(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private MpMenuDO createMenu(MpMenuSaveReqVO.Menu wxMenu, MpMenuDO parentMenu, MpAccountDO account) {
|
||||||
public MpMenuDO getMenu(Long id) {
|
MpMenuDO menu = CollUtil.isNotEmpty(wxMenu.getChildren())
|
||||||
return mpMenuMapper.selectById(id);
|
? new MpMenuDO().setName(wxMenu.getName())
|
||||||
|
: MpMenuConvert.INSTANCE.convert02(wxMenu);
|
||||||
|
if (account != null) {
|
||||||
|
menu.setAccountId(account.getId()).setAppId(account.getAppId());
|
||||||
|
}
|
||||||
|
if (parentMenu != null) {
|
||||||
|
menu.setParentId(parentMenu.getId());
|
||||||
|
} else {
|
||||||
|
menu.setParentId(MpMenuDO.ID_ROOT);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotEmpty(wxMenu.getReplyMediaId())) {
|
||||||
|
throw new IllegalArgumentException("未实现");
|
||||||
|
}
|
||||||
|
mpMenuMapper.insert(menu);
|
||||||
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,3 +7,23 @@ export function getMenuList(accountId) {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存公众号菜单
|
||||||
|
export function saveMenu(accountId, menus) {
|
||||||
|
return request({
|
||||||
|
url: '/mp/menu/save',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
accountId,
|
||||||
|
menus
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除公众号菜单
|
||||||
|
export function deleteMenu(accountId) {
|
||||||
|
return request({
|
||||||
|
url: '/mp/menu/delete?accountId=' + accountId,
|
||||||
|
method: 'delete',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -63,8 +63,8 @@ SOFTWARE.
|
||||||
<div class="menu_bottom menu_addicon" v-if="this.menuList.length < 3" @click="addMenu"><i class="el-icon-plus"></i></div>
|
<div class="menu_bottom menu_addicon" v-if="this.menuList.length < 3" @click="addMenu"><i class="el-icon-plus"></i></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="save_div">
|
<div class="save_div">
|
||||||
<!--<el-button class="save_btn" type="warning" size="small" @click="saveFun">保存菜单</el-button>-->
|
<el-button class="save_btn" type="success" size="small" @click="handleSave">保存并发布菜单</el-button>
|
||||||
<el-button class="save_btn" type="success" size="small" @click="handleSaveAndReleaseFun">保存并发布菜单</el-button>
|
<el-button class="save_btn" type="danger" size="small" @click="handleDelete">清空菜单</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--右边配置-->
|
<!--右边配置-->
|
||||||
|
@ -141,7 +141,7 @@ SOFTWARE.
|
||||||
import WxReplySelect from '@/views/mp/components/wx-news/main.vue'
|
import WxReplySelect from '@/views/mp/components/wx-news/main.vue'
|
||||||
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
import WxNews from '@/views/mp/components/wx-news/main.vue';
|
||||||
import WxMaterialSelect from '@/views/mp/components/wx-news/main.vue'
|
import WxMaterialSelect from '@/views/mp/components/wx-news/main.vue'
|
||||||
import { getMenuList } from "@/api/mp/menu";
|
import {deleteMenu, getMenuList, saveMenu} from "@/api/mp/menu";
|
||||||
import { getSimpleAccounts } from "@/api/mp/account";
|
import { getSimpleAccounts } from "@/api/mp/account";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -164,11 +164,6 @@ export default {
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
menu:{ // 横向菜单
|
|
||||||
button:[
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// ======================== 菜单操作 ========================
|
// ======================== 菜单操作 ========================
|
||||||
isActive: -1,// 一级菜单点中样式
|
isActive: -1,// 一级菜单点中样式
|
||||||
isSubMenuActive: -1, // 一级菜单点中样式
|
isSubMenuActive: -1, // 一级菜单点中样式
|
||||||
|
@ -178,7 +173,7 @@ export default {
|
||||||
showRightFlag: false, // 右边配置显示默认详情还是配置详情
|
showRightFlag: false, // 右边配置显示默认详情还是配置详情
|
||||||
nameMaxLength: 0, // 菜单名称最大长度;1 级是 4 字符;2 级是 7 字符;
|
nameMaxLength: 0, // 菜单名称最大长度;1 级是 4 字符;2 级是 7 字符;
|
||||||
showConfigureContent: true, // 是否展示配置内容;如果有子菜单,就不显示配置内容
|
showConfigureContent: true, // 是否展示配置内容;如果有子菜单,就不显示配置内容
|
||||||
|
hackResetWxReplySelect: false, // 重置 WxReplySelect 组件
|
||||||
|
|
||||||
tempObj:{}, // 右边临时变量,作为中间值牵引关系
|
tempObj:{}, // 右边临时变量,作为中间值牵引关系
|
||||||
tempSelfObj: { // 一些临时值放在这里进行判断,如果放在 tempObj,由于引用关系,menu 也会多了多余的参数
|
tempSelfObj: { // 一些临时值放在这里进行判断,如果放在 tempObj,由于引用关系,menu 也会多了多余的参数
|
||||||
|
@ -218,7 +213,6 @@ export default {
|
||||||
label: '选择地理位置'
|
label: '选择地理位置'
|
||||||
}],
|
}],
|
||||||
dialogNewsVisible: false,
|
dialogNewsVisible: false,
|
||||||
hackResetWxReplySelect: false,
|
|
||||||
|
|
||||||
// 公众号账号列表
|
// 公众号账号列表
|
||||||
accounts: [],
|
accounts: [],
|
||||||
|
@ -246,7 +240,6 @@ export default {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
getMenuList(this.accountId).then(response => {
|
getMenuList(this.accountId).then(response => {
|
||||||
this.menuList = this.handleTree(response.data, "id");
|
this.menuList = this.handleTree(response.data, "id");
|
||||||
console.log(this.menuList)
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
})
|
})
|
||||||
|
@ -354,31 +347,16 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
// ======================== 菜单编辑 ========================
|
// ======================== 菜单编辑 ========================
|
||||||
handleSaveAndReleaseFun(){
|
handleSave() {
|
||||||
this.$confirm('确定要保证并发布该菜单吗?', '提示', {
|
this.$modal.confirm('确定要保证并发布该菜单吗?').then(() => {
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
saveAndRelease({
|
return saveMenu(this.accountId, this.menuList);
|
||||||
strWxMenu:this.menu
|
}).then(() => {
|
||||||
}).then(response => {
|
this.getList();
|
||||||
this.loading = false
|
this.$modal.msgSuccess("发布成功");
|
||||||
if(response.code == 200){
|
}).catch(() => {}).finally(() => {
|
||||||
this.$message({
|
this.loading = false
|
||||||
showClose: true,
|
});
|
||||||
message: '发布成功',
|
|
||||||
type: 'success'
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
this.$message.error(response.data.msg)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// 表单 Editor 重置
|
// 表单 Editor 重置
|
||||||
resetEditor() {
|
resetEditor() {
|
||||||
|
@ -387,6 +365,17 @@ export default {
|
||||||
this.hackResetEditor = true // 重建组件
|
this.hackResetEditor = true // 重建组件
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleDelete() {
|
||||||
|
this.$modal.confirm('确定要清空所有菜单吗?').then(() => {
|
||||||
|
this.loading = true
|
||||||
|
return deleteMenu(this.accountId);
|
||||||
|
}).then(() => {
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("清空成功");
|
||||||
|
}).catch(() => {}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// TODO 芋艿:未归类
|
// TODO 芋艿:未归类
|
||||||
|
|
||||||
|
@ -431,7 +420,7 @@ div{
|
||||||
left:0px;
|
left:0px;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height:64px;
|
height:64px;
|
||||||
background: transparent url(assets/menu_head.png) no-repeat 0 0;
|
background: transparent url("assets/menu_head.png") no-repeat 0 0;
|
||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
background-size: 100%
|
background-size: 100%
|
||||||
}
|
}
|
||||||
|
@ -445,7 +434,7 @@ div{
|
||||||
left: 0px;
|
left: 0px;
|
||||||
}
|
}
|
||||||
.weixin-menu{
|
.weixin-menu{
|
||||||
background: transparent url(assets/menu_foot.png) no-repeat 0 0;
|
background: transparent url("assets/menu_foot.png") no-repeat 0 0;
|
||||||
padding-left: 43px;
|
padding-left: 43px;
|
||||||
font-size: 12px
|
font-size: 12px
|
||||||
}
|
}
|
||||||
|
@ -581,26 +570,26 @@ div{
|
||||||
<!--</style>-->
|
<!--</style>-->
|
||||||
<!--素材样式-->
|
<!--素材样式-->
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pagination{
|
.pagination {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
}
|
}
|
||||||
.select-item{
|
.select-item {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0 auto 10px auto;
|
margin: 0 auto 10px auto;
|
||||||
border: 1px solid #eaeaea;
|
border: 1px solid #eaeaea;
|
||||||
}
|
}
|
||||||
.select-item2{
|
.select-item2 {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0 auto 10px auto;
|
margin: 0 auto 10px auto;
|
||||||
border: 1px solid #eaeaea;
|
border: 1px solid #eaeaea;
|
||||||
}
|
}
|
||||||
.ope-row{
|
.ope-row {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.item-name{
|
.item-name {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow:ellipsis;
|
text-overflow:ellipsis;
|
||||||
|
|
Loading…
Reference in New Issue