实现搜索功能

This commit is contained in:
Minho 2017-05-02 18:09:46 +08:00
parent dc6ea88c58
commit b4b0a6b4cf
17 changed files with 343 additions and 86 deletions

92
controllers/search.go Normal file
View File

@ -0,0 +1,92 @@
package controllers
import (
"github.com/lifei6671/godoc/models"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/utils"
"github.com/astaxie/beego"
"strings"
"regexp"
"strconv"
)
type SearchController struct {
BaseController
}
func (c *SearchController) Index() {
c.Prepare()
c.TplName = "search/index.tpl"
keyword := c.GetString("keyword")
pageIndex,_ := c.GetInt("page",1)
c.Data["BaseUrl"] = c.BaseUrl()
if keyword != "" {
c.Data["Keyword"] = keyword
member_id := 0
if c.Member != nil {
member_id = c.Member.MemberId
}
search_result,totalCount,err := models.NewDocumentSearchResult().FindToPager(keyword,pageIndex,conf.PageSize,member_id)
if err != nil {
beego.Error(err)
return
}
if totalCount > 0 {
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount)
c.Data["PageHtml"] = html
}else {
c.Data["PageHtml"] = ""
}
if len(search_result) > 0 {
for _,item := range search_result {
item.DocumentName = strings.Replace(item.DocumentName,keyword,"<em>" + keyword + "</em>",-1)
if item.Description != "" {
src := item.Description
//将HTML标签全转换成小写
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower)
//去除STYLE
re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
src = re.ReplaceAllString(src, "")
//去除SCRIPT
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
src = re.ReplaceAllString(src, "")
//去除所有尖括号内的HTML代码并换成换行符
re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllString(src, "\n")
//去除连续的换行符
re, _ = regexp.Compile("\\s{2,}")
src = re.ReplaceAllString(src, "\n")
r := []rune(src)
beego.Info(r)
if len(r) > 100 {
src = string(r[:100])
}else{
src = string(r)
}
item.Description = strings.Replace(src, keyword, "<em>" + keyword + "</em>", -1)
}
if item.Identify == ""{
item.Identify = strconv.Itoa(item.DocumentId)
}
if item.ModifyTime.IsZero() {
item.ModifyTime = item.CreateTime
}
}
}
c.Data["Lists"] = search_result
}
}

View File

