2017年12月30日 11:39
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

哄孩子睡觉哄到现在,要两个孩子真的是不容易。孩子不睡觉,我没办法写博客。孩子睡着了,我一写就要写到半夜2点。6点起床,6:30骑自行车去上班,呼吸着雾霾,头皮冻得僵硬。到了软件园楼底下,还要排队买胡辣汤,排队上电梯。唉,生活不易。


今天,我们要说的当然是用户信息修改,请看下图。

image.png

看到一龙了么,重庆功夫盛典和日本变装拳手战成平手,打裂了日本拳手的眉骨。OK,我们点击铅笔,弹出用户信息修改界面。那么,我们在弹出用户信息修改界面之前,先要给弹出界面的form赋值。那么这一步要怎么做,当然了,是使用angular的copy方法。怎么copy呢,当然是copy当前行的用户对象。

我们看一下弹出修改界面的js方法。

<tr ng-repeat="userEntity in userEntityList">
    <td><input id="chk_{{userEntity.UserID}}" type="checkbox" ng-model="userEntity.IsChecked" /></td>
    <td>{{userEntity.UserID}}</td>
    <td>{{userEntity.UserName}}</td>
    <td>{{userEntity.UserSex=="1"? "男":"女"}}</td>
    <td>{{userEntity.UserBirthDay.slice(6,-2)|date:'yyyy-MM-dd HH:mm:ss'}}</td>
    <td>{{userEntity.UserPhone}}</td>
    <td>{{userEntity.UserEmail}}</td>
    <td>
        <span style="cursor:pointer;" ng-click="getSelectedUser(userEntity)" class="glyphicon glyphicon-pencil span-grid"></span>
        <span style="cursor:pointer;margin-left:5px;" ng-click="deleteUser(userEntity.UserID)" class="glyphicon glyphicon-trash span-grid"></span>
    </td>
</tr>

如上代码,点击铅笔我们调用了getSelectedUser方法,并且传入当前行的userEntity对象。看一下这个js方法是如何处理的。

$scope.modifyUser = {};
$scope.getSelectedUser = function (userEntity) {
     angular.copy(userEntity, $scope.modifyUser);
     $scope.modifyUser.UserBirthDay = new Date(parseInt($scope.modifyUser.UserBirthDay.substr(6))).format("yyyy-MM-dd");
     angular.element('#userModifyModal').modal('show');
};

我们定义一个modifyUser对象,然后将传递过来的对象copy到modifyUser对象。但是由于日期是json格式(/Date(1290371638000)/ ),所以需要进行转化。待对象中的数据都准备好之后,我们打开用户修改界面。

我们看一下用户修改功能在界面是如何运作的。

@using (Ajax.BeginForm("UserModify", "UserManage", null, new AjaxOptions()
        {
            HttpMethod = "Put",
            Confirm = "您确定要修改吗?",
            LoadingElementId = "div_modify_process",
            OnComplete = "modifyComplete",
            OnSuccess = "modifySuc",
            OnFailure = "modifyFail"
        }, new { @class = "form-horizontal", id = "userModify_form" }))
{
    <div class="modal fade" id="userModifyModal" role="dialog"
         data-backdrop="static" data-keyboard="false"
         aria-labelledby="userModifyModalElement" aria-hidden="true">
        <div class="modal-dialog" style="width:450px">

            <div class="modal-content" style="width:450px">
                <div class="modal-header modal-head">
                    <button type="button" class="close"
                            data-dismiss="modal" aria-hidden="true">
                        &times;
                    </button>
                    <h4 class="modal-title" id="userModifyModalElement">
                        <img src="../../Images/Base/useradd.png" class="img-panel-title" />
                        <label>用户信息修改</label>
                    </h4>
                </div>
                <div class="modal-body">
                    <div ng-include="'UserModifyView'"></div>
                </div>
                <div class="modal-footer">
                    <button type="submit" class="btn btn-primary">
                        <span class="glyphicon glyphicon-check" aria-hidden="true">
                            <label>保存</label>
                        </span>
                    </button>
                    <button type="button" ng-click="windowClose()" class="btn btn-danger">
                        <span class="glyphicon glyphicon-off" aria-hidden="true">
                            <label>关闭</label>
                        </span>
                    </button>
                </div>
            </div><!-- /.modal-content -->
        </div>
    </div>
}

在这里需要注意的是下面的这句

<div class="modal-body">
    <div ng-include="'UserModifyView'"></div>
</div>

