menus.vue 42KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. <template>
  2. <div class="main-contain">
  3. <div class="position">
  4. <bread-crumb :crumbs="crumbs"></bread-crumb>
  5. <el-col :span="5" style="text-align: right;" v-show="initButtons">
  6. <el-button type="primary" size="small" :disabled="subload" icon="el-icon-upload" @click="submitSave">保存并发布</el-button>
  7. <el-button type="danger" size="small" :disabled="subload" icon="el-icon-delete" @click="deleteMenus">停用菜单</el-button>
  8. </el-col>
  9. </div>
  10. <div class="app-container" id="winxin-menus-box">
  11. <div class="menu_tips clearfix">
  12. <span class="ico_menu_tips fl"></span>
  13. <div class="menu_tips_txt fl" v-show="initButtons">
  14. <p>菜单编辑中</p>
  15. <p>菜单不会即时发布,请确定菜单编辑完成后点击“保存并发布”同步到手机,若停用菜单,点击“停用菜单”</p>
  16. </div>
  17. <div class="menu_tips_txt fl" v-show="!initButtons">
  18. <p>未认证的订阅号没有自定义菜单接口权限,无法编辑菜单。</p>
  19. </div>
  20. </div>
  21. <div class="menu_setting_area clearfix" v-loading='subload' element-loading-text="正在保存..." v-show="initButtons">
  22. <div class="menu_preview_area fl">
  23. <div class="mobile_menu_preview">
  24. <div class="mobile_hd">{{authData.authorizer_nick_name}}</div>
  25. <div class="mobile_bd">
  26. <ul class="pre_menu_list">
  27. <li class="jsMenu pre_menu_li" :id="'menu_'+mi" v-for="(menu, mi) in menus.button" :key="mi" :class="mi==currentPatient&&currentChild==-1?'menu-active':''">
  28. <a href="javascript:void(0);" class="pre_menu_link jsMenuB" @click="selectItem(mi, -1, menu)"> <i class="icon_menu_dot "></i> <span class="js_l1Title_">{{menu.name}}</span> </a>
  29. <div class="sub_pre_menu_box" v-show="mi==currentPatient">
  30. <ul class="sub_pre_menu_list">
  31. <li class="jslevel2 jsSubMenu" :id="'subMenu_menu_'+ mi + '_'+ni" v-for="(node, ni) in childrenNode(menu.sub_button)" :key="ni" :class="mi==currentPatient&&currentChild==ni?'menu-active':''">
  32. <a href="javascript:void(0);" class="jsSubView jsSubMenuBtn" @click="selectItem(mi, ni, node)" > <span class="sub_pre_menu_inner "> <i class="icon20_common"></i> <span class="js_l2Title">{{node.name}}</span> </span> </a>
  33. </li>
  34. <li class="jslevel2 jsAddSubMenu" v-show="childrenNode(menu.sub_button).length<5">
  35. <a href="javascript:void(0);" class="jsSubView" @click="addItem(mi)"> <span class="sub_pre_menu_inner "> <i class="icon14_menu_add">+</i> </span> </a>
  36. </li>
  37. </ul>
  38. <i class="arrow arrow_out"></i>
  39. <i class="arrow arrow_in"></i>
  40. </div>
  41. </li>
  42. <li class="jsAddMenu pre_menu_li" v-show="!menus.button||menus.button.length<3">
  43. <a href="javascript:void(0);" class="pre_menu_link" @click="addItem(-1)">
  44. <i class="icon_menu_dot "></i>
  45. <span class="js_l1Title_">
  46. <i class="icon14_menu_add">+</i>
  47. </span>
  48. </a>
  49. <!-- <div class="sub_pre_menu_box">
  50. <ul class="sub_pre_menu_list">
  51. <li class="jslevel2 jsAddSubMenu">
  52. <a href="javascript:void(0);" class="jsSubView">
  53. <span class="sub_pre_menu_inner ">
  54. <i class="icon14_menu_add">+</i>
  55. </span>
  56. </a>
  57. </li>
  58. </ul>
  59. <i class="arrow arrow_out"></i>
  60. <i class="arrow arrow_in"></i>
  61. </div> -->
  62. </li>
  63. </ul>
  64. </div>
  65. </div>
  66. <div class="sort_btn_wrp">
  67. </div>
  68. </div>
  69. <div class="menu_form_area fl" v-show="currentPatient>=0&&currentMenu">
  70. <div class="menu_form_inner">
  71. <h2 class="menu_form_tit clearfix">
  72. <span class="delate fr delete_menu" @click="deleteButtonItem">{{deleteButtonName()}}</span>
  73. <span class="global_info">{{showMenuName()}}</span>
  74. </h2>
  75. <div class="menu_form_item">
  76. <label for="" class="tit">菜单名称</label>
  77. <input type="text" class="name clearfix js_menu_name" id="menu_name_input" v-model="currentMenu.name" placeholder="请输入菜单名称" />
  78. <span class="tips" id="tips" v-show="!menuNameError">{{menuNameTip()}}</span>
  79. <span class="tips" id="errinfo" v-show="menuNameError" style="color: #f00;">{{menuNameTip()}}</span>
  80. </div>
  81. <div class="menu_form_item menu_more_info" v-show="typeof(currentMenu.sub_button) == 'undefined' || !currentMenu.sub_button || currentMenu.sub_button.length==0">
  82. <div class="menu_form__nav clearfix">
  83. <label for="" class="tit">菜单内容</label>
  84. <el-radio-group v-model="menuType" class="radio_item" @change="changeBigType">
  85. <el-radio v-for="(menu, index) in menuTypeOptions" :key="index" :label="menu.id" :value="menu.id">{{menu.name}}</el-radio>
  86. </el-radio-group>
  87. </div>
  88. <div class="menu_form__con">
  89. <div class="inner send_message " v-show="menuType==1">
  90. <div class="send_message_tit">
  91. <div class="send_nav">
  92. <el-button type="text" icon="el-icon-edit-outline" style="padding:0" :disabled="currentMenu.type=='click'" @click="selectMenuType(1)">文字</el-button>
  93. </div>
  94. <div class="send_nav">
  95. <el-button type="text" icon="el-icon-picture-outline" style="padding:0" :disabled="currentMenu.type=='media_id'" @click="selectMenuType(2)">图片</el-button>
  96. </div>
  97. </div>
  98. <textarea v-show="currentMenu.type=='click'" class="send_message_edit" id="click_menu_act" v-model="currentMenu.message" placeholder="请输入你需要的文字"></textarea>
  99. <span v-show="currentMenu.type=='click'" class="tips" id="acterrinfo" v-if="!messageError" >&nbsp;&nbsp;{{menuMessageTip}}</span>
  100. <span v-show="currentMenu.type=='click'" class="tips" id="acterrinfo" v-if="messageError" style="color: #f00;">&nbsp;&nbsp;{{menuMessageTip}}</span>
  101. <div v-show="currentMenu.type=='media_id'" class="mediaID-box">
  102. <el-row>
  103. <el-col :span="12" >
  104. <div class="mediaID-item">
  105. <i class="el-icon-news" @click="openMediaBox"></i>
  106. <span class="icon-name">从素材库选择</span>
  107. </div>
  108. </el-col>
  109. <el-col :span="12" >
  110. <div class="mediaID-item">
  111. <el-upload
  112. class="media-uploader"
  113. :action="addMaterialUrl"
  114. :show-file-list="false"
  115. :with-credentials='true'
  116. :on-success="handleMediaSuccess"
  117. :before-upload="beforeMediaUpload"
  118. >
  119. <img v-if="currentMenu.media_url" :src="currentMenu.media_url" class="media">
  120. <i v-else class="el-icon-plus media-uploader-icon"></i>
  121. </el-upload>
  122. <span class="icon-name">上传图片</span>
  123. </div>
  124. </el-col>
  125. </el-row>
  126. <span class="tips" id="acterrinfo" >&nbsp;&nbsp;如果出现:此图片来自微信公众平台,未经允许不可引用!是正常情况</span>
  127. </div>
  128. </div>
  129. <div class="inner jump_page" v-show="menuType==2">
  130. <span class="tips_size">订阅者点击该子菜单会跳到以下链接</span>
  131. <div>
  132. <label for="" class="address">页面地址:</label>
  133. <input type="text" id="view_menu_url" class="address_input " v-model="currentMenu.url" :title="currentMenu.url"/>
  134. <el-button type="primary" size="small" icon="el-icon-menu">选择地址</el-button>
  135. <span class="mitips" v-if="urlError" style="color: #f00;">请填写url</span>
  136. </div>
  137. </div>
  138. <div class="inner miniprogram " v-show="menuType==3">
  139. <span class="tips_size">订阅者点击该子菜单会跳到以下小程序</span>
  140. <div class="miniprogram-item">
  141. <label for="" class="address">APPID:</label>
  142. <input type="text" id="view_menu_url" class="address_input " v-model="currentMenu.appid" :title="currentMenu.appid" placeholder="请确保小程序与公众号关联,填写小程序"/>
  143. <a href="https://weixiao.qq.com/notice/view?mid=0&cid=2&id=274" target="_blank" rel="noopener noreferrer">如何获取</a>
  144. <span class="mitips" v-if="appidError" style="color: #f00;">请填写appid</span>
  145. </div>
  146. <div class="miniprogram-item">
  147. <label for="" class="address">页面:</label>
  148. <input type="text" id="view_menu_url" class="address_input " v-model="currentMenu.pagepath" :title="currentMenu.pagepath" placeholder="请填写跳转页面的小程序访问路径"/>
  149. <a href="https://weixiao.qq.com/notice/view?mid=0&cid=2&id=275" target="_blank" rel="noopener noreferrer">填写指引</a>
  150. <span class="mitips" v-if="pagepathError" style="color: #f00;">请填写pagepath</span>
  151. </div>
  152. <div class="miniprogram-item">
  153. <label for="" class="address">备用页面:</label>
  154. <input type="text" id="view_menu_url" class="address_input " v-model="currentMenu.url" :title="currentMenu.url"/>
  155. <span class="mitips" v-if="urlError" style="color: #f00;">请填写url</span>
  156. <span class="mitips" >旧版微信客户端不支持小程序,用户点击菜单时会打开该网页</span>
  157. </div>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </div>
  163. </div>
  164. </div>
  165. <!--选择图片-->
  166. <image-material-box ref="imageMaterialBox" :currentMenu="currentMenu"></image-material-box>
  167. </div>
  168. </template>
  169. <script>
  170. import BreadCrumb from "../components/bread-crumb";
  171. import ImageMaterialBox from "./components/ImageMaterialBox";
  172. import {GetAuthorizationInfo} from "@/api/mpwechat/mpwechat";
  173. import {GetMenus,SaveMenus,DeleteMenu} from "@/api/mpwechat/mpmenus";
  174. export default {
  175. name: "menus",
  176. components: {
  177. BreadCrumb,
  178. ImageMaterialBox,
  179. },
  180. data() {
  181. return {
  182. crumbs: [
  183. { path: false, name: "系统设置" },
  184. { path: false, name: "公众号菜单" }
  185. ],
  186. menuTypeOptions:[
  187. {id:1, name:' 发送内容'},
  188. {id:2, name:' 跳转网页'},
  189. {id:3, name:' 跳转小程序'},
  190. ],
  191. addMaterialUrl: process.env.BASE_API + '/api/mpwechat/media/add_material',
  192. initButtons:false,
  193. subload:false,
  194. menus:{button:[]},
  195. currentMenu:{
  196. big_type:0,
  197. type:'',
  198. name:'',
  199. url:'',
  200. appid:'',
  201. pagepath:'',
  202. key:'',//key规则:V_[number]_click;VC_[number]_click
  203. message:'',
  204. sub_button:[],
  205. media_id:'',
  206. media_url:'',
  207. },
  208. menuType:0,
  209. currentPatient:-1,
  210. currentChild:-1,
  211. menuNameError:false,
  212. messageError:false,
  213. urlError:false,
  214. appidError:false,
  215. pagepathError:false,
  216. menuMessageTip:'还可以输入 600 字',
  217. pclick:0,
  218. cclick:0,
  219. authData: {
  220. id: 0,
  221. user_org_id: 0,
  222. authorizer_appid: "",
  223. authorizer_access_token: "",
  224. authorizer_refresh_token: "",
  225. authorizer_jsapi_ticket: "",
  226. authorizer_funcscope_category: "",
  227. authorizer_nick_name: "",
  228. authorizer_head_img: "",
  229. authorizer_service_type_info: 0,
  230. authorizer_verify_type_info: 0,
  231. authorizer_user_name: "",
  232. authorizer_principal_name: "",
  233. authorizer_business_info: "",
  234. authorizer_qrcode_url: "",
  235. created_time: "",
  236. updated_time: "",
  237. authorizer_status: 0
  238. }
  239. };
  240. },
  241. methods: {
  242. GetAuthorizationInfo:function(){
  243. GetAuthorizationInfo().then(response=>{
  244. var res = response.data;
  245. if(res.state===1) {
  246. if(res.data.authorization) {
  247. this.authData = res.data.authorization;
  248. if (this.authData.authorizer_status != 1) {
  249. this.$message.error("公众号未授权");
  250. this.$router.push({path:"/weixinmp/authorization"})
  251. return false;
  252. }else if (this.authData.authorizer_verify_type_info>=0 || this.authData.authorizer_service_type_info==2) {
  253. this.initButtons = true;
  254. }
  255. }else {
  256. this.$message.error("公众号未授权");
  257. this.$router.push({path:"/weixinmp/authorization"})
  258. }
  259. }else {
  260. this.$message.error(res.msg);
  261. }
  262. }).catch(e=>{});
  263. },
  264. openMediaBox:function(){
  265. this.$refs.imageMaterialBox.open();
  266. },
  267. handleMediaSuccess:function(res, file) {
  268. if (res.state==1) {
  269. this.$message.success('上传成功');
  270. this.currentMenu.media_url = 'http://img01.store.sogou.com/net/a/04/link?appid=100520029&url=' + res.data.media.media_url;
  271. this.currentMenu.media_id = res.data.media.media_id;
  272. }else {
  273. this.$message.error(res.msg);
  274. }
  275. },
  276. beforeMediaUpload:function(file) {
  277. var allow = {"image/bmp":1,"image/png":1,"image/jpeg":1,"image/jpg":1,"image/gif":1};
  278. // const isJPG = file.type === 'image/jpeg';
  279. const isImg = file.type in allow;
  280. const isLt2M = file.size / 1024 / 1024 < 2;
  281. if (!isImg) {
  282. this.$message.error('上传图片只能是 bmp/png/jpeg/jpg/gif 格式!');
  283. }
  284. if (!isLt2M) {
  285. this.$message.error('上传图片大小不能超过 2MB!');
  286. }
  287. return isImg && isLt2M;
  288. },
  289. deleteMenus:function(){
  290. this.$confirm('删除后,公众号的菜单也将被删除', '删除提示', {
  291. dangerouslyUseHTMLString:true,
  292. confirmButtonText: '确定',
  293. cancelButtonText: '取消',
  294. type: 'warning'
  295. }).then(() => {
  296. DeleteMenu().then(response=>{
  297. var res = response.data;
  298. if (res.state==1) {
  299. this.$message.success('删除成功');
  300. this.currentMenu = {
  301. type:'',
  302. name:'',
  303. url:'',
  304. appid:'',
  305. pagepath:'',
  306. key:'',//key规则:V_[number]_click;VC_[number]_click
  307. message:'',
  308. sub_button:[],
  309. media_id:'',
  310. media_url:'',
  311. big_type:0
  312. };
  313. this.currentPatient = -1;
  314. this.currentChild = -1;
  315. this.menus = {button:[]};
  316. }else {
  317. this.$message.error(res.msg);
  318. }
  319. }).catch(e=>{});
  320. }).catch(() => {
  321. });
  322. },
  323. submitSave:function () {
  324. this.subload = true;
  325. var res = this.checkMenus();
  326. if (!res) {
  327. this.$message.error("保存失败");
  328. this.subload = false;
  329. return false;
  330. }
  331. SaveMenus(this.menus).then(response=>{
  332. var res = response.data;
  333. if (res.state===1) {
  334. this.$message.success("保存成功")
  335. }else {
  336. this.$message.error(res.msg);
  337. }
  338. this.subload = false;
  339. }).catch(e=>{
  340. this.subload = false;
  341. });
  342. },
  343. addItem:function(mi){
  344. var menu={type:'click',name:'',url:'',appid:'',pagepath:'',key:'',message:'',sub_button:null,media_id:''};
  345. if (mi>-1) {
  346. this.cclick += 1;
  347. menu.key = 'VC_' + this.cclick + "_click";
  348. menu.name ='子菜单名称';
  349. if(!this.menus.button[mi].sub_button) {
  350. this.menus.button[mi].sub_button = [];
  351. }
  352. this.menus.button[mi].sub_button.push(menu);
  353. var sblen = this.menus.button[mi].sub_button.length;
  354. this.selectItem(mi, sblen-1, menu);
  355. }else {
  356. this.pclick += 1;
  357. menu.key = 'V_' + this.pclick + "_click";
  358. menu.name ='菜单名称';
  359. if (!this.menus.button) {
  360. this.menus.button = [];
  361. }
  362. this.menus.button.push(menu);
  363. var len = this.menus.button.length;
  364. this.selectItem(len-1, -1, menu);
  365. }
  366. },
  367. deleteButtonItem:function(){
  368. this.$confirm('删除后该菜单下设置的内容将被删除', '删除提示', {
  369. dangerouslyUseHTMLString:true,
  370. confirmButtonText: '确定',
  371. cancelButtonText: '取消',
  372. type: 'warning'
  373. }).then(() => {
  374. if (this.currentPatient>=0&&this.currentChild>=0) {
  375. this.menus.button[this.currentPatient].sub_button.splice(this.currentChild, 1);
  376. var sblen = this.menus.button[this.currentPatient].sub_button.length;
  377. if(sblen>0) {
  378. this.currentChild = sblen-1;
  379. this.selectItem(this.currentPatient, this.currentChild,this.menus.button[this.currentPatient].sub_button[this.currentChild]);
  380. }else {
  381. this.menus.button[this.currentPatient].sub_button = null;
  382. this.selectItem(this.currentPatient,-1,this.menus.button[this.currentPatient]);
  383. }
  384. }else if (this.currentPatient>=0) {
  385. this.menus.button.splice(this.currentPatient, 1);
  386. var blen = this.menus.buttonlength;
  387. if(blen>0) {
  388. this.currentPatient = blen-1;
  389. this.selectItem(this.currentPatient, -1,this.menus.button[this.currentPatient]);
  390. }else {
  391. this.currentPatient = -1;
  392. this.currentMenu={
  393. type:'',
  394. name:'',
  395. url:'',
  396. appid:'',
  397. pagepath:'',
  398. key:'',
  399. message:'',
  400. sub_button:[],
  401. media_id:'',
  402. media_url:'',
  403. big_type:0
  404. };
  405. }
  406. }
  407. }).catch(() => {
  408. });
  409. },
  410. GetMenus:function(){
  411. GetMenus().then(response=>{
  412. var res = response.data;
  413. if (res.state == 1) {
  414. if (res.data.menus){
  415. this.menus = res.data.menus;
  416. for (const index in this.menus.button) {
  417. var button = this.menus.button[index];
  418. this.menus.button[index]['big_type'] = typeof(button.type) !='undefined' && button.type ? this.setBigType(button.type):0;
  419. if(typeof(button.key) !='undefined' && button.key) {
  420. var keys = button.key.split("_")
  421. if (typeof(keys[1]) !='undefined') {
  422. var num = parseInt(keys[1]);
  423. this.pclick = !isNaN(num) && num>this.pclick?num:this.pclick;
  424. }
  425. }
  426. if(typeof(button.sub_button) !='undefined' && button.sub_button) {
  427. for (const chilid in button.sub_button) {
  428. var cbutton = button.sub_button[chilid];
  429. this.menus.button[index].sub_button[chilid]['big_type'] = typeof(cbutton.type) !='undefined' && cbutton.type ? this.setBigType(cbutton.type):0;
  430. if(typeof(cbutton.key) !='undefined' && cbutton.key) {
  431. var keys = cbutton.key.split("_")
  432. if (typeof(keys[1]) !='undefined') {
  433. var num = parseInt(keys[1]);
  434. this.cclick = !isNaN(num) && num>this.cclick?num:this.cclick;
  435. }
  436. }
  437. }
  438. }
  439. }
  440. }
  441. }else {
  442. this.$message.error(res.msg);
  443. }
  444. }).catch(e=>{});
  445. },
  446. SetMenuType:function(){
  447. switch (this.currentMenu.type) {
  448. case 'media_id':
  449. case 'click':
  450. this.menuType = 1;
  451. break;
  452. case 'view':
  453. this.menuType = 2;
  454. break;
  455. case 'miniprogram':
  456. this.menuType = 3;
  457. break;
  458. default:
  459. this.menuType = 0;
  460. break;
  461. }
  462. },
  463. setBigType(type) {
  464. var bitType = 0;
  465. switch (this.currentMenu.type) {
  466. case 'click':
  467. bitType = 1;
  468. break;
  469. case 'media_id':
  470. bitTypee = 2;
  471. break;
  472. }
  473. return bitType;
  474. },
  475. changeBigType:function(value){
  476. // this.currentMenu.big_type = value;
  477. switch (value) {
  478. case 1:
  479. if (this.currentMenu.big_type == 1 ) {
  480. this.currentMenu.type = 'click';
  481. } else if (this.currentMenu.big_type == 2) {
  482. this.currentMenu.type = 'media_id';
  483. } else {
  484. this.currentMenu.type = 'click';
  485. }
  486. break;
  487. case 2:
  488. this.currentMenu.type = 'view';
  489. break;
  490. case 3:
  491. this.currentMenu.type = 'miniprogram';
  492. break;
  493. default:
  494. break;
  495. }
  496. },
  497. selectMenuType:function(type){
  498. this.currentMenu.big_type = type;
  499. if(type==1) {
  500. this.currentMenu.type = 'click';
  501. }else if(type==2) {
  502. this.currentMenu.type = 'media_id';
  503. }
  504. },
  505. selectItem:function(mi, ni, node){
  506. this.currentPatient = mi;
  507. this.currentChild = ni;
  508. this.currentMenu={
  509. type:'',
  510. name:'',
  511. url:'',
  512. appid:'',
  513. pagepath:'',
  514. key:'',
  515. message:'',
  516. sub_button:[],
  517. media_id:'',
  518. media_url:'',
  519. big_type:0,
  520. };
  521. for (const key in node) {
  522. this.currentMenu[key] = node[key];
  523. }
  524. this.SetMenuType();
  525. },
  526. childrenNode:function(buttons) {
  527. if (buttons) {
  528. return buttons;
  529. }else {
  530. return [];
  531. }
  532. },
  533. deleteButtonName:function() {
  534. if(this.currentPatient>=0&&this.currentChild>=0) {
  535. return '删除子菜单';
  536. }
  537. return '删除菜单';
  538. },
  539. showMenuName:function(){
  540. if(this.currentMenu) {
  541. return this.currentMenu.name;
  542. }
  543. return '菜单名称';
  544. },
  545. menuNameTip:function(){
  546. if(this.currentPatient>=0&&this.currentChild>=0) {
  547. return '字数不超过8个汉字或16个字母';
  548. }else if (this.currentPatient>=0){
  549. return '字数不超过4个汉字或8个字母';
  550. }else {
  551. return '';
  552. }
  553. },
  554. ChcekMenuNameError:function(){
  555. if (this.currentPatient>=0&&this.currentChild>=0) {
  556. var res = /^[a-zA-Z0-9]{1,16}$/.test((this.currentMenu.name + '').replace(/[\u4e00-\u9fa5]/g, 'aa'));
  557. this.menuNameError = !res;
  558. } else if (this.currentPatient>=0){
  559. var res = /^[a-zA-Z0-9]{1,8}$/.test((this.currentMenu.name + '').replace(/[\u4e00-\u9fa5]/g, 'aa'));
  560. this.menuNameError = !res;
  561. } else {
  562. this.menuNameError = false;
  563. }
  564. return this.menuNameError;
  565. },
  566. CheckUrlError:function(){
  567. if (this.currentMenu.url.length==0) {
  568. this.urlError = true;
  569. }else {
  570. this.urlError = false;
  571. }
  572. return this.urlError;
  573. },
  574. CheckAppidError:function(){
  575. if (this.currentMenu.appid.length==0) {
  576. this.appidError = true;
  577. }else {
  578. this.appidError = false;
  579. }
  580. return this.appidError;
  581. },
  582. CheckPagePathError:function(){
  583. if (this.currentMenu.pagepath.length==0) {
  584. this.pagepathError = true;
  585. }else {
  586. this.pagepathError = false;
  587. }
  588. return this.pagepathError;
  589. },
  590. CheckMessageError:function(){
  591. var len = $.trim(this.currentMenu.message+'').length;
  592. var mt = 600-len;
  593. if ( mt < 0) {
  594. this.messageError = true;
  595. }else {
  596. this.messageError = false;
  597. }
  598. return this.messageError;
  599. },
  600. checkMenus:function(){
  601. let p = this.currentPatient;
  602. let c = this.currentChild;
  603. for (const parent in this.menus.button) {
  604. if (this.menus.button[parent].sub_button && this.menus.button[parent].sub_button.length>0) {
  605. let subs = this.menus.button[parent].sub_button;
  606. for (const child in subs) {
  607. this.selectItem(parent, child, subs[child]);
  608. if (this.ChcekMenuNameError()) {
  609. return false;
  610. }
  611. if (subs[child].type == 'click') {
  612. if (this.CheckMessageError()) {
  613. return false;
  614. }
  615. }
  616. if (subs[child].type == 'view') {
  617. if (this.CheckUrlError()) {
  618. return false;
  619. }
  620. }
  621. if (subs[child].type == 'miniprogram') {
  622. if (this.CheckUrlError()) {
  623. return false;
  624. }
  625. if (this.CheckAppidError()) {
  626. return false;
  627. }
  628. if (this.CheckPagePathError()) {
  629. return false;
  630. }
  631. }
  632. }
  633. }else {
  634. this.selectItem(parent, -1, this.menus.button[parent]);
  635. var res = this.ChcekMenuNameError();
  636. if (res) {
  637. return false;
  638. }
  639. if (this.menus.button[parent].type == 'click') {
  640. if (this.CheckMessageError()) {
  641. return false;
  642. }
  643. }
  644. if (this.menus.button[parent].type == 'view') {
  645. if (this.CheckUrlError()) {
  646. return false;
  647. }
  648. }
  649. if (this.menus.button[parent].type == 'miniprogram') {
  650. if (this.CheckUrlError()) {
  651. return false;
  652. }
  653. if (this.CheckAppidError()) {
  654. return false;
  655. }
  656. if (this.CheckPagePathError()) {
  657. return false;
  658. }
  659. }
  660. }
  661. }
  662. if (p>-1&&c>-1) {
  663. this.selectItem(p, c, this.menus.button[p].sub_button[c]);
  664. }else if(p>-1) {
  665. this.selectItem(p, -1, this.menus.button[p]);
  666. }
  667. return true;
  668. },
  669. },
  670. created() {
  671. this.GetAuthorizationInfo();
  672. },
  673. computed:{
  674. },
  675. watch:{
  676. 'initButtons':function(){
  677. if (this.initButtons) {
  678. this.GetMenus();
  679. }
  680. },
  681. 'currentMenu.name':function(){
  682. var res = this.ChcekMenuNameError();
  683. if (!res) { //如果当前的菜单名称没有错
  684. if (this.currentPatient>=0&&this.currentChild>=0) {
  685. this.menus.button[this.currentPatient].sub_button[this.currentChild].name = this.currentMenu.name;
  686. } else if (this.currentPatient>=0){
  687. this.menus.button[this.currentPatient].name = this.currentMenu.name;
  688. }
  689. }
  690. },
  691. 'currentMenu.type':function(){
  692. if (this.currentPatient>=0&&this.currentChild>=0) {
  693. this.menus.button[this.currentPatient].sub_button[this.currentChild].type = this.currentMenu.type;
  694. this.menus.button[this.currentPatient].sub_button[this.currentChild].big_type = this.currentMenu.big_type;
  695. if (this.currentMenu.type == 'click' && this.currentMenu.key.length==0) {
  696. this.cclick += 1;
  697. var key = 'VC_' + this.cclick + "_click";
  698. this.currentMenu.key = key;
  699. this.menus.button[this.currentPatient].sub_button[this.currentChild]['key'] = key;
  700. }
  701. } else if (this.currentPatient>=0){
  702. this.menus.button[this.currentPatient].type = this.currentMenu.type;
  703. this.menus.button[this.currentPatient].big_type = this.currentMenu.big_type;
  704. if (this.currentMenu.type == 'click' && this.currentMenu.key.length==0) {
  705. this.pclick += 1;
  706. var key = 'V_' + this.cclick + "_click";
  707. this.currentMenu.key = key;
  708. this.menus.button[this.currentPatient]['key'] = key;
  709. }
  710. }
  711. },
  712. 'currentMenu.url':function(){
  713. if (this.currentPatient>=0&&this.currentChild>=0) {
  714. this.menus.button[this.currentPatient].sub_button[this.currentChild].url = this.currentMenu.url;
  715. } else if (this.currentPatient>=0){
  716. this.menus.button[this.currentPatient].url = this.currentMenu.url;
  717. }
  718. this.CheckUrlError();
  719. },
  720. 'currentMenu.appid':function(){
  721. if (this.currentPatient>=0&&this.currentChild>=0) {
  722. this.menus.button[this.currentPatient].sub_button[this.currentChild].appid = this.currentMenu.appid;
  723. } else if (this.currentPatient>=0){
  724. this.menus.button[this.currentPatient].appid = this.currentMenu.appid;
  725. }
  726. this.CheckAppidError();
  727. },
  728. 'currentMenu.pagepath':function(){
  729. if (this.currentPatient>=0&&this.currentChild>=0) {
  730. this.menus.button[this.currentPatient].sub_button[this.currentChild].pagepath = this.currentMenu.pagepath;
  731. } else if (this.currentPatient>=0){
  732. this.menus.button[this.currentPatient].pagepath = this.currentMenu.pagepath;
  733. }
  734. this.CheckPagePathError();
  735. },
  736. 'currentMenu.media_id':function(){
  737. if (this.currentPatient>=0&&this.currentChild>=0) {
  738. this.menus.button[this.currentPatient].sub_button[this.currentChild].media_id = this.currentMenu.media_id;
  739. } else if (this.currentPatient>=0){
  740. this.menus.button[this.currentPatient].media_id = this.currentMenu.media_id;
  741. }
  742. },
  743. 'currentMenu.media_url':function(){
  744. if (this.currentPatient>=0&&this.currentChild>=0) {
  745. this.menus.button[this.currentPatient].sub_button[this.currentChild].media_url = this.currentMenu.media_url;
  746. } else if (this.currentPatient>=0){
  747. this.menus.button[this.currentPatient].media_url = this.currentMenu.media_url;
  748. }
  749. },
  750. 'currentMenu.message':function(){
  751. var len = $.trim(this.currentMenu.message+'').length;
  752. var mt = 600-len;
  753. if ( mt < 0) {
  754. mt = len-600;
  755. this.messageError = true;
  756. this.menuMessageTip = '已超出 ' + mt + ' 字,内容将不会保存。';
  757. }else {
  758. this.messageError = false;
  759. this.menuMessageTip = '还可以输入 ' + mt + ' 字';
  760. if (this.currentPatient>=0&&this.currentChild>=0) {
  761. this.menus.button[this.currentPatient].sub_button[this.currentChild].message = this.currentMenu.message;
  762. } else if (this.currentPatient>=0){
  763. this.menus.button[this.currentPatient].message = this.currentMenu.message;
  764. }
  765. }
  766. },
  767. },
  768. };
  769. </script>
  770. <style >
  771. #winxin-menus-box {
  772. font-size: 14px;
  773. color: #485b6d;
  774. }
  775. #winxin-menus-box .menu-active{
  776. border: 1px solid rgb(68, 181, 73) !important;
  777. }
  778. #winxin-menus-box .menu_tips{
  779. padding: 20px 0 18px 32px;
  780. background: #f4f7fa;
  781. }
  782. #winxin-menus-box .clearfix {
  783. clear: both;
  784. }
  785. #winxin-menus-box .clearfix:before {
  786. display: table;
  787. content: " ";
  788. }
  789. #winxin-menus-box .menu_tips .ico_menu_tips {
  790. width: 36px;
  791. height: 36px;
  792. background: url('https://images.shengws.com/icos-201906141103.png') no-repeat -691px -548px;
  793. display: block;
  794. margin-right: 11px;
  795. }
  796. #winxin-menus-box .fl {
  797. float: left;
  798. }
  799. #winxin-menus-box .menu_setting_area {
  800. padding: 42px 0 0 50px;
  801. display: flex;
  802. }
  803. #winxin-menus-box .menu_preview_area {
  804. width: 284px;
  805. border: 1px solid #e7e7eb;
  806. position: relative;
  807. }
  808. #winxin-menus-box .mobile_menu_preview {
  809. position: relative;
  810. width: 284px;
  811. height: 580px;
  812. background: transparent url("https://images.shengws.com/bg_mobile_head_default3a7b38.png") no-repeat 0 0;
  813. background-position: 0 0;
  814. background-size:100%;
  815. }
  816. #winxin-menus-box .mobile_menu_preview .mobile_hd {
  817. padding: 30px 0 0 20px;
  818. text-align: center;
  819. color: #fff;
  820. }
  821. #winxin-menus-box .menu_preview_area .pre_menu_list {
  822. position: absolute;
  823. bottom: 0;
  824. left: 0;
  825. right: 0;
  826. border-top: 1px solid #e7e7eb;
  827. background: transparent url("https://images.shengws.com/bg_mobile_foot_default3a7b38.png") no-repeat 0 0;
  828. background-position: 0 0;
  829. background-repeat: no-repeat;
  830. padding-left: 43px;
  831. }
  832. #winxin-menus-box ul, #winxin-menus-boxol {
  833. list-style: none;
  834. }
  835. #winxin-menus-box .radio_item {
  836. margin: 13px 0;
  837. }
  838. #winxin-menus-box .mobile_bd .pre_menu_list .pre_menu_li {
  839. border-right: 1px #e5e8ea solid;
  840. height: 50px;
  841. line-height: 50px;
  842. float: left;
  843. text-align: center;
  844. width: 33%;
  845. position: relative;
  846. }
  847. #winxin-menus-box .mobile_bd .pre_menu_list li a {
  848. display: block;
  849. width: auto;
  850. overflow: hidden;
  851. text-overflow: ellipsis;
  852. word-wrap: normal;
  853. text-decoration: none;
  854. color: #54657e;
  855. white-space: nowrap;
  856. }
  857. #winxin-menus-box .menu_preview_area .sub_pre_menu_box {
  858. bottom: 60px;
  859. border-top-width: 0;
  860. position: absolute;
  861. left: 0;
  862. width: 100%;
  863. border: 1px solid #d0d0d0;
  864. background-color: #fff;
  865. }
  866. #winxin-menus-box ul ul {
  867. margin-bottom: 0;
  868. }
  869. #winxin-menus-box .sub_pre_menu_box .jslevel2 {
  870. line-height: 44px;
  871. border: 1px solid transparent;
  872. margin: 0 -1px -1px;
  873. }
  874. #winxin-menus-box .sub_pre_menu_box .jslevel2 .jsSubView {
  875. padding: 0 .5em;
  876. display: block;
  877. overflow: hidden;
  878. text-overflow: ellipsis;
  879. white-space: nowrap;
  880. word-wrap: normal;
  881. color: #616161;
  882. text-decoration: none;
  883. }
  884. #winxin-menus-box .mobile_bd .pre_menu_list li a {
  885. display: block;
  886. width: auto;
  887. overflow: hidden;
  888. text-overflow: ellipsis;
  889. word-wrap: normal;
  890. text-decoration: none;
  891. color: #54657e;
  892. white-space: nowrap;
  893. }
  894. #winxin-menus-box .menu_preview_area .sub_pre_menu_inner {
  895. display: block;
  896. border-top: 1px solid #e7e7eb;
  897. width: auto;
  898. overflow: hidden;
  899. text-overflow: ellipsis;
  900. white-space: nowrap;
  901. word-wrap: normal;
  902. cursor: pointer;
  903. }
  904. #winxin-menus-box .menu_preview_area .icon14_menu_add {
  905. font-size: 26px;
  906. color: #d0d4d7;
  907. font-weight: 700;
  908. }
  909. #winxin-menus-box .sub_pre_menu_box .arrow_out {
  910. bottom: -6px;
  911. display: inline-block;
  912. width: 0;
  913. height: 0;
  914. border-width: 6px;
  915. border-style: dashed;
  916. border-color: transparent;
  917. border-bottom-width: 0;
  918. border-top-color: #d0d0d0;
  919. border-top-style: solid;
  920. position: absolute;
  921. left: 50%;
  922. margin-left: -6px;
  923. }
  924. #winxin-menus-box .sub_pre_menu_box .arrow_in {
  925. bottom: -5px;
  926. display: inline-block;
  927. width: 0;
  928. height: 0;
  929. border-width: 6px;
  930. border-style: dashed;
  931. border-color: transparent;
  932. border-bottom-width: 0;
  933. border-top-color: #fafafa;
  934. border-top-style: solid;
  935. position: absolute;
  936. left: 50%;
  937. margin-left: -6px;
  938. }
  939. #winxin-menus-box .arrow {
  940. float: right;
  941. margin-top: 9px;
  942. margin-right: 8px;
  943. color: #909399;
  944. }
  945. #winxin-menus-box .menu_form_area {
  946. margin-left: 26px;
  947. border: 1px #dee2e5 solid;
  948. background: #f4f7fa;
  949. flex: 1;
  950. }
  951. #winxin-menus-box .menu_form_inner {
  952. padding: 0 16px 30px 18px;
  953. }
  954. #winxin-menus-box .menu_setting_area .menu_form_tit {
  955. height: 38px;
  956. line-height: 38px;
  957. border-bottom: 1px #e5e8ea solid;
  958. color: #485b6d;
  959. font-size: 14px;
  960. margin-bottom: 29px;
  961. }
  962. #winxin-menus-box .menu_form_tit .delate {
  963. color: #485b6d;
  964. font-size: 13px;
  965. cursor: pointer;
  966. }
  967. #winxin-menus-box .fr {
  968. float: right;
  969. }
  970. #winxin-menus-box .menu_form_inner .menu_form_item {
  971. padding-bottom: 20px;
  972. }
  973. #winxin-menus-box .menu_form_inner .menu_form_item .tit {
  974. font-size: 13px;
  975. color: #485b6d;
  976. margin-right: 15px;
  977. font-weight: normal;
  978. display: block;
  979. float: left;
  980. height: 40px;
  981. line-height: 40px;
  982. width: 68px;
  983. text-align: right;
  984. }
  985. #winxin-menus-box label {
  986. display: inline-block;
  987. max-width: 100%;
  988. margin-bottom: 0;
  989. font-weight: normal;
  990. }
  991. #winxin-menus-box .menu_form_inner .menu_form_item .name {
  992. width: 377px;
  993. height: 38px;
  994. border: 1px #dee2e5 solid;
  995. padding-left: 18px;
  996. font-size: 12px;
  997. color: #c1c9d3;
  998. border-radius: 4px;
  999. color: #485b6d;
  1000. }
  1001. #winxin-menus-box input {
  1002. outline: none;
  1003. }
  1004. #winxin-menus-box input, #winxin-menus-box select, #winxin-menus-box textarea {
  1005. outline: none;
  1006. font-family: "Microsoft YaHei";
  1007. filter: chroma(color=#FFF);
  1008. padding: 0px;
  1009. }
  1010. #winxin-menus-box input, #winxin-menus-box select {
  1011. vertical-align: middle;
  1012. }
  1013. #winxin-menus-box .menu_form_inner .menu_form_item .tips {
  1014. display: block;
  1015. font-size: 13px;
  1016. color: #c0c8d4;
  1017. height: 30px;
  1018. line-height: 30px;
  1019. }
  1020. #winxin-menus-box .menu_form_inner .menu_form_item {
  1021. padding-bottom: 20px;
  1022. }
  1023. #winxin-menus-box .radio_item li {
  1024. float: left;
  1025. margin-right: 25px;
  1026. color: #2c3e50;
  1027. cursor: pointer;
  1028. line-height: 36px;
  1029. height: 36px;
  1030. position: relative;
  1031. }
  1032. #winxin-menus-box .menu_form__nav .radio_item li .type_radio {
  1033. width: 20px;
  1034. height: 20px;
  1035. margin-right: 10px;
  1036. }
  1037. #winxin-menus-box .radio_item li .type_radio {
  1038. appearance: none;
  1039. -moz-appearance: none;
  1040. -webkit-appearance: none;
  1041. }
  1042. #winxin-menus-box input[type=radio] {
  1043. margin: 0 0 0;
  1044. }
  1045. #winxin-menus-box .radio_item li.active .radio_name {
  1046. color: #58a2ec;
  1047. }
  1048. #winxin-menus-box .radio_item li.active .ico_radio {
  1049. background: url('https://images.shengws.com/icos-201906141103.png') no-repeat -171px -348px;
  1050. }
  1051. #winxin-menus-box .menu_form_item .menu_form__con {
  1052. background: #fff;
  1053. border: 1px #dee2e5 solid;
  1054. border-radius: 4px;
  1055. }
  1056. #winxin-menus-box .menu_form__con .active {
  1057. display: block;
  1058. }
  1059. #winxin-menus-box .menu_form_item .menu_form__con .send_message_tit {
  1060. font-size: 13px;
  1061. color: #485b6d;
  1062. padding: 10px 38px;
  1063. border-bottom: 1px #e5e8ea solid;
  1064. }
  1065. #winxin-menus-box .menu_form_item .send_message_tit .send_nav {
  1066. width: 80px;
  1067. display: inline-block;
  1068. }
  1069. #winxin-menus-box .menu_form_item .send_message_tit .ico_size {
  1070. width: 14px;
  1071. height: 18px;
  1072. background: url('https://images.shengws.com/icos-201906141103.png') -716px -310px;
  1073. display: block;
  1074. float: left;
  1075. margin-right: 10px;
  1076. }
  1077. #winxin-menus-box .menu_form__con .send_message_edit {
  1078. padding: 15px;
  1079. width: 100%;
  1080. height: 100%;
  1081. display: block;
  1082. border: 1px #fff solid;
  1083. height: 160px;
  1084. }
  1085. #winxin-menus-box .menu_form_inner .menu_form_item .tips {
  1086. display: block;
  1087. font-size: 13px;
  1088. color: #c0c8d4;
  1089. height: 30px;
  1090. line-height: 30px;
  1091. }
  1092. #winxin-menus-box .menu_form__con .jump_page, #winxin-menus-box .menu_form__con .miniprogram {
  1093. padding: 22px 0 50px 20px;
  1094. }
  1095. #winxin-menus-box .menu_form__con .miniprogram .miniprogram-item {
  1096. margin: 10px 0;
  1097. }
  1098. #winxin-menus-box .menu_form__con .jump_page .tips_size, #winxin-menus-box .menu_form__con .miniprogram .tips_size {
  1099. color: #7b8a97;
  1100. display: block;
  1101. margin-bottom: 14px;
  1102. }
  1103. #winxin-menus-box .menu_form__con .jump_page .address, #winxin-menus-box .menu_form__con .miniprogram .address {
  1104. font-weight: normal;
  1105. margin-right: 10px;
  1106. width: 70px;
  1107. }
  1108. #winxin-menus-box .menu_form__con .jump_page .address_input,#winxin-menus-box .menu_form__con .miniprogram .address_input {
  1109. width: 377px;
  1110. height: 38px;
  1111. border: 1px #dee2e5 solid;
  1112. padding-left: 18px;
  1113. font-size: 12px;
  1114. color: #c1c9d3;
  1115. border-radius: 4px;
  1116. color: #485b6d;
  1117. vertical-align: middle;
  1118. }
  1119. #winxin-menus-box .menu_form__con .mitips {
  1120. display:block;left:84px;position:relative;margin-top:10px;color: #c0c8d4;
  1121. }
  1122. #winxin-menus-box .mediaID-item {
  1123. text-align: center;
  1124. padding: 10px;
  1125. /* cursor: pointer; */
  1126. }
  1127. #winxin-menus-box .mediaID-item .el-icon-news{
  1128. cursor: pointer;
  1129. }
  1130. /* #winxin-menus-box .mediaID-item:hover {
  1131. background:#c0c8d4;
  1132. } */
  1133. #winxin-menus-box .mediaID-item i {
  1134. display: block;
  1135. width: 80px;
  1136. margin: 0 auto;
  1137. }
  1138. #winxin-menus-box .mediaID-item .el-icon-news {
  1139. font-size: 80px;
  1140. }
  1141. #winxin-menus-box .mediaID-item .media-uploader .el-upload {
  1142. border: 1px dashed #d9d9d9 !important;
  1143. border-radius: 6px;
  1144. cursor: pointer;
  1145. position: relative;
  1146. overflow: hidden;
  1147. margin: 10px;
  1148. }
  1149. #winxin-menus-box .mediaID-item .media-uploader .el-upload:hover {
  1150. border-color: #409EFF;
  1151. }
  1152. #winxin-menus-box .mediaID-item .media-uploader-icon {
  1153. font-size: 28px;
  1154. color: #8c939d;
  1155. width: 155px;
  1156. height: 70px;
  1157. line-height: 70px;
  1158. text-align: center;
  1159. }
  1160. #winxin-menus-box .mediaID-item .media {
  1161. width: 155px;
  1162. height: 70px;
  1163. display: block;
  1164. }
  1165. /*.app-container .cell.clearfix .time ul li {*/
  1166. /*float: left;*/
  1167. /*list-style: none;*/
  1168. /*cursor: pointer;*/
  1169. /*padding: 6px 20px;*/
  1170. /*color: #606266;*/
  1171. /*border-radius: 4px;*/
  1172. /*margin: 0 8px 0 0;*/
  1173. /*font-size: 14px;*/
  1174. /*text-align: center;*/
  1175. /*}*/
  1176. </style>