ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)

本文介绍如何使用ASP.NET MVC与jQuery DataTables结合实现客户管理模块的增删查改功能,包括分页和排序操作。通过示例代码详细展示了控制器与视图的交互过程。

目录

  1. ASP.NET MVC搭建项目后台UI框架—1、后台主框架
  2. ASP.NET MVC搭建项目后台UI框架—2、菜单特效
  3. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开
  4. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
  5. ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互
  6. ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)
  7. ASP.NET MVC搭建项目后台UI框架—7、统计报表
  8. ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中
  9. ASP.NET MVC搭建项目后台UI框架—9、服务器端排序

接着之前未写完的继续,本篇,我将讲解在此UI框架中和ASP.NET MVC4进行结合开发。效果如下:

这里,我将添加和修改用了两个不同的视图,当然也可以把添加和修改放到同一个视图中,但是要写一些业务逻辑代码来区分当前调用的是修改还是添加,根据添加和修改的不同,而对界面进行不同的操作。

添加控制器Customer,关于更新操作,我就不得不想吐槽一下NHibernate,他妹的,每次都要先load一次,然后再Update()一次,如果你直接save,它就把你表中有,但是界面上没有传过来的值全部更新为null了,相比之下EF就好多了。

 public class CustomerController : Controller
    {
 private string message = "<script>frameElement.api.opener.hidePublishWin('{0}', '{1}','{2}'); </script>"; //消息,是否关闭弹出窗,是否停留在当前分页(0,1)

        #region 客户管理主页
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 客户列表
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult List(CustomerFilter filter)
        {
            filter.PageSize = int.MaxValue;
            var dataSource = CustomerInfo.GetByFilter(filter);

            List<CustomerInfo> queryData = dataSource.ToList();

            var data = queryData.Select(u => new
            {
                ID = u.ID,
                CusCode = u.CusCode,
                CusName = u.CusName,
                BusssinessType = u.BusssinessType.GetDescription(false),
                Balance = u.Balance,
                CreditAmount = u.CreditAmount,
                Status = u.Status.GetDescription(false),
                Country = u.Country,
                CompanyName = u.CompanyName,
                Delivery = GetDeliveryList(u.ExpressCurInfoBy)

            });

            //构造成Json的格式传递
            var result = new { iTotalRecords = queryData.Count, iTotalDisplayRecords = 10, data = data };
            return Json(result, JsonRequestBehavior.AllowGet);
        }
        #region 添加客户
        /// <summary>
        /// 添加客户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult AddCustomer()
        {
            ViewBag.Title = "添加客户";
            return View();
        }

        /// <summary>
        /// 添加客户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddCustomer(CustomerInfo info)
        {
            string msg = string.Empty;
            if (ModelState.IsValid)
            {
                try
                {
                    info.Save();
                    msg = "添加客户成功。";
                }
                catch (Exception ex)
                {
                    msg = "添加客户失败!" + ex.Message;
                    ViewBag.Msg = string.Format(message, msg, false,"0");
                }
                ViewBag.Msg = string.Format(message, msg, true,"0");
            }
            return View();
        }
        #endregion

        #region 修改客户
        /// <summary>
        /// 修改客户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult UpdateCustomer(int id)
        {
            ViewBag.Title = "修改客户";
            var result = CustomerInfo.Load(id);

            return View(result);
        }

        /// <summary>
        /// 修改客户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult UpdateCustomer(CustomerInfo info)
        {
            string msg = string.Empty;
            if (ModelState.IsValid)
            {
                try
                {
                    info.Update();
                    msg = "修改客户成功。";
                }
                catch (Exception ex)
                {
                    msg = "修改客户失败!" + ex.Message;
                    ViewBag.Msg = string.Format(message, msg, false,"1");
                }
                ViewBag.Msg = string.Format(message, msg, true,"1");
            }
            return View();
        }
        #endregion
    }
View Code

添加视图Index

