古詩網站後臺實現

尹成發表於2018-11-14

#賬戶管理
##登入
效果圖如下:
這裡寫圖片描述
使用者輸入使用者名稱和密碼,點選登入系統按鈕,在後臺首先在cookie中獲取使用者登入相關資訊,如果獲取失敗再獲取使用者的輸入,對使用者輸入的資料進行校驗並再資料庫中查詢使用者,如果查詢失敗,再前臺頁面顯示相應的提示資訊,如果輸入的使用者名稱和密碼正確,會將使用者輸入的資料做MD5處理,然後將處理之後的結果存入cookie中,並設定cookie的存活時間為一週。


func (self *LoginController) LoginIn() {
	//判斷使用者id是否大於0
	if self.userId > 0 {
		fmt.Println("==========", beego.URLFor("HomeController.Index"), "=============")
		self.redirect(beego.URLFor("HomeController.Index"))
	}
	beego.ReadFromRequest(&self.Controller)
	//判斷是否是post方式提交
	if self.isPost() {
		//獲取使用者名稱,並去除兩邊的空格
		username := strings.TrimSpace(self.GetString("username"))
		//獲取密碼並去除兩邊的空格
		password := strings.TrimSpace(self.GetString("password"))
		//如果獲取到的使用者名稱和密碼都不為空
		if username != "" && password != "" {
			//根據使用者名稱查詢對應的管理員
			user, err := models.AdminGetByName(username)
			fmt.Println(user)
			flash := beego.NewFlash()
			errorMsg := ""
			//如果查詢出錯或者密碼不正確
			if err != nil || user.Password != libs.Md5([]byte(password+user.Salt)) {
				errorMsg = "帳號或密碼錯誤"
			} else if user.Status == -1 {//禁用
				errorMsg = "該帳號已禁用"
			} else {
				//獲取使用者IP地址
				user.LastIp = self.getClientIp()
				//登入時間
				user.LastLogin = time.Now().Unix()
				//更新使用者
				user.Update()
				//將使用者ip和使用者密碼以及密碼鹽通過|連線
				authkey := libs.Md5([]byte(self.getClientIp() + "|" + user.Password + user.Salt))
				//建立名為auth的cookie
				self.Ctx.SetCookie("auth", strconv.Itoa(user.Id)+"|"+authkey, 7*86400)

				self.redirect(beego.URLFor("HomeController.Index"))
			}
			//將錯誤提示寫入flash,鍵為error,值為錯誤提示
			flash.Error(errorMsg)
			flash.Store(&self.Controller)
			self.redirect(beego.URLFor("LoginController.LoginIn"))
		}
	}
	self.TplName = "login/login.html"
}

##使用者身份校驗
如果某個使用者再知道了後臺管理系統的網址,在位址列輸入該網址就可以隨意訪問後臺管理系統,此時登入功能便形同虛設,所以鑑於安全形度,應該實現使用者身份校驗功能。在使用者訪問後臺管理系統的時候,從cookie中取出相應的登入資訊,然後根據該資訊去資料庫中查詢資料,如果查詢失敗,說明使用者並沒有登入,直接重定向到登入頁面,讓使用者重新登入,如果查詢成功則允許使用者繼續訪問,並從資料庫中查詢出後臺管理系統的選單。

func (self *BaseController) auth() {
	//將名為auth的cooki而通過|分割
	arr := strings.Split(self.Ctx.GetCookie("auth"), "|")
	self.userId = 0
	//fmt.Println("arr_length = ", len(arr))
	//判斷分割之後的結果是否是2
	if len(arr) == 2 {
		idstr, password := arr[0], arr[1]
		//fmt.Println("idstr = ", idstr)
		//fmt.Println("password = ", password)
		//將id轉換為整數
		userId, _ := strconv.Atoi(idstr)
		//判斷id是否大於0
		if userId > 0 {
			//根據id查詢管理員
			user, err := models.AdminGetById(userId)
			//如果查詢沒有出錯並且從cookie中取出的password和雜湊之後的結果相同
			if err == nil && password == libs.Md5([]byte(self.getClientIp()+"|"+user.Password+user.Salt)) {
				self.userId = user.Id
				self.loginName = user.LoginName
				self.userName = user.RealName
				self.user = user
				self.AdminAuth()
			}

			/*isHasAuth := strings.Contains(self.allowUrl, self.controllerName+"/"+self.actionName)
			noAuth := "ajaxsave/ajaxdel/table/loginin/loginout/getnodes/start/show/ajaxapisave"
			isNoAuth := strings.Contains(noAuth, self.actionName)
			if isHasAuth == false && isNoAuth == false {
				self.Ctx.WriteString("沒有許可權")
				self.ajaxMsg("沒有許可權", MSG_ERR)
				return
			}*/
		}
	}

	if self.userId == 0 && (self.controllerName != "login" && self.actionName != "loginin") {
		self.redirect(beego.URLFor("LoginController.LoginIn"))
	}
}


