C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能

感谢广大博问博友的帮助和共同研究讨论,终于实现了一个无缓存无刷新仿购物车的小功能:

一、实现效果简述:

有一种列表,是由双层Repeater嵌套,第一层用来显示类别,第二层用来显示类别下的商品数据,

其显示效果如下:

且每一个菜名都可以单独点开进行配餐选择,效果如下:

现在要在页面无刷新不计入缓存(在最后提交选餐数据的时候计入缓存,类似购物车,但这里不希望页面刷新)

的情况下将所选择的商品名称和数量无重复的添加到一个叫做“餐饮盒”的容器里:

最终实现结果:

在修改订购数量的时候只修改餐饮盒中该商品的总价格,商品名称不能重复,并重新计算所有商品的总价格:

二、实现代码:

1.前台界面由2个Repeater组成:

                        <asp:Repeater ID="rptFoodKindList" runat="server" OnItemDataBound="rptFoodKindList_OnItemDataBound">
                            <ItemTemplate>
                                <div class="Cp_fl">
                                    <%#Eval("CategoryTwoName") %><asp:HiddenField ID="hidCategoryTwoID" Value='<%#Eval("CategoryTwoID") %>'
                                        runat="server" />
                                </div>
                                <asp:Repeater ID="rptFoodList" runat="server" OnItemDataBound="rptFoodList_OnItemDataBound">
                                    <ItemTemplate>
                                        <div class="CP_con">
                                            <ul>
                                                <li class="CP_xh"><span id="spIndex" runat="server"></span></li>
                                                <li class="CP_name"><span id="spProName">
                                                    <%#Eval("ProductName") %></span></li>
                                                <li class="CP_jg"><%#decimal.Parse(Eval("Price").ToString()).ToString("f2") %></li>
                                                <li class="CP_fs">(已选<span id="spCount">0</span>份)<asp:HiddenField ID="hidProductID"
                                                    runat="server" Value='<%#Eval("ProductID") %>' />
                                                </li>
                                            </ul>
                                            <div class="CP_mx" style="display: none;">
                                                <div class="img">
                                                    <img src="../ProductImg/160x120/201403011616.png" />
                                                    <a href="#">点击查看大图</a>
                                                </div>
                                                <div class="right">
                                                    <div class="R_name">
                                                        菜名:<%#Eval("ProductName") %>
                                                    </div>
                                                    <div class="R_dj">
                                                        单价:<span id="spPrice" runat="server"><%#decimal.Parse(Eval("Price").ToString()).ToString("f2") %></span>
                                                        元/份</div>
                                                    <div class="R_numer">
                                                        <span>订购数量:</span><a id="aRed" class="Redu1" runat="server"></a><input id="txtBuyNum"
                                                            type="text" value="1" runat="server" /><a class="Add1" id="aAdd" runat="server"></a></div>
                                                    <div class="R_but">
                                                        <a class="Add_CD" id="aAddTo" runat="server">加到我的餐饮盒</a><a class="Redu_CD">取消</a></div>
                                                </div>
                                            </div>
                                        </div>
                                    </ItemTemplate>
                                </asp:Repeater>
                            </ItemTemplate>
                        </asp:Repeater>
<asp:HiddenField ID="hidProInfo" runat="server" />

2.主要Jquery代码:

