标签:bootstrap angularjs asp.net mvc4 sqlserver 表值变量
最近一天真的都不知道自己在忙什么,当了回Scrum Master。给自己的感觉就是像大学时期,饭堂经理看员工给学生打饭太慢,自己抡起大勺子给学生打菜,偶尔有些学生有情绪还要忍着。说到饭堂,最近都不知道该吃啥。黄焖鸡,biangbiang面,镇川碗托,麻辣香锅,自助餐都吃的没啥可吃了。偶尔咥一碗麦利鸡汤刀削面或者米线凉皮沙县。不说了,这会也确实有些饿,洗个苹果吃一下。
上面这一碗就是我经常吃的biangbiang面。
今天我们主要是来看一下新闻链接的修改和新增,先上图,无图无真相。
看到了吧,这个实现其实很简单,我们在展示每行数据的时候,我们就生成一个编辑模版,只不过编辑模版是隐藏起来的,看代码。
<div ng-repeat="website in WebSites" class="a-list">
<div class="row" style="line-height:40px">
<div class="col-md-1">
<input class="chklist-vertical-align" type="checkbox" ng-model="website.IsChecked" />
</div>
<div class="col-md-5">
<a href="{{website.WebSiteURL}}">{{website.WebSiteName}}</a>
</div>
<div class="col-md-2">
<select class="form-control" ng-change="modifyTopCount(website.TransactionNumber,website.TopNewsCount)" ng-model="website.TopNewsCount" ng-options="number for number in numbers">
@*<option ng-repeat="num in numbers" label="{{num}}" value="{{num}}"></option>*@
</select>
</div>
<div class="col-md-2">
<span style="cursor: pointer;" class="glyphicon glyphicon-pencil span-grid" ng-click="showedit(website.TransactionNumber)"></span>
<span ng-click="newslinkdeleteSingle(website.TransactionNumber)" style="cursor:pointer;margin-left:5px;" class="glyphicon glyphicon-trash span-grid"></span>
</div>
<div class="col-md-2">
<span style="cursor:pointer;" ng-hide="{{$index==0}}" class="glyphicon glyphicon-arrow-up span-grid" ng-click="modifyPriority(website.TransactionNumber,1)"></span>
<span style="cursor: pointer; margin-left: 5px;" ng-hide="{{$index==TotalCount-1}}" ng-click="modifyPriority(website.TransactionNumber,0)" class="glyphicon glyphicon-arrow-down span-grid"></span>
</div>
</div>
<div ng-show="website.IsEditShow" class="form-inline" style="line-height: 40px; background-color: #99CCFF;">
网站名称:
<input id="txt_websitename_{{website.TransactionNumber}}" type="text" maxlength="30" class="form-control" style="width:150px;margin-right:20px" value="{{website.WebSiteName}}" />
URL:
<input id="txt_websiteurl_{{website.TransactionNumber}}" placeholder="请以http或者https开头" type="text" maxlength="200" class="form-control" style="width:300px" value="{{website.WebSiteURL}}" />
<img src="~/Images/Base/save.png" ng-click="editsubmit(website.TransactionNumber)" title="保存" alt="保存" class="img-submit" />
<img src="~/Images/Base/undo.png" ng-click="editcancel(website.TransactionNumber)" title="取消" alt="取消" class="img-submit" />
</div>
<div class="line-seperate-style"></div>
</div>看到了吧,就是<div ng-show="website.IsEditShow">这一个div用来编辑信息。当我们点击铅笔的时候
调用showedit,并传入本行的主键值TransactionNumber,看一下这个方法。
$scope.showedit = function (transactionNumber) {
angular.forEach($scope.WebSites, function (value, key) {
if (value.TransactionNumber == transactionNumber) {
value.IsEditShow = true;
//无法break
}
});
}其实这里呢很简单的做了一下循环,当集合中的对象的TransactionNumber和传递的TransactionNumber相等时,将该对象的IsEditShow修改为true,编辑模版就显示出来了。
OK,我们再看一下编辑模版的保存和取消,保存时调用editsubmit方法。
$scope.editsubmit = function (transactionNumber) {
if (transactionNumber == undefined) return;
var webisteUrl = $.trim(angular.element("#txt_websiteurl_" + transactionNumber).val());
var websiteName = $.trim(angular.element("#txt_websitename_" + transactionNumber).val());
if (websiteName == "") {
alert("网站名称不能为空!");
return;
}
if (webisteUrl == "") {
alert("URL不能为空!");
return;
}
var param = {
requestJson: JSON.stringify({
TransactionNumber: transactionNumber,
WebSiteURL: webisteUrl,
WebSiteName: websiteName
})
};
$http({
method: "Put",
url: "/NewsManage/ModifyNewsLink",
headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
data: $.param(param)
}).success(function (data, status, headers, config) {
alert(data.msg);
if (data.suc == 1) {
initData();
}
}).error(function (data, status, headers, config) {
alert(status);
});
};这里很简单,拿到修改的值去调用后台action做修改,这里后台比较简单,就不说了。
接着我们看取消,点击取消,调用editcancel方法。
$scope.editcancel = function (transactionNumber) {
for (var i = 0; i < $scope.WebSites.length; i++) {
if ($scope.WebSites[i].TransactionNumber == transactionNumber) {
$scope.WebSites[i].IsEditShow = false;
angular.element("#txt_websitename_" + transactionNumber).val($scope.WebSites[i].WebSiteName);
angular.element("#txt_websiteurl_" + transactionNumber).val($scope.WebSites[i].WebSiteURL);
break;
}
}
}如果取消的话,就将当前的编辑模版隐藏,并将表单值恢复为原始值。在上面我们使用了angular.foreach循环,因为这种写法无法break,所以在这里我还是用for循环好了。
OK,到此,编辑就讲完了,接着我们看一下优先级的设置。
<span style="cursor:pointer;" ng-hide="{{$index==0}}" class="glyphicon glyphicon-arrow-up span-grid" ng-click="modifyPriority(website.TransactionNumber,1)"></span>
<span style="cursor: pointer; margin-left: 5px;" ng-hide="{{$index==TotalCount-1}}" ng-click="modifyPriority(website.TransactionNumber,0)" class="glyphicon glyphicon-arrow-down span-grid"></span>优先级这里,当我们是优先级最高时,不能再升,最低时不能再降。所以这里的ng-hide="{{$index==0}}"和ng-hide="{{$index==TotalCount-1}}"就标识了优先级按钮的显示隐藏,效果如下。
我们看一下这个设置优先级的方法modifyPriority
$scope.modifyPriority = function (transactionNumber, priorityType) {
var param = {
requestJson: JSON.stringify({
TransactionNumber: transactionNumber,
PriorityType: priorityType
})
};
$http({
method: "Put",
url: "/NewsManage/ModifyNewsPriority",
headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
data: $.param(param)
}).success(function (data, status, headers, config) {
initData();
}).error(function (data, status, headers, config) {
alert(status);
});
}没什么逻辑,就是将主键和调整类型(调高还是调低)传递到后台,我们主要还是看下后台的脚本。
DECLARE @TempTranNumber INT DECLARE @TempPriority INT SELECT TOP(1) @TempPriority = Priority FROM dbo.InformationNewsLink WITH(NOLOCK) WHERE TransactionNumber = @TransactionNumber IF @PriorityType = 1 BEGIN SELECT TOP(1) @TempTranNumber = TransactionNumber FROM dbo.InformationNewsLink WITH(NOLOCK) WHERE Priority < @TempPriority ORDER BY Priority DESC IF @TempTranNumber IS NOT NULL BEGIN UPDATE TOP(1) dbo.InformationNewsLink SET Priority = Priority + 1, LastEditDate = GETDATE(), LastEditUser = @UserID WHERE TransactionNumber = @TempTranNumber UPDATE TOP(1) dbo.InformationNewsLink SET Priority = Priority - 1, LastEditDate = GETDATE(), LastEditUser = @UserID WHERE TransactionNumber = @TransactionNumber END END ELSE BEGIN SELECT TOP(1) @TempTranNumber = TransactionNumber FROM dbo.InformationNewsLink WITH(NOLOCK) WHERE Priority > @TempPriority ORDER BY Priority ASC IF @TempTranNumber IS NOT NULL BEGIN UPDATE TOP(1) dbo.InformationNewsLink SET Priority = Priority - 1, LastEditDate = GETDATE(), LastEditUser = @UserID WHERE TransactionNumber = @TempTranNumber UPDATE TOP(1) dbo.InformationNewsLink SET Priority = Priority + 1, LastEditDate = GETDATE(), LastEditUser = @UserID WHERE TransactionNumber = @TransactionNumber END END
很简单,成功之后,调用initData方法刷新界面。
OK,时间不早了,也不知道老吉这家伙睡了没,这家伙就是那个《程序员,你伤不起》的作者,走火入魔.net什么框架的开发者。刚才还在上微信,你说这人都快40了,怎么精力还这么大,得向人家学习呢,不过比谁睡得晚,老吉肯定比不过我。
OK,最后我们看一下新增连接的保存。
<div class="row" style="line-height:40px">
<div class="col-md-1">
<div class="div-circal-list">1</div>
</div>
<div class="col-md-1">
<input disabled type="checkbox" ng-model="IsChecked" class="chklist-vertical-align" />
</div>
<div class="col-md-4">
<input type="text" ng-model="WebSiteNameModel" maxlength="30" style="width:100%" class="form-control" />
</div>
<div class="col-md-6">
<input type="text" placeholder="请以http或者https开头" maxlength="200" ng-model="WebSiteURLModel" style="width:100%" class="form-control" />
</div>
</div>
<div ng-repeat="website in AddedWebSites">
<div class="row" style="line-height:40px">
<div class="col-md-1">
<div class="div-circal-list">{{$index + 2}}</div>
</div>
<div class="col-md-1">
<input type="checkbox" ng-model="website.IsChecked" class="chklist-vertical-align" />
</div>
<div class="col-md-4">
<input type="text" ng-model="website.WebSiteName" maxlength="30" style="width:100%" class="form-control" />
</div>
<div class="col-md-6">
<input type="text" placeholder="请以http或者https开头" maxlength="200" ng-model="website.WebSiteURL" style="width:100%" class="form-control" />
</div>
</div>
</div>
<div style="margin-top:20px">
<input type="button" class="btn btn-primary" value="新增" ng-click="addnewlink()" />
<input type="button" class="btn btn-info" value="保存" ng-click="saveWebsiteLink()" />
<input type="button" class="btn btn-danger" value="移除" ng-click="removelink()" />在这里,上节讲到,第一行就是默认存在的,后面的行就通过AddedWebSites这个对象集合来增加。
这里我看只看保存。
$scope.saveWebsiteLink = function () {
var tempAddedWebSites = [];
angular.copy($scope.AddedWebSites, tempAddedWebSites);
tempAddedWebSites.push({ WebSiteName: $scope.WebSiteNameModel, WebSiteURL: $scope.WebSiteURLModel });
for (var i = 0; i < tempAddedWebSites.length; i++) {
if ($.trim(tempAddedWebSites[i].WebSiteName) == ""
|| $.trim(tempAddedWebSites[i].WebSiteName) == undefined
|| $.trim(tempAddedWebSites[i].WebSiteURL) == ""
|| $.trim(tempAddedWebSites[i].WebSiteURL) == undefined) {
alert("网站名称和网站URL不能为空!");
return;
}
if (!angular.uppercase($.trim(tempAddedWebSites[i].WebSiteURL)).startWith("HTTP")
&& !angular.uppercase($.trim(tempAddedWebSites[i].WebSiteURL)).startWith("HTTPS")) {
alert("第" + (i + 1) + "条网站URL没有以Http或者Https开头!");
return;
}
}
var param = {
requestJson: JSON.stringify({
WebSiteList: tempAddedWebSites
})
};
$http({
method: "Post",
url: "/NewsManage/AddNewsLink",
headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ },
data: $.param(param)
}).success(function (data, status, headers, config) {
alert(data.msg);
if (data.suc == 1) {
initData();
$scope.WebSiteNameModel = "";
$scope.WebSiteURLModel = "";
$scope.AddedWebSites = [];
}
}).error(function (data, status, headers, config) {
alert(status);
});
}在这里上面是一些check,判断非空和URL格式的,在这里再次强调一下,任何的前端验证都是不可靠的,还是要靠后台验证。我们看一下后端的处理
[HttpPost]
public JsonResult AddNewsLink()
{
string requestJson = Request["requestJson"];
List<NewsLinkEntity> newsLinkList = JsonBuilder.BuildRequestList<NewsLinkEntity>(requestJson, "WebSiteList");
int suc = NewsMngBiz.GetInstance().AddNewsLink(newsLinkList, UserID);
if (suc > 0)
{
return GetJsonMessage("CM_001", JsonMsgType.SUCCESS);
}
return GetJsonMessage("CM_004");
}首先得到发送的json数据,然后反序列化为List<NewsLinkEntity>。
public static List<T> BuildRequestList<T>(string requestJson, string key) where T : class,new()
{
if (string.IsNullOrWhiteSpace(requestJson)) return new List<T>();
JObject jObj = (JObject)JsonConvert.DeserializeObject(requestJson);
JToken jToken = jObj[key];
return (List<T>)JsonConvert.DeserializeObject<List<T>>(jToken.ToString());
}然后调用Biz层
public int AddNewsLink(List<NewsLinkEntity> newLinkEntityList, string userID)
{
DataTable dt = new DataTable();
dt.Columns.Add("WebSiteName", typeof(string));
dt.Columns.Add("WebSiteURL", typeof(string));
DataRow drow = null;
foreach (var newsLinkEntity in newLinkEntityList)
{
drow = dt.NewRow();
drow.SetField<string>("WebSiteName", newsLinkEntity.WebSiteName);
drow.SetField<string>("WebSiteURL", newsLinkEntity.WebSiteURL);
dt.Rows.Add(drow);
}
return NewsMngDAL.GetInstance().AddNewsLink(dt, userID);
}在这里将List<T>转成了DataTable,为什么呢?还记得之前的文章提到过sqlServer处理批量数据。一种是传xml,一种是使用表值变量(table-valued variable)。今天我们就使用一下SqlServer2008的表值变量。首先我们在sqlserver中创建表值变量。
USE [ChinaInformation] GO CREATE TYPE [dbo].[NewsLinkTable] AS TABLE( [WebSiteName] [nvarchar](60) NOT NULL, [WebSiteURL] [varchar](200) NOT NULL ) GO
创建好之后,可以在这里查看
OK,创建好了,我们接着看DAL层。
public int AddNewsLink(DataTable dt,string userID)
{
string sqlScript = string.Empty;
try
{
sqlScript = DBScriptManager.GetScript(this.GetType(), "AddNewsLink");
SqlParameter[] sqlParameters =
{
new SqlParameter("@NewLinkTable",SqlDbType.Structured),
new SqlParameter("@UserID",SqlDbType.VarChar,15)
};
sqlParameters[0].Value = dt;
sqlParameters[0].TypeName = "dbo.NewsLinkTable";
sqlParameters[1].Value = userID;
return SqlHelper.ExecuteNonQuery(ConstValues.CON_DBConnection, CommandType.StoredProcedure, sqlScript, sqlParameters);
}
catch (Exception ex)
{
LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex);
return -1;
}
}在这里需要注意我们的参数@NewLinkTable,它的类型是Structured,它接受的值可以是DataTable,可以是SqlDataReader。这里我们传入DataTable,同时还要指定其TypeName,要不然系统无法判断是哪一种表值。OK,最后,我们看一下保存的脚本sp。
USE ChinaInformation GO ALTER PROCEDURE dbo.UP_NewLinkAddNew ( @NewLinkTable dbo.NewsLinkTable READONLY, @UserID VARCHAR(15) ) AS DECLARE @LastPriority INT DECLARE @WebSiteName NVARCHAR(60) DECLARE @WebSiteURL VARCHAR(20) SELECT TOP(1) @LastPriority = MAX(Priority) FROM dbo.InformationNewsLink WITH(NOLOCK) DECLARE WebSiteLinkCursor CURSOR LOCAL FORWARD_ONLY READ_ONLY FOR SELECT WebSiteName,WebSiteURL FROM @NewLinkTable OPEN WebSiteLinkCursor FETCH NEXT FROM WebSiteLinkCursor INTO @WebSiteName,@WebSiteURL WHILE @@FETCH_STATUS = 0 BEGIN SET @LastPriority = @LastPriority + 1 INSERT INTO dbo.InformationNewsLink ( WebSiteName, WebSiteURL, Priority, InDate, InUser, LastEditDate, LastEditUser ) SELECT @WebSiteName, @WebSiteURL, @LastPriority, GETDATE(), @UserID, GETDATE(), @UserID FETCH NEXT FROM WebSiteLinkCursor INTO @WebSiteName,@WebSiteURL END CLOSE WebSiteLinkCursor DEALLOCATE WebSiteLinkCursor
OK,这里就不多说了,注意传入的第一个参数。如果想要测试该sp,用如下代码即可
DECLARE @Tab AS dbo.NewsLinkTable INSERT INTO @Tab ( WebSiteName, WebSiteURL ) VALUES(‘1‘,‘www.nnn.com‘),(‘1‘,‘www.nnn.com‘) EXEC dbo.UP_NewLinkAddNew @Tab,‘‘
OK,都三点了,老夫也该睡了,磨豆浆,蒸包子的这会也该起来了。
本文出自 “技术创造价值” 博客,请务必保留此出处http://leelei.blog.51cto.com/856755/1622924
标签:bootstrap angularjs asp.net mvc4 sqlserver 表值变量
原文地址:http://leelei.blog.51cto.com/856755/1622924