##退出登入
當使用者點選退出登出按鈕的時候,通過路由找到對應的控制器和方法,將cookie中的使用者登入資訊設定為空,最後重定向到登入頁面。

#後臺首頁
效果圖如下:
這裡寫圖片描述
當使用者登入成功後重定向到後臺首頁,來到首頁先查詢資料庫,從資料庫中查詢出後臺選單欄資訊,具體分為:許可權管理,個人中心,諮詢管理等模組。

func (self *BaseController) AdminAuth() {
	// 左側導航欄
	//分頁查詢
	result, _ := models.AuthGetList()
	list := make([]map[string]interface{}, len(result))
	list2 := make([]map[string]interface{}, len(result))
	i, j := 0, 0
	//遍歷查詢結果
	for _, v := range result {
		row := make(map[string]interface{})
		//上級id為1且顯示
		/*
		SideMenu1 id Icon   AuthName
        Pid AuthUrl AuthName  Id  Icon
		*/
		if v.Pid == 1 {
			row["Id"] = int(v.Id)
			row["Icon"] = v.Icon
			row["AuthName"] = v.AuthName
			list[i] = row
			i++
		}
		//上級id不為1,且顯示
		if v.Pid != 1{
			row["Pid"] = int(v.Pid)
			row["AuthUrl"] = v.AuthUrl
			row["AuthName"] = v.AuthName
			row["Id"] = int(v.Id)
			row["Icon"] = v.Icon
			list2[j] = row
			j++
		}
	}
	self.Data["SideMenu1"] = list[:i]  //一級選單
	self.Data["SideMenu2"] = list2[:j] //二級選單
}

#許可權管理
效果圖如下:
這裡寫圖片描述
許可權管理模組實現了使用者的新增,編輯,刪除以及使用者列表等功能。
##新增使用者
效果圖如下:
這裡寫圖片描述
使用者在該頁面填寫相應的資訊,點選立即提交按鈕,將新增的資訊提交到後臺,在後臺接收使用者輸入的資料,並對使用者輸入的資料進行校驗,如果使用者輸入的資料不合法在前臺頁面給與相應的提示資訊,如果使用者輸入的資料符合要求,將新新增的使用者的密碼設定為預設值:george518並存入資料庫。

func (self *AdminController) AjaxSave() {
	Admin_id, _ := self.GetInt("id")
	if Admin_id == 0 {
		/*
		login_name  real_name  phone  email
		*/
		Admin := new(models.Admin)
		Admin.LoginName = strings.TrimSpace(self.GetString("login_name"))
		Admin.RealName = strings.TrimSpace(self.GetString("real_name"))
		Admin.Phone = strings.TrimSpace(self.GetString("phone"))
		Admin.Email = strings.TrimSpace(self.GetString("email"))
		Admin.UpdateTime = time.Now().Unix()
		Admin.UpdateId = self.userId
		Admin.Status = 1

		// 檢查登入名是否已經存在
		_, err := models.AdminGetByName(Admin.LoginName)

		if err == nil {
			self.ajaxMsg("登入名已經存在", MSG_ERR)
		}
		//新增
		pwd, salt := libs.Password(4, "")
		Admin.Password = pwd
		Admin.Salt = salt
		Admin.CreateTime = time.Now().Unix()
		Admin.CreateId = self.userId
		if _, err := models.AdminAdd(Admin); err != nil {
			self.ajaxMsg(err.Error(), MSG_ERR)
		}
		self.ajaxMsg("", MSG_OK)
	}

	Admin, _ := models.AdminGetById(Admin_id)
	//修改

	Admin.LoginName = strings.TrimSpace(self.GetString("login_name"))
	Admin.RealName = strings.TrimSpace(self.GetString("real_name"))
	Admin.Phone = strings.TrimSpace(self.GetString("phone"))
	Admin.Email = strings.TrimSpace(self.GetString("email"))

	Admin.Id = Admin_id
	Admin.UpdateTime = time.Now().Unix()
	Admin.UpdateId = self.userId

	Admin.UpdateTime = time.Now().Unix()
	Admin.UpdateId = self.userId
	Admin.Status = 1

	resetPwd, _ := self.GetInt("reset_pwd")
	if resetPwd == 1 {
		pwd, salt := libs.Password(4, "")
		Admin.Password = pwd
		Admin.Salt = salt
	}
	if err := Admin.Update(); err != nil {
		self.ajaxMsg(err.Error(), MSG_ERR)
	}
	self.ajaxMsg(strconv.Itoa(resetPwd), MSG_OK)
}

