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

连续三年年会中奖,第一年二等奖,价值2600元的魔音耳机,到现在才用了10几次。第二年中了个价值260元的飞利浦烧水壶,到现在还没用。今年中了个飞利浦挂烫机,也没查是多少钱,反正觉得奖项一年不如一年。在此我就给大家上一张年会热图。

wKioL1S7hymx-7wJADYasThCtD8104.jpg


男人的肚皮舞,嗨爆全场。好了,废话不多说,我们进入正题吧。

今天我们要说的就是主页面以及用户注册界面,功能做的都比较简单,我们先看一下Index界面。

<div id="div_navigation" style="margin-top:10px;" ng-app="indexModule" ng-controller="indexController">
    <div class="row">
        <div class="col-md-3">
            <div class="panel-group" id="accordion">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h4 class="panel-title">
                            <a data-toggle="collapse" data-parent="#accordion"
                               href="#collapseOne">
                                <b>用户管理</b>
                            </a>
                        </h4>
                    </div>
                    <div id="collapseOne" class="panel-collapse collapse in">
                        <div class="panel-body">
                            <ul class="navigation-ul">
                                <li>
                                    <img src="~/Images/Base/usermng.jpg" />
                                    <a href="#" onclick="redirectToPage('UserCreateView')">用户注册</a>
                                </li>
                                <li>
                                    <img src="~/Images/Base/useradd.png" />
                                    <a href="#" onclick="redirectToPage('UserManageView')">用户管理</a>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h4 class="panel-title">
                            <a data-toggle="collapse" data-parent="#accordion"
                               href="#collapseTwo">
                                <b>新闻管理</b>
                            </a>
                        </h4>
                    </div>
                    <div id="collapseTwo" class="panel-collapse collapse">
                        <div class="panel-body">
                            <ul class="navigation-ul">
                                <li>
                                    <img src="~/Images/Base/newsadd.png" />新增新闻
                                </li>
                                <li>
                                    <img src="~/Images/Base/newsquery.png" />新闻查询
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h4 class="panel-title">
                            <a data-toggle="collapse" data-parent="#accordion"
                               href="#collapseThree">
                                <b>图片管理</b>
                            </a>
                        </h4>
                    </div>
                    <div id="collapseThree" class="panel-collapse collapse">
                        <div class="panel-body">
                            <ul class="navigation-ul">
                                <li>
                                    <img src="~/Images/Base/photomng.jpg" />图片查看
                                </li>
                                <li>
                                    <img src="~/Images/Base/photorar.jpg" />图片压缩
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h4 class="panel-title">
                            <a data-toggle="collapse" data-parent="#accordion"
                               href="#collapseSys">
                                <b>系统管理</b>
                            </a>
                        </h4>
                    </div>
                    <div id="collapseSys" class="panel-collapse collapse">
                        <div class="panel-body">
                            <ul class="navigation-ul">
                                <li>
                                    <img src="~/Images/Base/syscodemng.jpg" />系统参数管理
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div id="div_content" class="col-md-9" style="padding-left:1px;">
            @Html.Partial("~/Views/UserManage/UserCreate.cshtml")
        </div>
    </div>
</div>
<script type="text/javascript">
    function redirectToPage(action) {
        var baseURL = '/Home/';
 
        $.get(baseURL + action).success(function (data, status) {
            $("#div_content").html(data);
        });
    }
 
    //var indexModule = angular.module('indexModule', []);
    //indexModule.controller("indexController", function ($scope, $http) {
    //    $scope.redirectToPage = function (action) {
    //        var baseURL = '/Home/';
 
    //        $http.get(baseURL + action).success(function (data) {
    //            angular.element('#div_content').html(data);
    //        });
    //    };
    //});
       //angular.element('#div_navigation').data('$injector', '');
    //angular.bootstrap(angular.element('#div_navigation'), ['indexModule']);
</script>