@{
    ViewBag.Title = "客户信息";
}
<link href="~/libs/DataTables-1.10.6/media/css/jquery.dataTablesNew.css" rel="stylesheet" />
<script src="~/libs/DataTables-1.10.6/media/js/jquery.dataTables.min.js"></script>
<script src="~/Scripts/DataTablesExt.js"></script>
<script type="text/javascript">
    //弹出框  
    var addDG, updateDG, matchDG;
    var w = 424, h = 520; //宽,高
    //添加记录
    function showPublishWin() {
        addDG = new $.dialog({
            id: "AddChannel",
            title: "添加客户",
            content: "url:/Customer/AddCustomer",
            width: w,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        addDG.show();
    }
    //修改记录
    function modifyRecord(id) {
        updateDG = new $.dialog({
            id: "UpdateCustomer",
            title: "修改客户",
            content: "url:/Customer/UpdateCustomer/" + id,
            width: w,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        updateDG.show();
    }
    //隐藏弹出框
    function hidePublishWin(msg, result, isStay) {
        var icon = "success.gif";
        if (result == "False") {
            icon = "error.gif";
        }
        $.dialog({
            title: "提示",
            icon: icon,
            titleIcon: 'lhgcore.gif',
            content: msg,
            lock: true,
            ok: true
        });
        if (result != "False") {
            if (addDG) {
                addDG.close();
            }
            if (updateDG) {
                updateDG.close();
            }
            if (matchDG) {
                matchDG.close();
            }
            if (isStay == 0) {
                reloadList();
            }
            else {
                reloadListNew();
            }
        }
    }
    function matchDelivery(id) {
        matchDG = new $.dialog({
            id: "UpdateCustomer",
            title: "客户匹配",
            content: "url:/Customer/DeliveryMatching/" + id,
            width: 800,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        matchDG.show();
    }
    //刷新,但是停留在当前分页
    function reloadListNew() {
        var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
        tables.ajax.reload(null,false);
    }
</script>
<script type="text/javascript">
    $(function () {
        var h = $(document).height() - 258;
        var table = $("#table_local").dataTable({
            bProcessing: true,
            "scrollY": h,
            "scrollCollapse": "true",
            "dom": 'ftr<"bottom"lip><"clear">',
            "bServerSide": false,                    //指定从服务器端获取数据  
            sServerMethod: "POST",
            sAjaxSource: "@Url.Action("List", "Customer")",
            "fnServerParams": function (aoData) {  //查询条件
                aoData.push(
                    { "name": "CusCode", "value": $("#CusCode").val() },
                    { "name": "CusName", "value": $("#CusName").val() }
                    );
            },
            columns: [{ title: "1", "visible": false, "data": "ID" },
               { "data": "CusCode", title: "客户代码" },
               { "data": "CusName", title: "客户名称" },
               { "data": "BusssinessType", title: "业务类型", width: "100" },
               { "data": "Country", title: "国家", width: "200" },
               { "data": "CompanyName", title: "公司名称", width: "200" },
               { "data": "Delivery", title: "收货商", width: "150" },
               { "data": "Balance", title: "账户余额", width: "150" },
               { "data": "CreditAmount", title: "信用额度", width: "150" },
               { "data": "Status", title: "是否启用", width: "100" },
               {
                   "data": "ID", orderable: false, title: "操作", width: "140", "render": function (data, type, row, meta) { //自定义列
                       var re = "<div style='text-align:center'><a style='visibility:visible' onclick='modifyRecord(" + data + ")'>修改</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                       re = re + "<a style='visibility:visible' onclick='matchDelivery(" + data + ")'>匹配</a></div>";
                       return re;
                   }
               }
            ],
            paging: true,//分页
            ordering: true,//是否启用排序
            searching: true,//搜索
            language: {
                "sProcessing": "处理中...",
                lengthMenu: '每页显示:<select class="form-control input-xsmall">' + '<option value="5">5</option>' + '<option value="10">10</option>' + '<option value="15">15</option>'
                    + '<option value="20">20</option>' + '<option value="25">25</option>' + '<option value="30">30</option>' + '<option value="35">35</option>' + '<option value="40">40</option>',//左上角的分页大小显示。
                search: '<span class="label label-success">搜索:</span>',//右上角的搜索文本,可以写html标签

                paginate: {//分页的样式内容。
                    previous: "上一页",
                    next: "下一页",
                    first: "",
                    last: ""
                },

                zeroRecords: "暂无记录",//table tbody内容为空时,tbody的内容。
                //下面三者构成了总体的左下角的内容。
                info: "总共 <span class='pagesStyle'>(_PAGES_) </span>页,显示 _START_ -- _END_ ,共<span class='recordsStyle'> (_TOTAL_)</span> 条",//左下角的信息显示,大写的词为关键字。初始_MAX_ 条 
                infoEmpty: "0条记录",//筛选为空时左下角的显示。
                infoFiltered: ""//筛选之后的左下角筛选提示,
            },
            pagingType: "full_numbers"//分页样式的类型

        });
        //设置选中行样式
        $('#table_local tbody').on('click', 'tr', function () {
            if ($(this).hasClass('selected')) {
                $(this).removeClass('selected');
            }
            else {
                table.$('tr.selected').removeClass('selected');
                $(this).addClass('selected');
            }
        });
    });
    //查询 刷新
    function reloadList() {
        var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
        tables.ajax.reload();
    }
</script>
<div class="areabx clear">
    @using (Html.BeginForm("List", null, FormMethod.Get, new { @clase = "form-inline", @role = "form" }))
    {
        <div class="areabx_header">客户信息</div>
        <ul class="formod mgt10">
            <li><span>客户代码:</span>@Html.TextBox("CusCode", "", new { @class = "trade-time wid153" })</li>
            <li><span>客户名称:</span>@Html.TextBox("CusName", "", new { @class = "trade-time" })</li>
            <li></li>
        </ul>
        <div class="botbtbx pdb0" style="margin-bottom: -30px;">
            <input type="button" value="添加客户" class="btn btn-primary" onclick="showPublishWin()" />
            <input type="button" value="查询" onclick="reloadList();" class="btn btn-primary">
        </div>
    }
    <div class="tob_box mgt15">
        <table id="table_local" class="display" cellspacing="0" cellpadding="0" border="0" style="width: 100%">
        </table>
    </div>
</div>
View Code

添加AddCustomer视图,之前公司ASP.NET MVC的项目没有启用模型验证,界面验证代码都是自己js写的,我晕,那用ASP.NET MVC干嘛呢?使用框架就是要充分发挥框架优良的功能,尽可能高效快速的开发,并减少开发人员的代码量。

@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@*    <div class="areabx_header">@ViewBag.Title</div>*@
    <div class="tian_xi">
        @using (Html.BeginForm("AddCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
        {
            <table width="100%" border="0" cellpadding="0" cellspacing="0">
                <tbody>
                    <tr style="height: 40px;">
                        <td style="width: 120px; text-align: right;">客户代码:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">客户名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">手机:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">电话:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">邮箱:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" })<span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">传真:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">国家:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">地址:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">公司名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">业务类型:</td>
                        <td>
                        @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">是否启用:</td>
                        <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) &nbsp;&nbsp;&nbsp;&nbsp;
                            <span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td>
                    </tr>
                </tbody>
            </table>
            <input type="submit" value="确定" class="popbtn1 mg">
            <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.addDG.close();" />
        }
    </div>
</div>
View Code

添加UpdateCustomer视图

@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@*    <div class="areabx_header">@ViewBag.Title</div>*@
    <div class="tian_xi">
        @using (Html.BeginForm("UpdateCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
        {
            <table width="100%" border="0" cellpadding="0" cellspacing="0">
                <tbody>
                    <tr style="height: 40px;">
                        <td style="width: 120px; text-align: right;">客户代码:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode", @readOnly = "readOnly" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td>
                        @Html.HiddenFor(x => x.ID)
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">客户名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">手机:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">电话:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">邮箱:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" }) <span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">传真:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">国家:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">地址:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">公司名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">业务类型:</td>
                        <td>
                        @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">是否启用:</td>
                        <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) &nbsp;&nbsp;&nbsp;&nbsp;
                            <span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td>
                    </tr>
                </tbody>
            </table>
            <input type="submit" value="确定" class="popbtn1 mg">
            <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.updateDG.close();" />
        }
    </div>
</div>
View Code

客户实体CustomerInfo

    /// <summary>
    /// 客户信息
    /// </summary>
    public class CustomerInfo //: DomainObject<CustomerInfo, int, ICustomerInfoRepository>
    {
        #region property
        /// <summary>
        /// 客户代码
        /// </summary>
        [Required(ErrorMessage = "客户代码不能为空!")]
        [StringLength(30, MinimumLength = 0, ErrorMessage = "客户代码最大长度为30个字符")]
        public virtual string CusCode { get; set; }
        /// <summary>
        /// 客户名称
        /// </summary>
        [Required(ErrorMessage = "客户名称不能为空!")]
        [StringLength(30, MinimumLength = 0, ErrorMessage = "客户名称最大长度为30个字符")]
        public virtual string CusName { get; set; }
        /// <summary>
        /// 客户业务类型
        /// </summary>
        public virtual Busssiness BusssinessType { get; set; }
        /// <summary>
        /// 手机
        /// </summary>
        public virtual string Phone { get; set; }
        /// <summary>
        /// 电话
        /// </summary>
        public virtual string Tel { get; set; }
        /// <summary>
        /// 邮箱
        /// </summary>
        [RegularExpression(@"^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$", ErrorMessage="邮箱格式不正确!")]
        public virtual string Email { get; set; }
        /// <summary>
        /// 传真
        /// </summary>
        public virtual string Fax { get; set; }
        /// <summary>
        /// 国家
        /// </summary>
        public virtual string Country { get; set; }
        /// <summary>
        /// 地址
        /// </summary>
        public virtual string Address { get; set; }
        /// <summary>
        /// 公司名称
        /// </summary>
        public virtual string CompanyName { get; set; }
        /// <summary>
        /// 金额
        /// </summary>
        public virtual decimal Balance { get; set; }
        /// <summary>
        /// 信用额度
        /// </summary>
        public virtual decimal CreditAmount { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public virtual CustomerStatus Status { get; set; }
        /// <summary>
        /// 快件收货商信息
        /// </summary>
        public virtual IList<ExpressCurInfo> ExpressCurInfoBy { get; set; }
        #endregion

        #region common method
        /// <summary>
        /// 分页获取数据
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static IPageOfList<CustomerInfo> GetByFilter(CustomerFilter filter)
        {
            return Dao.GetByFilter(filter);
        }
        #endregion
    }
View Code

查询类CustomerFilter

    public class CustomerFilter : ParameterFilter
    {
        /// <summary>
        /// 客户代码
        /// </summary>
        public virtual string CusCode { get; set; }
        /// <summary>
        /// 客户名称
        /// </summary>
        public virtual string CusName { get; set; }

        /// <summary>
        /// 生产NHQL查询语句
        /// </summary>
        /// <returns></returns>
        public override string ToHql()
        {
            string hql = "";
            if (!string.IsNullOrEmpty(CusCode))
            {
                hql += " and Cus_Code =:CusCode ";
            }
            if (!string.IsNullOrEmpty(CusName))
            {
                hql += " and Cus_Name =:CusName ";
            }

            return hql;
        }

        /// <summary>
        /// 构造查询参数
        /// </summary>
        /// <returns></returns>
        public override Dictionary<string, object> GetParameters()
        {
            var result = new Dictionary<string, object>();
            if (!string.IsNullOrEmpty(CusCode))
            {
                result["CusCode"] = CusCode.Trim();
            }
            if (!string.IsNullOrEmpty(CusName))
            {
                result["CusName"] = CusName.Trim();
            }
            return result;
        }
    }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProjectBase.Utils.Entities;

namespace ProjectBase.Data
{
    public abstract class ParameterFilter
    {
        public ParameterFilter()
        {
            HasQueryString = false;
            PageSize = 10;
        }

        public string OrderBy { get;set; }

        public abstract string ToHql();

        public override string ToString()
        {
            return ToHql();
        }

        public abstract Dictionary<string, object> GetParameters();

        public string GetOrderString()
        {
            if (OrderBy.HasValue())
                return " Order By " + OrderBy;
            return String.Empty;
        }

        protected string GetLike(string value)
        {
            return "%" + value + "%";
        }

        public int PageIndex { get; set; }

        public int PageSize { get; set; }

        /// <summary>
        /// 标识此构造器是包含全部查询语句。
        /// 若为 False,则ToHql() 只需要构造条件查询,系统会自动在前面加上<code>" from " + typeof(T).Name + " a where 1=1 "</code>
        /// 若为 True, ToHql() 需要返回 连form在类的完整Hql语句
        /// </summary>
        public bool HasQueryString { get; set; }

        protected static bool HasValue(string str)
        {
            return str.HasValue();
        }

        public static bool HasValue<T>(System.Nullable<T> value) where T:struct
        {
            return value.HasValue;
        }       
        
    }
}
View Code

在这里,我只演示了控制器和视图的交互,至于Hhibernate和Unity等数据的操作,这里暂时不讲,因为你也可以使用其它的ORM框架和IOC框架,诸如EF、AutoFac等等。这里主要讲解jquery datatables和ASP.NET MVC的结合使用,但是这里只演示了客户端分页排序,后面我会讲服务器分页排序。我发现,网上都没有ASP.NET MVC和Datatables结合的完整的服务器分页、排序的Demo,只看到PHP的。于是我不断的尝试,皇天不负有心人,终于试验成功了,后面我会为大家讲述实现方式。

转载于:https://www.cnblogs.com/jiekzou/p/4555452.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值