##編輯使用者
效果圖如下:
這裡寫圖片描述
當使用者點選編輯按鈕,將對應的古詩id提交到後臺,在後臺接收id並根據該id去資料庫查詢對應的記錄,將查詢到的資訊存入模板資料中,在前臺頁面顯示被編輯的使用者的資訊,即資料回顯。當使用者修改資訊之後點選立即提交按鈕,將資料提交到後臺,在後臺接收相應的資料並更新資料庫,對應的程式碼同上。

##刪除使用者
效果圖如下:
這裡寫圖片描述
該頁面實現了刪除使用者的功能,當使用者點選刪除按鈕,頁面給與相應的提示,因為一旦刪除,資料將不可恢復,如果使用者確定刪除,將被刪除的使用者的id提交到後臺,在後臺接收使用者id並查詢資料庫,如果查詢失敗,說明資料庫中不存在該使用者則刪除失敗,如果查詢成功,則將該使用者刪除。

func (self *AdminController) AjaxDel() {
	//獲取使用者id
	Admin_id, _ := self.GetInt("id")
	//根據id查詢管理員
	Admin, _ := models.AdminGetById(Admin_id)
	//修改時間
	Admin.UpdateTime = time.Now().Unix()
	//狀態,1-正常 0禁用
	Admin.Status = 0
	Admin.Id = Admin_id
	//判斷要刪除的使用者是不是超級管理員
	if Admin_id == 1 {
		self.ajaxMsg("超級管理員不允許刪除", MSG_ERR)
	}
	//更新使用者
	if err := Admin.Update(); err != nil {
		self.ajaxMsg(err.Error(), MSG_ERR)
	}
	self.ajaxMsg("", MSG_OK)
}

#個人中心
效果圖如下:
這裡寫圖片描述
該模組主要實現了個人資訊的修改,但使用者點選修改資料按鈕時,從cookie中獲取當前登入使用者的id,並根據該id去資料庫查詢資料,將查詢到的資料存入模板資料中,通過渲染將當前使用者的個人資訊顯示在前臺頁面,在使用者修改完資訊之後點選立即提交按鈕將資料提交到後臺,在後臺接收資料之後將更新對應的記錄。

func (self *UserController) AjaxSave() {
	/*
	login_name  real_name  phone  email  reset_pwd  password_old  password_new1  password_new2  id
	*/
	//獲取使用者id
	Admin_id, _ := self.GetInt("id")
	//根據id查詢管理員
	Admin, _ := models.AdminGetById(Admin_id)
	//修改
	Admin.Id = Admin_id
	/*
	login_name  real_name  phone  email
	*/
	Admin.LoginName = strings.TrimSpace(self.GetString("login_name"))
	Admin.RealName = strings.TrimSpace(self.GetString("real_name"))
	Admin.Phone = strings.TrimSpace(self.GetString("phone"))
	Admin.Email = strings.TrimSpace(self.GetString("email"))

	resetPwd := self.GetString("reset_pwd")
	//resetPwd=1為修改密碼,resetPwd=2為不修改
	if resetPwd == "1" {
		//獲取原始密碼並去除兩邊的空格
		pwdOld := strings.TrimSpace(self.GetString("password_old"))
		//將原始密碼和密碼鹽去雜湊
		pwdOldMd5 := libs.Md5([]byte(pwdOld + Admin.Salt))
		//對比結果
		if Admin.Password != pwdOldMd5 {
			self.ajaxMsg("舊密碼錯誤", MSG_ERR)
		}
		//獲取新密碼並去除兩邊的空格
		pwdNew1 := strings.TrimSpace(self.GetString("password_new1"))
		//獲取確認密碼並去除兩邊的空格
		pwdNew2 := strings.TrimSpace(self.GetString("password_new2"))
		//對比兩次輸入的密碼是否一致
		if pwdNew1 != pwdNew2 {
			self.ajaxMsg("兩次密碼不一致", MSG_ERR)
		}
		//返回新密碼和密碼鹽
		pwd, salt := libs.Password(4, pwdNew1)
		//密碼為使用者輸入的密碼和密碼鹽(隨機生成的字串)的雜湊值
		Admin.Password = pwd
		//密碼鹽
		Admin.Salt = salt
	}
	//修改時間
	Admin.UpdateTime = time.Now().Unix()
	//修改者ID
	Admin.UpdateId = self.userId

	//狀態,1-正常 0禁用
	Admin.Status = 1
	//更新使用者
	if err := Admin.Update(); err != nil {
		self.ajaxMsg(err.Error(), MSG_ERR)
	}
	self.ajaxMsg("", MSG_OK)
}