这个其实就是Index界面的全部代码,Index界面应用了布局模版。布局模版很简单,在这里代码就不贴出来了,主要是引用一些Js,css。OK,我们首先看一下页面是如何导航的。

<div id="collapseOne" class="panel-collapse collapse in">
    <div class="panel-body">
        <ul class="navigation-ul">
            <li class="span-nav">
                <img src="~/Images/Base/usermng.jpg" />
                <a href="#" onclick="redirectToPage('UserCreateView')">用户注册</a>
            </li>
            <li class="span-nav">
                <img src="~/Images/Base/useradd.png" />
                <a href="#" onclick="redirectToPage('UserManageView')">用户管理</a>
            </li>
        </ul>
    </div>
</div>

从这两段代码就可以看出来,在超链接onclick的时候,我们调用js方法redirectToPage。在这个方法中,我们调用action获取对应的页面显示到div_content中。上节我说过了,如果使用ng-click调用$scope中的方法,是会有问题的,因为module只能注册一次,如果每次点击导航链接你的页面都是整页刷新,则没有问题。只要你在每个页面上注册module就行了。

angular.element('#div_navigation').data('$injector', '');
angular.bootstrap(angular.element('#div_navigation'), ['indexModule']);

但是局部刷新,则不行,所以angular js是不支持多个页面以tab页形式加载到主页面的,是无法正常工作的。所以上面注释的代码就是没办法使用的,因为我们的界面是在主界面不停的更换如下div中的内容。

<div id="div_content" class="col-md-9" style="padding-left:1px;">
     @Html.Partial("~/Views/UserManage/UserCreate.cshtml")
</div>

ok,我们看一下action。

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

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

就是两个返回PartialView的action。ok,到此我们的主页导航就完了。


接着我们看一下用户注册界面。

image.png

很简单的一个页面,那么首先先看一下页面。

