edit.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <?php
  2. use yii\helpers\ArrayHelper;
  3. use yii\widgets\ActiveForm;
  4. use common\helpers\AddonHelper;
  5. use common\helpers\Url;
  6. use addons\Wechat\common\enums\MenuClientPlatformTypeEnum;
  7. use addons\Wechat\common\enums\MenuTypeEnum;
  8. $this->title = $model->isNewRecord ? '创建' : '编辑';
  9. $this->params['breadcrumbs'][] = ['label' => MenuTypeEnum::getValue($type), 'url' => ['index', 'type' => $type]];
  10. $this->params['breadcrumbs'][] = $this->title;
  11. ?>
  12. <?= AddonHelper::jsFile('js/sortable.min.js')?>
  13. <?= AddonHelper::jsFile('js/vuedraggable.min.js')?>
  14. <style>
  15. .menuView .btn-white {
  16. font-size: 12px;
  17. }
  18. </style>
  19. <div id="vueArea" class="wrapper-content animated fadeInRight">
  20. <?php $form = ActiveForm::begin(); ?>
  21. <div class="row">
  22. <!-- 菜单编辑模式 -->
  23. <div class="col-sm-3" style="width: 340px;max-width: 340px;">
  24. <div class="ibox float-e-margins" style="box-shadow: 3px 3px 3px #ccc;">
  25. <div class="phone-header">
  26. <span class="ng-binding">自定义菜单</span>
  27. </div>
  28. <div class="flex-row flex-vDirection menuView">
  29. <div class="flex-col"></div>
  30. <div>
  31. <draggable v-model="list" :options="{group:'mainMenu'}" class="flex-row phone-foot">
  32. <div v-for="(item,index) in list" class="flex-col custommenu">
  33. <div class="custommenu_sub_container">
  34. <draggable v-model="item.sub_button" :options="{group:'subMenu' + index}">
  35. <div v-for="sub in item.sub_button">
  36. <a class="btn btn-block btn-white" :class="{active:crtItem === sub}" @click="crtItem = sub">{{sub.name}}</a>
  37. </div>
  38. </draggable>
  39. <div v-show="item.sub_button.length < maxSubItemCount"><a class="btn btn-block btn-white" @click="addSubItem(item.sub_button)"><i class="icon ion-plus"></i></a></div>
  40. </div>
  41. <a class="btn btn-block btn-white" :class="{active:crtItem === item}" @click="crtItem = item">{{item.name}}</a>
  42. </div>
  43. <div class="flex-col" v-show="list.length < maxItemCount"><a class="btn btn-block btn-white" @click="addItem"><i class="icon ion-plus"></i> 添加菜单</a></div>
  44. </draggable>
  45. </div>
  46. </div>
  47. </div>
  48. <div class="form-group farPaddingJustV">
  49. <div class="hAlignCenter">
  50. <?php if ($type == 1 || (empty($model['id']) && $type == 2)){ ?>
  51. <a class="btn btn-primary" @click="submitForm">保存</a>
  52. <?php } ?>
  53. <a class="btn btn-white" @click="back">返回</a>
  54. </div>
  55. </div>
  56. </div>
  57. <div class="col-sm-9">
  58. <div class="row">
  59. <div class="col-sm-7">
  60. <div class="box">
  61. <div class="box-header with-border">
  62. <h3 class="box-title">菜单标题</h3>
  63. </div>
  64. <div class="box-body">
  65. <div class="col-lg-12">
  66. <?= $form->field($model, 'title')->textInput()->hint('给菜单起个名字吧!以便查找')->label(false) ?>
  67. <?php if ($type == MenuTypeEnum::INDIVIDUATION){ ?>
  68. <div class="row">
  69. <div class="col-sm-6">
  70. <?= $form->field($model, 'client_platform_type')->dropDownList(MenuClientPlatformTypeEnum::getMap(),[
  71. 'disabled' => $model->isNewRecord ? false : true
  72. ])->label('系统') ?>
  73. </div>
  74. <div class="col-sm-6">
  75. <?= $form->field($model, 'tag_id')->dropDownList(ArrayHelper::map($fansTags,'id','name'),[
  76. 'prompt' => '不限',
  77. 'disabled' => $model->isNewRecord ? false : true
  78. ])->label('标签') ?>
  79. </div>
  80. </div>
  81. <?php } ?>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. <!--
  87. added by wzq 自定义菜单操作区
  88. -->
  89. <div class="col-sm-7" v-if="crtItem">
  90. <div class="box">
  91. <div class="box-header with-border">
  92. <h3 class="box-title">菜单设置</h3>
  93. <a @click="deleteCrtItem" class="float-right" style="font-size: 14px">删除菜单</a>
  94. </div>
  95. <div class="box-content clearfix normalPaddingJustV">
  96. <div class="col-sm-12 p-lg" style="padding-top: 0">
  97. <div class="form-group">
  98. <label class="control-label">菜单名称</label>
  99. <input class="form-control" name="CustomMenu[title]" v-model="crtItem.name" aria-required="true" type="text">
  100. <div class="help-block"></div>
  101. </div>
  102. <div class="form-group" v-show="!hasSubItem(crtItem)">
  103. <label class="control-label">菜单动作</label>
  104. <div class="row">
  105. <div class="col-sm-12">
  106. <?php foreach ($menuTypes as $key => $menuType){ ?>
  107. <label>
  108. <input type="radio" value="<?= $key ?>" name="ipt" v-model="crtItem.type"> <i></i> <?= $menuType['name'] ?>
  109. </label>
  110. <?php } ?>
  111. </div>
  112. </div>
  113. </div>
  114. <div class="form-group" v-show="!hasSubItem(crtItem) && needContent(crtItem)">
  115. <hr>
  116. <input class="form-control" name="value" value="" aria-required="true" type="text" v-model="crtItem.content">
  117. </div>
  118. <!-- 小程序 -->
  119. <div class="form-group" v-show="!hasSubItem(crtItem) && needMiniprogram(crtItem)">
  120. <hr>
  121. <div class="form-group">
  122. <label class="col-sm-2 control-label">APPID</label>
  123. <div class="col-sm-10">
  124. <input class="form-control" name="value" placeholder="请确保小程序与公众号已关联,填写小程序的APPID" value="" aria-required="true" type="text" v-model="crtItem.appid">
  125. <span class="help-block"><a href="http://weixiao.qq.com/notice/view?mid=0&cid=2&id=274" target="_blank">如何获取?</a></span>
  126. </div>
  127. </div>
  128. <div class="form-group">
  129. <label class="col-sm-2 control-label">页面</label>
  130. <div class="col-sm-10">
  131. <input class="form-control" name="value" placeholder="请填写跳转页面的小程序访问路径" value="" aria-required="true" type="text" v-model="crtItem.pagepath">
  132. <span class="help-block"><a href="http://weixiao.qq.com/notice/view?mid=0&cid=2&id=275" target="_blank">填写指引</a></span>
  133. </div>
  134. </div>
  135. <div class="form-group">
  136. <label class="col-sm-2 control-label">备用网页</label>
  137. <div class="col-sm-10">
  138. <input class="form-control" name="value" placeholder="写入要跳转的链接" value="" aria-required="true" type="text" v-model="crtItem.url">
  139. <span class="help-block">旧版微信客户端不支持小程序,用户点击菜单时会打开该网页</span>
  140. </div>
  141. </div>
  142. </div>
  143. </div>
  144. </div>
  145. </div>
  146. </div>
  147. </div>
  148. </div>
  149. </div>
  150. <?php ActiveForm::end(); ?>
  151. </div>
  152. <script>
  153. $(function(){
  154. // 兼容老IE
  155. document.body.ondrop = function (event) {
  156. event = event || window.event;
  157. if (event.preventDefault) {
  158. event.preventDefault();
  159. event.stopPropagation();
  160. } else {
  161. event.returnValue = false;
  162. event.cancelBubble = true;
  163. }
  164. };
  165. var list = '<?= json_encode($model->menu_data ?? []) ?>';
  166. list = JSON.parse(list);
  167. for (var i=0; i<list.length; i++){
  168. var item = list[i];
  169. if(!item.sub_button) item.sub_button = [];
  170. if(item.type == 'click')
  171. {
  172. item.content = item.key
  173. }
  174. if(item.type == 'view')
  175. {
  176. item.content = item.url
  177. }
  178. // 子菜单判断
  179. for (var j = 0; j < item.sub_button.length; j++){
  180. var subButton = item.sub_button[j];
  181. if(subButton.type == 'click')
  182. {
  183. subButton.content = subButton.key
  184. }
  185. if(subButton.type == 'view')
  186. {
  187. subButton.content = subButton.url
  188. }
  189. }
  190. }
  191. // console.log(list);
  192. var vueArea = new Vue({
  193. data:{
  194. list: list ? list : [],
  195. maxItemCount: 3,
  196. maxSubItemCount: 5,
  197. crtItem: null,
  198. isSortMode: false
  199. },
  200. methods: {
  201. addItem: function(){
  202. var newOne = {name: '菜单名称', sub_button:[], type:'click',content:''};
  203. this.list.push(newOne);
  204. this.crtItem = newOne;
  205. },
  206. addSubItem: function(subList){
  207. var newOne = {name:'子菜单名称', type:'click',content:''};
  208. subList.push(newOne);
  209. this.crtItem = newOne;
  210. },
  211. deleteCrtItem: function(){
  212. var self = this;
  213. function doDelete(){
  214. var itemIndex;
  215. for (var i = 0; i < self.list.length; i++) {
  216. var item = self.list[i];
  217. if(item == self.crtItem)
  218. {
  219. self.list.splice(i, 1);
  220. self.crtItem = null;
  221. return;
  222. }
  223. itemIndex = item.sub_button.indexOf(self.crtItem);
  224. if (itemIndex >= 0) {
  225. item.sub_button.splice(itemIndex, 1);
  226. self.crtItem = null;
  227. return;
  228. }
  229. }
  230. }
  231. if(self.crtItem.sub_button){
  232. swal("您确定要删除这个菜单吗?", {
  233. buttons: {
  234. cancel: "取消",
  235. defeat: '确定',
  236. },
  237. title: "您确定要删除这个菜单吗?",
  238. text: "删除后将无法恢复,请谨慎操作!",
  239. }).then(function (value) {
  240. switch (value) {
  241. case "defeat":
  242. doDelete();
  243. break;
  244. default:
  245. }
  246. });
  247. }else{
  248. doDelete();
  249. }
  250. },
  251. submitForm: function(){
  252. // 检查子菜单类别是否都填了
  253. var self = this;
  254. function checkValidate(item){
  255. var needContent = self.needContent(item);
  256. if(needContent && !item.content)
  257. {
  258. rfAffirm('请填写"'+item.name+'"的' + needContent);
  259. self.crtItem = item;
  260. return false;
  261. }
  262. if(item.type == 'view' && !new RegExp('^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|top|cn|vip|xyz|wang|store|ink|xin|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$').test(item.content))
  263. {
  264. rfAffirm('您填写的链接地址格式不正确');
  265. self.crtItem = item;
  266. return false;
  267. }
  268. // 小程序判断
  269. if(item.type == 'miniprogram')
  270. {
  271. if(!item.appid)
  272. {
  273. rfAffirm('请填写appid');
  274. self.crtItem = item;
  275. return false;
  276. }
  277. if(!item.pagepath)
  278. {
  279. rfAffirm('请填写页面');
  280. self.crtItem = item;
  281. return false;
  282. }
  283. if(!item.url)
  284. {
  285. rfAffirm('请填写备用网页');
  286. self.crtItem = item;
  287. return false;
  288. }
  289. }
  290. return true;
  291. }
  292. for(var i = 0; i < this.list.length; i++) {
  293. var item = this.list[i];
  294. if(this.hasSubItem(item))
  295. {
  296. for(var j = 0; j < item.sub_button.length; j++)
  297. {
  298. var subItem = item.sub_button[j];
  299. if(!checkValidate(subItem))
  300. {
  301. return;
  302. }
  303. }
  304. }
  305. else
  306. {
  307. if(!checkValidate(item))
  308. {
  309. return;
  310. }
  311. }
  312. }
  313. var prevent = true;
  314. if(prevent){
  315. prevent = false;
  316. var id = '<?= $model->id ?>';
  317. var type = '<?= $type ?>';
  318. var title = $('#menu-title').val();
  319. var sex = $('#menu-sex').val();
  320. var language = $('#menu-language').val();
  321. var province = $('#menu-province').val();
  322. var city = $('#menu-city').val();
  323. var client_platform_type = $('#menu-client_platform_type').val();
  324. var tag_id = $('#menu-tag_id').val();
  325. $.ajax({
  326. type:"post",
  327. url:"<?= Url::to(['edit'])?>",
  328. dataType: "json",
  329. data: {id:id,
  330. list:this.list,
  331. type:type,
  332. title:title,
  333. city:city,
  334. client_platform_type:client_platform_type,
  335. province:province,
  336. tag_id:tag_id,
  337. sex:sex,
  338. language:language},
  339. success: function(data){
  340. prevent = true;
  341. if(data.code == 200) {
  342. window.location = '<?= Url::to(['index','type' => $type]) ?>';
  343. }else{
  344. rfAffirm(data.message);
  345. }
  346. }
  347. });
  348. }
  349. },
  350. back: function(){
  351. window.history.go(-1);
  352. },
  353. province: function(){
  354. var val = $('#menu-province').val();
  355. $.ajax({
  356. type:"GET",
  357. url:"<?= Url::to(['menu-provinces/index'])?>",
  358. dataType: "json",
  359. data: {title:val},
  360. success: function(data){
  361. $("#menu-city").html(data.data);
  362. }
  363. });
  364. },
  365. hasSubItem: function(item){
  366. return item.sub_button && item.sub_button.length > 0;
  367. },
  368. needContent: function(item){
  369. var dic = {click: '触发关键字', view: '跳转链接'};
  370. return dic[item.type];
  371. },
  372. needMiniprogram: function(item){
  373. var dic = {miniprogram: '关联小程序'};
  374. return dic[item.type];
  375. },
  376. }
  377. }).$mount('#vueArea');
  378. });
  379. </script>
粤ICP备19079148号