#諮詢管理
該模組主要實現了古詩的新增,刪除,編輯以及列表等功能,對古詩內容實現有效的管理。
##諮詢列表
效果圖如下:
這裡寫圖片描述
該頁面主要用來展示古詩詞的相關資訊,在下拉框中可以選擇想要現實的分類,例如:選擇了國學經典,會將國學經典的id提交到後臺,在後臺拿到id之後查詢屬於該id下的古詩詞並存入模板資料中,在前臺頁面顯示。

func (self *AdminController) Table() {
	//列表
	page, err := self.GetInt("page")
	if err != nil {
		page = 1
	}
	limit, err := self.GetInt("limit")
	fmt.Println("limit = ", limit)

	if err != nil {
		limit = 5
	}
	limit = 10
	self.pageSize = limit
	//查詢條件
	filters := make([]interface{}, 0)
	filters = append(filters, "status", 1)
	result, count := models.AdminGetList(page, self.pageSize, filters...)
	list := make([]map[string]interface{}, len(result))
	for k, v := range result {
		/*
		  <th lay-data="{field:'id', width:80, fixed: true}">ID</th>
			<th lay-data="{field:'login_name', width:200}">登入賬戶</th>
			<th lay-data="{field:'real_name', width:150}">真實姓名</th>
			<th lay-data="{field:'phone', width:200}">手機號碼</th>
			<th lay-data="{field:'email', width:200}">電子郵箱</th>
		*/
		row := make(map[string]interface{})
		row["id"] = v.Id
		row["login_name"] = v.LoginName
		row["real_name"] = v.RealName
		row["phone"] = v.Phone
		row["email"] = v.Email
		list[k] = row
	}
	self.ajaxList("成功", MSG_OK, count, list)
}

##新增古詩
效果圖如下:
這裡寫圖片描述
該頁面主要用於新增古詩詞,使用者在點選新增按鈕時,需要從資料庫中查詢出古詩的所有分類資訊,並將相關資訊存入模板資料中,在新增頁面回顯古詩的分類資訊。使用者在新增頁面填寫相應的資料並點選立即提交按鈕將資料提交到後臺,在後臺接收使用者輸入的資料並將該資料新增到資料庫中。

func (self *NewsController) AjaxSave() {
	/*
	title  class_id  author  keywords   pic_url   media  desc  content  orderid  id
	*/
	News := new(models.InfoList)
	//標題
	News.Title = strings.TrimSpace(self.GetString("title"))
	//獲取所屬欄目id
	classId, _ := self.GetInt("class_id")
	//所屬欄目id
	News.ClassId = classId
	//作者編輯
	News.Author = strings.TrimSpace(self.GetString("author"))
	//關鍵詞
	News.Keywords = strings.TrimSpace(self.GetString("keywords"))
	//縮圖片
	News.Picurl = strings.TrimSpace(self.GetString("pic_url"))
	//詩詞音訊
	News.Media = strings.TrimSpace(self.GetString("media"))
	//摘要
	News.Desc = strings.TrimSpace(self.GetString("desc"))
	//詳細內容
	News.Content = strings.TrimSpace(self.GetString("content"))

	orderid, err := self.GetInt("orderid")
	if err != nil {
		News.Orderid = orderid
	}

	id, _ := self.GetInt("id")

	//更新時間
	News.Updatetime = time.Now().Unix()

	//稽核狀態,1正常,2刪除,0未稽核
	News.Status = 1
	//新增
	if id == 0 {
		News.Posttime = time.Now().Unix()
		//插入古詩詞
		if _, err := models.NewsAdd(News); err != nil {
			self.ajaxMsg(err.Error(), MSG_ERR)
		}
		self.ajaxMsg("", MSG_OK)
	}
	News.Id = id
	//更新古詩詞
	if err := News.Update(); err != nil {
		self.ajaxMsg(err.Error(), MSG_ERR)
	}
	self.ajaxMsg("", MSG_OK)
}