@{
    Layout = null;
}
<form id="div_userCreate" ng-app="userCreateModule" autocomplete="off" ng-submit="saveUser()" class="form-horizontal" role="form" ng-controller="createUserController">
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">
                <b>用户注册</b>
            </h3>
        </div>
        <div class="div-panel-content">
            <div class="form-group">
                <label class="col-sm-2 control-label">用户名:</label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input name="userNo"
                           type="text"
                           maxlength="15"
                           placeholder="请输入登录用户名"
                           ng-model="userInfo.userNo"
                           class="form-control element-form-width"
                           data-toggle="tooltip"
                           data-placement="right"
                           pattern="^[a-zA-Z]\w{5,15}$"
                           title="用户名必须以字母开头,并且只能是字母和数字及下划线的组合(6-15位)" required>
                </div>
            </div>
            <div class="form-group">
                <label for="inputPassword" class="col-sm-2 control-label">
                    密码:
                </label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input name="passWord" ng-model="userInfo.passWord" class="form-control element-form-width" type="password" maxlength="15"
                           placeholder="请输入密码" data-toggle="tooltip" pattern="^\w+$"
                           data-placement="right" title="密码由字母和数字组成,不能超过15位" required>
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-2 control-label">姓名:</label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input name="userName"
                           type="text"
                           maxlength="10"
                           ng-model="userInfo.userName"
                           class="form-control element-form-width"
                           data-toggle="tooltip"
                           data-placement="right"
                           title="姓名不能超过10个汉字" required>
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-2 control-label">
                    性别:
                </label>
                <div class="col-sm-10 col-sm-5-pad">
                    <div class="radio-inline">
                        <label>
                            <input ng-model="userInfo.sex" ng-checked="true" name="radioSex" type="radio" value="1">男
                        </label>
                    </div>
                    <div class="radio-inline">
                        <label>
                            <input name="radioSex" type="radio" value="0">女
                        </label>
                    </div>
                </div>
            </div>
            <div class="form-group">
                <label for="disabledSelect" class="col-sm-2 control-label">
                    出生日期
                </label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input id="txtBirthDay" ng-model="userInfo.birthDay" type="date" class="form-control element-form-width" required />
                </div>
            </div>
 
            <div class="form-group">
                <label class="col-sm-2 control-label">
                    Emai:
                </label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input type="email" maxlength="30" ng-model="userInfo.email" class="form-control element-form-width" id="txtEmail" data-toggle="tooltip"
                           data-placement="right" title="请填写正确的邮箱地址,用于找回密码等" required>
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-2 control-label">
                    电话:
                </label>
                <div class="col-sm-10 col-sm-5-pad">
                    <input type="tel" maxlength="15" ng-model="userInfo.telPhone" class="form-control element-form-width" id="txtTelNo" data-toggle="tooltip"
                           data-placement="right" pattern="^\d{11}$" title="只能输入11位手机号码" required>
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-5 col-sm-offset-2" style="padding-left:2px">
                    <button id="btnSave" type="submit" class="btn btn-primary btn-form-width">保存</button>
                    <button type="reset" class="btn btn-primary btn-form-width">取消</button>
                </div>
            </div>
            <loading></loading>
        </div>
    </div>
    <script>
        var nowDateTime = getDateNow();
        var appModule = angular.module('userCreateModule', []);
 
        appModule.directive('loading', function () {
            return {
                restrict: 'E',
                replace: true,
                template: '<div style="margin-left:10px"><img src="./../Images/Base/loading.gif" style="height:35px;width:35px"/>' +
                    '<label style="margin-left:10px;color:#CC0033">正在处理,请稍后...</lable>' +
                    '</div>',
                link: function (scope, element, attr) {
                    scope.$watch('isLoading', function (val) {
                        if (val) {
                            $(element).show();
                        }
                        else
                            $(element).hide();
                    });
                }
            }
        });
 
        appModule.controller("createUserController", function ($scope, $http) {
            $scope.isLoading = false;
            $scope.userInfo = {
                userNo: "",
                passWord: "",
                userName: "",
                sex: "1",
                birthDay: nowDateTime,
                email: "",
                telPhone: ""
            };
 
            //convertParam($http);
 
            $scope.saveUser = function () {
                $scope.isLoading = true;
                var postData = {
                    requestJson: JSON.stringify({
                        userInfo: {
                            userNo: $scope.userInfo.userNo,
                            passWord: $scope.userInfo.passWord,
                            userName: $scope.userInfo.userName,
                            sex: $scope.userInfo.sex,
                            birthDay: $scope.userInfo.birthDay,
                            email: $scope.userInfo.email,
                            telPhone: $scope.userInfo.telPhone
                        }
                    })
                };
 
                $http({
                    url: "/UserManage/CreateUser",
                    method: "POST",
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    data: $.param(postData)
                }).success(function (data, status, headers, config) {
                    $scope.isLoading = false;
                    alert(data.msg);
                }).error(function (data, status, headers, config) {
                    alert(status);
                    $scope.isLoading = false;
                });
 
                //$.ajax({
                //    url: "/UserManage/CreateUser",
                //    type: "POST",
                //    dataType: "json",
                //    data: postData,
                //    success: function (data) {
                //        $scope.isLoading = false;
                //        alert(data.msg);
                //    }, error: function () {
                //        $scope.isLoading = false;
                //    }
                //});
            }
        });
        angular.bootstrap(angular.element('#div_userCreate'), ['userCreateModule']);
        $("[data-toggle='tooltip']").tooltip();
    </script>
</form>

加载到主页面中的每个Partial页面都必须设置Layout=null,不要应用布局模版。该页面必须还是BootStrap布局,ng-app,ng-controller,ng-submit这三个标签我在此就不再多说了。我们先看一下用户名表单。

