Commit 02ec5d455c20ea4e0e9d6d87334331acedfdccc6

Authored by YunaiV
1 parent f271ef8c

mp:1)引入 less-loader,解决 menu 的 less 样式;2)接入菜单列表接口

yudao-module-mp/yudao-module-mp-api/src/main/java/cn/iocoder/yudao/module/mp/enums/ErrorCodeConstants.java
... ... @@ -51,7 +51,7 @@ public interface ErrorCodeConstants {
51 51 ErrorCode DRAFT_UPDATE_FAIL = new ErrorCode(1006007002, "更新草稿失败,原因:{}");
52 52 ErrorCode DRAFT_DELETE_FAIL = new ErrorCode(1006007002, "删除草稿失败,原因:{}");
53 53  
54   - // TODO 要处理下
55   - ErrorCode MENU_NOT_EXISTS = new ErrorCode(1006001002, "菜单不存在");
  54 + // ========== 公众号菜单 1006008000============
  55 + ErrorCode MENU_NOT_EXISTS = new ErrorCode(1006008000, "菜单不存在");
56 56  
57 57 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/menu/MpMenuController.http
... ... @@ -32,3 +32,8 @@ tenant-id: {{adminTenentId}}
32 32 }]
33 33 }]
34 34 }
  35 +
  36 +### 请求 /mp/menu/list 接口 => 成功
  37 +GET {{baseUrl}}/mp/menu/list?accountId=1
  38 +Authorization: Bearer {{token}}
  39 +tenant-id: {{adminTenentId}}
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/menu/MpMenuController.java
1 1 package cn.iocoder.yudao.module.mp.controller.admin.menu;
2 2  
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuRespVO;
  5 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
3 6 import cn.iocoder.yudao.module.mp.convert.menu.MpMenuConvert;
4 7 import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
  8 +import cn.iocoder.yudao.module.mp.service.menu.MpMenuService;
  9 +import io.swagger.annotations.Api;
  10 +import io.swagger.annotations.ApiImplicitParam;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
5 14 import org.springframework.web.bind.annotation.*;
6 15  
7 16 import javax.annotation.Resource;
  17 +import javax.validation.Valid;
8 18  
9   -import org.springframework.validation.annotation.Validated;
10   -import org.springframework.security.access.prepost.PreAuthorize;
11   -import io.swagger.annotations.*;
12   -
13   -import javax.validation.*;
14   -
15   -import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  19 +import java.util.List;
16 20  
17 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
18 22  
19   -import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.*;
20   -import cn.iocoder.yudao.module.mp.service.menu.MpMenuService;
21   -
22   -@Api(tags = "管理后台 - 微信菜单")
  23 +@Api(tags = "管理后台 - 公众号菜单")