@ -134,4 +134,3 @@ func (m *Document) ReleaseContent(book_id int) {

View File

@ -0,0 +1,79 @@
package models
import (
"time"
"github.com/astaxie/beego/orm"
)
type DocumentSearchResult struct {
DocumentId int `json:"doc_id"`
DocumentName string `json:"doc_name"`
// Identify 文档唯一标识
Identify string `json:"identify"`
Description string `json:"description"`
Author string `json:"author"`
ModifyTime time.Time `json:"modify_time"`
CreateTime time.Time `json:"create_time"`
BookId int `json:"book_id"`
BookName string `json:"book_name"`
BookIdentify string `json:"book_identify"`
}
func NewDocumentSearchResult() *DocumentSearchResult {
return &DocumentSearchResult{}
}
func (m *DocumentSearchResult) FindToPager(keyword string,page_index,page_size,member_id int) (search_result []*DocumentSearchResult,total_count int,err error) {
o := orm.NewOrm()
offset := (page_index - 1) * page_size
if member_id <= 0 {
sql1 := `SELECT count(doc.document_id) as total_count FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id
WHERE book.privately_owned = 0 AND (doc.document_name LIKE '%?%' OR doc.release LIKE '%?%') `
sql2 := `SELECT doc.document_id,doc.modify_time,doc.create_time,doc.document_name,doc.identify,doc.release as description,doc.modify_time,book.identify as book_identify,book.book_name,rel.member_id,member.account AS author FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id
LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND role_id = 0
LEFT JOIN md_members as member ON rel.member_id = member.member_id
WHERE book.privately_owned = 0 AND (doc.document_name LIKE '%?%' OR doc.release LIKE '%?%')
ORDER BY doc.document_id DESC LIMIT ?,? `
err = o.Raw(sql1,keyword,keyword).QueryRow(&total_count)
if err != nil{
return
}
_,err = o.Raw(sql2,keyword,keyword,offset,page_size).QueryRows(&search_result)
if err != nil {
return
}
}else{
sql1 := `SELECT count(doc.document_id) as total_count FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id
LEFT JOIN md_relationship AS rel ON doc.book_id = rel.book_id AND role_id = 0
WHERE (book.privately_owned = 0 OR rel.relationship_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?) `
sql2 := `SELECT doc.document_id,doc.modify_time,doc.create_time,doc.document_name,doc.identify,doc.release as description,doc.modify_time,book.identify as book_identify,book.book_name,rel.member_id,member.account AS author FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id
LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND role_id = 0
LEFT JOIN md_members as member ON rel.member_id = member.member_id
WHERE (book.privately_owned = 0 OR rel.relationship_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?)
ORDER BY doc.document_id DESC LIMIT ?,? `
keyword = "%"+keyword+"%"
err = o.Raw(sql1,keyword,keyword).QueryRow(&total_count)
if err != nil{
return
}
_,err = o.Raw(sql2,keyword,keyword,offset,page_size).QueryRows(&search_result)
if err != nil {
return
}
}
return
}

View File

@ -63,4 +63,7 @@ func init() {
beego.Router("/comment/create", &controllers.CommentController{},"post:Create")
beego.Router("/comment/lists", &controllers.CommentController{},"get:Lists")
beego.Router("/comment/index", &controllers.CommentController{},"*:Index")
beego.Router("/search",&controllers.SearchController{},"get:Index")
}

View File

@ -289,6 +289,87 @@ textarea{
.users-list .list-item .operate{
float: right;
}
/**************用户搜索界面样式********************/
.manual-search-reader .searchbar{
padding: 8px;
}
.manual-search-reader .manual-body{
margin-top: 60px;
}
.manual-search-reader .search-head{
margin: 10px auto;
padding-bottom: 15px;
line-height: 1.5em;
border-bottom: 3px solid #EEEEEE;
}
.manual-search-reader .search-head .search-title{
font-size: 22px;
font-weight: 300;
}
.manual-search-reader .search-body {
margin-top: 80px;
}
.manual-search-reader .searchbar .search-btn {
display: inline-block;
line-height: 100%;
cursor: pointer;
margin-top: -10px;
margin-left: -45px;
border: 0;
background-color: transparent
}
.manual-search-reader .searchbar .search-btn>i.fa{
padding: 10px;
}
.manual-search-reader .search-empty .empty-image{
margin: 5px auto;
display: block;
text-align: center;
opacity: 0.3;
filter: alpha(opacity=30);
}
.manual-search-reader .search-item{
margin: 0 15px;
padding: 10px 20px;
line-height: 25px;
}
.manual-search-reader .search-item:hover{
background-color: #F5F5F5;
}
.manual-search-reader .search-item a{
color: #0886E9;
}
.manual-search-reader .search-item em{
color: #FF802C;
font-style:normal;
}
.manual-search-reader .search-item .title{
font-size: 16px;
font-weight: 400;
}
.manual-search-reader .search-item .description{
color: #666;
line-height: 25px;
min-height: 20px;
font-size: 12px;
}
.manual-search-reader .search-item .site {
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
white-space: nowrap;
max-width: 600px;
color: #008000;
font-size: 12px;
}
.manual-search-reader .search-item .source .item {
display: inline-block;
margin-right: 15px;
}
.manual-search-reader .search-item .source,.manual-search-reader .search-item .source a{
font-size: 12px;
color: #999999;
}
/**************用户登录界面样式*******************/
.login .login-body{

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -243,7 +243,7 @@ $(function () {
if (doc_name === ""){
return showError("目录名称不能为空","#add-error-message")
}
window.addDocumentFormIndex = layer.load(1, { shade: [0.1,'#fff'] });
$("#btnSaveDocument").button("loading");
return true;
},
success : function (res) {
@ -266,7 +266,7 @@ $(function () {
}else{
showError(res.message,"#add-error-message")
}
layer.close(window.addDocumentFormIndex);
$("#btnSaveDocument").button("reset");
}
});

View File

@ -1,73 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>概要 - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="/static/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="manual-reader">
{{template "widgets/header.tpl" .}}
<div class="container manual-body">
<div class="row">
<div class="page-left">
<ul class="menu">
<li><a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
<li><a href="{{urlfor "BookController.Users" ":key" "test"}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
{{if eq .Model.RoleId 0 1}}
<li class="active"><a href="{{urlfor "BookController.Setting" ":key" "test"}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
{{end}}
</ul>
</div>
<div class="page-right">
<div class="m-box">
<div class="box-head">
<strong class="box-title"> 项目设置</strong>
<button type="button" class="btn btn-success btn-sm pull-right">转让项目</button>
<button type="button" class="btn btn-danger btn-sm pull-right" style="margin-right: 5px;">删除项目</button>
</div>
</div>
<div class="box-body" style="padding-right: 200px;">
<div class="form-left">
<form method="post" id="bookEditForm">
<div class="form-group">
<label>标题</label>
<input type="text" class="form-control" placeholder="项目名称">
</div>
</form>
</div>
<div class="form-right">
<label>
<a href="javascript:;" data-toggle="modal" data-target="#upload-logo-panel">
<img src="/static/images/5fcb811e04c23cdb2088f26923fcc287_100.jpg" onerror="this.src='https://wiki.iminho.me/static/images/middle.gif'" alt="头像" style="max-width: 120px;" id="headimgurl">
</a>
</label>
</div>
</div>
</div>
</div>
</div>
{{template "widgets/footer.tpl" .}}
</div>
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/js/main.js" type="text/javascript"></script>
</body>
</html>

View File

@ -83,11 +83,15 @@
<span class="title">担任角色:</span>
<span class="body">{{.Model.RoleName}}</span>
</div>
<div class="list">
{{/* <div class="list">
<span class="title">评论数量:</span>
<span class="body">{{.Model.CommentCount}} 条</span>
</div>
<div class="summary">{{.Model.Description}} </div>
</div>*/}}
<div class="list">
<span class="title">文档标签:</span>
<span class="body">{{.Model.Label}}</span>
</div>
<div class="summary">{{.Model.Description}} </div>
</div>
</div>

View File

@ -168,7 +168,7 @@
<div class="modal-footer">
<span id="form-error-message"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-success">保存</button>
<button type="submit" class="btn btn-success" id="btnSaveDocument" data-loading-text="保存中...">保存</button>
</div>
</div>
</form>
@ -204,16 +204,18 @@
if(description.length > 500){
return showError("描述信息不超过500个字符");
}
$("#btnSaveDocument").button("loading");
return showSuccess("");
},
success : function (res) {
console.log(res);
$("#btnSaveDocument").button("reset");
if(res.errcode === 0){
window.app.lists.splice(0,0,res.data);
$("#addBookDialogModal").modal("hide");
}else{
showError(res.message);
}
}
});

