github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/models/attachment.go (about)

     1  package models
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"strconv"
     9  	"time"
    10  	"github.com/insionng/yougam/helper"
    11  )
    12  
    13  type Attachment struct {
    14  	Id            int64
    15  	Pid           int64   `xorm:"index"` //为0代表没有上级,本身就是顶层附件 大于0则本身是子附件,而该数字代表上级附件的id
    16  	Cid           int64   `xorm:"index"`
    17  	Nid           int64   `xorm:"index"` //nodeid
    18  	Uid           int64   `xorm:"index"`
    19  	Sort          int64   `xorm:"index"` //排序字段 需要手动对附件排序置顶等操作时使用
    20  	Ctype         int64   `xorm:"index"` //ctype作用在于区分附件的类型
    21  	Content       string  `xorm:"text"`  //资源URL
    22  	Tags          string  `xorm:"index"`
    23  	Created       int64   `xorm:"created index"`
    24  	Updated       int64   `xorm:"updated"`
    25  	Hotness       float64 `xorm:"index"`
    26  	Confidence    float64 `xorm:"index"` //信任度数值
    27  	Hotup         int64   `xorm:"index"`
    28  	Hotdown       int64   `xorm:"index"`
    29  	Hotscore      int64   `xorm:"index"` //Hotup  -	Hotdown
    30  	Hotvote       int64   `xorm:"index"` //Hotup  + Hotdown
    31  	Views         int64
    32  	Author        string `xorm:"index"`
    33  	Category      string `xorm:"index"`
    34  	Node          string `xorm:"index"` //nodename
    35  	FavoriteCount int64
    36  	Latitude      float64 `xorm:"index"`   //纬度
    37  	Longitude     float64 `xorm:"index"`   //经度
    38  	Version       int64   `xorm:"version"` //乐观锁
    39  }
    40  
    41  func AddAttachment(content string, pid, cid, nid, uid int64) (int64, error) {
    42  	// 创建 Session 对象
    43  	sess := Engine.NewSession()
    44  	defer sess.Close()
    45  	// 启动事务
    46  	if err := sess.Begin(); err != nil {
    47  		return -1, err
    48  	}
    49  
    50  	//执行事务
    51  	attachmentid := int64(0)
    52  	{
    53  		cat := &Category{}
    54  		if cid > 0 {
    55  			if has, err := sess.Where("id=?", cid).Get(cat); (err != nil) || (has == false) {
    56  				sess.Rollback()
    57  				return -1, err
    58  			}
    59  		}
    60  
    61  		nd := &Node{}
    62  		if nid > 0 {
    63  			if has, err := sess.Where("id=?", nid).Get(nd); (err != nil) || (has == false) {
    64  				sess.Rollback()
    65  				return -1, err
    66  			}
    67  		}
    68  
    69  		usr := &User{}
    70  		if uid > 0 {
    71  			if has, err := sess.Where("id=?", uid).Get(usr); (err != nil) || (has == false) {
    72  				sess.Rollback()
    73  				return -1, err
    74  			}
    75  		}
    76  
    77  		obj := new(Attachment)
    78  		obj.Pid = pid
    79  		obj.Cid = cat.Id
    80  		obj.Nid = nid
    81  		obj.Uid = uid
    82  		obj.Content = content
    83  		obj.Author = usr.Username
    84  		obj.Category = cat.Title
    85  		obj.Node = nd.Title
    86  		obj.Created = time.Now().Unix()
    87  
    88  		if row, err := sess.Insert(obj); (err == nil) && (row > 0) {
    89  			if obj.Uid > 0 {
    90  				n, _ := sess.Where("uid=?", obj.Uid).Count(&Attachment{})
    91  				_u := map[string]interface{}{"attachment_time": time.Now().Unix(), "attachment_count": n, "attachment_last_nid": obj.Nid, "attachment_last_node": obj.Node}
    92  				if row, err := sess.Table(&User{}).Where("id=?", obj.Uid).Update(&_u); err != nil || row <= 0 {
    93  
    94  					return -1, errors.New(fmt.Sprint("AddAttachment更新user表附件相关信息时:出现", row, "行影响,错误:", err))
    95  
    96  				}
    97  			}
    98  			attachmentid = obj.Id
    99  		} else {
   100  			sess.Rollback()
   101  			return -1, err
   102  		}
   103  
   104  	}
   105  
   106  	// 提交事务
   107  	return attachmentid, sess.Commit()
   108  }
   109  
   110  func SetAttachment(tid int64, obj *Attachment) (int64, error) {
   111  	obj.Id = tid
   112  	return Engine.Insert(obj)
   113  }
   114  
   115  func GetAttachmentsByHotnessNodes(nodelimit int, attachmentlimit int) []*[]*Attachment {
   116  	//找出最热的节点:views优先 然后按 hotness排序 大概找出5到10个节点
   117  	//按上面找的节点读取下级附件
   118  	nds, _ := GetNodes(0, nodelimit, "hotness")
   119  	attachments := make([]*[]*Attachment, 0)
   120  
   121  	if len(*nds) > 0 {
   122  		i := 0
   123  		for _, v := range *nds {
   124  			i = i + 1
   125  			objs := GetAttachmentsByNid(v.Id, 0, attachmentlimit, 0, "views")
   126  			if len(*objs) != 0 {
   127  				attachments = append(attachments, objs)
   128  			}
   129  			if i == len(*nds)-1 {
   130  				break
   131  			}
   132  		}
   133  	}
   134  
   135  	return attachments
   136  
   137  }
   138  
   139  func GetAttachmentsByScoreNodes(nodelimit int, attachmentlimit int) []*[]*Attachment {
   140  	//找出最热的节点:views优先 然后按 hotness排序 大概找出5到10个节点
   141  	//按上面找的节点读取下级附件
   142  	nds, _ := GetNodes(0, nodelimit, "hotscore")
   143  	attachments := make([]*[]*Attachment, 0)
   144  
   145  	if len(*nds) > 0 {
   146  		i := 0
   147  		for _, v := range *nds {
   148  			i = i + 1
   149  			objs := GetAttachmentsByNid(v.Id, 0, attachmentlimit, 0, "views")
   150  			if len(*objs) != 0 {
   151  				attachments = append(attachments, objs)
   152  			}
   153  			if i == len(*nds) {
   154  				break
   155  			}
   156  		}
   157  	}
   158  
   159  	return attachments
   160  
   161  }
   162  
   163  func GetAttachmentsByHotnessCategory(catlimit int, attachmentlimit int) []*[]*Attachment {
   164  	//找出最热的分类:views优先 然后按 hotness排序 大概找出5到10个节点
   165  	//按上面找的节点读取下级附件
   166  	cats, _ := GetCategories(0, catlimit, "hotness")
   167  	attachments := make([]*[]*Attachment, 0)
   168  
   169  	if len(*cats) > 0 {
   170  		i := 0
   171  		for _, v := range *cats {
   172  			i = i + 1
   173  			//(cid int64, offset int, limit int, ctype int64, field string)
   174  			objs := GetAttachmentsByCid(v.Id, 0, attachmentlimit, 0, "views")
   175  			if len(*objs) != 0 {
   176  				attachments = append(attachments, objs)
   177  			}
   178  			if i == len(*cats) {
   179  				break
   180  			}
   181  		}
   182  	}
   183  
   184  	return attachments
   185  
   186  }
   187  
   188  func GetAttachment(id int64) (*Attachment, error) {
   189  	obj := new(Attachment)
   190  	has, err := Engine.Id(id).Get(obj)
   191  	if has {
   192  		return obj, err
   193  	} else {
   194  		return nil, err
   195  	}
   196  }
   197  
   198  func GetAttachments(offset int, limit int, field string) (*[]*Attachment, error) {
   199  	objs := new([]*Attachment)
   200  	err := Engine.Limit(limit, offset).Desc(field).Find(objs)
   201  	return objs, err
   202  }
   203  
   204  func GetSubAttachments(pid int64, offset int, limit int, field string) (*[]*Attachment, error) {
   205  	objs := new([]*Attachment)
   206  	err := Engine.Where("pid=?", pid).Limit(limit, offset).Desc(field).Find(objs)
   207  	return objs, err
   208  }
   209  
   210  func GetAttachmentsCount(offset int, limit int) (int64, error) {
   211  	total, err := Engine.Limit(limit, offset).Count(&Attachment{})
   212  	return total, err
   213  }
   214  
   215  func GetAttachmentsByPid4Count(pid int64, offset int, limit int, ctype int64) (int64, error) {
   216  
   217  	if ctype != 0 {
   218  		return Engine.Where("(pid=? or id=?) and ctype=?", pid, pid, ctype).Limit(limit, offset).Count(&Attachment{})
   219  	} else {
   220  		return Engine.Where("pid=? or id=?", pid, pid).Limit(limit, offset).Count(&Attachment{})
   221  	}
   222  
   223  }
   224  
   225  func GetAttachmentsCountByNode(node string, offset int, limit int) (int64, error) {
   226  	total, err := Engine.Where("node=?", node).Limit(limit, offset).Count(&Attachment{})
   227  	return total, err
   228  }
   229  
   230  func GetAttachmentsByCategoryCount(category string, offset int, limit int, field string) (int64, error) {
   231  	total, err := Engine.Where("category=?", category).Limit(limit, offset).Count(&Attachment{})
   232  	return total, err
   233  }
   234  
   235  //GetAttachmentsByCid大数据下如出现性能问题 可以使用 GetAttachmentsByCidOnBetween
   236  func GetAttachmentsByCid(cid int64, offset int, limit int, ctype int64, field string) *[]*Attachment {
   237  	//排序首先是热值优先,然后是时间优先。
   238  	objs := new([]*Attachment)
   239  	switch {
   240  	case field == "asc":
   241  		if ctype != 0 {
   242  			Engine.Where("cid=? and ctype=?", cid, ctype).Limit(limit, offset).Asc("id").Find(objs)
   243  		} else {
   244  			Engine.Where("cid=?", cid).Limit(limit, offset).Asc("id").Find(objs)
   245  
   246  		}
   247  	case field == "views" || field == "reply_count":
   248  		if ctype != 0 {
   249  			Engine.Where("cid=? and ctype=?", cid, ctype).Desc(field).Limit(limit, offset).Find(objs)
   250  
   251  		} else {
   252  			if cid == 0 {
   253  				Engine.Desc(field).Limit(limit, offset).Find(objs)
   254  			} else {
   255  				Engine.Where("cid=?", cid).Desc(field).Limit(limit, offset).Find(objs)
   256  			}
   257  
   258  		}
   259  	default:
   260  		if ctype != 0 {
   261  			Engine.Where("cid=? and ctype=?", cid, ctype).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   262  		} else {
   263  			if cid == 0 {
   264  				Engine.Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   265  			} else {
   266  				Engine.Where("cid=?", cid).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   267  			}
   268  		}
   269  
   270  	}
   271  	return objs
   272  }
   273  
   274  func GetAttachmentsByCidOnBetween(cid int64, startid int64, endid int64, offset int, limit int, ctype int64, field string) *[]*Attachment {
   275  	objs := new([]*Attachment)
   276  	switch {
   277  	case field == "asc":
   278  		if ctype != 0 {
   279  			Engine.Where("cid=? and ctype=? and id>? and id<?", cid, ctype, startid-1, endid+1).Limit(limit, offset).Asc("id").Find(objs)
   280  		} else {
   281  			if cid == 0 {
   282  				Engine.Where("id>? and id<?", startid-1, endid+1).Limit(limit, offset).Asc("id").Find(objs)
   283  			} else {
   284  				Engine.Where("cid=? and id>? and id<?", cid, startid-1, endid+1).Limit(limit, offset).Asc("id").Find(objs)
   285  			}
   286  		}
   287  	default: //Desc
   288  		if ctype != 0 {
   289  			Engine.Where("cid=? and ctype=? and id>? and id<?", cid, ctype, startid-1, endid+1).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   290  		} else {
   291  			if cid == 0 {
   292  				Engine.Where("id>? and id<?", startid-1, endid+1).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   293  			} else {
   294  				Engine.Where("cid=? and id>? and id<?", cid, startid-1, endid+1).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   295  			}
   296  		}
   297  	}
   298  
   299  	return objs
   300  }
   301  
   302  func GetAttachmentsByCategory(category string, offset int, limit int, ctype int64, field string) *[]*Attachment {
   303  	//排序首先是热值优先,然后是时间优先。
   304  	objs := new([]*Attachment)
   305  	switch {
   306  	case field == "asc":
   307  		if ctype != 0 {
   308  			Engine.Where("category=? and ctype=?", category, ctype).Limit(limit, offset).Asc("id").Find(objs)
   309  		} else {
   310  			Engine.Where("category=?", category).Limit(limit, offset).Asc("id").Find(objs)
   311  
   312  		}
   313  	case field == "views" || field == "reply_count":
   314  		if ctype != 0 {
   315  			Engine.Where("category=? and ctype=?", category, ctype).Desc(field).Limit(limit, offset).Find(objs)
   316  
   317  		} else {
   318  			if category == "" {
   319  				Engine.Desc(field).Limit(limit, offset).Find(objs)
   320  			} else {
   321  				Engine.Where("category=?", category).Desc(field).Limit(limit, offset).Find(objs)
   322  			}
   323  
   324  		}
   325  	default:
   326  		if ctype != 0 {
   327  			Engine.Where("category=? and ctype=?", category, ctype).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   328  		} else {
   329  			if category == "" {
   330  				Engine.Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   331  			} else {
   332  				Engine.Where("category=?", category).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   333  			}
   334  		}
   335  
   336  	}
   337  	return objs
   338  }
   339  
   340  //GetAttachmentsByUid不区分父子附件
   341  func GetAttachmentsByUid(uid int64, offset int, limit int, ctype int64, field string) *[]*Attachment {
   342  	//排序首先是热值优先,然后是时间优先。
   343  	objs := new([]*Attachment)
   344  
   345  	switch {
   346  	case field == "asc":
   347  		if uid == 0 {
   348  			//q.Offset(offset).Limit(limit).OrderByDesc(field).OrderByDesc("views").OrderByDesc("reply_count").OrderByDesc("created").FindAll(&allt)
   349  			return nil
   350  		} else {
   351  			if ctype != 0 {
   352  				Engine.Where("uid=? and ctype=?", uid, ctype).Limit(limit, offset).Asc("id").Find(objs)
   353  			} else {
   354  				Engine.Where("uid=?", uid).Limit(limit, offset).Asc("id").Find(objs)
   355  			}
   356  		}
   357  	default:
   358  		if uid <= 0 {
   359  			//q.Offset(offset).Limit(limit).OrderByDesc(field).OrderByDesc("views").OrderByDesc("reply_count").OrderByDesc("created").FindAll(&allt)
   360  			return nil
   361  		} else {
   362  			if ctype != 0 {
   363  				Engine.Where("uid=? and ctype=?", uid, ctype).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   364  			} else {
   365  				Engine.Where("uid=?", uid).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   366  			}
   367  		}
   368  	}
   369  	return objs
   370  }
   371  
   372  func GetAttachmentsByNid(nodeid int64, offset int, limit int, ctype int64, field string) *[]*Attachment {
   373  	//排序首先是热值优先,然后是时间优先。
   374  	objs := new([]*Attachment)
   375  
   376  	switch {
   377  	case field == "asc":
   378  		if nodeid == 0 {
   379  			//q.Offset(offset).Limit(limit).OrderByDesc(field).OrderByDesc("views").OrderByDesc("reply_count").OrderByDesc("created").FindAll(&allt)
   380  			return nil
   381  		} else {
   382  			if ctype != 0 {
   383  				Engine.Where("nid=? and ctype=?", nodeid, ctype).Limit(limit, offset).Asc("id").Find(objs)
   384  			} else {
   385  				Engine.Where("nid=?", nodeid).Limit(limit, offset).Asc("id").Find(objs)
   386  			}
   387  		}
   388  	default:
   389  		if nodeid == 0 {
   390  			//q.Offset(offset).Limit(limit).OrderByDesc(field).OrderByDesc("views").OrderByDesc("reply_count").OrderByDesc("created").FindAll(&allt)
   391  			return nil
   392  		} else {
   393  			if ctype != 0 {
   394  				Engine.Where("nid=? and ctype=?", nodeid, ctype).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   395  			} else {
   396  				Engine.Where("nid=?", nodeid).Limit(limit, offset).Desc(field, "views", "reply_count", "created").Find(objs)
   397  			}
   398  		}
   399  	}
   400  	return objs
   401  }
   402  
   403  func GetAttachmentsByPid(pid int64, offset int, limit int, ctype int64, field string) *[]*Attachment {
   404  
   405  	objs := new([]*Attachment)
   406  
   407  	switch {
   408  	case field == "asc":
   409  		{
   410  			if pid > 0 { //即只查询单个附件的父级与子级,此时sort字段无效,所以无须作为条件参与排序
   411  				if ctype != 0 {
   412  					Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.ctype=?", pid, pid, ctype).Limit(limit, offset).Asc("attachment.id").Find(objs)
   413  				} else {
   414  					Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?)", pid, pid).Limit(limit, offset).Asc("attachment.id").Find(objs)
   415  				}
   416  			} else {
   417  				if ctype != 0 {
   418  					Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort<=?", pid, pid, ctype, 0).Limit(limit, offset).Asc("attachment.id").Find(objs)
   419  				} else {
   420  					Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.sort<=?", pid, pid, 0).Limit(limit, offset).Asc("attachment.id").Find(objs)
   421  				}
   422  			}
   423  
   424  		}
   425  	case field == "cold":
   426  		{
   427  			if ctype != 0 {
   428  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort<=?", pid, pid, ctype, 0).Limit(limit, offset).Asc("attachment.views").Find(objs)
   429  			} else {
   430  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.sort<=?", pid, pid, 0).Limit(limit, offset).Asc("attachment.views").Find(objs)
   431  			}
   432  		}
   433  	case field == "sort":
   434  		{ //Desc("attachment.sort", "attachment.confidence") ,这段即是"attachment.sort"的优先级较"attachment.confidence"要高
   435  			if ctype != 0 {
   436  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort>?", pid, pid, ctype, 0).Limit(limit, offset).Desc("attachment.sort", "attachment.confidence").Find(objs)
   437  			} else {
   438  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.sort>?", pid, pid, 0).Limit(limit, offset).Desc("attachment.sort", "attachment.confidence").Find(objs)
   439  			}
   440  		}
   441  	default:
   442  		{
   443  			if field == "desc" {
   444  				field = "id"
   445  			}
   446  			if ctype != 0 {
   447  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort<=?", pid, pid, ctype, 0).Limit(limit, offset).Desc("attachment."+field, "attachment.views", "attachment.reply_count", "attachment.created").Find(objs)
   448  			} else {
   449  				Engine.Table("attachment").Where("(attachment.pid=? or attachment.id=?)", pid, pid).And("attachment.sort<=?", 0).Limit(limit, offset).Desc("attachment."+field, "attachment.views", "attachment.reply_count", "attachment.created").Find(objs)
   450  			}
   451  		}
   452  	}
   453  	return objs
   454  }
   455  
   456  func GetAttachmentsByPidSinceCreated(pid int64, offset int, limit int, ctype int64, field string, since int64) *[]*Attachment {
   457  
   458  	switch objs := new([]*Attachment); {
   459  	case field == "asc":
   460  		{
   461  			if ctype != 0 {
   462  				Engine.Table("attachment").Where("attachment.created>? and (attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort<=?", since, pid, pid, ctype, 0).Limit(limit, offset).Asc("attachment.id").Find(objs)
   463  			} else {
   464  				Engine.Table("attachment").Where("attachment.created>? and (attachment.pid=? or attachment.id=?) and attachment.sort<=?", since, pid, pid, 0).Limit(limit, offset).Asc("attachment.id").Find(objs)
   465  			}
   466  			return objs
   467  		}
   468  	default:
   469  		{
   470  			if ctype != 0 {
   471  				Engine.Table("attachment").Where("attachment.created>? and (attachment.pid=? or attachment.id=?) and attachment.ctype=? and attachment.sort<=?", since, pid, pid, ctype, 0).Limit(limit, offset).Desc("attachment."+field, "attachment.views", "attachment.reply_count", "attachment.created").Find(objs)
   472  			} else {
   473  				Engine.Table("attachment").Where("attachment.created>? and (attachment.pid=? or attachment.id=?) and attachment.sort<=?", since, pid, pid, 0).Limit(limit, offset).Desc("attachment."+field, "attachment.views", "attachment.reply_count", "attachment.created").Find(objs)
   474  			}
   475  			return objs
   476  		}
   477  	}
   478  
   479  }
   480  
   481  func GetAttachmentsByNode(node string, offset int, limit int, field string) (*[]*Attachment, error) {
   482  	objs := new([]*Attachment)
   483  	err := Engine.Where("node=?", node).Limit(limit, offset).Desc(field).Find(objs)
   484  	return objs, err
   485  }
   486  
   487  //发布附件  返回 附件id,错误
   488  func PostAttachment(obj *Attachment) (int64, error) {
   489  	// 创建 Session 对象
   490  	sess := Engine.NewSession()
   491  	defer sess.Close()
   492  	// 启动事务
   493  	if err := sess.Begin(); err != nil {
   494  		return -1, err
   495  	}
   496  
   497  	//执行事务
   498  	attachmentid := int64(0)
   499  	if _, err := sess.Insert(obj); err == nil && obj != nil {
   500  
   501  		if obj.Nid > 0 {
   502  			n, _ := sess.Where("nid=?", obj.Nid).Count(&Attachment{})
   503  			_n := map[string]interface{}{"author": obj.Author, "attachment_time": time.Now().Unix(), "attachment_count": n, "attachment_last_user_id": obj.Uid}
   504  			if row, err := sess.Table(&Node{}).Where("id=?", obj.Nid).Update(&_n); err != nil || row <= 0 {
   505  				sess.Rollback()
   506  				return -1, errors.New(fmt.Sprint("PostAttachment更新node表附件相关信息时,执行:", row, "行变更,出现错误:", err))
   507  			}
   508  		}
   509  
   510  		if obj.Uid > 0 {
   511  			n, _ := sess.Where("uid=?", obj.Uid).Count(&Attachment{})
   512  			_u := map[string]interface{}{"attachment_time": time.Now().Unix(), "attachment_count": n, "attachment_last_nid": obj.Nid, "attachment_last_node": obj.Node}
   513  			if row, err := sess.Table(&User{}).Where("id=?", obj.Uid).Update(&_u); err != nil || row == 0 {
   514  				sess.Rollback()
   515  				return -1, errors.New(fmt.Sprint("PostAttachment更新user表附件相关信息时,执行:", row, "行变更,出现错误:", err))
   516  			}
   517  		}
   518  
   519  		attachmentid = obj.Id
   520  	} else {
   521  		// 发生错误时进行回滚
   522  		sess.Rollback()
   523  		return -1, err
   524  	}
   525  
   526  	// 提交事务
   527  	return attachmentid, sess.Commit()
   528  }
   529  
   530  func PutAttachment(tid int64, obj *Attachment) (int64, error) {
   531  	//覆盖式更新
   532  	sess := Engine.NewSession()
   533  	defer sess.Close()
   534  	// 启动事务
   535  	if err := sess.Begin(); err != nil {
   536  		return -1, err
   537  	}
   538  
   539  	//执行事务
   540  	attachmentid := int64(0)
   541  	if row, err := sess.Update(obj, &Attachment{Id: tid}); err != nil || row <= 0 {
   542  		sess.Rollback()
   543  		return -1, err
   544  	} else {
   545  		if obj.Uid > 0 {
   546  			n, _ := sess.Where("uid=?", obj.Uid).Count(&Attachment{})
   547  			_u := map[string]interface{}{"attachment_time": time.Now().Unix(), "attachment_count": n, "attachment_last_nid": obj.Nid, "attachment_last_node": obj.Node}
   548  			if row, err := sess.Table(&User{}).Where("id=?", obj.Uid).Update(&_u); err != nil || row <= 0 {
   549  				sess.Rollback()
   550  				return -1, errors.New(fmt.Sprint("PutAttachment更新user表附件相关信息时,执行:", row, "行变更,出现错误:", err))
   551  			}
   552  		}
   553  
   554  		attachmentid = obj.Id
   555  	}
   556  
   557  	// 提交事务
   558  	return attachmentid, sess.Commit()
   559  }
   560  
   561  func PutAttachmentViaVersion(tid int64, attachment *Attachment) (int64, error) {
   562  	/*
   563  		//乐观锁目前不支持map 以下句式无效!
   564  			return Engine.Table(&Attachment{}).Where("id=?", tid).Update(&map[string]interface{}{
   565  				"views":   views,
   566  				"version": version,
   567  			})
   568  	*/
   569  	//return Engine.Table(&Attachment{}).Where("id=?", tid).Update(attachment)
   570  	return Engine.Id(tid).Update(attachment)
   571  }
   572  
   573  func PutViews2AttachmentViaVersion(tid int64, attachment *Attachment) (int64, error) {
   574  	/*
   575  		return Engine.Table(&Attachment{}).Where("id=?", tid).Update(&map[string]interface{}{
   576  			"views": views,
   577  		})
   578  	*/
   579  	return Engine.Id(tid).Cols("views").Update(attachment)
   580  }
   581  
   582  //func PutSort2Attachment(tid int64, sort int64) (int64, error) {
   583  func PutSort2AttachmentViaVersion(tid int64, attachment *Attachment) (int64, error) {
   584  	/*
   585  		return Engine.Table(&Attachment{}).Where("id=?", tid).Update(&map[string]interface{}{
   586  			"sort": sort,
   587  		})
   588  	*/
   589  	return Engine.Id(tid).Cols("sort").Update(attachment)
   590  }
   591  
   592  func DelAttachment(id int64, uid int64, role int64) error {
   593  
   594  	allow := false
   595  	if role < 0 {
   596  		allow = true
   597  	}
   598  
   599  	attachment := new(Attachment)
   600  
   601  	if has, err := Engine.Id(id).Get(attachment); has == true && err == nil {
   602  
   603  		if attachment.Uid == uid || allow {
   604  			//检查附件字段并尝试删除文件
   605  			if len(attachment.Content) > 0 {
   606  
   607  				if p := helper.URL2local(attachment.Content); helper.Exist(p) {
   608  
   609  					//验证是否管理员权限
   610  					if allow {
   611  						if err := os.Remove(p); err != nil {
   612  							//可以输出错误,但不要反回错误,以免陷入死循环无法删掉
   613  							log.Println("ROOT DEL ATTACHMENT Content, ATTACHMENT ID:", id, ",ERR:", err)
   614  						}
   615  					} else { //检查用户对文件的所有权
   616  						if helper.VerifyUserfile(p, strconv.Itoa(int(uid))) {
   617  							if err := os.Remove(p); err != nil {
   618  								log.Println("DEL ATTACHMENT Content, ATTACHMENT ID:", id, ",ERR:", err)
   619  							}
   620  						}
   621  					}
   622  				} /*else {
   623  
   624  					////删除七牛云存储中的图片
   625  					rsCli := rs.New(nil)
   626  
   627  					//2014-8-21-134506AB4F24A56EF60543.jpg,2014-8-21-134506AB4F24A56EF60543.jpg
   628  					imgkeys := strings.Split(attachment.Attachment, ",")
   629  					for _, v := range imgkeys {
   630  						rsCli.Delete(nil, BUCKET, strings.Split(v, ".")[0]) //key是32位  不含后缀
   631  					}
   632  
   633  				}
   634  				*/
   635  			}
   636  
   637  			//检查内容字段并尝试删除文件
   638  			if len(attachment.Content) > 0 {
   639  				//若内容中存在图片则开始尝试删除图片
   640  				delfiles_local := []string{}
   641  
   642  				if m, n := helper.GetImages(attachment.Content); n > 0 {
   643  
   644  					for _, v := range m {
   645  						if helper.IsLocal(v) {
   646  							delfiles_local = append(delfiles_local, v)
   647  							//如果本地同时也存在banner缓存文件,则加入旧图集合中,等待后面一次性删除
   648  							if p := helper.URL2local(helper.SetSuffix(v, "_banner.jpg")); helper.Exist(p) {
   649  								delfiles_local = append(delfiles_local, p)
   650  							}
   651  							if p := helper.URL2local(helper.SetSuffix(v, "_large.jpg")); helper.Exist(p) {
   652  								delfiles_local = append(delfiles_local, p)
   653  							}
   654  							if p := helper.URL2local(helper.SetSuffix(v, "_medium.jpg")); helper.Exist(p) {
   655  								delfiles_local = append(delfiles_local, p)
   656  							}
   657  							if p := helper.URL2local(helper.SetSuffix(v, "_small.jpg")); helper.Exist(p) {
   658  								delfiles_local = append(delfiles_local, p)
   659  							}
   660  						}
   661  					}
   662  					for k, v := range delfiles_local {
   663  						if p := helper.URL2local(v); helper.Exist(p) { //如若文件存在,则处理,否则忽略
   664  							//先行判断是否缩略图  如果不是则执行删除image表记录的操作 因为缩略图是没有存到image表记录里面的
   665  							/*
   666  								isThumbnails := bool(true) //false代表不是缩略图 true代表是缩略图
   667  								if (!strings.HasSuffix(v, "_large.jpg")) &&
   668  									(!strings.HasSuffix(v, "_medium.jpg")) &&
   669  									(!strings.HasSuffix(v, "_small.jpg")) {
   670  									isThumbnails = false
   671  
   672  								}
   673  							*/
   674  
   675  							//验证是否管理员权限
   676  							if allow {
   677  								if err := os.Remove(p); err != nil {
   678  									log.Println("#", k, ",ROOT DEL FILE ERROR:", err)
   679  								}
   680  
   681  								//删除image表中已经被删除文件的记录
   682  								/*
   683  									if !isThumbnails {
   684  										if e := DelImageByLocation(v); e != nil {
   685  											fmt.Println("DelImageByLocation删除未使用文件", v, "的数据记录时候出现错误:", e)
   686  										}
   687  									}
   688  								*/
   689  							} else { //检查用户对文件的所有权
   690  								if helper.VerifyUserfile(p, strconv.Itoa(int(uid))) {
   691  									if err := os.Remove(p); err != nil {
   692  										log.Println("#", k, ",DEL FILE ERROR:", err)
   693  									}
   694  
   695  									//删除image表中已经被删除文件的记录
   696  									/*
   697  										if !isThumbnails {
   698  											if e := DelImageByLocation(v); e != nil {
   699  												fmt.Println("v:", v)
   700  												fmt.Println("DelImageByLocation删除未使用文件", v, "的数据记录时候出现错误:", e)
   701  											}
   702  										}
   703  									*/
   704  								}
   705  							}
   706  
   707  						}
   708  					}
   709  				}
   710  			}
   711  
   712  			//不管实际路径中是否存在文件均删除该数据库记录,以免数据库记录陷入死循环无法删掉
   713  			if attachment.Id == id {
   714  
   715  				if row, err := Engine.Id(id).Delete(new(Attachment)); err != nil || row == 0 {
   716  					log.Println("row:", row, "删除附件错误:", err)
   717  					return errors.New("E,删除附件错误!")
   718  				}
   719  				return nil
   720  			}
   721  
   722  		}
   723  		return errors.New("你无权删除此附件:" + strconv.FormatInt(id, 10))
   724  	}
   725  	return errors.New("无法删除不存在的ATTACHMENT ID:" + strconv.FormatInt(id, 10))
   726  }
   727  
   728  func GetAttachmentCountByNid(nid int64) int64 {
   729  	n, _ := Engine.Where("nid=?", nid).Count(&Attachment{Nid: nid})
   730  	return n
   731  }