|
|
<template>
|
|
|
<!-- 最外层的 div 作为整体容器 -->
|
|
|
<div>
|
|
|
<!-- 菜单输入组容器,设置底部边框样式,用于展示菜单名称以及删除菜单按钮 -->
|
|
|
<div class="menu-input-group" style="border-bottom: 2px #e8e8e8 solid;">
|
|
|
<!-- 展示菜单名称,通过插值表达式绑定 button.name 获取名称值 -->
|
|
|
<div class="menu-name">{{button.name}}</div>
|
|
|
<!-- 删除菜单按钮,点击时通过 $emit 触发父组件的 'delMenu' 事件,由父组件来处理菜单删除相关逻辑 -->
|
|
|
<div class="menu-del" @click="$emit('delMenu')">删除菜单</div>
|
|
|
</div>
|
|
|
<!-- 菜单输入组容器,用于输入菜单名称 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 菜单名称标签 -->
|
|
|
<div class="menu-label">菜单名称</div>
|
|
|
<!-- 菜单名称输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入菜单名称,绑定 v-model 到 button.name 实现双向数据绑定,监听 input 事件,触发 checkMenuName 方法来检查名称长度是否合规 -->
|
|
|
<input type="text" name="name" placeholder="请输入菜单名称" class="menu-input-text" v-model="button.name" @input="checkMenuName(button.name)">
|
|
|
<!-- 提示信息,当 menuNameBounds 为 true 时显示,提示字数超过上限,通过 v-show 根据条件控制显示与否 -->
|
|
|
<p class="menu-tips" style="color:#e15f63" v-show="menuNameBounds">字数超过上限</p>
|
|
|
<!-- 提示信息,显示菜单名称的字数限制规则,根据 selectedMenuLevel 的值动态展示不同的字数上限说明 -->
|
|
|
<p class="menu-tips">字数不超过{{selectedMenuLevel==1?'5':'8'}}个汉字</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 根据按钮是否有子按钮或者子按钮数组长度是否为 0 来决定是否显示下面的内容,若没有子按钮则展示以下配置项 -->
|
|
|
<div v-show="!button.subButtons || button.subButtons.length==0">
|
|
|
<!-- 菜单输入组容器,用于选择菜单内容类型 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 菜单内容类型标签 -->
|
|
|
<div class="menu-label">菜单内容</div>
|
|
|
<!-- 下拉选择框,用于选择菜单的类型,通过 v-model 双向绑定 button.type,绑定不同的选项值,每个选项对应不同的菜单功能 -->
|
|
|
<div class="menu-input">
|
|
|
<select v-model="button.type" name="type" class="menu-input-text">
|
|
|
<option value="view">跳转网页(view)</option>
|
|
|
<option value="media_id">发送消息(media_id)</option>
|
|
|
<!--<option value="view_limited">跳转公众号图文消息链接(view_limited)</option>-->
|
|
|
<option value="miniprogram">打开指定小程序(miniprogram)</option>
|
|
|
<option value="click">自定义点击事件(click)</option>
|
|
|
<option value="scancode_push">扫码上传消息(scancode_push)</option>
|
|
|
<option value="scancode_waitmsg">扫码提示下发(scancode_waitmsg)</option>
|
|
|
<option value="pic_sysphoto">系统相机拍照(pic_sysphoto)</option>
|
|
|
<option value="pic_photo_or_album">弹出拍照或者相册(pic_photo_or_album)</option>
|
|
|
<option value="pic_weixin">弹出微信相册(pic_weixin)</option>
|
|
|
<option value="location_select">弹出地理位置选择器(location_select)</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 当菜单类型为 'view' 时显示的内容,用于配置跳转网页相关信息 -->
|
|
|
<div class="menu-content" v-if="button.type=='view'">
|
|
|
<!-- 菜单输入组容器,用于输入页面地址 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 提示信息,说明点击该子菜单后的跳转行为 -->
|
|
|
<p class="menu-tips">订阅者点击该子菜单会跳到以下链接</p>
|
|
|
<!-- 页面地址标签 -->
|
|
|
<div class="menu-label">页面地址</div>
|
|
|
<!-- 页面地址输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入页面地址,通过 v-model 双向绑定 button.url -->
|
|
|
<input type="text" placeholder="" class="menu-input-text" v-model="button.url">
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 当菜单类型为 'media_id' 时显示的内容,用于配置发送图文消息相关信息 -->
|
|
|
<div class="menu-content" v-else-if="button.type=='media_id'">
|
|
|
<!-- 菜单输入组容器,用于输入图文消息的 media_id -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 提示信息,说明点击该菜单后的行为 -->
|
|
|
<p class="menu-tips">订阅者点击该菜单会收到以下图文消息</p>
|
|
|
<!-- media_id 标签 -->
|
|
|
<div class="menu-label">media_id</div>
|
|
|
<!-- media_id 输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入图文消息的 media_id,通过 v-model 双向绑定 button.mediaId -->
|
|
|
<input type="text" placeholder="图文消息media_id" class="menu-input-text" v-model="button.mediaId">
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 当菜单类型为 'miniprogram' 时显示的内容,用于配置小程序相关信息,包含 appId、页面路径以及备用网页等 -->
|
|
|
<div class="menu-content" v-else-if="button.type=='miniprogram'">
|
|
|
<!-- 菜单输入组容器,用于输入小程序的 appId -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 提示信息,说明点击该子菜单后的跳转行为 -->
|
|
|
<p class="menu-tips">订阅者点击该子菜单会跳到以下小程序</p>
|
|
|
<!-- 小程序 appId 标签 -->
|
|
|
<div class="menu-label">小程序appId</div>
|
|
|
<!-- 小程序 appId 输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入小程序的 appId,通过 v-model 双向绑定 button.appId,并提示仅认证公众号可配置 -->
|
|
|
<input type="text" placeholder="小程序的appId(仅认证公众号可配置)" class="menu-input-text" v-model="button.appId">
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 菜单输入组容器,用于输入小程序的页面路径 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 小程序路径标签 -->
|
|
|
<div class="menu-label">小程序路径</div>
|
|
|
<!-- 小程序路径输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入小程序的页面路径,通过 v-model 双向绑定 button.pagePath,并给出示例路径 -->
|
|
|
<input type="text" placeholder="小程序的页面路径 pages/index/index" class="menu-input-text" v-model="button.pagePath">
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 菜单输入组容器,用于输入备用网页地址 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 备用网页标签 -->
|
|
|
<div class="menu-label">备用网页</div>
|
|
|
<!-- 备用网页地址输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入备用网页地址,通过 v-model 双向绑定 button.url,并给出相关说明 -->
|
|
|
<input type="text" placeholder="" class="menu-input-text" v-model="button.url">
|
|
|
<p class="menu-tips">旧版微信客户端无法支持小程序,用户点击菜单时将会打开备用网页。</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 当菜单类型为其他值(非上述几种情况)时显示的内容,用于配置菜单 KEY 值 -->
|
|
|
<div class="menu-content" v-else>
|
|
|
<!-- 菜单输入组容器,用于输入菜单 KEY 值 -->
|
|
|
<div class="menu-input-group">
|
|
|
<!-- 提示信息,说明 KEY 值的长度限制及用途 -->
|
|
|
<p class="menu-tips">用于消息接口推送,不超过128字节</p>
|
|
|
<!-- 菜单 KEY 值标签 -->
|
|
|
<div class="menu-label">菜单KEY值</div>
|
|
|
<!-- 菜单 KEY 值输入框所在的容器 -->
|
|
|
<div class="menu-input">
|
|
|
<!-- 文本输入框,用于输入菜单 KEY 值,通过 v-model 双向绑定 button.key -->
|
|
|
<input type="text" placeholder="" class="menu-input-text" v-model="button.key">
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
export default {
|
|
|
// 定义组件接收的属性
|
|
|
props: {
|
|
|
// 表示选中的菜单层级,类型为数字,默认值为 1
|
|
|
selectedMenuLevel: {
|
|
|
type: Number,
|
|
|
default: 1
|
|
|
},
|
|
|
// 表示菜单相关的数据对象,类型为对象,是必填项
|
|
|
button: {
|
|
|
type: Object,
|
|
|
required: true
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
// 用于标记菜单名称长度是否超出上限,初始值为 false
|
|
|
menuNameBounds: false,
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
// 检查菜单名称长度的方法
|
|
|
checkMenuName: function (val) {
|
|
|
// 如果选中的菜单层级为 1 且菜单名称长度(通过 getMenuNameLen 方法获取)小于等于 10
|
|
|
if (this.selectedMenuLevel == 1 && this.getMenuNameLen(val) <= 10) {
|
|
|
// 将 menuNameBounds 设置为 false,表示菜单名称长度未超出上限
|
|
|
this.menuNameBounds = false;
|
|
|
}
|
|
|
// 如果选中的菜单层级为 2 且菜单名称长度小于等于 16
|
|
|
else if (this.selectedMenuLevel == 2 && this.getMenuNameLen(val) <= 16) {
|
|
|
this.menuNameBounds = false;
|
|
|
}
|
|
|
// 其他情况,即超出对应层级的长度限制,将 menuNameBounds 设置为 true
|
|
|
else {
|
|
|
this.menuNameBounds = true;
|
|
|
}
|
|
|
},
|
|
|
// 获取菜单名称长度的方法
|
|
|
getMenuNameLen: function (val) {
|
|
|
var len = 0;
|
|
|
// 遍历菜单名称字符串的每个字符
|
|
|
for (var i = 0; i < val.length; i++) {
|
|
|
var a = val.charAt(i);
|
|
|
// 判断字符是否为双字节字符(非 ASCII 码字符),如果是则长度计为 2,否则计为 1
|
|
|
a.match(/[^\x00-\xff]/ig)!= null? len += 2 : len += 1;
|
|
|
}
|
|
|
return len;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script> |