ASP.NET MVC4+BootStrap 实战(十三)

最近公司来了一个陕北的实习妹子,据说家里是开矿的,人长得一般,但很有气质。开矿的,当然钱很多了。以前在大学有个同学,家里是开油田的,有节毛概课,老师说西安的房价都是陕北人轰起来的,西安人都怨陕北人。我这个同学听了不开心了,周末直接在东西南北各买一套。牛逼啊,让你老师多嘴。这几天周围的同事心思都在这个姑娘身上,装作喝咖啡过去瞄一眼,或者站起来瞅瞅背影。IT爷们真的是空虚,IT界无美女啊,还是吉日嘎啦说的好,公司有美女,可以提升爷们的战斗力。


OK,今天我们来看一下新闻审核界面,本来这节是要说ueditor上传图片到mongoDB,但是最近实在精力有限,先放放,稍后再上博客。我们先看一下界面,提提神。

技术分享

这个界面上面部分是查询,采用响应式布局方式。当在手机或者pad的浏览器上的时候,依然能够正常显示并使用。

技术分享

OK,我们今天主要看的不是界面,还是看功能的实现。


首先先看一下查询功能,查询有个新闻类别的下拉列表,后台Action代码如下

[HttpGet]
public JsonResult GetNewsTypeList()
{
    List<NewsTypesEntity> newsTypeEntityList = NewsMngBiz.GetInstance().GetNewsTypes();
    newsTypeEntityList.Insert(0, new NewsTypesEntity() { TransactionNumber = null, NewsTypeName = CommonResouce.DefaultSelectText });
    return Json(newsTypeEntityList, JsonRequestBehavior.AllowGet);
}

OK,接下来我们就要看界面了

