配置文件
runmode = dev
应用的运行模式,可选prod, dev 或 test
,默认是dev
,为开发者模式sessionon=true
设置session
控制开启,主要用于验证登录信息,在登录页面SetSession("Login", true)
和c.SetSession("authority", int(1))
或c.SetSession("authority", int(2))
用以区分超级管理员和普通管理员,在其他需要验证登录的页面利用v := c.GetSession("authority")
,判断v
的值为1或者是2判断登录的用户是否是超级管理员
//由于在controllers文件夹中把前端控制和后端控制文件分为两个文件夹Back 和Front ,因此路由设置时要注意
func init() {
// 后端路由设置
beego.Router("/", &Back.MainController{} , "get:LoginIndex;post:Post" )
beego.Router("/index" , &Back .IndexController{} )
beego.Router("/category" , &Back .FormController{} )
beego.Router("/addTeacher" , &Back .AddTeacherController{} )
beego.Router("/addLink" , &Back .AddLinkController{} )
beego.Router("/addDownload" , &Back .AddDownloadController{} )
beego.Router("/user" , &Back .UserController{} )
beego.Router("/teacherlist" , &Back .TeacherListController{} )
beego.Router("/linkerlist" , &Back .LinkerListController{} )
beego.Router("/articlelist" , &Back .AticleListController{} )
beego.Router("/onearticle" , &Back .OneAticleController{} )
//前端路由设置
beego.Router("/Judge" , &Front .JudgeController{} , "get:Judge" )
beego.Router("/jxdz" , &Front .JxdzController{} )
beego.Router("/jxdzN1" , &Front .JxdzN1Controller{} )
beego.Router("/jxdzN2" , &Front .JxdzN2Controller{} )
beego.Router("/jxdzN3" , &Front .JxdzN3Controller{} )
beego.Router("/jxdzN4" , &Front .JxdzN4Controller{} )
beego.Router("/jxdzN5" , &Front .JxdzN5Controller{} )
beego.Router("/jxdzN6" , &Front .JxdzN6Controller{} )
}
models文件夹
Category.go文件
Category
结构体用于管理栏目,使用的是无限极分类的方法
type Category struct {
Id int
Name string `orm:"size(45)" `
ParentID int
ChildID string `orm:"size(100)" `
Depth int
Type string
Content string `orm:"size(1000)" `
}
Id
默认为主键并自增ParentID
为栏目的父栏目的Id
,命名应该使用大驼峰ParentId ChildID
为子栏目的Id
,使用","
隔开,因此要使用string格式Depth
为此栏目的层深,一级栏目层深为一,二级栏目层深为二,以此类推Type
为此栏目对应的类型,分为目录、单页面、教师列表、文章列表、下载列表和链接列表几种,例如热点新闻
栏目的类型就是文章列表,包含一篇或多篇文章Content
字段是为单页面类型准备的,只有类型为单页面的栏目才会在这个字段中存数据,例如学院简介
栏目
CategoryListOne
用于渲染前端一级栏目的结构体
type CategoryListOne struct {
Id int
DepthNumber int
CateOne *Category
CateTwo []*Category
}
该结构体有4个字段,CateOne
代表层深为一的栏目,CateTwo
代表着其对应的子栏目,DepthNumber
为CateTwo
对应的slice的个数,例如当Id=1
时对应的CateOne
是学院概况
,其有三个子栏目学院简介
、学院机构
和院长寄语三个
,对应着字段CateTwo
,则DepthNumber
字段为3,代表着此栏目有3个二级子栏目 该结构体用函数func CreateCateList()([]*CategoryListOne, error)
构建,其中CateOne字段中不包括快速链接,因为此栏目并不是用在首页顶部的一级栏目当中
函数及其功能
增加栏目函数func AddCategory(name string, parentid int, typ string, cont string) error
,输入栏目名、父类Id、类型和内容四个字段,返回错误。beego的增删改查 删除栏目函数func DelCategory(id int, name string, parentid int) int
,传入栏目的Id,栏目名和父类Id,返回一个整型变量,删除成功则返回0,删除有错误则返回1,其中要删除的栏目必须是底层栏目,即不能有子栏目,ChildID=="0"
查找栏目函数func SearchCategory(id int) (cate Category, err error)
,读取错误则返回错误err
查找所有栏目函数func GetAllCategories() ([]*Category, error)
,按数据库的顺序输出所有的栏目信息 无限极排序函数 (递归)func MakeSort(id int, CateNotSort []*Category) []*Category
,用于根据父-子栏目的顺序输出无限极分类之后的栏目信息
var CateSort []*Category
func MakeSort(id int , CateNotSort []*Category) []*Category {
var i int
if id == 0 {
CateSort = make ([]*Category, 0 )
}
for i = 0 ; i < len (CateNotSort); i++ {
if id == CateNotSort[i].ParentID {
CateSort = append (CateSort, CateNotSort[i])
MakeSort(CateNotSort[i].Id, CateNotSort)
}
}
return CateSort
}
Content.go文件
Content
结构体用于存储文章信息
type Content struct {
Id int
BelongsId int
Title string `orm:"size(30)" `
Content string `orm:"size(15000)" `
From string
CreatTime string
ReadTime int
ImgPath string
}
BelongsId
字段存储该文章所属栏目的Id,此栏目的类型需为文章列表 Title
字段存储题目,`orm:”size(30)”`代表题目长度最多为30,中英文同样适用 Content
存储内容,由于是使用富文本编辑器,因此有部分冗余信息,因此其长度限制`orm:”size(15000)”`比较大mysql表中字段存储限制 From
、CreatTime
和ReadTime
字段分别存储文章的来源、创建时间和阅读次数,其中创建时间默认为time.Now()
,格式为”2006-01-01”,阅读次数默认为0ImgPath
字段是专为热点新闻准备的,因为热点新闻要选取5篇作为首页轮播图内容,需要对应的图片增加、删除和获取文章函数和之前一样 函数func SearchFunction(cont string) []*Content
对应网页的搜索功能beego中自定义条件表达式用法
//输入要查询的内容,返回查找到的文章列表
func SearchFunction(cont string) []*Content {
o := orm.NewOrm ()
cond := orm.NewCondition ()
Article := make([]*Content, 0 )
//自定义表达式,文章题目或者内容包含要查找的内容,用or 连接
cond1 := cond.Or ("Title__icontains" , cont).Or ("Content__icontains" , cont)
qs := o.QueryTable ("Content" )
var err error
_, err = qs.SetCond (cond1).All (&Article)
if err != nil {
beego.Debug (err)
}
return Article
}
函数func SearchArticleByBelongid(id int) []*Content
根据文章的BelongsId
找到指定Id的栏目包含的所有文章列表
Employee.go文件
Employee
结构体
type Employee struct {
Id int
Name string
Job string
Telphone string
Email string
Script string `orm:"size(800)" `
EducationBackground string
IsDocTeacher string `orm:"size(5)" `
Department string
Img string
Research string `orm:"size(5000)" `
Teaching string `orm:"size(5000)" `
Prize string `orm:"size(5000)" `
}
Img
字段用于存储教师的图片信息的路径,一般为本地图片路径Script
、Research
、Teaching
和Prize
分别存储老师的个人经历,科研经历,教学经历和其他获奖
user.go文件
Users
结构体
type Users struct {
Id int
Account string `orm:"unique" `
Password string `orm:"size(30)" `
Authority string
}
Account
字段代表用户的账号信息,账户信息必须是unique
的Authority
字段代表用户的权限,有超级管理员super
和普通管理员common
两种,只有超级管理员才能操作栏目信息和用户信息
func init() {
orm.RegisterModel(new (Users), new (Category), new (Content), new (Employee), new (Linker), new (Download))
orm.RegisterDataBase("default" , "mysql" , "root:golang@/user?charset=utf8" , 30 )
orm.RunSyncdb("default" , false , true )
}
controllers文件夹
Back文件夹包含了控制后台页面的控制文件
loginController.go文件
控制登录页面,输入账号密码,与数据库中的账号密码信息对比,判断账号密码是否正确,正确时取出其权限信息,若为超级管理员,则this.SetSession("authority", int(1))
,若为普通管理员,则this.SetSession("authority", int(2))
。错误时提示输入错误,重定位到登录页面this.Redirect("/", 302)
,重新输入账号密码。
categoryController.go文件
首先判断Session,利用v := c.GetSession("authority")
,如果v等于1,代表这此时登录的是超级管理员,如果v等于2,代表这此时登录的是超级管理员,否则代表这用户尚未登录,重定向到登录页面。 然后就是增加或者删除栏目的操作,增加栏目用的是form表单提交,方法是POST,删除则用的是默认的GET方法。 其余的后台控制文件相差不多
Font文件夹包括了前端控制文件
Judge.go文件
作用是分发路由,根据Id判断跳转到哪一个二级页面 目录类型的处理
//目的是寻找到该目录的第一个类型不是目录的子栏目(一定非空)并显示其内容
if cateType == "目录" {
//找到其子栏目,返回slice
cateSon, _ := models.FindAllSon (id)
//找到其第一个子栏目,判断其类型是否是目录
//如果是,则继续往下级寻找;若否,则显示该子栏目的内容
if cateSon[0 ].Type != "目录" {
cateType = cateSon[0 ].Type
idSon := cateSon[0 ].Id
idstr = strconv.Itoa (idSon)
} else {
cateGrandson, _ := models.FindAllSon (cateSon[0 ].Id )
cateType = cateGrandson[0 ].Type
idGrandson := cateGrandson[0 ].Id
idstr = strconv.Itoa (idGrandson)
}
}
在前端页面的处理上,主要包括了4个页面,分别是单页面,文章列表页面,教师列表页面和下载列表页面,分别根据栏目所属的类型来选择跳转到哪一个页面
if cateType == "文章列表" {
c.Redirect("/jxdzN2?Id=" +idstr, 302 )
} else if cateType == "单页面" {
c.Redirect("/jxdzN1?Id=" +idstr, 302 )
} else if cateType == "教师列表" {
c.Redirect("/jxdzN4?Job=职称&Id=" +idstr, 302 )
} else if cateType == "下载列表" {
c.Redirect("/jxdzN3?Id=" +idstr, 302 )
} else {
beego.Error ("类型错误" )
}
jxdzController.go文件
前端页面之首页控制,二级菜单的实现c.Data["CatesForMenu"], err = models.CreateCateList()
即为创建一级菜单和二级菜单的CategoryListOne
结构体,然后按照父-子栏目的顺序依次显示出来,即显示一个一级栏目,下面挂着以这个一级栏目为父节点的所有二级栏目 控制显示所有的链接列表c.Data["link"] = models.GetAllLinker()
控制轮播图,轮播内容为热点新闻的前5篇,热点新闻是根据添加时间倒序排列,因此轮播的是热点新闻的最新添加的5篇 控制重要通知,显示最新的8篇重要通知
jxdzN1Controller.go~jxdzN6Controller.go文件
分别控制前端的单页面、文章列表、下载列表、教师列表和单篇文章的页面显示 共同点是都需要控制其面包屑以找到其路径c.Data["Path"] = models.FindAllFather(id)
,即根据Id按照层深一层层的找到其所有父节点并依次显示出来; 都有一个左菜单栏c.Data["LeftMenu"] = models.FindLeftMenu(id)
,显示其所有的兄弟栏目(即与此栏目有同一个父栏目);左栏目之下有热点新闻
导航栏,同样显示最新的5篇热点新闻 每个页面都有一搜索框,可以点击搜索,通过关键字搜索新闻,搜索范围为所有文章的题目和内容,通过或 连接。 不同点是教师页面jxdzN4中需要通过职称、博导和系所分类;下载列表jxdzN3和文章列表jxdzN2需要取出所需Id对应下的所有文章和下载列表;单篇文章显示页面须有下一页功能
static文件夹
用于放置views中用到的js、css等文件,还包括一些用于显示的图片文件和用于下载的下载文件
views文件夹
jxdzN1.html~jxdzN6.html
{{range .CatesForMenu }}
<li onmouseover ="drop('d {{.Id }} ',' {{.DepthNumber }} ')" onmouseout ="drop('d {{.Id }} ','0')" >
<a href ="/Judge?ID= {{.CateOne.Id }} " target ="_blank" >{{.CateOne.Name }} </a >
<ul class ="dropDown" id ="d {{.Id }} " >
{{range .CateTwo }}
<li style ="border-top:none;" >
<a href ="/Judge?ID= {{.Id }} " >{{.Name }} </a >
</li >
{{end }}
</ul >
</li >
{{end }}
{{range .HotNews }}
{{$idout := .Id |Idconvrtforimg }}
<li id ="ro {{$idout }} " >
<a href ="/jxdzN5?Id= {{.Id }} &BeId=23" class ="rotationTab" target ="_blank" >
<img src =" {{.ImgPath }} " class ="ro" >
</a >
<div class ="label" >
<a class ="bannerTitle" target ="_blank" href ="/jxdzN5?Id= {{.Id }} &BeId=23" >{{.Title }} </a >
{{.Id }} {{.Content }}
</div >
</li >
{{end }}
{{range .Newsimp }}
{{$top := .Id |Counttop }}
{{$ID := .Id |Idconvert }}
<li id ="li {{$ID }} " style ="top: {{$top }} px;" >
<a href ="/jxdzN5?Id= {{.Id }} &BeId=35" >
<div class ="date" >
<p class ="year" > {{substr .CreatTime 0 7}} </p >
<p class ="day" > {{substr .CreatTime 8 10}} </p >
</div >
{{$IsLong := .Title |Istoolong }}
{{if $IsLong }}
<p class ="tabInfo" > {{substr .Title 0 37}} ...</p >
{{else }}
<p class ="tabInfo" > {{.Title }} </p >
{{end }}
</a >
</li >
{{end }}
总结:从前到后梳理了一遍思路,发现好像也没有什么特别难搞定的……