23 24 @RestController
24 25 @RequestMapping("/mp/menu")
25 26 @Validated
... ... @@ -29,14 +30,14 @@ public class MpMenuController {
29 30 private MpMenuService mpMenuService;
30 31  
31 32 @PostMapping("/save")
32   - @ApiOperation("保存微信菜单")
  33 + @ApiOperation("保存公众号菜单")
33 34 @PreAuthorize("@ss.hasPermission('mp:menu:save')")
34 35 public CommonResult<Long> saveMenu(@Valid @RequestBody MpMenuSaveReqVO createReqVO) {
35 36 return success(mpMenuService.saveMenu(createReqVO));
36 37 }
37 38  
38 39 @DeleteMapping("/delete")
39   - @ApiOperation("删除微信菜单")
  40 + @ApiOperation("删除公众号菜单")
40 41 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
41 42 @PreAuthorize("@ss.hasPermission('mp:menu:delete')")
42 43 public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
... ... @@ -45,7 +46,7 @@ public class MpMenuController {
45 46 }
46 47  
47 48 @GetMapping("/get")
48   - @ApiOperation("获得微信菜单")
  49 + @ApiOperation("获得公众号菜单")
49 50 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
50 51 @PreAuthorize("@ss.hasPermission('mp:menu:query')")
51 52 public CommonResult<MpMenuRespVO> getMenu(@RequestParam("id") Long id) {
... ... @@ -53,4 +54,13 @@ public class MpMenuController {
53 54 return success(MpMenuConvert.INSTANCE.convert(menu));
54 55 }
55 56  
  57 + @GetMapping("/list")
  58 + @ApiOperation("获得公众号菜单列表")
  59 + @ApiImplicitParam(name = "accountId", value = "公众号账号的编号", required = true, example = "10", dataTypeClass = Long.class)
  60 + @PreAuthorize("@ss.hasPermission('mp:menu:query')")
  61 + public CommonResult<List<MpMenuRespVO>> getMenuList(@RequestParam("accountId") Long accountId) {
  62 + List<MpMenuDO> list = mpMenuService.getMenuListByAccountId(accountId);
  63 + return success(MpMenuConvert.INSTANCE.convertList(list));
  64 + }
  65 +
56 66 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/menu/vo/MpMenuBaseVO.java
1 1 package cn.iocoder.yudao.module.mp.controller.admin.menu.vo;
2 2  
  3 +import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
  4 +import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO;
3 5 import io.swagger.annotations.ApiModelProperty;
4   -import lombok.*;
5   -import me.chanjar.weixin.common.bean.menu.WxMenuButton;
  6 +import lombok.Data;
  7 +import me.chanjar.weixin.common.api.WxConsts;
6 8  
7 9 import javax.validation.constraints.NotNull;
8 10 import java.util.List;
9 11  
  12 +// TODO 芋艿:完善 swagger 注解
10 13 /**
11 14 * 微信菜单 Base VO,提供给添加、修改、详细的子 VO 使用
12 15 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
... ... @@ -18,4 +21,112 @@ public class MpMenuBaseVO {
18 21 @NotNull(message = "公众号账号的编号不能为空")
19 22 private Long accountId;
20 23  
  24 + /**
  25 + * 微信公众号 appid
  26 + *
  27 + * 冗余 {@link MpAccountDO#getAppId()}
  28 + */
  29 + private String appId;
  30 +
  31 + /**
  32 + * 菜单名称
  33 + */
  34 + private String name;
  35 + /**
  36 + * 菜单标识
  37 + *
  38 + * 支持多 DB 类型时,无法直接使用 key + @TableField("menuKey") 来实现转换,原因是 "menuKey" AS key 而存在报错
  39 + */
  40 + private String menuKey;
  41 + /**
  42 + * 父菜单编号
  43 + */
  44 + private Long parentId;
  45 + /**
  46 + * 排序
  47 + */
  48 + private Integer sort;
  49 +
  50 + // ========== 按钮操作 ==========
  51 +
  52 + /**
  53 + * 按钮类型
  54 + *
  55 + * 枚举 {@link WxConsts.MenuButtonType}
  56 + */
  57 + private String type;
  58 +
  59 + /**
  60 + * 网页链接
  61 + *
  62 + * 用户点击菜单可打开链接,不超过 1024 字节
  63 + *
  64 + * 类型为 {@link WxConsts.XmlMsgType} 的 VIEW、MINIPROGRAM
  65 + */
  66 + private String url;
  67 +
  68 + /**
  69 + * 小程序的 appId
  70 + *
  71 + * 类型为 {@link WxConsts.MenuButtonType} 的 MINIPROGRAM
  72 + */
  73 + private String miniProgramAppId;
  74 + /**
  75 + * 小程序的页面路径
  76 + *
  77 + * 类型为 {@link WxConsts.MenuButtonType} 的 MINIPROGRAM
  78 + */
  79 + private String miniProgramPagePath;
  80 +
  81 + // ========== 消息内容 ==========
  82 +
  83 + /**
  84 + * 消息类型
  85 + *
  86 + * 当 {@link #type} 为 CLICK、SCANCODE_WAITMSG
  87 + *
  88 + * 枚举 {@link WxConsts.XmlMsgType} 中的 TEXT、IMAGE、VOICE、VIDEO、NEWS
  89 + */
  90 + private String replyMessageType;
  91 +
  92 + /**
  93 + * 回复的消息内容
  94 + *
  95 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 TEXT
  96 + */
  97 + private String replyContent;
  98 +
  99 + /**
  100 + * 回复的媒体 id
  101 + *
  102 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 IMAGE、VOICE、VIDEO
  103 + */
  104 + private String replyMediaId;
  105 + /**
  106 + * 回复的媒体 URL
  107 + *
  108 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 IMAGE、VOICE、VIDEO
  109 + */
  110 + private String replyMediaUrl;
  111 +
  112 + /**
  113 + * 回复的标题
  114 + *
  115 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 VIDEO
  116 + */
  117 + private String replyTitle;
  118 + /**
  119 + * 回复的描述
  120 + *
  121 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 VIDEO
  122 + */
  123 + private String replyDescription;
  124 +
  125 + /**
  126 + * 回复的图文消息数组
  127 + *
  128 + * 消息类型为 {@link WxConsts.XmlMsgType} 的 NEWS
  129 + */
  130 + private List<MpMessageDO.Article> replyArticles;
  131 +
21 132 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/convert/menu/MpMenuConvert.java
1 1 package cn.iocoder.yudao.module.mp.convert.menu;
2 2  
3   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -
  3 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuRespVO;
  4 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
  5 +import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
5 6 import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
6 7 import org.mapstruct.Mapper;
7 8 import org.mapstruct.Mapping;
8 9 import org.mapstruct.Mappings;
9 10 import org.mapstruct.factory.Mappers;
10   -import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.*;
11   -import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
  11 +
  12 +import java.util.List;
12 13  
13 14 @Mapper
14 15 public interface MpMenuConvert {
... ... @@ -19,6 +20,8 @@ public interface MpMenuConvert {
19 20  
20 21 MpMenuRespVO convert(MpMenuDO bean);
21 22  
  23 + List<MpMenuRespVO> convertList(List<MpMenuDO> list);
  24 +
22 25 @Mappings({
23 26 @Mapping(source = "menu.appId", target = "appId"),
24 27 @Mapping(source = "menu.replyMessageType", target = "type"),
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/menu/MpMenuMapper.java
... ... @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 4 import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
5 5 import org.apache.ibatis.annotations.Mapper;
6 6  
  7 +import java.util.List;
  8 +
7 9 @Mapper
8 10 public interface MpMenuMapper extends BaseMapperX<MpMenuDO> {
9 11  
... ... @@ -12,4 +14,8 @@ public interface MpMenuMapper extends BaseMapperX&lt;MpMenuDO&gt; {
12 14 MpMenuDO::getMenuKey, menuKey);
13 15 }
14 16  
  17 + default List<MpMenuDO> selectListByAccountId(Long accountId) {
  18 + return selectList(MpMenuDO::getAccountId, accountId);
  19 + }
  20 +
15 21 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/menu/MpMenuService.java
1 1 package cn.iocoder.yudao.module.mp.service.menu;
2 2  
3   -import javax.validation.*;
4   -
5   -import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.*;
  3 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
6 4 import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
7   -import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
8 5 import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
9 6  
  7 +import javax.validation.Valid;
  8 +import java.util.List;
  9 +
10 10 /**
11   - * 微信菜单 Service 接口
  11 + * 公众号菜单 Service 接口
12 12 *
13 13 * @author 芋道源码
14 14 */
15 15 public interface MpMenuService {
16 16  
17 17 /**
18   - * 保存微信菜单
  18 + * 保存公众号菜单
19 19 *
20 20 * @param createReqVO 创建信息
21 21 * @return 编号
... ... @@ -23,17 +23,17 @@ public interface MpMenuService {
23 23 Long saveMenu(@Valid MpMenuSaveReqVO createReqVO);
24 24  
25 25 /**
26   - * 删除微信菜单
  26 + * 删除公众号菜单
27 27 *
28 28 * @param id 编号
29 29 */
30 30 void deleteMenu(Long id);
31 31  
32 32 /**
33   - * 获得微信菜单
  33 + * 获得公众号菜单
34 34 *
35 35 * @param id 编号
36   - * @return 微信菜单
  36 + * @return 公众号菜单
37 37 */
38 38 MpMenuDO getMenu(Long id);
39 39  
... ... @@ -47,4 +47,12 @@ public interface MpMenuService {
47 47 */
48 48 WxMpXmlOutMessage reply(String appId, String key, String openid);
49 49  
  50 + /**
  51 + * 获得公众号菜单列表
  52 + *
  53 + * @param accountId 公众号编号
  54 + * @return 公众号菜单列表
  55 + */
  56 + List<MpMenuDO> getMenuListByAccountId(Long accountId);
  57 +
50 58 }
... ...
yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/menu/MpMenuServiceImpl.java
1 1 package cn.iocoder.yudao.module.mp.service.menu;
2 2  
3 3 import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.MpMenuSaveReqVO;
4 5 import cn.iocoder.yudao.module.mp.convert.menu.MpMenuConvert;
5 6 import cn.iocoder.yudao.module.mp.dal.dataobject.menu.MpMenuDO;
  7 +import cn.iocoder.yudao.module.mp.dal.mysql.menu.MpMenuMapper;
6 8 import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
7 9 import cn.iocoder.yudao.module.mp.service.message.MpMessageService;
8 10 import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO;
... ... @@ -13,20 +15,16 @@ import me.chanjar.weixin.mp.api.WxMpService;
13 15 import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
14 16 import org.springframework.context.annotation.Lazy;
15 17 import org.springframework.stereotype.Service;
16   -
17   -import javax.annotation.Resource;
18   -
19 18 import org.springframework.validation.annotation.Validated;
20 19  
21   -import cn.iocoder.yudao.module.mp.controller.admin.menu.vo.*;
22   -
23   -import cn.iocoder.yudao.module.mp.dal.mysql.menu.MpMenuMapper;
  20 +import javax.annotation.Resource;
  21 +import java.util.List;
24 22  
25 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26   -import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.*;
  24 +import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.MENU_NOT_EXISTS;
27 25  
28 26 /**
29   - * 微信菜单 Service 实现类
  27 + * 公众号菜单 Service 实现类
30 28 *
31 29 * @author 芋道源码
32 30 */
... ... @@ -76,7 +74,6 @@ public class MpMenuServiceImpl implements MpMenuService {
76 74  
77 75 private void validateMenuExists(Long id) {
78 76 if (mpMenuMapper.selectById(id) == null) {
79   - // TODO 芋艿:错误码不太对
80 77 throw exception(MENU_NOT_EXISTS);
81 78 }
82 79 }
... ... @@ -105,4 +102,9 @@ public class MpMenuServiceImpl implements MpMenuService {
105 102 return mpMessageService.sendOutMessage(sendReqBO);
106 103 }
107 104  
  105 + @Override
  106 + public List<MpMenuDO> getMenuListByAccountId(Long accountId) {
  107 + return mpMenuMapper.selectListByAccountId(accountId);
  108 + }
  109 +
108 110 }
... ...
yudao-ui-admin/package.json
... ... @@ -90,6 +90,8 @@
90 90 "eslint-plugin-prettier": "^3.1.0",
91 91 "eslint-plugin-vue": "9.0.0",
92 92 "fs-extra": "^8.1.0",
  93 + "less": "^4.1.3",
  94 + "less-loader": "^7.3.0",
93 95 "lint-staged": "12.5.0",
94 96 "runjs": "4.4.2",
95 97 "sass": "1.32.13",
... ...
yudao-ui-admin/src/api/mp/menu.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获得公众号菜单列表
  4 +export function getMenuList(accountId) {
  5 + return request({
  6 + url: '/mp/menu/list?accountId=' + accountId,
  7 + method: 'get',
  8 + })
  9 +}
... ...
yudao-ui-admin/src/views/mp/menu/index.vue
... ... @@ -23,344 +23,405 @@ SOFTWARE.
23 23 -->
24 24 <template>
25 25 <div class="app-container">
26   - <div class="public-account-management clearfix" v-loading="saveLoading">
27   - <!--左边配置菜单-->
28   - <div class="left">
29   - <div class="weixin-hd">
30   - <div class="weixin-title">
31   - {{menuName}}
32   - </div>
33   - </div>
34   - <div class="weixin-menu menu_main clearfix">
35   - <div class="menu_bottom" v-for="(item, i) of menu.button" :key="i" >
36   - <!-- 一级菜单 -->
37   - <div @click="menuFun(i,item)" class="menu_item el-icon-s-fold" :class="{'active': isActive == i}">{{item.name}}</div>
38   - <!--以下为二级菜单-->
39   - <div class="submenu" v-if="isSubMenuFlag == i">
40   - <div class="subtitle menu_bottom" v-if="item.sub_button" v-for="(subItem, k) in item.sub_button" :key="k">
41   - <div class="menu_subItem" :class="{'active': isSubMenuActive == i + '' +k}" @click="subMenuFun(subItem, i, k)">{{subItem.name}}</div>
42   - </div>
43   - <!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
44   - <div class="menu_bottom menu_addicon" v-if="!item.sub_button || item.sub_button.length < 5" @click="addSubMenu(i,item)"><i class="el-icon-plus"></i></div>
45   - </div>
46   - </div>
47   - <!-- 一级菜单加号 -->
48   - <div class="menu_bottom menu_addicon" v-if="menuKeyLength < 3" @click="addMenu"><i class="el-icon-plus"></i></div>
49   - </div>
50   - <div class="save_div">
51   - <!--<el-button class="save_btn" type="warning" size="small" @click="saveFun">保存菜单</el-button>-->
52   - <el-button class="save_btn" type="success" size="small" @click="saveAndReleaseFun">保存并发布菜单</el-button>
53   - </div>
54   - </div>
55   - <!--右边配置-->
56   - <div v-if="showRightFlag" class="right">
57   - <div class="configure_page">
58   - <div class="delete_btn">
59   - <el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteMenu(tempObj)">删除当前菜单</el-button>
60   - </div>
61   - <div>
62   - <span>菜单名称:</span>
63   - <el-input class="input_width" v-model="tempObj.name" placeholder="请输入菜单名称" :maxlength=nameMaxlength clearable></el-input>
64   - </div>
65   - <div v-if="showConfigurContent">
66   - <div class="menu_content">
67   - <span>菜单内容:</span>
68   - <el-select v-model="tempObj.type" clearable placeholder="请选择" class="menu_option">
69   - <el-option v-for="item in menuOptions" :label="item.label" :value="item.value" :key="item.value"></el-option>
70   - </el-select>
71   - </div>
72   - <div class="configur_content" v-if="tempObj.type == 'view'">
73   - <span>跳转链接:</span>
74   - <el-input class="input_width" v-model="tempObj.url" placeholder="请输入链接" clearable></el-input>
75   - </div>
76   - <div class="configur_content" v-if="tempObj.type == 'miniprogram'">
77   - <div class="applet">
78   - <span>小程序的appid:</span>
79   - <el-input class="input_width" v-model="tempObj.appid" placeholder="请输入小程序的appid" clearable></el-input>
80   - </div>
81   - <div class="applet">
82   - <span>小程序的页面路径:</span>
83   - <el-input class="input_width" v-model="tempObj.pagepath" placeholder="请输入小程序的页面路径,如:pages/index" clearable></el-input>
84   - </div>
85   - <div class="applet">
86   - <span>备用网页:</span>
87   - <el-input class="input_width" v-model="tempObj.url" placeholder="不支持小程序的老版本客户端将打开本网页" clearable></el-input>
88   - </div>
89   - <p class="blue">tips:需要和公众号进行关联才可以把小程序绑定带微信菜单上哟!</p>
90   - </div>
91   - <div class="configur_content" v-if="tempObj.type == 'article_view_limited'">
92   - <el-row>
93   - <div class="select-item" v-if="tempObj && tempObj.content && tempObj.content.articles">
94   - <WxNews :objData="tempObj.content.articles"></WxNews>
95   - <el-row class="ope-row">
96   - <el-button type="danger" icon="el-icon-delete" circle @click="deleteTempObj"></el-button>
97   - </el-row>
98   - </div>
99   - <div v-if="!tempObj.content || !tempObj.content.articles">
100   - <el-row>
101   - <el-col :span="24" style="text-align: center">
102   - <el-button type="success" @click="openMaterial">素材库选择<i class="el-icon-circle-check el-icon--right"></i></el-button>
103   - </el-col>
104   - </el-row>
105   - </div>
106   - <el-dialog title="选择图文" :visible.sync="dialogNewsVisible" width="90%">
107   - <WxMaterialSelect :objData="{repType:'news'}" @selectMaterial="selectMaterial"></WxMaterialSelect>
108   - </el-dialog>
109   - </el-row>
110   - </div>
111   - <div class="configur_content" v-if="tempObj.type == 'click' || tempObj.type == 'scancode_waitmsg'">
112   - <WxReplySelect :objData="tempObj" v-if="hackResetWxReplySelect"></WxReplySelect>
113   - </div>
114   - </div>
115   - </div>
116   - </div>
117   - <!--一进页面就显示的默认页面,当点击左边按钮的时候,就不显示了-->
118   - <div v-if="!showRightFlag" class="right">
119   - <p>请选择菜单配置</p>
120   - </div>
121   - </div>
  26 + <!-- 搜索工作栏 -->
  27 + <el-form ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  28 + <el-form-item label="公众号" prop="accountId">
  29 + <el-select v-model="accountId" placeholder="请选择公众号">
  30 + <el-option v-for="item in accounts" :key="parseInt(item.id)" :label="item.name" :value="parseInt(item.id)" />
  31 + </el-select>
  32 + </el-form-item>
  33 + <el-form-item>
  34 + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
  35 + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  36 + </el-form-item>
  37 + </el-form>
  38 +
  39 + <div class="public-account-management clearfix" v-loading="loading">
  40 + <!--左边配置菜单-->
  41 + <div class="left">
  42 + <div class="weixin-hd">
  43 + <div class="weixin-title">{{menuName}}</div>
  44 + </div>
  45 + <div class="weixin-menu menu_main clearfix">
  46 + <div class="menu_bottom" v-for="(item, i) of menuList" :key="i" >
  47 + <!-- 一级菜单 -->
  48 + <div @click="menuClick(i, item)" class="menu_item el-icon-s-fold" :class="{'active': isActive === i}">{{item.name}}</div>
  49 + <!-- 以下为二级菜单-->
  50 + <div class="submenu" v-if="isSubMenuFlag === i">
  51 + <div class="subtitle menu_bottom" v-if="item.children" v-for="(subItem, k) in item.children" :key="k">
  52 + <div class="menu_subItem" :class="{'active': isSubMenuActive === i + '' + k}" @click="subMenuClick(subItem, i, k)">
  53 + {{subItem.name}}
  54 + </div>
  55 + </div>
  56 + <!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
  57 + <div class="menu_bottom menu_addicon" v-if="!item.children || item.children.length < 5" @click="addSubMenu(i,item)">
  58 + <i class="el-icon-plus" />
  59 + </div>
  60 + </div>
  61 + </div>
  62 + <!-- 一级菜单加号 -->
  63 + <div class="menu_bottom menu_addicon" v-if="menuKeyLength < 3" @click="addMenu"><i class="el-icon-plus"></i></div>
  64 + </div>
  65 + <div class="save_div">
  66 + <!--<el-button class="save_btn" type="warning" size="small" @click="saveFun">保存菜单</el-button>-->
  67 + <el-button class="save_btn" type="success" size="small" @click="saveAndReleaseFun">保存并发布菜单</el-button>
  68 + </div>
  69 + </div>
  70 + <!--右边配置-->
  71 + <div v-if="showRightFlag" class="right">
  72 + <div class="configure_page">
  73 + <div class="delete_btn">
  74 + <el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteMenu(tempObj)">删除当前菜单</el-button>
  75 + </div>
  76 + <div>
  77 + <span>菜单名称:</span>
  78 + <el-input class="input_width" v-model="tempObj.name" placeholder="请输入菜单名称" :maxlength=nameMaxlength clearable></el-input>
  79 + </div>
  80 + <div v-if="showConfigurContent">
  81 + <div class="menu_content">
  82 + <span>菜单内容:</span>
  83 + <el-select v-model="tempObj.type" clearable placeholder="请选择" class="menu_option">
  84 + <el-option v-for="item in menuOptions" :label="item.label" :value="item.value" :key="item.value"></el-option>
  85 + </el-select>
  86 + </div>
  87 + <div class="configur_content" v-if="tempObj.type === 'view'">
  88 + <span>跳转链接:</span>
  89 + <el-input class="input_width" v-model="tempObj.url" placeholder="请输入链接" clearable></el-input>
  90 + </div>
  91 + <div class="configur_content" v-if="tempObj.type === 'miniprogram'">
  92 + <div class="applet">
  93 + <span>小程序的appid:</span>
  94 + <el-input class="input_width" v-model="tempObj.appid" placeholder="请输入小程序的appid" clearable></el-input>
  95 + </div>
  96 + <div class="applet">
  97 + <span>小程序的页面路径:</span>
  98 + <el-input class="input_width" v-model="tempObj.pagepath" placeholder="请输入小程序的页面路径,如:pages/index" clearable></el-input>
  99 + </div>
  100 + <div class="applet">
  101 + <span>备用网页:</span>
  102 + <el-input class="input_width" v-model="tempObj.url" placeholder="不支持小程序的老版本客户端将打开本网页" clearable></el-input>
  103 + </div>
  104 + <p class="blue">tips:需要和公众号进行关联才可以把小程序绑定带微信菜单上哟!</p>
  105 + </div>
  106 + <div class="configur_content" v-if="tempObj.type == 'article_view_limited'">
  107 + <el-row>
  108 + <div class="select-item" v-if="tempObj && tempObj.content && tempObj.content.articles">
  109 + <WxNews :objData="tempObj.content.articles"></WxNews>
  110 + <el-row class="ope-row">
  111 + <el-button type="danger" icon="el-icon-delete" circle @click="deleteTempObj"></el-button>
  112 + </el-row>
  113 + </div>
  114 + <div v-if="!tempObj.content || !tempObj.content.articles">
  115 + <el-row>
  116 + <el-col :span="24" style="text-align: center">
  117 + <el-button type="success" @click="openMaterial">素材库选择<i class="el-icon-circle-check el-icon--right"></i></el-button>
  118 + </el-col>
  119 + </el-row>
  120 + </div>
  121 + <el-dialog title="选择图文" :visible.sync="dialogNewsVisible" width="90%">
  122 + <WxMaterialSelect :objData="{repType:'news'}" @selectMaterial="selectMaterial"></WxMaterialSelect>
  123 + </el-dialog>
  124 + </el-row>
  125 + </div>
  126 + <div class="configur_content" v-if="tempObj.type == 'click' || tempObj.type == 'scancode_waitmsg'">
  127 + <WxReplySelect :objData="tempObj" v-if="hackResetWxReplySelect"></WxReplySelect>
  128 + </div>
  129 + </div>
  130 + </div>
  131 + </div>
  132 + <!--一进页面就显示的默认页面,当点击左边按钮的时候,就不显示了-->
  133 + <div v-if="!showRightFlag" class="right">
  134 + <p>请选择菜单配置</p>
  135 + </div>
122 136 </div>
  137 + </div>
123 138 </template>
124 139  
125 140 <script>
126   - // import { save, saveAndRelease ,getList} from '@/api/wxmp/wxmenu'
127   - import WxReplySelect from '@/views/mp/components/wx-news/main.vue'
128   - import WxNews from '@/views/mp/components/wx-news/main.vue';
129   - import WxMaterialSelect from '@/views/mp/components/wx-news/main.vue'
  141 +// import { save, saveAndRelease ,getList} from '@/api/wxmp/wxmenu'
  142 +import WxReplySelect from '@/views/mp/components/wx-news/main.vue'
  143 +import WxNews from '@/views/mp/components/wx-news/main.vue';
  144 +import WxMaterialSelect from '@/views/mp/components/wx-news/main.vue'
  145 +import {getMenuList} from "@/api/mp/menu";
  146 +import {getSimpleAccounts} from "@/api/mp/account";
130 147  
131   - export default {
132   - name: 'mpMenu',
133   - components: {
134   - WxReplySelect,
135   - WxNews,
136   - WxMaterialSelect
137   - },
138   - data(){
139   - return{
140   - showRightFlag:false,//右边配置显示默认详情还是配置详情
141   - menu:{
142   - button:[
143   - ]
144   - },//横向菜单
145   - isActive: -1,// 一级菜单点中样式
146   - isSubMenuActive: -1,// 一级菜单点中样式
147   - isSubMenuFlag: -1,// 二级菜单显示标志
148   - tempObj:{},//右边临时变量,作为中间值牵引关系
149   - tempSelfObj:{
150   - //一些临时值放在这里进行判断,如果放在tempObj,由于引用关系,menu也会多了多余的参数
151   - },
152   - visible2: false,//素材内容 "选择素材"按钮弹框显示隐藏
153   - tableData:[], //素材内容弹框数据,
154   - menuName:'',
155   - showConfigurContent:true,
156   - nameMaxlength:0,//名称最大长度
157   - menuOptions: [{
158   - value: 'view',
159   - label: '跳转网页'
160   - }, {
161   - value: 'miniprogram',
162   - label: '跳转小程序'
163   - }, {
164   - value: 'click',
165   - label: '点击回复'
166   - }, {
167   - value: 'article_view_limited',
168   - label: '跳转图文消息'
169   - }, {
170   - value: 'scancode_push',
171   - label: '扫码直接返回结果'
172   - }, {
173   - value: 'scancode_waitmsg',
174   - label: '扫码回复'
175   - }, {
176   - value: 'pic_sysphoto',
177   - label: '系统拍照发图'
178   - }, {
179   - value: 'pic_photo_or_album',
180   - label: '拍照或者相册'
181   - }, {
182   - value: 'pic_weixin',
183   - label: '微信相册'
184   - }, {
185   - value: 'location_select',
186   - label: '选择地理位置'
187   - }],
188   - dialogNewsVisible:false,
189   - saveLoading:false,
190   - hackResetWxReplySelect:false
191   - }
192   - },
193   - created() {
194   - this.getMenuFun()
195   - },
196   - mounted() {
  148 +export default {
  149 + name: 'mpMenu',
  150 + components: {
  151 + WxReplySelect,
  152 + WxNews,
  153 + WxMaterialSelect
  154 + },
  155 + data(){
  156 + return {
  157 + // 遮罩层
  158 + loading: true,
  159 + // 显示搜索条件
  160 + showSearch: true,
  161 + // 查询参数
  162 + accountId: undefined,
  163 + menuList: {
  164 + children: [],
  165 + },
197 166  
198   - },
199   - filters:{
200   - },
201   - computed: {
202   - },
203   - methods:{
204   - deleteTempObj(){
205   - this.$delete(this.tempObj,'repName')
206   - this.$delete(this.tempObj,'repUrl')
207   - this.$delete(this.tempObj,'content')
208   - },
209   - openMaterial(){
210   - this.dialogNewsVisible = true
211   - },
212   - selectMaterial(item){
213   - if(item.content.articles.length>1){
214   - this.$alert('您选择的是多图文,将默认跳转第一篇', '提示', {
215   - confirmButtonText: '确定'
216   - })
217   - }
218   - this.dialogNewsVisible = false
219   - this.tempObj.article_id = item.articleId
220   - this.tempObj.mediaName = item.name
221   - this.tempObj.url = item.url
222   - item.mediaType = this.tempObj.mediaType
223   - item.content.articles = item.content.articles.slice(0,1)
224   - this.tempObj.content = item.content
225   - },
226   - getMenuFun(){
227   - getList().then((res)=>{
228   - this.menu.button = JSON.parse(res.msg).button;
229   - });
230   - },
231   - handleClick(tab, event){
232   - this.tempObj.mediaType = tab.name
233   - },
234   - saveAndReleaseFun(){
235   - this.$confirm('确定要保证并发布该菜单吗?', '提示', {
236   - confirmButtonText: '确定',
237   - cancelButtonText: '取消',
238   - type: 'warning'
239   - }).then(() => {
240   - this.saveLoading = true
241   - saveAndRelease({
242   - strWxMenu:this.menu
243   - }).then(response => {
244   - this.saveLoading = false
245   - if(response.code == 200){
246   - this.$message({
247   - showClose: true,
248   - message: '发布成功',
249   - type: 'success'
250   - })
251   - }else{
252   - this.$message.error(response.data.msg)
253   - }
254   - }).catch(() => {
255   - this.saveLoading = false
  167 + showRightFlag:false, // 右边配置显示默认详情还是配置详情
  168 + menu:{ // 横向菜单
  169 + button:[
  170 + ]
  171 + },
  172 +
  173 + isActive: -1,// 一级菜单点中样式
  174 + isSubMenuActive: -1, // 一级菜单点中样式
  175 + isSubMenuFlag: -1, // 二级菜单显示标志
  176 + tempObj:{}, // 右边临时变量,作为中间值牵引关系
  177 + tempSelfObj: {
  178 + // 一些临时值放在这里进行判断,如果放在 tempObj,由于引用关系,menu 也会多了多余的参数
  179 + },
  180 + visible2: false, //素材内容 "选择素材"按钮弹框显示隐藏
  181 + tableData:[], //素材内容弹框数据,
  182 + menuName:'',
  183 + showConfigurContent:true,
  184 + nameMaxlength:0,//名称最大长度
  185 + menuOptions: [{
  186 + value: 'view',
  187 + label: '跳转网页'
  188 + }, {
  189 + value: 'miniprogram',
  190 + label: '跳转小程序'
  191 + }, {
  192 + value: 'click',
  193 + label: '点击回复'
  194 + }, {
  195 + value: 'article_view_limited',
  196 + label: '跳转图文消息'
  197 + }, {
  198 + value: 'scancode_push',
  199 + label: '扫码直接返回结果'
  200 + }, {
  201 + value: 'scancode_waitmsg',
  202 + label: '扫码回复'
  203 + }, {
  204 + value: 'pic_sysphoto',
  205 + label: '系统拍照发图'
  206 + }, {
  207 + value: 'pic_photo_or_album',
  208 + label: '拍照或者相册'
  209 + }, {
  210 + value: 'pic_weixin',
  211 + label: '微信相册'
  212 + }, {
  213 + value: 'location_select',
  214 + label: '选择地理位置'
  215 + }],
  216 + dialogNewsVisible: false,
  217 + hackResetWxReplySelect: false,
  218 +
  219 + // 公众号账号列表
  220 + accounts: [],
  221 + }
  222 + },
  223 + created() {
  224 + getSimpleAccounts().then(response => {
  225 + this.accounts = response.data;
  226 + // 默认选中第一个
  227 + if (this.accounts.length > 0) {
  228 + this.setAccountId(this.accounts[0].id);
  229 + }
  230 + // 加载数据
  231 + this.getList();
  232 + })
  233 + },
  234 + computed: {
  235 + menuKeyLength:function() {
  236 + // menuObj 的长度,当长度小于 3 才显示一级菜单的加号
  237 + return this.menu.button.length;
  238 + }
  239 + },
  240 + methods: {
  241 + // ======================== 列表查询 ========================
  242 + /** 设置账号编号 */
  243 + setAccountId(accountId) {
  244 + this.accountId = accountId;
  245 + // this.uploadData.accountId = accountId;
  246 + },
  247 + getList() {
  248 + this.loading = false;
  249 + getMenuList(this.accountId).then(response => {
  250 + this.menuList = this.handleTree(response.data, "id");
  251 + console.log(this.menuList)
  252 + }).finally(() => {
  253 + this.loading = false;
  254 + })
  255 + },
  256 + /** 搜索按钮操作 */
  257 + handleQuery() {
  258 + // 默认选中第一个
  259 + if (this.accountId) {
  260 + this.setAccountId(this.accountId)
  261 + }
  262 + this.getList()
  263 + },
  264 + /** 重置按钮操作 */
  265 + resetQuery() {
  266 + this.resetForm('queryForm')
  267 + // 默认选中第一个
  268 + if (this.accounts.length > 0) {
  269 + this.setAccountId(this.accounts[0].id)
  270 + }
  271 + this.handleQuery()
  272 + },
  273 +
  274 + // TODO 芋艿:未归类
  275 +
  276 + deleteTempObj(){
  277 + this.$delete(this.tempObj,'repName')
  278 + this.$delete(this.tempObj,'repUrl')
  279 + this.$delete(this.tempObj,'content')
  280 + },
  281 + openMaterial(){
  282 + this.dialogNewsVisible = true
  283 + },
  284 + selectMaterial(item){
  285 + if(item.content.articles.length>1){
  286 + this.$alert('您选择的是多图文,将默认跳转第一篇', '提示', {
  287 + confirmButtonText: '确定'
  288 + })
  289 + }
  290 + this.dialogNewsVisible = false
  291 + this.tempObj.article_id = item.articleId
  292 + this.tempObj.mediaName = item.name
  293 + this.tempObj.url = item.url
  294 + item.mediaType = this.tempObj.mediaType
  295 + item.content.articles = item.content.articles.slice(0,1)
  296 + this.tempObj.content = item.content
  297 + },
  298 + handleClick(tab, event){
  299 + this.tempObj.mediaType = tab.name
  300 + },
  301 + saveAndReleaseFun(){
  302 + this.$confirm('确定要保证并发布该菜单吗?', '提示', {
  303 + confirmButtonText: '确定',
  304 + cancelButtonText: '取消',
  305 + type: 'warning'
  306 + }).then(() => {
  307 + this.loading = true
  308 + saveAndRelease({
  309 + strWxMenu:this.menu
  310 + }).then(response => {
  311 + this.loading = false
  312 + if(response.code == 200){
  313 + this.$message({
  314 + showClose: true,
  315 + message: '发布成功',
  316 + type: 'success'
256 317 })
257   - }).catch(() => {
258   - })
259   - },
260   - // 一级菜单点击事件
261   - menuFun(i, item){
262   - this.hackResetWxReplySelect = false//销毁组件
263   - this.$nextTick(() => {
264   - this.hackResetWxReplySelect = true//重建组件
265   - })
266   - this.showRightFlag = true;//右边菜单
267   - this.tempObj = item;//这个如果放在顶部,flag会没有。因为重新赋值了。
268   - this.tempSelfObj.grand = "1";//表示一级菜单
269   - this.tempSelfObj.index = i;//表示一级菜单索引
270   - this.isActive = i; //一级菜单选中样式
271   - this.isSubMenuFlag = i; //二级菜单显示标志
272   - this.isSubMenuActive = -1; //二级菜单去除选中样式
273   - this.nameMaxlength = 4
274   - if(item.sub_button&&item.sub_button.length>0){
275   - this.showConfigurContent = false
276 318 }else{
277   - this.showConfigurContent = true
278   - }
279   - },
280   - // 二级菜单点击事件
281   - subMenuFun(subItem, index, k){
282   - this.hackResetWxReplySelect = false//销毁组件
283   - this.$nextTick(() => {
284   - this.hackResetWxReplySelect = true//重建组件
285   - })
286   - this.showRightFlag = true;//右边菜单
287   - this.tempObj = subItem;//将点击的数据放到临时变量,对象有引用作用
288   - this.tempSelfObj.grand = "2";//表示二级菜单
289   - this.tempSelfObj.index = index;//表示一级菜单索引
290   - this.tempSelfObj.secondIndex = k;//表示二级菜单索引
291   - this.isSubMenuActive = index + "" + k; //二级菜单选中样式
292   - this.isActive = -1;//一级菜单去除样式
293   - this.showConfigurContent = true;
294   - this.nameMaxlength = 7
295   - },
296   - // 添加横向一级菜单
297   - addMenu(){
298   - let menuKeyLength = this.menuKeyLength
299   - let addButton = {
300   - name: "菜单名称",
301   - sub_button: []
302   - }
303   - this.$set(this.menu.button,menuKeyLength,addButton)
304   - this.menuFun(this.menuKeyLength-1, addButton)
305   - },
306   - // 添加横向二级菜单
307   - addSubMenu(i,item){
308   - if(!item.sub_button||item.sub_button.length<=0){
309   - this.$set( item, 'sub_button',[])
310   - this.$delete( item, 'type')
311   - this.$delete( item, 'pagepath')
312   - this.$delete( item, 'url')
313   - this.$delete( item, 'key')
314   - this.$delete( item, 'article_id')
315   - this.$delete( item, 'textContent')
316   - this.showConfigurContent = false
317   - }
318   - let subMenuKeyLength = item.sub_button.length;//获取二级菜单key长度
319   - let addButton = {
320   - name: "子菜单名称"
  319 + this.$message.error(response.data.msg)
321 320 }
322   - this.$set(item.sub_button,subMenuKeyLength,addButton);
323   - this.subMenuFun(item.sub_button[subMenuKeyLength], i, subMenuKeyLength)
324   - },
325   - //删除当前菜单
326   - deleteMenu(obj){
327   - let _this = this;
328   - this.$confirm('确定要删除吗?', '提示', {
329   - confirmButtonText: '确定',
330   - cancelButtonText: '取消',
331   - type: 'warning'
332   - }).then(() => {
333   - _this.deleteData();// 删除菜单数据
334   - _this.tempObj = {};
335   - _this.showRightFlag = false;
336   - this.isActive = -1;
337   - this.isSubMenuActive = -1;
338   - }).catch(() => {
339   - });
340   - },
341   - // 删除菜单数据
342   - deleteData(){
343   - // 一级菜单的删除方法
344   - if(this.tempSelfObj.grand == "1"){
345   - this.menu.button.splice(this.tempSelfObj.index,1);
346   - }
347   - // 二级菜单的删除方法
348   - if(this.tempSelfObj.grand == "2"){
349   - this.menu.button[this.tempSelfObj.index].sub_button.splice(this.tempSelfObj.secondIndex, 1);
350   - }
351   - this.$message({
352   - type: 'success',
353   - message: '删除成功!'
354   - });
355   - }
356   - },
357   - computed:{
358   - // menuObj的长度,当长度 小于 3 才显示一级菜单的加号
359   - menuKeyLength:function(){
360   - return this.menu.button.length;
361   - }
  321 + }).catch(() => {
  322 + this.loading = false
  323 + })
  324 + }).catch(() => {
  325 + })
  326 + },
  327 + // 一级菜单点击事件
  328 + menuClick(i, item){
  329 + this.hackResetWxReplySelect = false//销毁组件
  330 + this.$nextTick(() => {
  331 + this.hackResetWxReplySelect = true//重建组件
  332 + })
  333 + this.showRightFlag = true;//右边菜单
  334 + this.tempObj = item;//这个如果放在顶部,flag会没有。因为重新赋值了。
  335 + this.tempSelfObj.grand = "1";//表示一级菜单
  336 + this.tempSelfObj.index = i;//表示一级菜单索引
  337 + this.isActive = i; //一级菜单选中样式
  338 + this.isSubMenuFlag = i; //二级菜单显示标志
  339 + this.isSubMenuActive = -1; //二级菜单去除选中样式
  340 + this.nameMaxlength = 4
  341 + if(item.sub_button && item.sub_button.length > 0){
  342 + this.showConfigurContent = false
  343 + }else{
  344 + this.showConfigurContent = true
  345 + }
  346 + },
  347 + // 二级菜单点击事件
  348 + subMenuClick(subItem, index, k){
  349 + this.hackResetWxReplySelect = false//销毁组件
  350 + this.$nextTick(() => {
  351 + this.hackResetWxReplySelect = true//重建组件
  352 + })
  353 + this.showRightFlag = true;//右边菜单
  354 + this.tempObj = subItem;//将点击的数据放到临时变量,对象有引用作用
  355 + this.tempSelfObj.grand = "2";//表示二级菜单
  356 + this.tempSelfObj.index = index;//表示一级菜单索引
  357 + this.tempSelfObj.secondIndex = k;//表示二级菜单索引
  358 + this.isSubMenuActive = index + "" + k; //二级菜单选中样式
  359 + this.isActive = -1;//一级菜单去除样式
  360 + this.showConfigurContent = true;
  361 + this.nameMaxlength = 7
  362 + },
  363 + // 添加横向一级菜单
  364 + addMenu(){
  365 + let menuKeyLength = this.menuKeyLength
  366 + let addButton = {
  367 + name: "菜单名称",
  368 + sub_button: []
  369 + }
  370 + this.$set(this.menu.button,menuKeyLength,addButton)
  371 + this.menuClick(this.menuKeyLength-1, addButton)
  372 + },
  373 + // 添加横向二级菜单
  374 + addSubMenu(i,item){
  375 + if(!item.sub_button||item.sub_button.length<=0){
  376 + this.$set( item, 'sub_button',[])
  377 + this.$delete( item, 'type')
  378 + this.$delete( item, 'pagepath')
  379 + this.$delete( item, 'url')
  380 + this.$delete( item, 'key')
  381 + this.$delete( item, 'article_id')
  382 + this.$delete( item, 'textContent')
  383 + this.showConfigurContent = false
362 384 }
  385 + let subMenuKeyLength = item.sub_button.length;//获取二级菜单key长度
  386 + let addButton = {
  387 + name: "子菜单名称"
  388 + }
  389 + this.$set(item.sub_button,subMenuKeyLength,addButton);
  390 + this.subMenuClick(item.sub_button[subMenuKeyLength], i, subMenuKeyLength)
  391 + },
  392 + //删除当前菜单
  393 + deleteMenu(obj){
  394 + let _this = this;
  395 + this.$confirm('确定要删除吗?', '提示', {
  396 + confirmButtonText: '确定',
  397 + cancelButtonText: '取消',
  398 + type: 'warning'
  399 + }).then(() => {
  400 + _this.deleteData();// 删除菜单数据
  401 + _this.tempObj = {};
  402 + _this.showRightFlag = false;
  403 + this.isActive = -1;
  404 + this.isSubMenuActive = -1;
  405 + }).catch(() => {
  406 + });
  407 + },
  408 + // 删除菜单数据
  409 + deleteData(){
  410 + // 一级菜单的删除方法
  411 + if(this.tempSelfObj.grand == "1"){
  412 + this.menu.button.splice(this.tempSelfObj.index,1);
  413 + }
  414 + // 二级菜单的删除方法
  415 + if(this.tempSelfObj.grand == "2"){
  416 + this.menu.button[this.tempSelfObj.index].sub_button.splice(this.tempSelfObj.secondIndex, 1);
  417 + }
  418 + this.$message({
  419 + type: 'success',
  420 + message: '删除成功!'
  421 + });
363 422 }
  423 + },
  424 +}
364 425 </script>
365 426 <!--本组件样式-->
366 427 <style lang="less" scoped="scoped">
... ... @@ -368,153 +429,153 @@ SOFTWARE.
368 429 .clearfix{*zoom:1;}
369 430 .clearfix::after{content: "";display: table; clear: both;}
370 431 div{
371   - text-align: left;
  432 + text-align: left;
372 433 }
373 434 .weixin-hd{
374   - color: #fff;
375   - text-align: center;
376   - position: relative;
377   - bottom: 426px;
378   - left:0px;
379   - width: 300px;
380   - height:64px;
381   - background: transparent url(assets/menu_head.png) no-repeat 0 0;
382   - background-position: 0 0;
383   - background-size: 100%
  435 + color: #fff;
  436 + text-align: center;
  437 + position: relative;
  438 + bottom: 426px;
  439 + left:0px;
  440 + width: 300px;
  441 + height:64px;
  442 + background: transparent url(assets/menu_head.png) no-repeat 0 0;
  443 + background-position: 0 0;
  444 + background-size: 100%
384 445 }
385 446 .weixin-title{
386   - color:#fff;
387   - font-size:14px;
388   - width:100%;
389   - text-align: center;
390   - position:absolute;
391   - top: 33px;
392   - left: 0px;
  447 + color:#fff;
  448 + font-size:14px;
  449 + width:100%;
  450 + text-align: center;
  451 + position:absolute;
  452 + top: 33px;
  453 + left: 0px;
393 454 }
394 455 .weixin-menu{
395   - background: transparent url(assets/menu_foot.png) no-repeat 0 0;
396   - padding-left: 43px;
397   - font-size: 12px
  456 + background: transparent url(assets/menu_foot.png) no-repeat 0 0;
  457 + padding-left: 43px;
  458 + font-size: 12px
398 459 }
399 460 .menu_option{
400   - width: 40%!important;
  461 + width: 40%!important;
401 462 }
402 463 .public-account-management{
403   - min-width: 1200px;
404   - width: 1200px;
405   - margin: 0 auto;
406   - .left{
407   - float: left;
408   - display: inline-block;
409   - width: 350px;
410   - height: 715px;
411   - background: url("assets/iphone_backImg.png") no-repeat;
412   - background-size: 100% auto;
413   - padding: 518px 25px 88px;
414   - position: relative;
415   - box-sizing: border-box;
416   - /*第一级菜单*/
417   - .menu_main{
418   - .menu_bottom{
419   - position: relative;
420   - float: left;
421   - display: inline-block;
422   - box-sizing: border-box;
423   - width: 85.5px;
424   - text-align: center;
425   - border: 1px solid #ebedee;
426   - background-color: #fff;
427   - cursor: pointer;
428   - &.menu_addicon{
429   - height: 46px;
430   - line-height: 46px;
431   - }
432   - .menu_item{
433   - height: 44px;
434   - line-height: 44px;
435   - text-align: center;
436   - box-sizing: border-box;
437   - width: 100%;
438   - &.active{
439   - border: 1px solid #2bb673;
440   - }
441   - }
442   - .menu_subItem{
443   - height: 44px;
444   - line-height: 44px;
445   - text-align: center;
446   - box-sizing: border-box;
447   - &.active{
448   - border: 1px solid #2bb673;
449   - }
450   - }
451   - }
452   - i{
453   - color:#2bb673;
454   - }
455   - /*第二级菜单*/
456   - .submenu{
457   - position: absolute;
458   - width: 85.5px;
459   - bottom: 45px;
460   - .subtitle{
461   - background-color: #fff;
462   - box-sizing: border-box;
463   - }
464   - }
465   - }
466   - .save_div{
467   - margin-top: 15px;
468   - text-align: center;
469   - .save_btn{
470   - bottom: 20px;
471   - left: 100px;
472   - }
473   - }
474   - }
475   - /*右边菜单内容*/
476   - .right{
477   - float: left;
478   - width: 63%;
479   - background-color: #e8e7e7;
480   - padding: 20px;
481   - margin-left: 20px;
482   - -webkit-box-sizing: border-box;
483   - box-sizing: border-box;
484   - .configure_page{
485   - .delete_btn{
486   - text-align: right;
487   - margin-bottom: 15px;
488   - }
489   - .menu_content{
490   - margin-top: 20px;
491   - }
492   - .configur_content{
493   - margin-top: 20px;
494   - background-color: #fff;
495   - padding: 20px 10px;
496   - border-radius: 5px
497   - }
498   - .blue{
499   - color:#29b6f6;
500   - margin-top: 10px;
501   - }
502   - .applet{
503   - margin-bottom: 20px;
504   - span{
505   - width: 20%;
506   - }
507   - }
508   - .material{
509   - .input_width{
510   - width: 30%;
511   - }
512   - .el-textarea{
513   - width: 80%
514   - }
515   - }
516   - }
517   - }
  464 + min-width: 1200px;
  465 + width: 1200px;
  466 + margin: 0 auto;
  467 + .left{
  468 + float: left;
  469 + display: inline-block;
  470 + width: 350px;
  471 + height: 715px;
  472 + background: url("assets/iphone_backImg.png") no-repeat;
  473 + background-size: 100% auto;
  474 + padding: 518px 25px 88px;
  475 + position: relative;
  476 + box-sizing: border-box;
  477 + /*第一级菜单*/
  478 + .menu_main{
  479 + .menu_bottom{
  480 + position: relative;
  481 + float: left;
  482 + display: inline-block;
  483 + box-sizing: border-box;
  484 + width: 85.5px;
  485 + text-align: center;
  486 + border: 1px solid #ebedee;
  487 + background-color: #fff;
  488 + cursor: pointer;
  489 + &.menu_addicon{
  490 + height: 46px;
  491 + line-height: 46px;
  492 + }
  493 + .menu_item{
  494 + height: 44px;
  495 + line-height: 44px;
  496 + text-align: center;
  497 + box-sizing: border-box;
  498 + width: 100%;
  499 + &.active{
  500 + border: 1px solid #2bb673;
  501 + }
  502 + }
  503 + .menu_subItem{
  504 + height: 44px;
  505 + line-height: 44px;
  506 + text-align: center;
  507 + box-sizing: border-box;
  508 + &.active{
  509 + border: 1px solid #2bb673;
  510 + }
  511 + }
  512 + }
  513 + i{
  514 + color:#2bb673;
  515 + }
  516 + /*第二级菜单*/
  517 + .submenu{
  518 + position: absolute;
  519 + width: 85.5px;
  520 + bottom: 45px;
  521 + .subtitle{
  522 + background-color: #fff;
  523 + box-sizing: border-box;
  524 + }
  525 + }
  526 + }
  527 + .save_div{
  528 + margin-top: 15px;
  529 + text-align: center;
  530 + .save_btn{
  531 + bottom: 20px;
  532 + left: 100px;
  533 + }
  534 + }
  535 + }
  536 + /*右边菜单内容*/
  537 + .right{
  538 + float: left;
  539 + width: 63%;
  540 + background-color: #e8e7e7;
  541 + padding: 20px;
  542 + margin-left: 20px;
  543 + -webkit-box-sizing: border-box;
  544 + box-sizing: border-box;
  545 + .configure_page{
  546 + .delete_btn{
  547 + text-align: right;
  548 + margin-bottom: 15px;
  549 + }
  550 + .menu_content{
  551 + margin-top: 20px;
  552 + }
  553 + .configur_content{
  554 + margin-top: 20px;
  555 + background-color: #fff;
  556 + padding: 20px 10px;
  557 + border-radius: 5px
  558 + }
  559 + .blue{
  560 + color:#29b6f6;
  561 + margin-top: 10px;
  562 + }
  563 + .applet{
  564 + margin-bottom: 20px;
  565 + span{
  566 + width: 20%;
  567 + }
  568 + }
  569 + .material{
  570 + .input_width{
  571 + width: 30%;
  572 + }
  573 + .el-textarea{
  574 + width: 80%
  575 + }
  576 + }
  577 + }
  578 + }
518 579 }
519 580 </style>
520 581 <!--修改UI框架样式-->
... ...
yudao-ui-admin/yarn.lock
... ... @@ -3340,6 +3340,13 @@
3340 3340 "resolved" "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz"
3341 3341 "version" "0.5.0"
3342 3342  
  3343 +"copy-anything@^2.0.1":
  3344 + "integrity" "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw=="
  3345 + "resolved" "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz"
  3346 + "version" "2.0.6"
  3347 + dependencies:
  3348 + "is-what" "^3.14.1"
  3349 +
3343 3350 "copy-concurrently@^1.0.0":
3344 3351 "integrity" "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A=="
3345 3352 "resolved" "https://registry.npmmirror.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz"
... ... @@ -3696,6 +3703,13 @@
3696 3703 dependencies:
3697 3704 "ms" "2.0.0"
3698 3705  
  3706 +"debug@^3.2.6":
  3707 + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="
  3708 + "resolved" "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz"
  3709 + "version" "3.2.7"
  3710 + dependencies:
  3711 + "ms" "^2.1.1"
  3712 +
3699 3713 "debug@^3.2.7":
3700 3714 "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="
3701 3715 "resolved" "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz"
... ... @@ -4215,7 +4229,7 @@
4215 4229 "resolved" "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz"
4216 4230 "version" "2.2.0"
4217 4231  
4218   -"errno@^0.1.3", "errno@~0.1.7":
  4232 +"errno@^0.1.1", "errno@^0.1.3", "errno@~0.1.7":
4219 4233 "integrity" "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A=="
4220 4234 "resolved" "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz"
4221 4235 "version" "0.1.8"
... ... @@ -5633,6 +5647,13 @@
5633 5647 dependencies:
5634 5648 "safer-buffer" ">= 2.1.2 < 3"
5635 5649  
  5650 +"iconv-lite@^0.6.3":
  5651 + "integrity" "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="
  5652 + "resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz"
  5653 + "version" "0.6.3"
  5654 + dependencies:
  5655 + "safer-buffer" ">= 2.1.2 < 3.0.0"
  5656 +
5636 5657 "icss-utils@^4.0.0", "icss-utils@^4.1.1":
5637 5658 "integrity" "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA=="
5638 5659 "resolved" "https://registry.npmmirror.com/icss-utils/-/icss-utils-4.1.1.tgz"
... ... @@ -5665,7 +5686,7 @@
5665 5686 "resolved" "https://registry.npmmirror.com/ignore/-/ignore-4.0.6.tgz"
5666 5687 "version" "4.0.6"
5667 5688  
5668   -"image-size@^0.5.1":
  5689 +"image-size@^0.5.1", "image-size@~0.5.0":
5669 5690 "integrity" "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ=="
5670 5691 "resolved" "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz"
5671 5692 "version" "0.5.5"
... ... @@ -6150,6 +6171,11 @@
6150 6171 dependencies:
6151 6172 "call-bind" "^1.0.2"
6152 6173  
  6174 +"is-what@^3.14.1":
  6175 + "integrity" "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
  6176 + "resolved" "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz"
  6177 + "version" "3.14.1"
  6178 +
6153 6179 "is-windows@^1.0.2":
6154 6180 "integrity" "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
6155 6181 "resolved" "https://registry.npmmirror.com/is-windows/-/is-windows-1.0.2.tgz"
... ... @@ -6402,6 +6428,32 @@
6402 6428 "picocolors" "^1.0.0"
6403 6429 "shell-quote" "^1.7.3"
6404 6430  
  6431 +"less-loader@^7.3.0":
  6432 + "integrity" "sha512-Mi8915g7NMaLlgi77mgTTQvK022xKRQBIVDSyfl3ErTuBhmZBQab0mjeJjNNqGbdR+qrfTleKXqbGI4uEFavxg=="
  6433 + "resolved" "https://registry.npmmirror.com/less-loader/-/less-loader-7.3.0.tgz"
  6434 + "version" "7.3.0"
  6435 + dependencies:
  6436 + "klona" "^2.0.4"
  6437 + "loader-utils" "^2.0.0"
  6438 + "schema-utils" "^3.0.0"
  6439 +
  6440 +"less@^3.5.0 || ^4.0.0", "less@^4.1.3":
  6441 + "integrity" "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA=="
  6442 + "resolved" "https://registry.npmmirror.com/less/-/less-4.1.3.tgz"
  6443 + "version" "4.1.3"
  6444 + dependencies:
  6445 + "copy-anything" "^2.0.1"
  6446 + "parse-node-version" "^1.0.1"
  6447 + "tslib" "^2.3.0"
  6448 + optionalDependencies:
  6449 + "errno" "^0.1.1"
  6450 + "graceful-fs" "^4.1.2"
  6451 + "image-size" "~0.5.0"
  6452 + "make-dir" "^2.1.0"
  6453 + "mime" "^1.4.1"
  6454 + "needle" "^3.1.0"
  6455 + "source-map" "~0.6.0"
  6456 +
6405 6457 "levn@^0.4.1":
6406 6458 "integrity" "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="
6407 6459 "resolved" "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz"
... ... @@ -6629,6 +6681,14 @@
6629 6681 "pify" "^4.0.1"
6630 6682 "semver" "^5.6.0"
6631 6683  
  6684 +"make-dir@^2.1.0":
  6685 + "integrity" "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA=="
  6686 + "resolved" "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz"
  6687 + "version" "2.1.0"
  6688 + dependencies:
  6689 + "pify" "^4.0.1"
  6690 + "semver" "^5.6.0"
  6691 +
6632 6692 "make-dir@^3.0.2", "make-dir@^3.1.0":
6633 6693 "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="
6634 6694 "resolved" "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz"
... ... @@ -6819,6 +6879,11 @@
6819 6879 dependencies:
6820 6880 "mime-db" "1.52.0"
6821 6881  
  6882 +"mime@^1.4.1":
  6883 + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
  6884 + "resolved" "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz"
  6885 + "version" "1.6.0"
  6886 +
6822 6887 "mime@^2.4.4":
6823 6888 "integrity" "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
6824 6889 "resolved" "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz"
... ... @@ -7111,6 +7176,15 @@
7111 7176 "resolved" "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz"
7112 7177 "version" "1.4.0"
7113 7178  
  7179 +"needle@^3.1.0":
  7180 + "integrity" "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ=="
  7181 + "resolved" "https://registry.npmmirror.com/needle/-/needle-3.2.0.tgz"
  7182 + "version" "3.2.0"
  7183 + dependencies:
  7184 + "debug" "^3.2.6"
  7185 + "iconv-lite" "^0.6.3"
  7186 + "sax" "^1.2.4"
  7187 +
7114 7188 "negotiator@0.6.3":
7115 7189 "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
7116 7190 "resolved" "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz"
... ... @@ -7607,6 +7681,11 @@
7607 7681 "json-parse-even-better-errors" "^2.3.0"
7608 7682 "lines-and-columns" "^1.1.6"
7609 7683  
  7684 +"parse-node-version@^1.0.1":
  7685 + "integrity" "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
  7686 + "resolved" "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz"
  7687 + "version" "1.0.1"
  7688 +
7610 7689 "parse5-htmlparser2-tree-adapter@^6.0.0":
7611 7690 "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="
7612 7691 "resolved" "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz"
... ... @@ -8850,7 +8929,7 @@
8850 8929 dependencies:
8851 8930 "ret" "~0.1.10"
8852 8931  
8853   -"safer-buffer@^2.0.2", "safer-buffer@^2.1.0", "safer-buffer@>= 2.1.2 < 3", "safer-buffer@~2.1.0":
  8932 +"safer-buffer@^2.0.2", "safer-buffer@^2.1.0", "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", "safer-buffer@~2.1.0":
8854 8933 "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
8855 8934 "resolved" "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
8856 8935 "version" "2.1.2"
... ... @@ -10017,7 +10096,7 @@
10017 10096 "resolved" "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz"
10018 10097 "version" "2.4.1"
10019 10098  
10020   -"tslib@2.3.0":
  10099 +"tslib@^2.3.0", "tslib@2.3.0":
10021 10100 "integrity" "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
10022 10101 "resolved" "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz"
10023 10102 "version" "2.3.0"
... ...