DiscuzNT 交易插件设计之商品添加,编辑和删除(CUD)
以上文中的“管理商品”用例来说明一下商品的添加,编辑和删除方面的设计。
首先看一下商品添加功能。我们打开一个商品添加页面如下:
上图中说明了发布商品时要填写的内容和数据约束项,其中的"商品类目"一侧的“选择”链接点击后效果如下图所示:
当填写完相应的商品信息,并通过JS和aspx.cs数据校验之后,就会在postgoods.aspx.cs中执行下面
语句,以便向商品列表中添加数据: 其中的CreateGoods方法内容如下(discuz.mall项目的App_Code文件夹下的Goods.cs文件)
/// 创建商品数据信息
/// </summary>
/// <param name="goodsinfo">商品信息</param>
/// <returns>创建商品的id</returns>
public static int CreateGoods(Goodsinfo goodsinfo)
{
int goodsid = DbProvider.GetInstance().CreateGoods(goodsinfo);
//当成功创建商品信息且可在前台正常显示时
if (goodsid > 0 && goodsinfo.Displayorder>=0)
{
DbProvider.GetInstance().UpdateCategoryGoodsCounts(goodsinfo.Categoryid,
goodsinfo.Parentcategorylist, 1);
}
return goodsid;
}
而上面方法中的DbProvider.GetInstance().CreateGoods(goodsinfo)即是向数据库中添加相应商品的
sql语句(相应内容参见discuz.mall项目的Data文件夹下的SqlDataProvider.cs文件中的相应方法).
上面代码中还包括一个更新当前添加商品所属分类的商品数的语句。这里面有必要介绍一个商品分类表,
因为要更新的字段即是该表中的goodscount字段(分类的商品数),见下图:
当然到这里只是完成了初始化添加商品数据的功能。而商品标签,附件等功能还需要通过上面方法的
返回值即新创建的商品id来进行添加,请看下面代码(postgoods.aspx.cs):
if (enabletag && tagsArray != null && tagsArray.Length > 0)
{
DbProvider.GetInstance().CreateGoodsTags(string.Join(" ", tagsArray), goodsinfo.Goodsid, userid,
curdatetime);
GoodsTags.WriteGoodsTagsCacheFile(goodsinfo.Goodsid);
}
上面代码即是将当前商品的标签添加到商品标签列表中的语句(注:这部分代码将来可能要重构)。
其中的CreateGoodsTags方法是直接向数据库中插入指定商品的标签,并根据标签是否已存在来更新已有标签的使用数。
而第二个方法即:GoodsTags.WriteGoodsTagsCacheFile(goodsinfo.Goodsid)则是将标签写入缓存文件,以便加快
页面浏览速度。其方法内容如下:
/// 写入主题标签缓存文件
/// </summary>
/// <param name="tagsArray">标签数组</param>
/// <param name="topicid">主题Id</param>
public static void WriteGoodsTagsCacheFile(int goodsid)
{
StringBuilder dir = new StringBuilder();
dir.Append(BaseConfigs.GetForumPath);
dir.Append("cache/goods/magic/");
dir.Append((goodsid / 1000 + 1).ToString());
dir.Append("/");
string filename = Utils.GetMapPath(dir.ToString() + goodsid.ToString() + "_tags.config");
#if NET1
TagInfoCollection tags = GetTagsListByGoods(goodsid);
#else
List<TagInfo> tags = GetTagsListByGoods(goodsid);
#endif
Tags.WriteTagsCacheFile(filename, tags, string.Empty, false);
}
完成了标签(文件)的创建之后。下面是商品附件的上传和数据添加(postgoods.aspx.cs):
Goodsattachmentinfo[] attachmentinfo = Discuz.Mall.MallUtils.SaveRequestFiles(categoryid,
config.Maxattachments, usergroupinfo.Maxsizeperday, usergroupinfo.Maxattachsize,
MaxTodaySize, attachextensions, watermarkstatus, config, "postfile");
if (attachmentinfo != null)
{
if (attachmentinfo.Length > config.Maxattachments)
{
AddErrLine("系统设置为每个商品附件不得多于" + config.Maxattachments + "个");
return;
}
int errorAttachment = GoodsAttachments.BindAttachment(attachmentinfo, goodsinfo.Goodsid, sb,
goodsinfo.Categoryid, userid);
int[] aid = GoodsAttachments.CreateAttachments(attachmentinfo);
string tempMessage = GoodsAttachments.FilterLocalTags(aid, attachmentinfo, goodsinfo.Message);
goodsinfo.Goodspic = (attachmentinfo.Length > 0) ? attachmentinfo[0].Filename : "";
if (!tempMessage.Equals(goodsinfo.Message))
{
goodsinfo.Message = tempMessage;
goodsinfo.Aid = aid[0];
}
Goods.UpdateGoods(goodsinfo);
UserCredits.UpdateUserCreditsByUploadAttachment(userid, aid.Length - errorAttachment);
}
//加入相册
#region 相册
if (config.Enablealbum == 1 && apb != null)
{
sb.Append(apb.CreateAttachment(attachmentinfo, usergroupid, userid, username));
}
#endregion
因为使用了与版块下上传附件所相似的逻辑代码,这里就不多加说明了,要注意的是因为商品交易
插件也支持远程附件功能,因此我们也需要在后台设置相应的FTP信息后才会启用,而有关这部分的内
容请参见我之前的一篇文章:
这样,“添加商品”的主要的流程应该就走的差不多了,当然还有一些功能如添加HTML标题,商品所在
地数据js文件绑定,商品分类的js数据绑定等就暂不介绍了,大家找到相应的js文件或CS文件一看便知。
下面要介绍是“编辑商品”这个功能。当我们正常发布商品(选择“上架”且不需“审核”)时,该商品
在发布之后,会重定向到“商品显示”页面,如下图:
当我们点击“编辑商品”链接后,会进入商品编辑页面,如下:
大家可能看出了,这个页面与添加页面的差异不大,主要是(如果有附件的话)多了编辑附件的功能。
而这部分差异也体现在了editgoods.cs文件中,因为这里面的代码逻辑有些复杂,主要是判断用户是否修
改过附件信息(如阅读权限,上传文件)等,以便进行更新或删除已废掉的附件内容等:
string delAttId = DNTRequest.GetFormString("deleteaid");
if (delAttId != string.Empty)
{
if (Utils.IsNumericArray(delAttId.Split(',')))//如果要删除的附件ID列表为数字数组
{
GoodsAttachments.DeleteGoodsAttachment(delAttId);
}
}
//编辑帖子时如果进行了更新附件操作
string updatedAttId = DNTRequest.GetFormString("attachupdatedid");//被更新的附件Id列表
string updateAttId = DNTRequest.GetFormString("attachupdateid");//所有已上传的附件Id列表
string[] descriptionArray = DNTRequest.GetFormString("attachupdatedesc").Split(',');//所有已上传的附件的描述
string[] readpermArray = DNTRequest.GetFormString("attachupdatereadperm").Split(',');//所有已上传得附件的阅读权限
ArrayList updateAttArrayList = new ArrayList();
if (updateAttId != string.Empty)
{
foreach (string s in updateAttId.Split(','))
{
if (!Utils.InArray(s, delAttId, ","))//已上传的附件Id不在被删除的附件Id列表中时
{
updateAttArrayList.Add(s);
}
}
}
string[] updateAttArray = (string[])updateAttArrayList.ToArray(typeof(string));
if (updateAttId != string.Empty)//原来有附件
{
int watermarkstate = config.Watermarkstatus;
if (forum.Disablewatermark == 1)
watermarkstate = 0;
string[] updatedAttArray = updatedAttId.Split(',');
string filekey = "attachupdated";
//保存新的文件
Goodsattachmentinfo[] attArray = Discuz.Mall.MallUtils.SaveRequestFiles(
goodsinfo.Categoryid, config.Maxattachments + updateAttArray.Length,
usergroupinfo.Maxsizeperday, usergroupinfo.Maxattachsize, MaxTodaySize,
attachextensions, watermarkstate, config, filekey);
if (Utils.IsNumericArray(updateAttArray))
{
for (int i = 0; i < updateAttArray.Length; i++) //遍历原来所有附件
{
string attachmentId = updateAttArray[i];
if (Utils.InArray(attachmentId, updatedAttArray)) //附件文件被更新
{
if (Utils.InArray(attachmentId, delAttId, ","))//附件进行了删除操作, 则不操作此附件,即使其也被更新
{
continue;
}
//更新附件
int attachmentUpdatedIndex = GetAttachmentUpdatedIndex(attachmentId, updatedAttArray);//获取此次上传的被更新附件在数组中的索引
if (attachmentUpdatedIndex > -1)//附件索引存在
{
if (attArray[attachmentUpdatedIndex].Sys_noupload.Equals(string.Empty)) //由此属性为空可以判断上传成功
{
//获取将被更新的附件信息
Goodsattachmentinfo attachmentInfo =
GoodsAttachments.GetGoodsAttachmentsByAid(
Utils.StrToInt(updatedAttArray[attachmentUpdatedIndex], 0));
if (attachmentInfo != null)
{
if (attachmentInfo.Filename.Trim().ToLower().IndexOf("http") < 0)
{
//删除原来的文件
File.Delete(
Utils.GetMapPath(BaseConfigs.GetForumPath + "upload/" +
attachmentInfo.Filename));
}
//记住Aid以便稍后更新
attArray[attachmentUpdatedIndex].Aid = attachmentInfo.Aid;
attArray[attachmentUpdatedIndex].Description = descriptionArray[i];
int att_readperm = Utils.StrToInt(readpermArray[i], 0);
att_readperm = att_readperm > 255 ? 255 : att_readperm;
attArray[attachmentUpdatedIndex].Readperm = att_readperm;
attArray[attachmentUpdatedIndex].Categoryid = attachmentInfo.Categoryid;
attArray[attachmentUpdatedIndex].Goodscount = attachmentInfo.Goodscount;
attArray[attachmentUpdatedIndex].Goodsid = attachmentInfo.Goodsid;
GoodsAttachments.SaveGoodsAttachment(attArray[attachmentUpdatedIndex]);
}
}
else //上传失败的附件,稍后提示
{
sb.Append("<tr><td align=\"left\">");
sb.Append(attArray[attachmentUpdatedIndex].Attachment);
sb.Append("</td>");
sb.Append("<td align=\"left\">");
sb.Append(attArray[attachmentUpdatedIndex].Sys_noupload);
sb.Append("</td></tr>");
}
}
}
else //仅修改了阅读权限和描述等
{
if (Utils.InArray(updateAttArray[i], delAttId, ","))
{
continue;
}
if ((attachmentlist[i].Readperm.ToString() != readpermArray[i]) ||
(attachmentlist[i].Description.Trim() != descriptionArray[i]))
{
int att_readperm = Utils.StrToInt(readpermArray[i], 0);
att_readperm = att_readperm > 255 ? 255 : att_readperm;
GoodsAttachments.SaveGoodsAttachment(Utils.StrToInt(updateAttArray[i], 0), att_readperm,
descriptionArray[i]);
}
}
}
}
}
int watermarkstatus = config.Watermarkstatus;
if (forum.Disablewatermark == 1)
{
watermarkstatus = 0;
}
Goodsattachmentinfo[] attachmentinfo = Discuz.Mall.MallUtils.SaveRequestFiles(forumid,
config.Maxattachments, usergroupinfo.Maxsizeperday, usergroupinfo.Maxattachsize,
MaxTodaySize, attachextensions, watermarkstatus, config, "postfile");
if (attachmentinfo != null)
{
if (attachmentinfo.Length > config.Maxattachments)
{
AddErrLine("系统设置为每个商品附件不得多于" + config.Maxattachments + "个");
return;
}
int errorAttachment = GoodsAttachments.BindAttachment(attachmentinfo, goodsinfo.Goodsid, sb,
goodsinfo.Categoryid, userid);
int[] aid = GoodsAttachments.CreateAttachments(attachmentinfo);
string tempMessage = GoodsAttachments.FilterLocalTags(aid, attachmentinfo, goodsinfo.Message);
if (attachmentinfo.Length == (System.Web.HttpContext.Current.Request.Files.Count-2))
{
goodsinfo.Goodspic = attachmentinfo[0].Filename;
goodsinfo.Aid = aid[0];
}
if (!tempMessage.Equals(goodsinfo.Message))
{
goodsinfo.Message = tempMessage;
}
Goods.UpdateGoods(goodsinfo);
UserCredits.UpdateUserCreditsByUploadAttachment(userid, aid.Length - errorAttachment);
}
当然,如果我们修改了商品分类,则在我们编辑完商品并提交后,系统会对商品原来所在分类进行减1操作,而对所选择
的目标分类进行加1操作,如下所示(discuz.mall项目的App_Code文件夹下的Goods.cs文件):
/// 更新指定商品数据信息
/// </summary>
/// <param name="goodsinfo">商品信息</param>
/// <param name="oldgoodscategoryid">商品分类原值</param>
/// <param name="oldparentcategorylist">商品父分类原值</param>
public static void UpdateGoods(Goodsinfo goodsinfo, int oldgoodscategoryid, string oldparentcategorylist)
{
if (goodsinfo.Categoryid != oldgoodscategoryid && goodsinfo.Categoryid >0)
{
DbProvider.GetInstance().UpdateCategoryGoodsCounts(goodsinfo.Categoryid, goodsinfo.Parentcategorylist, 1);
DbProvider.GetInstance().UpdateCategoryGoodsCounts(oldgoodscategoryid, oldparentcategorylist, -1);
}
DbProvider.GetInstance().UpdateGoods(goodsinfo);
}
当然,如果商品发生“上架”或“下架”变化时,也会执行类似的操作,以确保前台商品列表页面中的商品分类数准备。
如下(discuz.mall项目的Pages文件夹下的editgoods.cs文件):
{
if (displayorder < 0 && goodsinfo.Displayorder > 0) //该商品转为上架
{
DbProvider.GetInstance().UpdateCategoryGoodsCounts(goodsinfo.Categoryid,
goodsinfo.Parentcategorylist, 1);
}else if (displayorder >= 0 && goodsinfo.Displayorder < 0) //该商品转为下架(或进入回收站/待审核状态)
{
DbProvider.GetInstance().UpdateCategoryGoodsCounts(goodsinfo.Categoryid,
goodsinfo.Parentcategorylist, -1);
}}
当然,我们在管理后台还提供了“分类商品数”数据维护的功能,以确保其数值准确。如下图:
到这时,编辑商品的主要功能介绍完了。下面说一下删除商品的功能。
我们可以在“用户中心”中的“我的商品”下的全部商品中找到删除商品的功能(批量删除),如下图:
当系统确认当前用户即是该商品的发布人时,会执行的如下逻辑:
{
Goods.DeleteGoods(goodsidlist, false);
SetUrl("usercpmygoods.aspx?item=" + item + "&filter=" + filter);
SetMetaRefresh();
AddMsgLine("操作成功. <br />(<a href=""usercpmygoods.aspx?item=" + item + "&filter=" + filter + """>点击这里返回</a>)<br />");
}
else
{
AddErrLine("你不是当前商品的卖家,因些无法删除该商品");
return;
}
其中的DeleteGoods方法将会运行如下操作:
/// 在数据库中删除指定商品
/// </summary>
/// <param name="goodsidlist">商品id列表</param>
/// <param name="subtractCredits">是否减少用户积分(0不减少,1减少)</param>
/// <param name="reserveAttach">是否保留附件</param>
/// <returns>删除个数</returns>
public static int DeleteGoods(string goodsidlist, int subtractCredits, bool reserveAttach)
{
if (!Utils.IsNumericArray(goodsidlist.Split(',')))
{
return -1;
}
if (!reserveAttach)
{
IDataReader reader = DbProvider.GetInstance().GetGoodsAttachmentList(goodsidlist);
while (reader.Read())
{
if (reader["filename"].ToString().Trim().ToLower().IndexOf("http") < 0)
{
if ((Utils.FileExists(Utils.GetMapPath(BaseConfigs.GetForumPath + "upload/mall/" +
reader["filename"].ToString()))))
{File.Delete(Utils.GetMapPath(BaseConfigs.GetForumPath + "upload/mall/" +
reader["filename"].ToString()));
}
}
}
reader.Close();
DbProvider.GetInstance().DeleteGoodsAttachments(goodsidlist);
}
foreach (DataRow dr in Goods.GetGoodsList(goodsidlist).Rows)
{
DbProvider.GetInstance().UpdateCategoryGoodsCounts(Convert.ToInt32(dr["categoryid"].ToString()),
dr["parentcategorylist"].ToString().Trim(), -1);
}int reval = DbProvider.GetInstance().DeleteGoods(goodsidlist);
return reval;
}
主要是对商品附件的删除,用户积分以及分类商品数等的相关操作,代码比较简单,这里就不多说了:)
好了,今天的内容就先到这里了,因为一些细节暂未详细描述,只是粗略的浏览了一遍,如果大家感兴趣
欢迎在回复中讨论。
作者:代震军,daizhj
原文链接:http://www.cnblogs.com/daizhj/archive/2008/08/12/1260333.html