View File

@ -29,7 +29,7 @@
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
</ul>

View File

@ -30,7 +30,7 @@
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
</ul>
</div>

View File

@ -29,7 +29,7 @@
<li class="active"><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
</ul>
</div>
@ -55,11 +55,13 @@
<span class="fa-class">会员数量</span>
<span class="fa-class">{{.Model.MemberNumber}}</span>
</div>
{{/*
<div class="dashboard-item">
<span class="fa fa-comments-o" aria-hidden="true"></span>
<span class="fa-class">评论数量</span>
<span class="fa-class">{{.Model.CommentNumber}}</span>
</div>
*/}}
<div class="dashboard-item">
<span class="fa fa-cloud-download" aria-hidden="true"></span>
<span class="fa-class">附件数量</span>

View File

@ -28,7 +28,7 @@
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li class="active"><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
</ul>
</div>

View File

@ -29,7 +29,7 @@
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li class="active"><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
</ul>

58
views/search/index.tpl Normal file
View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>搜索 - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="/static/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="manual-reader manual-container manual-search-reader">
{{template "widgets/header.tpl" .}}
<div class="container manual-body">
<div class="search-head">
<strong class="search-title">显示"{{.Keyword}}"的搜索结果</strong>
</div>
<div class="row">
<div class="manual-list">
{{range $index,$item := .Lists}}
<div class="search-item">
<div class="title"><a href="{{urlfor "DocumentController.Read" ":key" $item.BookIdentify ":id" $item.Identify}}" title="{{$item.DocumentName}}" target="_blank">{{str2html $item.DocumentName}}</a> </div>
<div class="description">
{{str2html $item.Description}}
</div>
<div class="site">{{$.BaseUrl}}{{urlfor "DocumentController.Read" ":key" $item.BookIdentify ":id" $item.Identify}}</div>
<div class="source">
<span class="item">来自:<a href="{{urlfor "DocumentController.Index" ":key" $item.BookIdentify}}" target="_blank">{{$item.BookName}}</a></span>
<span class="item">作者:{{$item.Author}}</span>
<span class="item">更新时间:{{date $item.ModifyTime "Y-m-d H:i:s"}}</span>
</div>
</div>
{{else}}
<div class="search-empty">
<img src="/static/images/search_empty.png" class="empty-image">
</div>
{{end}}
<div class="clearfix"></div>
</div>
</div>
</div>
{{template "widgets/footer.tpl" .}}
</div>
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -8,6 +8,15 @@
{{.SITE_NAME}}
{{end}}
</a>
<div class="searchbar pull-left visible-lg-inline-block visible-md-inline-block">
<form class="form-inline" action="{{urlfor "SearchController.Index"}}" method="get">
<input class="form-control" name="keyword" type="search" style="width: 230px;" placeholder="请输入关键词..." value="{{.Keyword}}">
<button class="search-btn">
<i class="fa fa-search"></i>
</button>
</form>
</div>
{{/*
<div class="btn-group dropdown-menu-right pull-right slidebar visible-xs-inline-block visible-sm-inline-block">
<button class="btn btn-default dropdown-toggle hidden-lg" type="button" data-toggle="dropdown"><i class="fa fa-align-justify"></i></button>
<ul class="dropdown-menu" role="menu">
@ -22,6 +31,7 @@
</li>
</ul>
</div>
*/}}
</div>
<nav class="navbar-collapse hidden-xs hidden-sm" role="navigation">
<ul class="nav navbar-nav navbar-right">