@{
    Layout = null;
}
<div ng-app="newsAuditModule" ng-controller="newsAuditController" id="div_newsAudit" class="panel panel-primary">
    <div class="panel-heading">
        <h3 class="panel-title">
            <img class="img-panel-title" src="~/Images/Base/audit.png" />
            <b>新闻审核</b>
        </h3>
    </div>
    <div class="panel-body">
        <div class="row" style="line-height:30px">
            <label for="newsTitle" class="col-sm-2 control-label">新闻标题</label>
            <div class="col-sm-10">
                <input type="text" maxlength="100" class="form-control" id="newsTitle" ng-model="newsTitle"
                       placeholder="请输入新闻标题查询">
            </div>
        </div>
        <div class="row" style="margin-top: 5px; margin-bottom: 5px; line-height: 30px">
            <label for="newsTitle" class="col-sm-2 control-label">新闻类别</label>
            <div class="col-sm-10">
                <select id="newsTitle" class="form-control" ng-model="newsType">
                    @*<option value="">---请选择---</option>*@
                    <option ng-repeat="type in NewsTypeList" value="{{type.TransactionNumber}}">{{type.NewsTypeName}}</option>
                </select>
            </div>
        </div>
        <div class="row" style="line-height:30px">
            <label for="newsTitle" class="col-sm-2 control-label">审核状态</label>
            <div class="col-sm-10">
                <select id="newsTitle" class="form-control" ng-model="newsState">
                    <option value="">---请选择---</option>
                    <option value="-1">未审核</option>
                    <option value="0">未通过</option>
                    <option value="1">通过</option>
                </select>
            </div>
        </div>
        <div class="row" style="margin-top:10px">
            <div class="col-sm-3">
                <button type="button" class="btn btn-primary btn-form-width" ng-click="getDataList()">查询</button>
            </div>
        </div>
        <div class="pre-scroll" style="margin-top:10px">
            <table class="table table-bordered table-striped table-hover" ng-init="load()">
                <tr style="background-color: #428bca; color: white">
                    <th><input type="checkbox" ng-model="isCheckAll" ng-change="setCheckState()"></th>
                    <th>新闻标题</th>
                    <th>新闻类别</th>
                    <th>创建日期</th>
                    <th>审核状态</th>
                    <th>审核人</th>
                    <th>审核日期</th>
                    <th>操作</th>
                </tr>
                <tr ng-repeat="newsEntity in NewsList">
                    <td><input id="chk_{{newsEntity.TransactionNumber}}" type="checkbox" ng-model="newsEntity.IsChecked" /></td>
                    <td title="{{newsEntity.Title}}">{{newsEntity.SubTitle}}</td>
                    <td>{{newsEntity.InforType}}</td>
                    <td>{{newsEntity.InDate.slice(6,-2)|date:‘yyyy-MM-dd‘}}</td>
                    <td style="color:{{ newsEntity.Color }}">{{newsEntity.AuditStatus}}</td>
                    <td>{{newsEntity.AuditUserName}}</td>
                    <td>{{newsEntity.AuditDate.slice(6,-2)|date:‘yyyy-MM-dd‘}}</td>
                    <td>
                        <span style="cursor:pointer;">
                            <a href="#"><img title="浏览"  src="~/Images/Base/preview.png" class="img-table-column" /></a>
                            <a href="#"><img title="审核" ng-click="auditModalShow(newsEntity)"  src="~/Images/Base/key.png" class="img-table-column" /></a>
                        </span>
                    </td>
                </tr>
            </table>
        </div>
        <div class="btn-group dropup">
            <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                批量操作<span class="caret"></span>
            </button>
            <ul class="dropdown-menu" role="menu">
                <li><a href="#" ng-click="batchOperation(‘A‘)">批量通过</a></li>
                <li class="divider"></li>
                <li><a href="#" ng-click="batchOperation(‘D‘)">批量删除</a></li>
            </ul>
        </div>
    </div>

    <div class="modal fade" id="newAuditModal" tabindex="-1" role="dialog"
         aria-labelledby="auditModalTitle" aria-hidden="true" data-backdrop="static">
        <div class="modal-dialog">
            <div class="modal-content" style="width:550px">
                <div class="modal-header" style="background-color: #009966;height:45px;line-height:45px">
                    <button type="button" class="close"
                            data-dismiss="modal" aria-hidden="true">
                        &times;
                    </button>
                    <h5 class="modal-title" id="auditModalTitle" style="color:white">
                        新闻审核
                    </h5>
                </div>
                <div class="modal-body">
                    <div class="form-horizontal">
                        <div class="form-group">
                            <label class="col-md-3" for="labTitle">新闻标题:</label>
                            <div class="col-md-9">
                                <label id="labTitle"></label>
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="col-md-3">审核结果:</label>
                            <div class="col-md-9">
                                <input type="radio" name="radAuditResult" ng-change="setAuditResaonEditable()" value="1" checked ng-model="AuditResult"> 通过
                                <input type="radio" name="radAuditResult" ng-change="setAuditResaonEditable()" value="0" ng-model="AuditResult" style="margin-left:10px"> 不通过
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="col-md-3" for="div_reason">未通过原因:</label>
                            <div class="col-md-9">
                                <div id="div_reason" style="border: 1px solid #003366; height: 90px; word-break: break-all;max-height:90px;overflow-y:scroll"
                                     contenteditable="true"></div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" ng-click="auditNews()" class="btn btn-primary btn-form-width">
                        提交
                    </button>
                    <button type="button" class="btn btn-danger btn-form-width"
                            data-dismiss="modal">
                        关闭
                    </button>
                </div>
            </div><!-- /.modal-content -->
        </div><!-- /.modal -->
    </div>
</div>

查询条件下拉列表的初始化很简单。

$scope.getNewsTypeList = function () {
    $http.get("/NewsManage/GetNewsTypeList").success(function (data) {
        $scope.NewsTypeList = data;
    });
};

接下来我们看一下查询功能,点击查询按钮,调用getDataList方法