(1)控制商品详情的显示和隐藏:

         $(function(){
            var n = 0; //商品详情和订购选择区域默认隐藏
            $(".CP_con").each(function () {
                var t = $(this);//获取当前的行
                t.find("ul").click(function () {
                    if (n == 0) {//如果隐藏则显示
                        t.find(".CP_mx").show();
                        n = 1; //设置为显示
                    }
                    else {//如果显示则隐藏
                        t.find(".CP_mx").hide();
                        n = 0;
                    }
                });

                var $cancel = $(".Redu_CD");//取消
                var $CP_mx = $(".CP_mx");
                t.find($cancel).click(function () {
                    t.find($CP_mx).hide();
                });
//鼠标放置和离开时当前行的样式控制,这里是淡蓝色; $(".CP_con>ul").mouseover(function () { $(this).attr("style", "background-color:#F5F9FD"); }).mouseout(function () { $(this).removeAttr("style"); }); }); }); })

(2)修改商品订购数量以及更新餐饮盒情况:

        //修改订购产品数量,type=1:添加;type=2:减少
        function UpdateProductNum(btn, type, price) {
            var text = $(btn).parent().find(":text");

            if (type == 1) {
                text.val(parseInt(text.val()) + 1);
                if (parseInt(text.val()) <= 0)
                    text.val("1");
            }
            else {
                text.val(parseInt(text.val()) - 1);
                if (parseInt(text.val()) <= 0)
                    text.val("1");
            }
        }

        //添加到我的餐饮盒,修改其品数量,商品详情变动和价格计算
        function AddProductNum(btn, price, proid, index) {
            var proAmount = 0;//每一种商品的总价格
            var text = $(btn).parent().parent().find(":text");//查找修改数量的文本框
            var count = $(".CP_fs>span")[index];//获取当前商品已选择份数控件
            var proname = $(".CP_name>span")[index];//获取当前商品名称控件
            var spCount = $(btn).parent().parent().parent().parent().find(count);
            var spProName = $(btn).parent().parent().parent().parent().find(proname);

            spCount.html(text.val());//将当前份数设置为文本框中选择的份数
            var curAmount = price * text.val();//计算当前总订购商品的价格

            if ($("#ul" + proid).length > 0) {//如果已经存在该商品
                $("#ul" + proid).attr("class", proid + "|" + text.val());//样式妙用,class用来存放商品id和订购数量,便于以下隐藏域使用
                $("#ul" + proid).attr("title", "单价:¥"+price+".00;数量:"+text.val()+"份");//设置提示信息
                $("#ul" + proid).html("<li class='li_l' >" + spProName.html() + "</li><li class='li_r'>¥" + curAmount + ".00</li>");//修改该商品的总价格信息
            }
            else {//不存在则添加一行
                $("#divFoodBox").html($("#divFoodBox").html() + "<ul id='ul" + proid + "' class='" + proid + "|" + text.val() + "' title='单价:¥"+price+".00;数量:"+text.val()+"份''><li class='li_l' >" + spProName.html() + "</li><li class='li_r'>¥" + curAmount + ".00</li><ul>");
            }

            $("#divFoodBox .li_r").each(function () {//循环查找显示总价格的li控件
                proAmount += parseFloat($(this).html().replace("¥", ""));//计算当前行商品总价格并追加到临时变量中;
            });

            var arrClass="";//初始化样式字符串
            $("#divFoodBox>ul").each(function () {
                arrClass+=$(this).attr("class")+",";
            });

            $("#hidProInfo").val(arrClass);
            $("#liSum").html("¥" + proAmount+ ".00");//更新所有订购商品总价格
        }

3.后台第一个Reapeter绑定时追加前台js方法:

        /// <summary>
        /// 菜谱分类列表绑定事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void rptFoodKindList_OnItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                Repeater rptFoodList = e.Item.FindControl("rptFoodList") as Repeater;//第一个Reapeter的每行绑定时查找第二层里面的Reapeter
                HiddenField hidCategoryTwoID = e.Item.FindControl("hidCategoryTwoID") as HiddenField;
                rptFoodList.DataSource = HSSM_Public_DB.PblicQuery("ProductID,ProductName,Price", "Product", "CategoryTwoID = " + hidCategoryTwoID.Value);
                rptFoodList.DataBind();//绑定里面的Reapeter

                //循环里面Reapeter的项,并给相应控件追加前台js方法
                foreach (RepeaterItem item in rptFoodList.Items)
                {
                    HtmlInputText txtBuyNum = item.FindControl("txtBuyNum") as HtmlInputText;//查找订购数量输入框
                    HtmlGenericControl spPrice = item.FindControl("spPrice") as HtmlGenericControl;//查找显示价格的控件
                    HtmlGenericControl spIndex = item.FindControl("spIndex") as HtmlGenericControl;//查找显示该商品所属分类的序号控件
                    string Price = spPrice.InnerText.Replace("", "");
                    spIndex.InnerText = item.ItemIndex + 1 + ".";//设置序号

                    HtmlAnchor aAdd = item.FindControl("aAdd") as HtmlAnchor;//添加订购数量的控件
                    HtmlAnchor aRed = item.FindControl("aRed") as HtmlAnchor;//减少订购数量的控件
                    HtmlAnchor aAddTo = item.FindControl("aAddTo") as HtmlAnchor;//添加到我的餐饮盒的控件
                    HiddenField hidProductID = item.FindControl("hidProductID") as HiddenField;//存放商品id的隐藏域                   aAdd.Attributes.Add("onclick", string.Format("UpdateProductNum(this,1,{0})", Price));//追加添加订购数量的js方法
                    aRed.Attributes.Add("onclick", string.Format("UpdateProductNum(this,2,{0})", Price));//追加减少订购数量的js方法
                    aAddTo.Attributes.Add("onclick", string.Format("AddProductNum(this,{0},{1},{2})", Price, hidProductID.Value, proIndex));//追加更新我的餐饮盒详情的js方法

                    proIndex++;//每绑定一行商品让这个全局变量值自加1,用于前台js调用find方法寻找当前商品已选择份数和商品名称时使用,
                }
            }
        }

        /// <summary>
        /// 产品记录索引(全局变量)
        /// </summary>
        public int proIndex = 0;

4.最后填写好订购人信息后计入缓存:

        /// <summary>
        /// 设置Cookie
        /// </summary>
        protected void SetFoodList()
        {
            string ProInfos = hidProInfo.Value.Substring(0, hidProInfo.Value.Length - 1);//获取最后所有的商品的id和数量信息,这里需要去掉最后一个逗号
            string[] arrProInfos = ProInfos.Split(',');
            HttpCookie cookieFood = new HttpCookie("MyShoppingCart");//初始化一个Cookie对象

            foreach (string strProInfo in arrProInfos)
            {
                string strProID = strProInfo.Split('|')[0];//商品id
                string strProCount = strProInfo.Split('|')[1];//该商品订购数量

                ProModel = GetProModel(strProID);
                ImagesModel = GetProImageModel(strProID);

                //DateTime dt = DateTime.Now;
                //TimeSpan ts = new TimeSpan(0, 0, 1, 0, 0);//过期时间为1分钟
                //cookie.Expires = dt.Add(ts);//设置过期时间

                //设置cookie的值
                cookieFood.Values.Add("Company", ComModel.Company);
                cookieFood.Values.Add("ProductID", strProID);
                cookieFood.Values.Add("ProductName", ProModel.ProductName);
                cookieFood.Values.Add("SaleUserID", SaleUserID.ToString());
                cookieFood.Values.Add("ProductImg", ImagesModel.ImageUrl);
                cookieFood.Values.Add("Price", ProModel.Price.Value.ToString("f2"));
                cookieFood.Values.Add("Bonus", "1");
                cookieFood.Values.Add("Count", strProCount);

                Response.Cookies.Add(cookieFood);
            }
        }

        /// <summary>
        /// 保存配送信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnDispatch_Click(object sender, EventArgs e)
        {
            SetFoodList();
            Response.Redirect("OrderInfo.aspx");
        }

小插曲→计入到关键隐藏域hidProInfo的值是这样的:

ok,感谢主,这个功能就此结束了,之前有博问博友建议加到餐饮盒时就加入缓存,但是考虑到需要后台处理,页面会刷新,如果用ajax也可以实现局部异步刷新,过后我再尝试一下看看,不过我这种实现方法是另一种思路,我选择最后点击“OK,下一步”的时候计入缓存到那边选餐订单确认页面获取缓存显示商品情况。其实这当中关键点就是一个class的妙用(本来class是用来指定样式表,这里用来存放数据未尝不可)和隐藏域的使用。

posted @ 2014-03-06 15:09  以便以谢  阅读(464)  评论(0编辑  收藏  举报