//古詩詞列表
func (self *NewsController) Table() {
	//獲取頁碼
	page, err := self.GetInt("page")
	//出現錯誤,賦予預設值1
	if err != nil {
		page = 1
	}
	//獲取查詢的數量
	limit, err := self.GetInt("limit")
	//出現錯誤,賦予預設值30
	if err != nil {
		limit = 30
	}
	//獲取分類id
	class_id ,_ := self.GetInt("class_id")

	self.pageSize = limit
	//建立切片,用於儲存過濾條件
	filters := make([]interface{}, 0)
	//追加過濾條件:正常狀態
	filters = append(filters, "status", 1)
	//判斷分類id是否大於0
	if class_id > 0 {
		filters = append(filters, "class_id", class_id)
	}
	//分頁查詢古詩詞
	result, count := models.NewsGetList(page, self.pageSize, filters...)
	//建立切片,用於儲存查詢結果
	list := make([]map[string]interface{}, len(result))
	//遍歷結果
	for k, v := range result {
		/*
		   <th lay-data="{field:'id', width:80, fixed: true}">ID</th>
			<th lay-data="{field:'title', width:200}">標題</th>
			<th lay-data="{field:'class_id', width:80}">分類</th>
			<th lay-data="{field:'author', width:80}">作者</th>
			<th lay-data="{field:'desc', width:200}">簡介</th>
			<th lay-data="{field:'posttime', width:100}">時間</th>
		*/
		row := make(map[string]interface{})
		row["id"] = v.Id
		row["title"] = v.Title
		row["class_id"] = v.ClassId
		row["author"] = v.Author
		row["desc"] = v.Desc
		row["posttime"] = beego.Date(time.Unix(v.Posttime, 0), "Y-m-d")//根據秒數和納秒,返回Time型別
		list[k] = row
	}
	fmt.Println("list = ", list)
	self.ajaxList("成功", MSG_OK, count, list)
}

##編輯古詩
效果圖如下:
這裡寫圖片描述
當使用者點選編輯按鈕,將被編輯的古詩的id提交到後臺,在後臺接收使用者輸入的id查詢資料庫,將查詢出的資料存入模板資料中,在編輯頁面回顯被編輯的古詩的資料,即從模板資料中取出被編輯的古詩的相關資訊展示在編輯頁面,當使用者修改了相關的資訊之後並點選立即提交按鈕將古詩的相關的資料提交到後臺,在後臺接收相關資料並存入資料庫中,實現古詩的編輯功能。

func (self *NewsController) Edit() {
	self.Data["pageTitle"] = "編輯資訊"
	//獲取id
	id, _ := self.GetInt("id", 0)
	//根據id查詢古詩詞
	News, _ := models.NewsGetById(id)

	//分頁查詢分類資訊
	result, _ := models.ClassGetList()
	//建立切片,用於儲存分類資訊
	classList := make([]map[string]interface{}, len(result))
	//遍歷結果
	for k, v := range result {
		/*
		    id   class_name
		*/
		row := make(map[string]interface{})
		row["id"] = v.Id//欄目id
		row["class_name"] = v.ClassName//欄目名稱
		classList[k] = row
	}
	//顯示文章詳情
	/*
	title  class_id   author  keywords  pic_url  media  desc  content   orderid
	*/
	row := make(map[string]interface{})
	row["title"] = News.Title
	row["class_id"] = News.ClassId
	row["author"] = News.Author
	row["keywords"] = News.Keywords
	row["pic_url"] = News.Picurl
	row["media"] = News.Media
	row["desc"] = News.Desc
	row["content"] = News.Content
	row["orderid"] = News.Orderid
	row["id"] = News.Id

	//row["posttime"] = beego.Date(time.Unix(News.Posttime, 0), "Y/m/d")

	self.Data["news_class"] = classList
	self.Data["news"] = row
	self.display()
}

##刪除古詩
效果圖如下:
這裡寫圖片描述
該頁面實現了刪除古詩的功能,當使用者點選刪除按鈕,頁面給與相應的提示,因為一旦刪除,資料將不可恢復,如果使用者確定刪除,將被刪除的古詩的id提交到後臺,在後臺接收用古詩d並查詢資料庫,如果查詢失敗,說明資料庫中不存在該古詩則刪除失敗,如果查詢成功,則將該古詩刪除。

func (self *NewsController) AjaxDel() {
	//獲取id
	NewsId, _ := self.GetInt("id")
	//根據id查詢古詩詞
	News, _ := models.NewsGetById(NewsId)
	News.Updatetime = time.Now().Unix()
	//狀態為2表示刪除
	News.Status = 2
	News.Id = NewsId
	//跟新
	if err := News.Update(); err != nil {
		self.ajaxMsg(err.Error(), MSG_ERR)
	}
	self.ajaxMsg("", MSG_OK)
}

學院Go語言視訊主頁
https://edu.csdn.net/lecturer/1928

清華團隊帶你實戰區塊鏈開發
掃碼獲取海量視訊及原始碼 QQ群:721929980
在這裡插入圖片描述

相關文章