<input name="userNo"
       type="text"
       maxlength="15"
       placeholder="请输入登录用户名"
       ng-model="userInfo.userNo"
       class="form-control element-form-width"
       data-toggle="tooltip"
       data-placement="right"
       pattern="^[a-zA-Z]\w{5,15}$"
       title="用户名必须以字母开头,并且只能是字母和数字及下划线的组合(6-15位)" required>

注意,这里我们设置最大长度为15,绑定的model变量是userInfo.userNo。为什么是这样,因为我们整个表单对象是userInfo。所以在controller中我们首先初始化了userInfo这个Json对象。

$scope.userInfo = {
    userNo: "",
    passWord: "",
    userName: "",
    sex: "1",
    birthDay: nowDateTime,
    email: "",
    telPhone: ""
};

再看有个属性data-toggle,data-placement,这两个其实是BootStrap提供的用来展示tooltip的属性。看一下效果

image.png

看到了吧,其实这里大家发现它把title的内容显示在了这里,并且tooltip是显示在了右边,data-placement这个属性设置是显示在哪边,有right,left,top,bottom四个值,那么这个tooltip仅仅是设置了这两个属性就会鼠标mouseover的时候显示?No,还有一段js。

$("[data-toggle='tooltip']").tooltip();

OK,最后我们看到有个Pattern属性,这个不是BootStrap的,是Html5的。我们在这里设置了用户名必须是以字母开头,6-15位,看一下下面的效果图。

image.png

OK,其他的元素我就不说了,我们再看一下Email。

<input type="email" maxlength="30" ng-model="userInfo.email" class="form-control element-form-width" id="txtEmail" data-toggle="tooltip"
                           data-placement="right" title="请填写正确的邮箱地址,用于找回密码等" required>

type=email,这个是html5提供的。在这里我们不需要写任何的正则验证,他自己会验证的。

image.png

看到了吧,通不过,我们改成正确的格式就可通过。

最后我们填写完整,提交。

image.png

看到了吧,出现了正在处理,请稍后的字样。那么这个正在处理请稍后,是怎么整的呢?其实第一篇我们在讲Login界面的时候,用的Jquery的ajax。beforsend时展示一个div,success的时候隐藏div。但是在这里我们使用到了angular js的指令。

