Esempio n. 1
0
/* 解析完整html代码中charset属性 */
func HtmlMetaCharset(html string) string {
	html = strings.ToLower(html)
	top := beego.Substr(html, 0, 2000) //取出足够多的头部
	start := strings.Index(top, "charset=")
	bs := []byte(top)[start+8:]
	out := string(bs)                                                                            //截取charset后面的字符串
	quoteStart := strings.Index(out, "\"")                                                       //找到第一个"
	ltStart := strings.Index(out, "<")                                                           //第一个<
	gtStart := strings.Index(out, ">")                                                           //第一个>
	eqStart := strings.Index(out, "=")                                                           //第一个=
	if quoteStart > -1 && quoteStart < ltStart && quoteStart < gtStart && quoteStart < eqStart { //"存在并且在< > =左边
		return beego.Substr(out, 0, quoteStart)
	}
	return ""
}
Esempio n. 2
0
/* 获取分类部分文章内容 */
func (this *ArticleController) CategoryGetArticles() {
	category := &models.Category{}
	//获得页面数
	page, _ := this.GetInt("page")

	if page < 1 {
		page = 1
	}

	ok, _, _, articles, _, _ := category.FindByName(this.GetString("category"), int(page-1)*15, int(page)*15, 15)

	if !ok { //不存在此分类
		this.StopRun()
	}

	results := make([]ArticleReturn, len(articles))

	//查询每个文章的分类信息
	for k, _ := range articles {
		category.FindOne(articles[k].Category)
		results[k].Art = articles[k]
		//查找第一个图片
		results[k].Image = FindImages(results[k].Art.Content, 1)[0]
		//移除markdown标识
		results[k].Art.Content = RemoveMarkdown(results[k].Art.Content)
		//截取长度200
		if isMobile := IsMobile(this.Ctx.Input.UserAgent()); isMobile {
			results[k].Art.Content = beego.Substr(results[k].Art.Content, 0, 100)
		} else {
			results[k].Art.Content = beego.Substr(results[k].Art.Content, 0, 200)
		}
		results[k].CategoryName = category.Title
		results[k].CategoryPath = category.Name
		results[k].Time = results[k].Art.Time.Format("2006-01-02 15:04:05")
	}

	//查询每个文章作者信息和日期
	member := &models.Member{}
	for k, _ := range articles {
		member.FindOne(articles[k].Uid.Hex())
		results[k].AuthorName = member.Nickname
	}

	this.Data["json"] = results
	this.ServeJson()
}
Esempio n. 3
0
func genBackBtn(currentpath string) (out template.HTML) {
	if currentpath != "/" {
		subpath := beego.Substr(currentpath, 0, len(currentpath)-len(filepath.Base(currentpath))-1)

		return template.HTML("<a href=\"/index?path=" + subpath + "\"  class=\"btn-sm btn-primary \">后退</a>")
	}
	return

}
Esempio n. 4
0
/* 获取游戏基本信息 */
func (this *GameController) GetInfo() {
	game := &models.Game{}

	ok, data := func() (bool, interface{}) {
		if !game.FindPath(this.GetString("game")) {
			return false, nil
		}

		//查询该游戏的下属分类
		gameCategory := &models.GameCategory{}
		categorys := gameCategory.FindCategorys(game.Id)

		//遍历每个分类,查询前N个最新推送
		news := make([][]*models.Topic, len(categorys))
		topic := &models.Topic{}
		for k, _ := range categorys {
			// 推荐数量0则不查询
			if categorys[k].Recommend == 0 {
				news[k] = nil
				continue
			}

			news[k] = topic.FindNew(game.Id, categorys[k].Id, categorys[k].Recommend)
			for key, _ := range news[k] {
				news[k][key].Content = beego.Substr(news[k][key].Content, 0, 200)
			}
		}

		return true, map[string]interface{}{
			"Ok":        true,
			"Game":      game,      //游戏信息
			"News":      news,      //最新资讯(每个分类的)
			"Categorys": categorys, //分类信息
		}
	}()

	this.Data["json"] = map[string]interface{}{
		"ok":   ok,
		"data": data,
	}
	this.ServeJson()
}
Esempio n. 5
0
// 获取列表
func (this *TagController) GetList() {
	ok, data := func() (bool, interface{}) {
		if len([]rune(this.GetString("name"))) > 30 {
			return false, "标签最大长度为30"
		}

		from, _ := this.GetInt("from")
		number, _ := this.GetInt("number")

		if number > 100 {
			return false, "最多显示100项"
		}

		//查找标签
		topic := &models.Topic{}
		articles := topic.FindByTag(this.GetString("game"), this.GetString("tag"), from, number)

		//找出前3个图片并取内容前200个字符
		images := make([][]string, len(articles))
		for k, _ := range articles {
			//查询每个文章前3个图片
			images[k] = FindImages(articles[k].Content, 3)
			//内容长度截取
			articles[k].Content = beego.Substr(articles[k].Content, 0, 200)
		}

		//查询该分类文章总数
		count := topic.FindTagCount(this.GetString("game"), this.GetString("tag"))

		return true, map[string]interface{}{
			"articles": articles,
			"images":   images,
			"count":    count,
		}
	}()

	this.Data["json"] = map[string]interface{}{
		"ok":   ok,
		"data": data,
	}
	this.ServeJson()
}
Esempio n. 6
0
// 首页
func (this *MainController) Index() {
	this.Data["pageTitle"] = "系统概况"

	// 即将执行的任务
	entries := jobs.GetEntries(30)
	jobList := make([]map[string]interface{}, len(entries))
	for k, v := range entries {
		row := make(map[string]interface{})
		job := v.Job.(*jobs.Job)
		row["task_id"] = job.GetId()
		row["task_name"] = job.GetName()
		row["next_time"] = beego.Date(v.Next, "Y-m-d H:i:s")
		jobList[k] = row
	}

	// 最近执行的日志
	logs, _ := models.TaskLogGetList(1, 20)
	recentLogs := make([]map[string]interface{}, len(logs))
	for k, v := range logs {
		task, err := models.TaskGetById(v.TaskId)
		taskName := ""
		if err == nil {
			taskName = task.TaskName
		}
		row := make(map[string]interface{})
		row["task_name"] = taskName
		row["id"] = v.Id
		row["start_time"] = beego.Date(time.Unix(v.CreateTime, 0), "Y-m-d H:i:s")
		row["process_time"] = float64(v.ProcessTime) / 1000
		row["ouput_size"] = libs.SizeFormat(float64(len(v.Output)))
		row["output"] = beego.Substr(v.Output, 0, 100)
		row["status"] = v.Status
		recentLogs[k] = row
	}

	this.Data["recentLogs"] = recentLogs
	this.Data["jobs"] = jobList
	this.Data["cpuNum"] = runtime.NumCPU()
	this.display()
}
Esempio n. 7
0
// 获取具有相同标签的文章
func (this *TagController) Same() {
	ok, data := func() (bool, interface{}) {
		// 查找文章
		topic := &models.Topic{}
		if _ok := topic.FindOne(this.GetString("game"), this.GetString("id")); !_ok {
			return false, "文章不存在"
		}

		result := topic.Same()

		//内容截取长度20
		for k, _ := range result {
			result[k].Content = beego.Substr(result[k].Content, 0, 20)
		}

		return true, result
	}()

	this.Data["json"] = map[string]interface{}{
		"ok":   ok,
		"data": data,
	}
	this.ServeJson()
}
func QueryOpenId(accessToken string) (map[string]string, error) {

	var baseUrl = AuthConfig.String("openid_url")
	var fullRequestStr = baseUrl + "?access_token=" + accessToken

	resp, err := http.Get(fullRequestStr)
	if nil != err {
		beego.Error(err)
		return nil, err
	}
	result, err := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	if nil != err {
		beego.Error(err)
		return nil, err
	}

	content := string(result)
	if len(content) == 0 {
		beego.Error(err)
		return nil, err
	}

	beego.Debug("******************queryOpenID:before", content)
	start := strings.Index(content, "{") - 1
	end := strings.LastIndex(content, "}") + 1
	content = beego.Substr(content, start, end-start)
	beego.Debug("******************queryOpenID:after", content)

	var paramMap map[string]string

	err = json.Unmarshal([]byte(content), &paramMap)
	return paramMap, err

}
Esempio n. 9
0
/* 发帖 回帖 回复 编辑请求-post */
func (this *GameController) AddTopic() {
	ok, data := func() (bool, interface{}) {
		if len([]rune(this.GetString("title"))) > 60 {
			return false, "标题最多60个字符"
		}

		if len([]rune(this.GetString("content"))) > 10000 {
			return false, "内容最多10000个字符"
		}

		//未登录
		if this.GetSession("WOKUID") == nil {
			return false, "未登录"
		}

		//查询用户
		member := &models.Member{}
		if ok := member.FindOne(this.GetSession("WOKUID").(string)); !ok {
			return false, "用户不存在"
		}

		//获取游戏信息
		game := &models.Game{}
		if ok := game.FindPath(this.GetString("game")); !ok {
			return false, "该板块不存在"
		}

		//获取分类信息
		gameCategory := &models.GameCategory{}
		if ok := gameCategory.Find(this.GetString("game"), this.GetString("category")); !ok {
			return false, "该分类不存在"
		}

		// 文档模式允许内容为空
		if len([]rune(this.GetString("content"))) < 3 && gameCategory.Type != 1 {
			return false, "内容至少3个字符"
		}

		//3秒钟之内才能回帖
		if time.Now().Sub(member.LastTime).Seconds() < 1 {
			return false, "发帖间隔1秒"
		}
		member.UpdateFinish() //回帖时间重置

		switch this.GetString("type") {
		case "addTopic": //发帖
			if gameCategory.Type == 1 && strings.Trim(this.GetString("title"), " ") == "" {
				return false, "标题不能为空"
			}

			//判断是否有权限
			switch gameCategory.Add {
			case 0: //是否为管理员或版主
				if member.Id != game.Manager && !inArray(member.Id.Hex(), game.Managers) {
					return false, "管理员或版主才能发帖"
				}
				break
			case 1: //登陆即可,不做限制
				break
			}

			// 判断标签是否合法
			tags := this.GetStrings("tag")

			// 标签数量限制、长度限制、同文章不能重复
			if len(tags) >= 5 {
				return false, "最多5个标签"
			}

			for k, _ := range tags {
				if len([]rune(tags[k])) > 30 || len([]rune(tags[k])) < 1 {
					return false, "标签最大长度为30"
				}
			}

			copyTags := tags

			for k, _ := range tags {
				count := 0
				for _k, _ := range copyTags {
					if copyTags[_k] == tags[k] {
						count++

						if count >= 2 {
							return false, "标签不能重复"
						}
					}
				}
			}

			tag := &models.Tag{}
			// tag新增
			for k, _ := range tags {
				tag.Upsert(game.Id, tags[k])
			}

			// 实例化新增文章
			topic := &models.Topic{}
			topic.SetId() //设置id

			// 判断分类类型
			switch gameCategory.Type {
			case 0: // 论坛
			case 1: // 文档
				doc := &DocController{}

				isFolder, _ := this.GetBool("isFolder")

				// 新增文档
				tempOk := false
				tempData := ""
				if tempOk, tempData = doc.Add(this.GetString("title"), isFolder, this.GetString("docId"), this.GetString("docParent"), gameCategory.Id.Hex(), topic.Id.Hex()); !tempOk {
					return false, tempData
				}

				// 如果是目录,不进行后续插入文章操作
				if isFolder {
					return true, tempData
				}
			}

			var title string
			if this.GetString("title") != "" {
				title = this.GetString("title")
			} else {
				title = beego.Substr(this.GetString("content"), 0, 60)
			}

			// 文章赋值
			topic.Game = this.GetString("game")
			topic.Title = title
			topic.Category = gameCategory.Id
			topic.Content = this.GetString("content")
			topic.Ip = this.Ctx.Input.IP()
			topic.Author = member.Id
			topic.AuthorName = member.Nickname
			topic.AuthorImage = member.Image
			topic.LastReply = topic.Author
			topic.Tag = tags

			// 查找内容中所有图片信息,并移动到正确位置,同时替换图片路径
			var uploadSize int64
			uploadSize, topic.Content = HandleNewImage(topic.Content, "game/"+game.Id+"/"+topic.Id.Hex()+"/")

			// 生成内容分词表
			sego := &SegoController{}
			topic.ContentSego = sego.ToSlices(topic.Content, false)

			// 记录用户上传量
			member.UploadSize += uploadSize
			member.Save()

			//插入数据库
			objectId := topic.Insert()

			//TODO: 刷新缓存

			//游戏活跃度+1
			game.Hot++

			//保存板块修改
			game.SaveAll()

			return true, objectId.Hex()
		case "reply": //回复
			//判断是否有权限
			switch gameCategory.Add {
			case 0: //是否为管理员或版主
				if member.Id != game.Manager && !inArray(member.Id.Hex(), game.Managers) {
					return false, "管理员或版主才能发帖"
				}
				break
			case 1: //登陆即可,不做限制
				break
			}

			if len([]rune(this.GetString("content"))) > 5000 {
				return false, "回帖最多5000个字符"
			}

			//查找话题
			topic := &models.Topic{}
			if ok := topic.FindById(this.GetString("topic")); !ok { //不存在此话题
				return false, "回复的帖子不存在"
			}

			//回复数自增1,更新最后一个回复者的id
			topic.Reply++
			topic.OutReply++
			topic.LastReply = member.Id
			topic.LastReplyName = member.Nickname
			topic.LastTime = time.Now()
			topic.Save()

			//实例化回复
			reply := &models.Reply{}
			reply.Game = this.GetString("game")
			reply.Topic = this.GetString("topic")
			reply.Content = this.GetString("content")
			reply.Author = member.Id
			reply.AuthorName = member.Nickname
			reply.AuthorImage = member.Image
			reply.Ip = this.Ctx.Input.IP()
			reply.SetId()

			// 查找内容中所有图片信息,并移动到正确位置,同时替换图片路径
			var uploadSize int64
			uploadSize, reply.Content = HandleNewImage(reply.Content, "game/"+game.Id+"/"+topic.Id.Hex()+"/"+reply.Id.Hex()+"/")

			// 记录用户上传量
			member.UploadSize += uploadSize
			member.Save()

			//插入回复
			reply.Insert()

			//推送消息,如果操作用户不是回复作者的话,通知他
			if topic.Author != member.Id {
				//AddMessage(topic.Author.Hex(), "game", "/g/"+this.GetString("game")+"/"+this.GetString("topic")+".html?p="+this.GetString("page")+"#"+reply.Id.Hex(), "您的一个帖子有了新回复", "<img userImage='"+member.Image+"'>&nbsp;<span class='text-info'>"+member.Nickname+"</span>&nbsp;回复了您的帖子:<span class='text-muted'>&nbsp"+reply.Content+"&nbsp;</span>", "")
			}

			//游戏活跃度+1
			game.Hot++
			game.SaveAll()

			return true, reply.Id.Hex()
		case "rReply": //回复评论
			//判断是否有权限
			switch gameCategory.Add {
			case 0: //是否为管理员或版主
				if member.Id != game.Manager && !inArray(member.Id.Hex(), game.Managers) {
					return false, "管理员或版主才能发帖"
				}
				break
			case 1: //登陆即可,不做限制
				break
			}

			if len([]rune(this.GetString("content"))) > 500 {
				return false, "追加评论最多500个字符"
			}

			//查找话题
			topic := &models.Topic{}
			if ok := topic.FindById(this.GetString("topic")); !ok { //不存在此话题
				return false, "帖子不存在"
			}

			//查找回复
			reply := &models.Reply{}
			if ok := reply.FindById(this.GetString("reply")); ok == false { //没有查找到回复则退出
				return false, "回复不存在"
			}

			//实例化嵌套评论
			newReply := &models.Reply{}
			newReply.Game = this.GetString("game")
			newReply.Topic = this.GetString("topic")
			newReply.Reply = reply.Id.Hex()
			newReply.Content = this.GetString("content")
			newReply.Author = member.Id
			newReply.AuthorName = member.Nickname
			newReply.AuthorImage = member.Image
			newReply.Ip = this.Ctx.Input.IP()
			newReply.SetId()

			//插入嵌套评论
			newReply.Insert()

			//刷新前五个嵌套评论
			reply.FreshCache()

			//回复的评论数量+1
			reply.ReplyNumber++
			reply.Save()

			//帖子回复数自增1,更新最后一个回复者的id
			topic.Reply++
			topic.LastReply = member.Id
			topic.LastReplyName = member.Nickname
			topic.LastTime = time.Now()

			//保存
			topic.Save()

			//TODO:刷新缓存

			//推送消息,如果操作用户不是回复作者的话,通知他
			if reply.Author != member.Id {
				//AddMessage(reply.Author.Hex(), "game", "/g/"+this.GetString("category")+"/"+this.GetString("topic")+"#"+newReply.Id.Hex(), "您的一个回复有了新评论", "<img userImage='"+member.Image+"'>&nbsp;<span class='text-info'>"+member.Nickname+"</span>&nbsp;评论了您的回复:<span class='text-muted'>&nbsp"+newReply.Content+"&nbsp;</span>", "")
			}

			return true, newReply.Id.Hex()
		case "edit": //编辑
			//查询该话题
			topic := &models.Topic{}
			topic.FindById(this.GetString("topic"))

			if topic == nil { //话题不存在
				return false, "帖子不存在"
			}

			if member.Id != game.Manager && member.Id != topic.Author && !inArray(member.Id.Hex(), game.Managers) { //既不是管理组也不是作者
				return false, "无权限"
			}

			// 删除编辑后删除的图片(必须包含前缀路径保证是此文章的)
			// 移动编辑后新增的图片(并返回更新路径后的内容)
			var uploadSize int64
			uploadSize, topic.Content = HandleUpdateImage(topic.Content, this.GetString("content"), "game/"+game.Id+"/"+topic.Id.Hex()+"/")

			// 生成内容分词表
			sego := &SegoController{}
			topic.ContentSego = sego.ToSlices(topic.Content, false)

			// 记录用户上传量
			member.UploadSize += uploadSize
			member.Save()

			//保存
			topic.Save()

			//TODO:刷新缓存

			//推送消息,如果操作用户不是回复作者的话,通知他
			if topic.Author != member.Id {
				//AddMessage(topic.Author.Hex(), "game", "/game/"+this.GetString("game")+"/"+this.GetString("topic")+".html", "您有一个帖子被管理员编辑", "<img userImage='"+member.Image+"'>&nbsp;<span class='text-info'>"+member.Nickname+"</span>&nbsp;编辑了您的帖子:<span class='text-muted'>&nbsp"+topic.Title+"&nbsp;</span>", "")
			}
			break
		}

		return true, ""
	}()

	this.Data["json"] = map[string]interface{}{
		"ok":   ok,
		"data": data,
	}
	this.ServeJson()
}
Esempio n. 10
0
//文件上传
func (this *base) upload(key string) (files []*models.UploadFile, err error) {
	//处理上传文件
	var header *multipart.FileHeader
	var file multipart.File
	var f *os.File

	//根据年月选择文件夹
	t := time.Now().Format(time.RFC3339)
	//文件夹是否存在或创建文件夹
	UploadPath := beego.AppConfig.String("UploadPath")
	folder := utils.MergePath(UploadPath)
	err = utils.GetDir(folder)
	if err != nil {
		return
	}
	// //用户文件夹是否存在或创建文件夹
	// folder = filepath.Join(folder, strconv.Itoa(int(this.xm.Updator)))
	// err = utils.GetDir(folder)
	// if err != nil {
	// 	return
	// }
	//文件夹是否存在或创建文件夹
	UploadPath = path.Join(UploadPath, beego.Substr(t, 0, 7))
	folder = path.Join(folder, beego.Substr(t, 0, 7))
	err = utils.GetDir(folder)
	if err != nil {
		return
	}

	fs := this.Ctx.Request.MultipartForm.File[key]

	n := len(fs)
	if n == 0 {
		err = errors.New("files not found")
		return
	}

	for i := 0; i < n; i++ {
		header = fs[i]
		file, err = fs[i].Open()

		if err != nil {
			return
		}

		defer file.Close()

		//提取原始文件信息
		disposition := strings.Split(header.Header.Get("Content-Disposition"), ";")

		var key, value string
		for _, v := range disposition {

			pos := strings.Index(v, "=")
			if pos > -1 {
				key = v[:pos]

				if strings.TrimSpace(key) == "filename" {
					value = strings.Replace(v[pos+1:], "\"", "", -1)
					break
				}
			}
		}
		//
		filename := filepath.Base(value)

		//新建文件
		UploadPath = path.Join("/", UploadPath, fmt.Sprintf("%d%s", time.Now().UnixNano(), filepath.Ext(filename)))
		f, err = os.OpenFile(path.Join(folder, fmt.Sprintf("%d%s", time.Now().UnixNano(), filepath.Ext(filename))), os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			return
		}

		defer f.Close()

		io.Copy(f, file)

		upf := new(models.UploadFile)
		upf.Name = filename
		upf.Ext = filepath.Ext(filename)
		upf.Path = UploadPath
		fi, _ := f.Stat()
		upf.Size = fi.Size()

		files = append(files, upf)
	}
	return
}
Esempio n. 11
0
/* 分类显示页面 */
func (this *ArticleController) Category() {
	//是否用手机访问
	isMobile := IsMobile(this.Ctx.Input.UserAgent())
	//验证
	valid := validation.Validation{}
	valid.Alpha(this.Ctx.Input.Param(":category"), "category")
	if valid.HasErrors() { //没有通过验证则返回首页
		this.Ctx.Redirect(302, this.UrlFor("IndexController.Index"))
		this.StopRun()
	}

	//获得页面数
	page, _ := this.GetInt("page")

	if page < 1 {
		page = 1
	}

	category := &models.Category{}
	ok, parent, childs, articles, hots, allPage := category.FindByName(this.Ctx.Input.Param(":category"), (page-1)*15, page*15, 15)
	if !ok { //不存在此分类
		this.Ctx.Redirect(302, this.UrlFor("IndexController.Index"))
		this.StopRun()
	}
	//保存分类信息
	mainCategory := *category
	results := make([]ArticleReturn, len(articles))
	//查询每个文章的分类信息
	for k, _ := range articles {
		category.FindOne(articles[k].Category)
		results[k].Art = articles[k]
		//查找第一个图片
		results[k].Image = FindImages(results[k].Art.Content, 1)[0]
		//移除markdown标识
		results[k].Art.Content = RemoveMarkdown(results[k].Art.Content)
		//截取长度200
		results[k].Art.Content = beego.Substr(results[k].Art.Content, 0, 200)
		results[k].CategoryName = category.Title
		results[k].CategoryPath = category.Name
		results[k].Time = results[k].Art.Time.Format("2006-01-02 15:04:05")
	}
	//查询每个文章作者信息
	member := &models.Member{}
	for k, _ := range articles {
		member.FindOne(articles[k].Uid.Hex())
		results[k].AuthorName = member.Nickname
	}
	//赋值模版变量
	this.Data["category"] = mainCategory
	this.Data["parent"] = parent
	this.Data["childs"] = childs
	this.Data["articles"] = results
	this.Data["hots"] = hots
	this.Data["allpage"] = allPage
	this.Data["page"] = page //当前页数
	if isMobile {            //如果是手机访问
		this.TplNames = "mobile/article/category.html"
	} else {
		this.TplNames = "article/category.html"
	}
	this.Render()
}
Esempio n. 12
0
//新增文章
func (this *ArticleController) Add() {
	ok, data := func() (bool, interface{}) {
		if this.GetSession("ID") == nil {
			return false, "未登录"
		}

		//查询用户
		member := &models.Member{}
		if _ok, _data := member.FindOne(this.GetSession("ID").(string)); !_ok {
			return false, _data
		}

		category, _ := this.GetInt("category")
		if category != 0 && category != 1 {
			return false, "分类错误"
		}

		if len([]rune(this.GetString("title"))) > 60 {
			return false, "标题最长60"
		}

		if len([]rune(this.GetString("content"))) < 3 || len([]rune(this.GetString("content"))) > 20000 {
			return false, "内容长度3-20000"
		}

		// 判断标签是否合法
		tags := this.GetStrings("tag")

		// 标签数量限制、长度限制、同文章不能重复
		if len(tags) >= 5 {
			return false, "最多5个标签"
		}

		for k, _ := range tags {
			if len([]rune(tags[k])) > 15 || len([]rune(tags[k])) < 1 {
				return false, "标签最大长度为15"
			}
		}

		copyTags := tags

		for k, _ := range tags {
			count := 0
			for _k, _ := range copyTags {
				if copyTags[_k] == tags[k] {
					count++

					if count >= 2 {
						return false, "标签不能重复"
					}
				}
			}
		}

		tag := &models.Tag{}
		// tag新增
		for k, _ := range tags {
			tag.Upsert(tags[k])
		}

		article := &models.Article{}
		article.Uid = bson.ObjectIdHex(this.GetSession("ID").(string))
		article.Category = category
		article.Title = this.GetString("title")
		article.Content = this.GetString("content")
		article.Tag = tags
		article.GetId()

		fmt.Println(article.Id)

		//如果标题为空,截取内容前15个字符
		if article.Title == "" {
			article.Title = beego.Substr(article.Content, 0, 15)
		}

		// 查找内容中所有图片信息,并移动到正确位置,同时替换图片路径
		var uploadSize int64
		uploadSize, article.Content = HandleNewImage(article.Content, "article/"+article.Id.Hex()+"/")

		// 记录用户上传量
		member.UploadSize += uploadSize
		member.Save()

		//用户发表量+1
		member.AddArticleNumber()

		//插入文章
		return article.Insert()
	}()

	this.Data["json"] = map[string]interface{}{
		"ok":   ok,
		"data": data,
	}
	this.ServeJson()
}