$scope.getDataList = function () {
    $scope.isCheckAll = false;
    var param = {
        requestJson: JSON.stringify({
            Title: $.trim($scope.newsTitle),
            InforType: $scope.newsType,
            AuditStatus: $scope.newsState
        })
    };

    $http({
        method: "post",
        url: "/NewsManage/GetNewsNativeList",
        headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
        data: $.param(param)
    }).success(function (data, status, headers, config) {
        $scope.NewsList = data;
        angular.forEach($scope.NewsList, function (value, key) {
            if ($.trim(value.AuditState) == "") {
                value.Color = "#003366;"
            }
            else if (value.AuditState == "0") {
                value.Color = "#FF0033;"
            }
            else {
                value.Color = "#009966";
            }
        });
    });
}

传入查询条件,并且在返回结果后,对颜色进行设置,未审核是蓝色,审核通过是绿色,不通过是红色。<td style="color:{{ newsEntity.Color }}">{{newsEntity.AuditStatus}}</td>这段就是设置审核状态颜色的,颜色是根据Color属性显示的。


OK,查询完了之后,我们看一下最底下的批量操作按钮。

技术分享

点击批量操作按钮,其实是弹出一个菜单,有批量通过和批量删除两个选项,这正是BootStrap中的按钮菜单。点击批量通过,其实是要将上面选中的新闻全部审核通过,删除也雷同。我们看一下,点击批量通过调用的js方法batchOperation(‘A‘)。

$scope.batchOperation = function (operationType) {
    var selectedIDs = [];
    angular.forEach($scope.NewsList, function (value, key) {
        if (value.IsChecked) {
            selectedIDs.push(value.TransactionNumber);
        }
    });

    if (selectedIDs.length == 0) {
        alert(‘请选择要批量操作的数据!‘);
        return;
    }

    var param = {
        requestJson: JSON.stringify({
            newsIDs: selectedIDs
        })
    };

    var postAction = operationType == "A" ? "BatchPassNewsAudit" : "BatchNativeNewsDelete";

    $http({
        method: "post",
        url: "/NewsManage/" + postAction,
        headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
        data: $.param(param)
    }).success(function (data, status, headers, config) {
        if (data.suc == "1") {
            $scope.getDataList();
        }
        alert(data.msg);
    });
}

首先会check有没有选中的数据,然将选中的主键传到后台action进行处理。

[HttpPost]
public JsonResult BatchPassNewsAudit()
{
    string requestJson = Request["requestJson"];
    string[] userIDArray = JsonBuilder.BuildStringArray(requestJson, "newsIDs");
    int suc = NewsMngBiz.GetInstance().BatchAuditPass(string.Join(",", userIDArray), this.UserID);
    if (suc > 0)
    {
        return GetJsonMessage("NM_001", JsonMsgType.SUCCESS);
    }

    return GetJsonMessage("NM_002");
}

ok,我们再看一下批量删除,批量删除和批量通过走的是一个js方法并且action也雷同,所以在这里我们只看一下删除的sql脚本。

DECLARE @NewsIDTable TABLE
(
    ID INT IDENTITY(1,1),
    TransactionNumber INT NOT NULL
)

INSERT INTO @NewsIDTable
(
    TransactionNumber
)
SELECT short_str
FROM ChinaInformation.dbo.F_SQLSERVER_SPLIT(@NewsIDs,‘,‘)

DELETE FROM ChinaInformation.dbo.InformationNative
OUTPUT
	DELETED.NewsContent,
	DELETED.InfoTypeID,
	DELETED.AuditState,
	DELETED.InDate,
	DELETED.InUser,
	DELETED.LastEditDate,
	DELETED.LastEditUser,
	DELETED.AuditUser,
	DELETED.AuditDate,
	DELETED.Title,
  GETDATE(),
  @UserID
INTO ChinaInformation.dbo.InformationNativeDeleteLog
WHERE TransactionNumber IN(
  SELECT TransactionNumber
  FROM @NewsIDTable
)

删除的时候要将删除记录插入log表。


接下来我们再看一下单个审核功能技术分享

当点击审核图标的时候,弹出modal页面。