其实这里的ng-include是包含页面的意思。如果是静态页面,这里可能就是一个html页面。但是在asp.net mvc中,这里一定不能写cshtml或者aspx页面。因为cshtml和aspx页面是需要在服务端进行解析替换内容后才发送到客户端浏览器的。所以在这里我写的是一个controller中的action。这个action返回一个页面。

public PartialViewResult UserModifyView()
{
   return PartialView("~/Views/UserManage/UserModify.cshtml");
}

那么我们为什么要用include呢,原因是不想将修改界面的代码直接写在查询界面上,这样通过include的方式更容易进行维护。

OK,我们看一下这个页面的代码

<div style="width:98%">
    <input name="UserID" type="hidden" value="`modifyUser`.`UserID`"/>
    <div class=" form-group">
        <div class="row">
            <label class="col-md-2 control-label">姓名:</label>
            <div class="col-md-10 col-sm-5-pad">
                <input name="UserName"
                       type="text"
                       maxlength="10"
                       ng-model="modifyUser.UserName"
                       class="form-control"
                       data-toggle="tooltip"
                       data-placement="bottom"
                       title="姓名不能超过10个汉字" required>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="row">
            <label class="col-md-2 control-label">
                性别:
            </label>
            <div class="col-md-10 col-sm-5-pad">
                <div class="radio-inline">
                    <label>
                        <input ng-model="modifyUser.UserSex" name="UserSex" type="radio" value="1">男
                    </label>
                </div>
                <div class="radio-inline">
                    <label>
                        <input ng-model="modifyUser.UserSex" name="UserSex" type="radio" value="0">女
                    </label>
                </div>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="row">
            <label for="disabledSelect" class="col-md-2 control-label">
                生日:
            </label>
            <div class="col-md-10 col-sm-5-pad">
                <input name="UserBirthDay" id="txtBirthDay" ng-model="modifyUser.UserBirthDay" type="date" class="form-control" required />
            </div>
        </div>
    </div>
 
    <div class="form-group">
        <div class="row">
            <label class="col-md-2 control-label">
                Emai:
            </label>
            <div class="col-md-10 col-sm-5-pad">
                <input name="UserEmail" type="email" maxlength="30" ng-model="modifyUser.UserEmail" class="form-control" id="txtEmail" data-toggle="tooltip"
                       data-placement="bottom" title="请填写正确的邮箱地址,用于找回密码等" required>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="row">
            <label class="col-md-2 control-label">
                电话:
            </label>
            <div class="col-md-10 col-sm-5-pad">
                <input name="UserPhone" type="tel" maxlength="15" ng-model="modifyUser.UserPhone" class="form-control" id="txtTelNo" data-toggle="tooltip"
                       data-placement="bottom" pattern="^\d{11}$" title="只能输入11位手机号码" required>
            </div>
        </div>
    </div>
</div>
<div id="div_modify_process" style="text-align:center;display:none">
    <img src="~/Images/Base/loading.gif" style="width:30px;height:30px"/>
    <label style="color: #003399">正在处理,请稍候......</label>
</div>
<script type="text/javascript">
    $("[data-toggle='tooltip']").tooltip();
</script>

通过include的引用,则个界面就成为了userManage界面的一部分。大家注意到,这里的表单元素绑定的都是刚才我们在弹出用户信息修改界面之前copy的对象modifyUser,这样当我们打开用户修改界面,表单上已经绑上了要修改的值,没有任何问题。由此说明,通过include引用的页面修改界面,和用户管理界面是共享$scope的。

image.png

而且大家也注意到表单元素的name属性都是我们后台实体类中的属性。为什么这样呢,查看过asp.net mvc前端生成代码的同学都知道,其实页面最顶端声明的viewModel,只是为了方便智能提示,例如@Html.TextBoxFor(t=>t.UserID),其实这个html helper标签最终生成的html元素就是<input type='text' name='UserID'>。所以我觉得页面顶端声明的viewModel类型并不会起到什么特殊的作用,因为我这个人不追求原理。所以在这里我也没在页面顶端声明什么@model xxx.xxxEntity。我只是将表单元素的name设置为后台实体的属性而已。经过验证,提交到后台是可以直接映射到实体中的。

image.png

OK,说到提交,我们看一下这个页面表单的提交,首先,上面提到这个表单的form定义如下

