11、ABPZero系列教程之拼多多卖家工具 拼团提醒功能页面实现
上一篇讲解了拼团提醒逻辑功能实现,现在继续实现页面功能。
Core项目
打开AbpZeroTemplate-zh-CN.xml语言文件,在末尾添加如下代码:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Localization\AbpZeroTemplate\AbpZeroTemplate-zh-CN.xml
<text name="Pdd" value="拼多多" /> <text name="Pdd.KaiTuan" value="开团提醒" /> <text name="Pdd.MallExist" value="店铺已存在" />
打开文件AppPermissions.cs,在末尾添加如下代码:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Authorization\AppPermissions.cs
public const string Pages_Pdd = "Pages.Pdd";//权限路径 public const string Pages_Pdd_KaiTuan = "Pages.Pdd.KaiTuan";//权限路径
打开AppAuthorizationProvider.cs文件,在SetPermissions方法最后添加如下代码:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Authorization\AppAuthorizationProvider.cs
var pdd = pages.CreateChildPermission(AppPermissions.Pages_Pdd, L("Pdd")); pdd.CreateChildPermission(AppPermissions.Pages_Pdd_KaiTuan, L("Pdd.KaiTuan"));
Web项目
打开文件PageNames.cs,
文件路径 :D:\abpweb\PddSellerAssistant\PddSellerAssistant.Web\App_Start\Navigation\PageNames.cs
在Command下添加一个常量:
public const string Pdd = "Pdd";
在32行位置添加如下代码:
/// <summary> ///拼多多 /// </summary> public static class Pdd { public const string KaiTuan = "KaiTuan"; //开团提醒 }
打开MpaNavigationProvider.cs文件,在末尾添加菜单,代码如下:
文件路径:D:\abpweb\PddSellerAssistant\PddSellerAssistant.Web\Areas\Mpa\Startup\MpaNavigationProvider.cs
.AddItem(new MenuItemDefinition( PageNames.App.Common.Pdd,//一个常量,控制菜单是否被选中 L("Pdd"),//菜单显示名称,在语言文件中配置 url: "Mpa/Pdd",//菜单路径 icon: "icon-social-dropbox"//菜单图标 ).AddItem(new MenuItemDefinition( PageNames.App.Pdd.KaiTuan,//一个常量,控制菜单是否被选中 L("Pdd.KaiTuan"),//菜单显示名称,在语言文件中配置 url: "Mpa/KaiTuan",//菜单路径 icon: "icon-pie-chart",//菜单图标 requiredPermissionName: AppPermissions.Pages_Pdd_KaiTuan//菜单权限,登录用户所在角色有此权限才会显示出来 )) )
以上就把菜单添加好了,生成解决方案,浏览器打开网站后台,以管理员身份登录,但是并没有发现刚刚添加的菜单,这是因为加了菜单加权限的关系,接以下操作即可。
打开角色菜单,分别修改admin、user角色:
切换到权限选项卡,勾选我们需要显示的菜单,如下:
保存之后,再次登录就可以显示出来菜单了。以下是user角色的菜单:
控制器
我先在Areas\Mpa\Controllers目录下新建Pdd目录,用于保存所有跟拼多多相关的控制器。
添加文件 KaiTuanController.cs 代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Controllers\Pdd\KaiTuanController.cs
/// <summary> /// 开团提醒 /// </summary> public class KaiTuanController : AbpZeroTemplateControllerBase { private readonly IMallAppService _mallAppService; public KaiTuanController(IMallAppService mallAppService) { _mallAppService = mallAppService; } // GET: Mpa/KaiTuan public ActionResult Index() { return View(); } public ActionResult CreateModal() { return PartialView("_CreateModal"); } public ActionResult SharpModal(string title, string link, string img, string timeOut) { ViewBag.title = title; ViewBag.link = link; ViewBag.img = img; ViewBag.timeOut = timeOut; return PartialView("_SharpModal"); } }
视图
接着再创建对应的视图文件
添加文件Index.cshtml,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\Index.cshtml
@using Abp.Web.Mvc.Extensions @using MyCompanyName.AbpZeroTemplate.Web.Navigation @{ ViewBag.CurrentPageName = PageNames.App.Pdd.KaiTuan;//作用就是选中菜单时会高亮 } @section Styles{ <style> .jtable-child-table-container { margin-left: 50px; } </style> <link href="~/metronic/assets/global/plugins/bootstrap-toastr/toastr.css" rel="stylesheet" /> } @section Scripts { @Html.IncludeScript("~/metronic/assets/global/plugins/fuelux/js/spinner.min.js") @Html.IncludeScript("~/metronic/assets/global/plugins/bootstrap-toastr/toastr.min.js") @Html.IncludeScript("~/Areas/Mpa/Views/KaiTuan/Index.js") @Html.IncludeScript("~/Areas/Mpa/Common/Scripts/GolbalHelper.js") @Html.IncludeScript("~/Areas/Mpa/Views/KaiTuan/ui-toastr.js") <!--分享功能代码--> <script type="text/javascript" src="http://v1.jiathis.com/code/jia.js?uid=1575631" charset="utf-8"></script> } <div class="row margin-bottom-5"> <div class="col-xs-6"> <div class="page-head"> <div class="page-title"> <h1> <span>@L("Pdd.KaiTuan")</span> <small></small> </h1> </div> </div> </div> @*这里是添加的按钮代码*@ <div class="col-xs-6 text-right"> <button id="CreateNewMallButton" class="btn btn-primary blue"><i class="fa fa-plus"></i>添加店铺</button> </div> </div> <div class="portlet light margin-bottom-0"> <div class="portlet-title portlet-title-filter"> <div class="inputs inputs-full-width"> <div class="portlet-input"> <div class="row"> <div class="col-xs-6"> <div class="form-group"> <label class="control-label">店铺</label> <select id="mallCombobox" class="form-control"></select> </div> </div> <div class="col-xs-6"> <div class="form-group"> <label class="control-label">提醒间隔(分钟)</label> <div id="spinner3"> <div class="input-group" style="width: 150px;"> <input type="text" id="interval" class="spinner-input form-control" maxlength="3" readonly> <div class="spinner-buttons input-group-btn"> <button type="button" class="btn spinner-up default"> <i class="fa fa-angle-up"></i> </button> <button type="button" class="btn spinner-down default"> <i class="fa fa-angle-down"></i> </button> </div> </div> </div> </div> </div> </div> <div class="row"> <div class="col-sm-12 text-right"> <button id="LoginPddButton" class="btn red"><i class="fa fa-user"></i> 登录拼多多</button> <button id="StartButton" class="btn blue"><i class="fa fa-play"></i> 开始监控</button> <button id="StopButton" class="btn purple"><i class="fa fa-stop"></i> 停止监控</button> </div> </div> </div> </div> </div> <div class="portlet-body"> <div> <div id="Table"></div> </div> </div> </div> <script id="tm" type="template"> <button type="button" class="sharp btn red" data-link="{link}" data-title="{title}" data-img="{img}" data-timeOut="{timeOut}">分享到...</button> </script>
添加对应的JS文件Index.js,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\Index.js
var _$kaituanTable = $('#Table'); var _mallService = abp.services.app.mall; var _productService = abp.services.app.product; var timer;//调用setInterval,返回的数字,用于停止时钟 var mallId;//记录店铺id (function () { $(function () { /** 添加店铺模态框 */ var _createModal = new app.ModalManager({ viewUrl: abp.appPath + 'Mpa/KaiTuan/CreateModal',//加载视图 scriptUrl: abp.appPath + 'Areas/Mpa/Views/KaiTuan/_CreateModal.js',//加载对应js modalClass: 'CreateMallModal' }); /** 分享模态框 */ var _sharpModal = new app.ModalManager({ viewUrl: abp.appPath + 'Mpa/KaiTuan/SharpModal', scriptUrl: abp.appPath + 'Areas/Mpa/Views/KaiTuan/_SharpModal.js', modalClass: 'SharpModal' }); _$kaituanTable.jtable({ title: app.localize('Pdd.KaiTuan'), paging: true, //启用分页 sorting: true, //启用排序 pageSize: 500, multiSorting: true, //启用多列排序 defaultSorting: 'goodId ASC', recordsLoaded: function (e, data) { var count = data.serverResponse.TotalRecordCount; if (count > 0) { SoundHelper.PlaySound(); } }, actions: { listAction: { method: _productService.getKaiTuanProductsAsync, } }, fields: { id: { key: true, list: false }, kaituan: { title: '操作', width: '5%', sorting: false, edit: false, create: false, display: function (product) { //创建一个将用于打开子表的图像 var $img = $('<img src="/metronic/assets/admin/layout4/img/hor-menu-red-arrow.png" title="打开开团详细列表" />'); //用户单击图像时打开子表 $img.click(function () { $('#Table').jtable('openChildTable', $img.closest('tr'), { title: '最新开团列表(最后更新时间为:' + DateHelper.CurentTime() + ")", paging: true, //启用分页 sorting: true, //启用排序 recordsLoaded: function (e, data) { console.info(data); var count = data.serverResponse.TotalRecordCount; toastr["info"]("当前开团人数共有(" + count + ")人", "提示"); }, actions: { listAction: { method: _productService.getAllKaiTuansByGoodId } }, fields: { action: { title: '', width: '15%', display: function (kaituan) { //操作按钮 var a = $("#tm").html(); a = a.replace(new RegExp(/(\{title\})/gm), product.record.name); a = a.replace(new RegExp(/(\{link\})/gm), "http://mobile.yangkeduo.com/group500.html?group_order_id=" + kaituan.record.kaiTuanOrderNum + "&cid=nogroup_expire_mms_" + mallId); a = a.replace(new RegExp(/(\{img\})/gm), product.record.img); a = a.replace(new RegExp(/(\{timeOut\})/gm), kaituan.record.timeLeft); return a; } }, id: { title: '宝贝ID', //defaultValue: product.record.goodId, width: '10%', sorting: false }, nickName: { title: '用户昵称', width: '20%', sorting: false }, sku: { title: 'SKU', width: '20%', sorting: false }, orderNum: { title: '订单编号', width: '20%', sorting: false }, timeLeft: { title: '剩余时间', width: '20%', }, kaiTuanOrderNum: { title: '开团单号', width: '20%', sorting: false } } }, function (data) { //加载子表数据 data.childTable.jtable('load', { goodId: product.record.goodId, mallId: mallId, username: username }); }); }); //返回图像显示在行上 return $img; } }, goodId: { title: "宝贝ID", width: '10%', display: function (product) { var img = "<img src='" + product.record.img + "' style='width: 64px; height: 64px;'/>"; var a = "<a href='http://mobile.yangkeduo.com/goods.html?goods_id=" + product.record.goodId + "' target='_blank'>" + product.record.goodId + "</a>"; return a + img; } }, name: { title: "宝贝名称", width: '70%' }, kaiTuanCount: { title: "开团人数", width: '20%' }, } }); //页面加载完执行 getMalls(); $('#spinner3').spinner({ value: 60, min: 30, max: 1000 }); UIToastr.init(); //添加店铺点击事件 $('#CreateNewMallButton').click(function () { _createModal.open(); }); //店铺成功保存后事件注册 abp.event.on('app.createMallModalSaved', function () { //getCategories(true); getMalls(); }); $("#Table").delegate(".sharp", "click", function () { var t = $(this); _sharpModal.open({ title: $(t).attr("data-title"), link: $(t).attr("data-link"), img: $(t).attr("data-img"), timeOut: $(t).attr("data-timeOut") }); }); //开始监控点击事件 $("#StartButton").click(function () { mallId = $('#mallCombobox').val(); if (mallId == null) { abp.message.warn('请至少添加一个店铺!', '警告'); return; } $(this).attr("Disabled", "Disabled"); $(this).text("正在监控中"); getkaituans(); timer = window.setInterval("getkaituans(false)", 1000 * 60 * $("#interval").val()); }); //停止监控点击事件 $("#StopButton").click(function () { window.clearInterval(timer); $("#StartButton").removeAttr("Disabled"); $("#StartButton").html("<i class='fa fa-play'></i> 开始监控"); }); }); })(); //获取列表 function getkaituans(reload) { if (reload) { _$kaituanTable.jtable('reload'); } else { $(_$kaituanTable.find(".jtable-title-text")[0]).html(app.localize('Pdd.KaiTuan') + "(最后更新时间为:" + DateHelper.CurentTime() + ")"); _$kaituanTable.jtable('load', { mallId: mallId, interval: $("#interval").val() }); } } function getMalls() { _mallService.getMalls().done(function (result) { var malls = result.items; console.log(result); $("#mallCombobox").html(""); for (var i = 0; i < malls.length; i++) { console.info(1); $("#mallCombobox").append("<option value='" + malls[i].mallId + "'>" + malls[i].mallId + "【" + malls[i].name + "】</option>"); } }); }
添加_CreateModal.cshtml文件,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\_CreateModal.cshtml
@using MyCompanyName.AbpZeroTemplate.Web.Areas.Mpa.Models.Common.Modals @Html.Partial("~/Areas/Mpa/Views/Common/Modals/_ModalHeader.cshtml", new ModalHeaderViewModel("添加店铺")) <div class="modal-body"> <form name="MallForm"> <div class="form-group form-md-line-input form-md-floating-label"> <input class="form-control" type="text" name="mallId" required> <label>店铺ID</label> </div> </form> </div> @Html.Partial("~/Areas/Mpa/Views/Common/Modals/_ModalFooterWithSaveAndCancel.cshtml")
添加_CreateModal.js文件,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\_CreateModal.js
(function ($) { app.modals.CreateMallModal = function () { var _mallService = abp.services.app.mall; var _$mallForm = null; var _modalManager; this.init = function (modalManager) { _modalManager = modalManager; //取出Form表单 _$mallForm = _modalManager.getModal().find('form[name=MallForm]'); }; this.save = function () { //验证不通过返回 if (!_$mallForm.valid()) { return; } //序列化参数 var mallid = _$mallForm.serializeFormToObject(); _modalManager.setBusy(true); _mallService.createByMallId( mallid ).done(function () { abp.notify.info(app.localize('SavedSuccessfully')); _modalManager.close(); abp.event.trigger('app.createMallModalSaved'); }).always(function () { _modalManager.setBusy(false); }); }; }; })(jQuery);
添加_SharpModal.cshtml文件,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\_SharpModal.cshtml
@using PddSellerAssistant.Web.Areas.Mpa.Models.Common.Modals @Html.Partial("~/Areas/Mpa/Views/Common/Modals/_ModalHeader.cshtml", new ModalHeaderViewModel("分享拼团连接")) <div class="modal-body"> <ul class="media-list"> <li class="media"> <a class="pull-left" href="javascript:;"> <img class="media-object" src="@ViewBag.img" alt="64x64" style="width: 64px; height: 64px;"> </a> <div class="media-body"> <h4 class="media-heading">还有 @(ViewBag.timeOut) 小时后结束</h4> <p> @ViewBag.title </p> </div> </li> </ul> <!-- JiaThis Button BEGIN --> <div class="jiathis_style_32x32"> <a class="jiathis_button_qzone"></a> <a class="jiathis_button_tsina"></a> <a class="jiathis_button_tqq"></a> <a class="jiathis_button_weixin"></a> <a class="jiathis_button_renren"></a> <a href="http://www.jiathis.com/share?uid=1575631" class="jiathis jiathis_txt jtico jtico_jiathis" target="_blank"></a> </div> <script type="text/javascript"> var jiathis_config = { data_track_clickback: 'true', title:'@ViewBag.title', url:'@ViewBag.link' }; </script> <script type="text/javascript" src="http://v3.jiathis.com/code/jia.js?uid=1575631" charset="utf-8"></script> <!-- JiaThis Button END --> </div> @Html.Partial("~/Areas/Mpa/Views/Common/Modals/_ModalFooterWithCancel.cshtml")
发现最后一行代码报错,继续按路径添加_ModalFooterWithCancel视图即可,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\Common\Modals\_ModalFooterWithCancel.cshtml
<div class="modal-footer"> <button type="button" class="btn default close-button" data-dismiss="modal">@L("Cancel")</button> </div>
添加_SharpModal.js文件,暂无代码,备用
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\_SharpModal.js
再添加ui-toastr.js文件,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Views\KaiTuan\ui-toastr.js
var UIToastr = function () { return { //模块初始化 init: function () { toastr.options = { "closeButton": true, "debug": false, "positionClass": "toast-bottom-right", "onclick": null, "showDuration": "1000", "hideDuration": "1000", "timeOut": "2000", "extendedTimeOut": "1000", "showEasing": "swing", "hideEasing": "linear", "showMethod": "fadeIn", "hideMethod": "fadeOut" }; $('#StartButton').click(function () { toastr["info"]("开始监控", "提示"); }); } }; }();
添加GolbalHelper.js文件,代码如下:
文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Areas\Mpa\Common\Scripts\GolbalHelper.js
var DateHelper= { //获取当前时间 CurentTime:function() { var now = new Date(); var year = now.getFullYear(); //年 var month = now.getMonth() + 1; //月 var day = now.getDate(); //日 var hh = now.getHours(); //时 var mm = now.getMinutes(); //分 var se = now.getSeconds(); //秒 var clock = year + "-"; if (month < 10) clock += "0"; clock += month + "-"; if (day < 10) clock += "0"; clock += day + " "; if (hh < 10) clock += "0"; clock += hh + ":"; if (mm < 10) clock += '0'; clock += mm; clock +=":"+ se; return (clock); }, //取当前日期 GetDate:function() { var now = new Date(); var year = now.getFullYear(); //年 var month = now.getMonth() + 1; //月 var day = now.getDate(); //日 return year + "-" + month + "-" + day; } } var SoundHelper= { PlaySound:function() { var borswer = window.navigator.userAgent.toLowerCase(); if ( borswer.indexOf( "ie" ) >= 0 ) { //IE内核浏览器 var strEmbed = '<embed name="embedPlay" src="/Common/Sound/ding.mp3" autostart="true" hidden="true" loop="false"></embed>'; if ( $( "body" ).find( "embed" ).length <= 0 ) $( "body" ).append( strEmbed ); var embed = document.embedPlay; //浏览器不支持 audion,则使用 embed 播放 embed.volume = 100; //embed.play(); } else { //非IE内核浏览器 var strAudio = "<audio id='audioPlay' src='/Common/Sound/ding.mp3' hidden='true'>"; if ( $( "body" ).find( "audio" ).length <= 0 ) $( "body" ).append( strAudio ); var audio = document.getElementById( "audioPlay" ); //浏览器支持 audion audio.play(); } } } var jiathis_config = { data_track_clickback: true, summary: "", ralateuid: { "tsina": "2214346710" }, shortUrl: false, hideMore: false } var SharpHelper= { SetShare:function(title, url) { jiathis_config.title = title; jiathis_config.url = url; } }
现在,重新生成解决方案,登录系统访问开团提醒菜单,F12启动调试面板,可以看到一堆404,这是因为项目中还使用了其它js插件,不用担心,相关文件已经打包在以下连接:
相关插件下载:https://files.cnblogs.com/files/shensigzs/plugins.zip
下载后解压,存放到metronic目录下,如下图所示:
声音文件下载:https://files.cnblogs.com/files/shensigzs/Sound.zip
下载后解压,存入到Common目录下,如下图所示:
最终功能效果如下:
按照http://www.cnblogs.com/shensigzs/p/8302521.html这篇文件末尾提到找店铺编号的方式,找一个有拼团的店铺,添加店铺中需要用到。
最后,附上几张运行之后的效果图,下一篇将介绍框架实现登录拼多多功能,登录之后再去监控店铺就可以获取到SKU和订单号(只限自己的店铺有效)。