<a href="#"><img title="审核" ng-click="auditModalShow(newsEntity)"  src="~/Images/Base/key.png" class="img-table-column" /></a>
$scope.auditModalShow = function (newsEntity) {
    angular.element("#labTitle").text(newsEntity.SubTitle);
    angular.element("#labTitle").attr("title", newsEntity.Title);
    $scope.SelectID = newsEntity.TransactionNumber;
    angular.AuditResult = "1";

    if (typeof (Storage) !== "undefined"
        && sessionStorage.auditReason != undefined
        && sessionStorage.auditReason != ""
        && $scope.AuditResult == "0") {
        document.getElementById("div_reason").innerHTML = sessionStorage.auditReason;
    }

    angular.element(‘#newAuditModal‘).modal(‘show‘);
}


在这里我们把标题什么的,都附上。标题因为有的可能太长,所以我就设置需要显示的为SubTitle,title为原有没有截断的新闻标题,这样用户鼠标放上去就可以看到完整的标题。

技术分享

默认值设置完了之后,我们判断如果本地session存储sessionStorage中存储的auditReason有值,我们就把它赋给div。注意这里的div,它的contenteditable为true的话是可以编辑的。另外,想让它换行,又不至于高度一直扩展,我们加了滚动条。

<div id="div_reason" style="border: 1px solid #003366; height: 90px; word-break: break-all;max-height:90px;overflow-y:scroll"
                                     contenteditable="true"></div>

OK,最后我们看一下通过和不通过的change事件。

$scope.setAuditResaonEditable = function () {
    var div_auditReason = document.getElementById("div_reason");
    if ($scope.AuditResult == "1") {
        div_auditReason.contentEditable = "false";
        div_auditReason.style.backgroundColor = "#999999";

        if (typeof (Storage) !== "undefined") {
            sessionStorage.auditReason = document.getElementById("div_reason").innerHTML;
        }

        div_auditReason.innerHTML = "";
    }
    else {
        div_auditReason.contentEditable = "true";
        div_auditReason.style.backgroundColor = "#FFFFFF";
    }
}

当radio的值有变化的时候,调用上面js方法。如果审核通过被选中,那么我们需要把不通过原因存储在本地session中,注意本地session的作用域是浏览器,浏览器关了就没有了。另外还要特别注意的是这里的div_auditReason.contentEditable = "true";一定得是"true",双引号括起来的true。contentEditable 这个单词的E一定要大写,不然就不会有任何效果。下面这两张图就是radio change效果。

技术分享

技术分享

OK,最后我们再看一下后台的处理

$scope.auditNews = function () {
    var unPassReason = document.getElementById("div_reason").innerHTML;

    if ($scope.AuditResult == "0" && (unPassReason == "" || unPassReason.length < 10)) {
        alert("不通过原因不能少于10个字!");
        return;
    }

    var param = {
        requestJson: JSON.stringify({
            TransactionNumber: $scope.SelectID,
            AuditStatus: $scope.AuditResult,
            UnPassReason: $scope.AuditResult == "1" ? "" : unPassReason
        })
    };

    $http({
        method: "post",
        url: "/NewsManage/NewsAuditSingle",
        headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
        data: $.param(param)
    }).success(function (data, status, headers, config) {
        if (data.suc == "1") {
            $scope.getDataList();
        }
        alert(data.msg);
    });
};

后台代码如下

[HttpPost]
public JsonResult NewsAuditSingle(FormCollection fc)
{
    string requestJson = fc["requestJson"];
    string auditState = JsonBuilder.BuildValueByType<string>(requestJson, "AuditStatus");
    int transactionNumber = JsonBuilder.BuildValueByType<int>(requestJson, "TransactionNumber");
    string unPassReason = JsonBuilder.BuildValueByType<string>(requestJson, "UnPassReason");

    int suc = NewsMngBiz.GetInstance().NewsNativeAuditSingle(transactionNumber, auditState, unPassReason, this.UserID);
    if (suc > 0)
    {
        return GetJsonMessage("NM_005", JsonMsgType.SUCCESS);
    }

    return GetJsonMessage("NM_006");
}

OK,今天就到这里,这个界面还剩余一个新闻预览功能,和审核不通过原因查看。

技术分享

本文出自 “技术创造价值” 博客,请务必保留此出处http://leelei.blog.51cto.com/856755/1640131

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。