@using (Ajax.BeginForm("UserModify", "UserManage", null, new AjaxOptions()
            {
                HttpMethod = "Put",
                Confirm = "您确定要修改吗?",
                LoadingElementId = "div_modify_process",
                OnComplete = "modifyComplete",
                OnSuccess = "modifySuc",
                OnFailure = "modifyFail"
            }, new { @class = "form-horizontal", id = "userModify_form" }))
    {

这个意思是ajax方式提交到UserModify这个action,HttpMethod是Put,在提交前先弹出确认,确认后显示正在处理(LoadingElementId = "div_modify_process"),成功后弹出提示。我们看一下这几个js方法。

function modifySuc(data) {
    alert(data.msg);
    angular.element('#userModifyModal').modal('hide');

    //$scope.getDatabyPageIndex($scope.PageIndex);
}

function modifyFail(data) {
    alert(data);
}

function modifyComplete() {
    angular.element('#div_modify_process').hide();
}

当成功后,弹出提示信息,这里的data是mvc框架返回的回调参数,即我们后台action返回的json对象。

当ajax请求完成以后,我们需要手动隐藏正在处理(LoadingElementId = "div_modify_process")


OK,我们来看一下后端代码

[HttpPut]
public JsonResult UserModify(UserAddRequest request)
{
    int suc = UserInfoBiz.GetInstance().ModifyUser(request);

    if (suc >= 0)
    {
        return GetJsonMessage("CM_003", JsonMsgType.SUCCESS);
    }

    return GetJsonMessage("CM_004");
}

提交一下试试,先弹出确认信息

image.png

点击确定之后,会出现正在处理(LoadingElementId = "div_modify_process")

image.png

提交到后台,也确实如前面所说,实体有值。

如此可见,我们只要name值和实体中的属性一致就行了。好的,我们接着看Biz层

public int ModifyUser(UserAddRequest request)
{
    if (string.IsNullOrEmpty(request.UserID)) return -1;

    string xmlRequest = this.BuildUserXml(request);
    return UserInfoDAL.GetInstance().ModifyUser(xmlRequest);
}

看到了吧,构造一个xml格式的数据,传入DAL层。

public int ModifyUser(string xmlRequest)
{
    try
    {  
        string sqlScript = DBScriptManager.GetScript(this.GetType(), "ModifyUserInfoByID");
        SqlParameter[] sqlParameters = 
        {
            new SqlParameter("@UserXml",SqlDbType.Xml)
        };

        sqlParameters[0].Value = xmlRequest;
        return SqlHelper.ExecuteNonQuery(ConstValues.CON_DBConnection, CommandType.Text, sqlScript, sqlParameters);
    }
    catch (Exception ex)
    {
        LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex);
        return -1;
    }
}

接收的是一个xml类型的数据,其实在这里我们是直接将一个对象xml序列化之后传入sql脚本中。或者我们可以使用表值变量,直接传table进来。但是我觉得还是xml方便一些,表值变量还要在如下的地方预先定义好方能使用,比较麻烦。

wKiom1TSWC2zMrCmAADUnqhcK-c524.jpg

最后我们看一下脚本

DECLARE @UserID VARCHAR(15)
DECLARE @UserSex CHAR(1)
DECLARE @UserName NVARCHAR(20)
DECLARE @UserBirthDay DATETIME
DECLARE @UserEmail VARCHAR(30)
DECLARE @UserPhone VARCHAR(11)
  
;WITH UserIDList AS
 (
        SELECT 
        U.C.value('(UserID/text())[1]','VARCHAR(15)') AS UserID,
        U.C.value('(UserSex/text())[1]','CHAR(1)') AS UserSex,
        U.C.value('(UserName/text())[1]','NVARCHAR(20)') AS UserName,
        U.C.value('(UserBirthDay/text())[1]','DATETIME') AS UserBirthDay,
        U.C.value('(UserEmail/text())[1]','VARCHAR(30)') AS UserEmail,
        U.C.value('(UserPhone/text())[1]','VARCHAR(11)') AS UserPhone
    FROM @UserXml.nodes(N'UserInfo') AS U(C)
 )
  
SELECT TOP(1)
    @UserID = UserID,
    @UserSex = UserSex,
    @UserName = UserName,
    @UserBirthDay = UserBirthDay,
    @UserEmail = UserEmail,
    @UserPhone = UserPhone
FROM UserIDList
  
UPDATE TOP(1) dbo.InformationUser
SET UserName = @UserName,
    UserSex = @UserSex,
    UserBirthDay = @UserBirthDay,
    UserEmail = @UserEmail,
    UserPhone = @UserPhone
WHERE UserID = @UserID

OK,最后提交完成后,弹出成功的提示。

image.png

点击确定,修改页面关闭。

发表评论
匿名  
用户评论
暂无评论