appModule.directive('loading', function () {
    return {
        restrict: 'E',
        replace: true,
        template: '<div style="margin-left:10px"><img src="./../Images/Base/loading.gif" style="height:35px;width:35px"/>' +
            '<label style="margin-left:10px;color:#CC0033">正在处理,请稍后...</lable>' +
            '</div>',
        link: function (scope, element, attr) {
            scope.$watch('isLoading', function (val) {
                if (val) {
                    $(element).show();
                }
                else
                    $(element).hide();
            });
        }
    }

指令可以应用于元素,属性等。在这里我们将其设置为只能应用于元素(E),我们为其设置了一个template,用来替换页面中的指令标签内容。同时我们提供了一个link函数,用来实现模版是否显示的逻辑。如下是关于restrict和replace的解释

image.png

通过上面的这段解释,我们可以设置模版url而非像上面直接在指令中设置模版内容。

好的,再看一下link函数的解释

image.png

上面都是官方翻译的文档,没什么可以解释的,毕竟这东西不是我发明的。

在link函数中,我们通过一个isLoading变量来控制指令元素的显示隐藏,OK,说了这么多,这个指令就是html页面中的如下标签

<div class="form-group">
    <div class="col-sm-5 col-sm-offset-2" style="padding-left:2px">
        <button id="btnSave" type="submit" class="btn btn-primary btn-form-width">保存</button>
        <button type="reset" class="btn btn-primary btn-form-width">取消</button>
    </div>
</div>
<loading></loading>

那么我们在controller中是如何调用的呢?

controller中,我们初始化设置这个变量为false,$scope.isLoading = false。

然后在saveUser方法还未发送请求之前,设置这个变量的值为true

$http({
    url: "/UserManage/CreateUser",
    method: "POST",
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    data: $.param(postData)
}).success(function (data, status, headers, config) {
    $scope.isLoading = false;
    alert(data.msg);
}).error(function (data, status, headers, config) {
    alert(status);
    $scope.isLoading = false;
});

在这里大家需要注意headers和data。在上节我说过,因为angular post的数据,asp.net mvc action接收不到,原因是发送的数据格式和asp.net mvc所要接收的数据格式不一致。那么为什么jquery的请求action可以收到呢?因为jquery发送的数据格式默认是application/x-www-form-urlencoded,而且对post的数据格式也是进行了转换。

Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See processData option to prevent this automatic processing. Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below).

而angular默认发送的是json格式,所以我们在上节对它post的数据进行了转化。本节我们使用更简单的一种方式让angular $http.post也能正确发送数据到action,设置headers为{ 'Content-Type': 'application/x-www-form-urlencoded' },然后传数据的时候,使用jquery的$.param方法进行转换。这样就不用像上节那样去写一堆东西转换。


OK,说了这么多,我们看一下保存成功了没有。

image.png

虽然代码写的是先消失,再弹出alert,但是我们在关闭了alert之后,正在处理请稍后才消失。

OK,最后,再强调一下,一定不要忘了下面这句,这个意思是设置angular的启动入口。

angular.bootstrap(angular.element('#div_userCreate'), ['userCreateModule']);

好了,我们最后看一下后台控制器。

public JsonResult CreateUser()
{
    string requestJson = Request["requestJson"];
    UserAddRequest request = JsonBuilder.BuildUserInfoRequest(requestJson);
    request.InUserID = UserID;

    int suc = UserInfoBiz.GetInstance().CreateUser(request);

    if (suc >= 0)
    {
        return GetJsonMessage("CM_001");
    }

    return GetJsonMessage("CM_004");
}

接收到数据,然后Json反序列化得到request

public static UserAddRequest BuildUserInfoRequest(string requestJson)
{
    if (string.IsNullOrWhiteSpace(requestJson)) return new UserAddRequest();

    JObject jObj = (JObject)JsonConvert.DeserializeObject(requestJson);
    JToken jToken = jObj["userInfo"];
    string userNo = jToken.Value<string>("userNo");
    string userName = jToken.Value<string>("userName");
    string userPwd = jToken.Value<string>("passWord");
    string sex = jToken.Value<string>("sex");
    DateTime birthDay = jToken.Value<DateTime>("birthDay");
    string email = jToken.Value<string>("email");
    string telPhone = jToken.Value<string>("telPhone");

    UserAddRequest userInfoRequest = new UserAddRequest();
    userInfoRequest.UserID = userNo;
    userInfoRequest.UserName = userName;
    userInfoRequest.UserPwd = Cryptor.Encrypt(userPwd);
    userInfoRequest.UserSex = sex;
    userInfoRequest.UserBirthDay = birthDay;
    userInfoRequest.UserEmail = email;
    userInfoRequest.UserPhone = telPhone;
    return userInfoRequest;
}

得到request之后,调用Biz=>DAL完成保存,CreateUser脚本如下

IF NOT EXISTS(
  SELECT TOP 1 1
  FROM dbo.InformationUser WITH(NOLOCK)
  WHERE UserID = @UserID
)
BEGIN
  INSERT INTO dbo.InformationUser
  (
      UserID,
      UserName,
      UserPwd,
      UserSex,
      UserBirthDay,
      UserEmail,
      UserPhone,
      InDate,
      InUser
  )
  VALUES
  (
    @UserID,
    @UserName,
    @UserPwd,
    @UserSex,
    @UserBirthDay,
    @UserEmail,
    @UserPhone,
    GETDATE(),
    @InUserID
  )
END

OK,到这里代码就全部结束了,最后我们再看看刚才注册的用户能否查出来

image.png

OK,没啥问题,在这篇文章里我只做了客户端的验证,在正式开发中后端一定是要有验证的,好了,洗洗睡。

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