添加文章模板的后端实现

master
DESKTOP-4RNDQIC\29019 2020-08-24 02:08:26 +08:00
parent 1c2ff37630
commit aeb0b55a43
11 changed files with 468 additions and 330 deletions

View File

@ -2,10 +2,9 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="7cf7b6b3-0082-44ef-bb0f-bfcc57e19eb1" name="Default Changelist" comment=""> <list default="true" id="7cf7b6b3-0082-44ef-bb0f-bfcc57e19eb1" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/fork.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/controller/blog.go" beforeDir="false" afterPath="$PROJECT_DIR$/controller/blog.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/main.go" afterDir="false" /> <change beforePath="$PROJECT_DIR$/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/main.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/model/blog.go" beforeDir="false" afterPath="$PROJECT_DIR$/model/blog.go" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -54,10 +53,11 @@
<property name="go.import.settings.migrated" value="true" /> <property name="go.import.settings.migrated" value="true" />
<property name="go.sdk.automatically.set" value="true" /> <property name="go.sdk.automatically.set" value="true" />
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" /> <property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../DroneIntegratedManagementServer" /> <property name="last_opened_file_path" value="$PROJECT_DIR$/../gobase" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="settings.editor.selected.configurable" value="go.sdk" /> <property name="settings.editor.selected.configurable" value="go.sdk" />
</component> </component>
<component name="RunManager"> <component name="RunManager" selected="Go Build.background">
<configuration name="background" type="GoApplicationRunConfiguration" factoryName="Go Application"> <configuration name="background" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="background" /> <module name="background" />
<working_directory value="$PROJECT_DIR$/" /> <working_directory value="$PROJECT_DIR$/" />
@ -70,6 +70,26 @@
<output_directory value="$PROJECT_DIR$/" /> <output_directory value="$PROJECT_DIR$/" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="fork2" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true">
<module name="background" />
<working_directory value="$PROJECT_DIR$/" />
<parameters value="background.exe" />
<kind value="FILE" />
<filePath value="$PROJECT_DIR$/fork.go" />
<package value="background" />
<directory value="$PROJECT_DIR$/" />
<output_directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Go Build.background" />
<item itemvalue="Go Build.fork2" />
</list>
<recent_temporary>
<list>
<item itemvalue="Go Build.fork2" />
</list>
</recent_temporary>
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
<option name="version" value="2" /> <option name="version" value="2" />
@ -91,30 +111,30 @@
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state x="767" y="429" key="#Go_Modules/0.40.2048.1112@0.40.2048.1112" timestamp="1595431702688" /> <state x="767" y="429" key="#Go_Modules/0.40.2048.1112@0.40.2048.1112" timestamp="1595431702688" />
<state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1595432372558"> <state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1595778748175">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.40.2048.1112@0.40.2048.1112" timestamp="1595432372558" /> <state x="479" y="251" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.40.2048.1112@0.40.2048.1112" timestamp="1595778748175" />
<state x="805" y="351" key="FileChooserDialogImpl" timestamp="1595431879732"> <state x="805" y="351" key="FileChooserDialogImpl" timestamp="1595857317209">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state x="805" y="351" key="FileChooserDialogImpl/0.40.2048.1112@0.40.2048.1112" timestamp="1595431879732" /> <state x="805" y="351" key="FileChooserDialogImpl/0.40.2048.1112@0.40.2048.1112" timestamp="1595857317209" />
<state width="2005" height="305" key="GridCell.Tab.0.bottom" timestamp="1595746777201"> <state width="2005" height="305" key="GridCell.Tab.0.bottom" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state width="2005" height="305" key="GridCell.Tab.0.bottom/0.40.2048.1112@0.40.2048.1112" timestamp="1595746777201" /> <state width="2005" height="305" key="GridCell.Tab.0.bottom/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.center" timestamp="1595746777200"> <state width="2005" height="305" key="GridCell.Tab.0.center" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state width="2005" height="305" key="GridCell.Tab.0.center/0.40.2048.1112@0.40.2048.1112" timestamp="1595746777200" /> <state width="2005" height="305" key="GridCell.Tab.0.center/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.left" timestamp="1595746777200"> <state width="2005" height="305" key="GridCell.Tab.0.left" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state width="2005" height="305" key="GridCell.Tab.0.left/0.40.2048.1112@0.40.2048.1112" timestamp="1595746777200" /> <state width="2005" height="305" key="GridCell.Tab.0.left/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="305" key="GridCell.Tab.0.right" timestamp="1595746777200"> <state width="2005" height="305" key="GridCell.Tab.0.right" timestamp="1595778772403">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state width="2005" height="305" key="GridCell.Tab.0.right/0.40.2048.1112@0.40.2048.1112" timestamp="1595746777200" /> <state width="2005" height="305" key="GridCell.Tab.0.right/0.40.2048.1112@0.40.2048.1112" timestamp="1595778772403" />
<state width="2005" height="376" key="GridCell.Tab.1.bottom" timestamp="1595433941254"> <state width="2005" height="376" key="GridCell.Tab.1.bottom" timestamp="1595433941254">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
@ -135,9 +155,9 @@
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state x="526" y="240" key="SettingsEditor/0.40.2048.1112@0.40.2048.1112" timestamp="1595432383541" /> <state x="526" y="240" key="SettingsEditor/0.40.2048.1112@0.40.2048.1112" timestamp="1595432383541" />
<state x="687" y="283" width="672" height="678" key="search.everywhere.popup" timestamp="1595431850294"> <state x="687" y="283" width="672" height="678" key="search.everywhere.popup" timestamp="1595757093391">
<screen x="0" y="40" width="2048" height="1112" /> <screen x="0" y="40" width="2048" height="1112" />
</state> </state>
<state x="687" y="283" width="672" height="678" key="search.everywhere.popup/0.40.2048.1112@0.40.2048.1112" timestamp="1595431850294" /> <state x="687" y="283" width="672" height="678" key="search.everywhere.popup/0.40.2048.1112@0.40.2048.1112" timestamp="1595757093391" />
</component> </component>
</project> </project>

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {},
"args": []
}
]
}

42
11.yaml Normal file
View File

@ -0,0 +1,42 @@
listen_api: 4596
runmode: debug
max_conn: 121
logs:
dir: /var/log/user
file: user.log
level: 1
savefile: false
redis1:
addr: 49.235.25.67:16379
password: ~
db: 1
mysql:
addr: 49.235.25.67
user: caiyu
password: 12345678
db: background
max_open: 100
MaxIdle: 99
elasticsearch:
address: http://hyrtc.net:9200
mysql1:
addr: 49.235.25.67
user: caiyu
password: 12345678
db: background
max_open: 100
MaxIdle: 99
mongo:
addr: 49.235.25.67
port: 27017
user: root
password: root
db: test
max_open: 100
MaxIdle: 99
ca_cert: ""
client_cert: ""
client_key: ""
test_arr:
- 1
- 23

View File

@ -5,9 +5,10 @@ import (
"background/logs" "background/logs"
"background/model" "background/model"
"fmt" "fmt"
"strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"qiniupkg.com/x/log.v7" "qiniupkg.com/x/log.v7"
"strconv"
) )
func GetPageParaFromQuery(c *gin.Context) (int, int) { func GetPageParaFromQuery(c *gin.Context) (int, int) {
@ -112,7 +113,7 @@ func GetArticleCount(c *gin.Context) {
type Cnt struct { type Cnt struct {
Cnt int64 `sql:"cnt" json:"cnt"` Cnt int64 `sql:"cnt" json:"cnt"`
} }
cnt := []Cnt{}; cnt := []Cnt{}
e := db.GetMysqlClient().Query2(query, &cnt) e := db.GetMysqlClient().Query2(query, &cnt)
if nil != e { if nil != e {
@ -158,7 +159,7 @@ func GetArticle(c *gin.Context) {
} }
func UpdateArtilce(c *gin.Context) { func UpdateArtilce(c *gin.Context) {
rsp := RespBase{Msg:"FAIL", Status:210,} rsp := RespBase{Msg: "FAIL", Status: 210}
type ReqUpdateArticle struct { type ReqUpdateArticle struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@ -199,13 +200,13 @@ func UpdateArtilce(c *gin.Context) {
} }
func SearchArticle(c *gin.Context) { func SearchArticle(c *gin.Context) {
rsp := RespBase{Msg:"FAIL", Status:210,} rsp := RespBase{Msg: "FAIL", Status: 210}
defer func() { defer func() {
c.JSON(200, rsp) c.JSON(200, rsp)
}() }()
} }
func AddArticle(c *gin.Context) { func AddArticle(c *gin.Context) {
rsp := RespBase{Msg:"FAIL", Status:210,} rsp := RespBase{Msg: "FAIL", Status: 210}
type ReqAddArticle struct { type ReqAddArticle struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@ -244,9 +245,8 @@ func AddArticle(c *gin.Context) {
rsp.Status = 0 rsp.Status = 0
} }
func ArticlesType(c *gin.Context) { func ArticlesType(c *gin.Context) {
rsp := RespBase{Msg:"FAIL", Status:210,} rsp := RespBase{Msg: "FAIL", Status: 210}
defer func() { defer func() {
c.JSON(200, rsp) c.JSON(200, rsp)
}() }()
@ -314,7 +314,7 @@ func AddArticleType(c *gin.Context) {
} }
func DeleteArticle(c *gin.Context) { func DeleteArticle(c *gin.Context) {
rsp := RespBase{Msg:"FAIL", Status:210,} rsp := RespBase{Msg: "FAIL", Status: 210}
defer func() { defer func() {
c.JSON(200, rsp) c.JSON(200, rsp)
}() }()
@ -334,7 +334,6 @@ func DeleteArticle(c *gin.Context) {
rsp.Msg = "OK" rsp.Msg = "OK"
} }
func ArticlesTypes(c *gin.Context) { func ArticlesTypes(c *gin.Context) {
resp := RespBase{"unkown error", -231, nil} resp := RespBase{"unkown error", -231, nil}
defer func() { defer func() {
@ -378,7 +377,6 @@ func CreateMemo(c *gin.Context) {
resp.Status = 0 resp.Status = 0
} }
func UpdateMemo(c *gin.Context) { func UpdateMemo(c *gin.Context) {
resp := RespBase{"unkown error", -231, nil} resp := RespBase{"unkown error", -231, nil}
defer func() { defer func() {
@ -414,6 +412,15 @@ func GetDocGroup(c *gin.Context) {
rsp.Status = 0 rsp.Status = 0
rsp.Msg = "OK" rsp.Msg = "OK"
} }
func GetTemplates(c *gin.Context) {
rsp := RespBase{"ERR", -1, nil}
defer func() {
c.JSON(200, rsp)
}()
}
func GetMemos(c *gin.Context) { func GetMemos(c *gin.Context) {
rsp := RespBase{"ERR", -1, nil} rsp := RespBase{"ERR", -1, nil}
defer func() { defer func() {
@ -448,7 +455,9 @@ func GetMemos(c *gin.Context) {
} }
} }
func GetDocTemplate(c *gin.Context) {
}
func GetMemo(c *gin.Context) { func GetMemo(c *gin.Context) {
rsp := RespBase{"ERR", -1, nil} rsp := RespBase{"ERR", -1, nil}
defer func() { defer func() {

View File

@ -3,6 +3,7 @@ package controller
import ( import (
"background/logs" "background/logs"
"background/model" "background/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"qiniupkg.com/x/log.v7" "qiniupkg.com/x/log.v7"
) )

View File

@ -0,0 +1,19 @@
package helper
import (
"background/controller/params"
"github.com/gin-gonic/gin"
)
func GetPageParam(c *gin.Context) (int, int) {
var limit, offset int
var ok bool
limit, ok = c.Keys[params.K_OFFSET].(int)
if !ok {
}
offset, ok = c.Keys[params.K_OFFSET].(int)
if !ok {
}
return limit, offset
}

5
controller/params/params Normal file
View File

@ -0,0 +1,5 @@
package params
const K_OFFSET = "offset"
const K_LIMIT = "limit"

View File

@ -1,16 +1,17 @@
package controller package controller
import ( import (
"background/config"
"background/db"
"background/logs"
"background/model"
"background/redis"
"background/utils" "background/utils"
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/fatih/structs"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/tommy351/gin-sessions"
"io" "io"
"log" "log"
"math/rand" "math/rand"
@ -20,15 +21,14 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"background/config"
"background/db" "github.com/fatih/structs"
"background/logs" "github.com/gin-gonic/gin"
"background/model" _ "github.com/go-sql-driver/mysql"
"background/redis" sessions "github.com/tommy351/gin-sessions"
) )
type UserController struct { type UserController struct {
} }
type ReqSendEmailCode struct { type ReqSendEmailCode struct {
@ -137,7 +137,6 @@ func (this *UserController) GetUser(c *gin.Context) {
resp.Data = users resp.Data = users
} }
func (this *UserController) Users(c *gin.Context) { func (this *UserController) Users(c *gin.Context) {
var statuscode int var statuscode int
var resp RespBase var resp RespBase
@ -169,7 +168,6 @@ func (this *UserController) Users(c *gin.Context) {
resp.Data = dat resp.Data = dat
} }
func (this *UserController) SerarchUsers(c *gin.Context) { func (this *UserController) SerarchUsers(c *gin.Context) {
var statuscode int var statuscode int
var resp RespBase var resp RespBase
@ -234,7 +232,6 @@ func DefaultOption(c *gin.Context) {
}() }()
} }
func (this *UserController) Login(c *gin.Context) { func (this *UserController) Login(c *gin.Context) {
type LoginReq struct { type LoginReq struct {
RememberMe int32 `json:"remember_me"` RememberMe int32 `json:"remember_me"`

View File

@ -7,36 +7,50 @@ import (
"crypto/x509" "crypto/x509"
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/go-sql-driver/mysql"
_ "github.com/go-sql-driver/mysql"
"gopkg.in/mgo.v2"
"gopkg.in/olivere/elastic.v7"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"github.com/go-sql-driver/mysql"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"gopkg.in/mgo.v2"
"gopkg.in/olivere/elastic.v7"
) )
var gEla ElkEngine var gEla ElkEngine
var gDb Database var gDb Database
var blogDb Database var blogDb Database
var gMongo *mgo.Session var gMongo *mgo.Session
var gElkEngine ElkEngine var gElkEngine ElkEngine
var gOrm *gorm.DB
func Init() { func Init() {
var e error
mysqlconf := config.GetMysqlConfig() mysqlconf := config.GetMysqlConfig()
blogConf := config.GetMysqlBlogConfig()
//InitMongoDb() //InitMongoDb()
fmt.Print("api runmode is " + config.ApiConfig().RunMode) log.Print("api runmode is " + config.ApiConfig().RunMode)
if config.ApiConfig().RunMode == "debug" { if config.ApiConfig().RunMode == "debug" {
blogDb = Database{Type: string(""), DB: initMysqlTLS(blogConf)} gDb = Database{Type: string(""), DB: initMysql(mysqlconf)}
}else{ sqls := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8&parseTime=True&loc=Local",
blogDb = Database{Type: string(""), DB: initMysqlTLS(blogConf)} mysqlconf.UserName, mysqlconf.Password, mysqlconf.Addr,
mysqlconf.Db)
log.Print(sqls)
gOrm, e = gorm.Open("mysql", sqls)
if nil != e {
log.Print(e.Error())
os.Exit(-1)
} }
if config.ApiConfig().RunMode == "debug"{
gDb = Database{Type: string(""), DB: initMysqlTLS(mysqlconf)}
} else { } else {
gDb = Database{Type: string(""), DB: initMysqlTLS(mysqlconf)} sqls := fmt.Sprintf("%s:%s@/%s?charset=utf8&parseTime=True&loc=Local", mysqlconf.UserName, mysqlconf.Password,
mysqlconf.Db)
gOrm, e = gorm.Open("mysql", sqls)
if nil != e {
log.Print(e.Error())
os.Exit(-1)
} }
}
InitELK() InitELK()
} }
@ -47,7 +61,7 @@ func InitELK() {
gElkEngine.cli, e = elastic.NewClient( gElkEngine.cli, e = elastic.NewClient(
elastic.SetURL(elkconf.Address), elastic.SetURL(elkconf.Address),
// Must turn off sniff in docker // Must turn off sniff in docker
elastic.SetSniff(false),) elastic.SetSniff(false))
if nil != e { if nil != e {
logs.Error(e.Error()) logs.Error(e.Error())
gElkEngine.cli = nil gElkEngine.cli = nil
@ -150,3 +164,6 @@ func InitMongoDb() {
func GetElastic() *ElkEngine { func GetElastic() *ElkEngine {
return &gElkEngine return &gElkEngine
} }
func GetOrm() *gorm.DB {
return gOrm
}

20
main.go
View File

@ -8,12 +8,14 @@ import (
_ "background/docs" _ "background/docs"
"background/logs" "background/logs"
"background/model" "background/model"
"github.com/gin-gonic/gin"
"github.com/swaggo/files" // swagger embed files
"github.com/swaggo/gin-swagger" // gin-swagger middleware
"github.com/tommy351/gin-sessions"
"log" "log"
"os"
"strconv" "strconv"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files" // swagger embed files
ginSwagger "github.com/swaggo/gin-swagger" // gin-swagger middleware
sessions "github.com/tommy351/gin-sessions"
) )
// @title 大厅功能api // @title 大厅功能api
@ -28,7 +30,6 @@ var (
webhookController = controller.WebHookController{} webhookController = controller.WebHookController{}
) )
func CORSMiddleware(c *gin.Context) { func CORSMiddleware(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
if config.ApiConfig().RunMode == "release" { if config.ApiConfig().RunMode == "release" {
@ -90,6 +91,8 @@ func InitLogs() {
logs.Init(config.GetLogConfig().Dir, config.GetLogConfig().File, config.GetLogConfig().Level, config.GetLogConfig().SaveFile) logs.Init(config.GetLogConfig().Dir, config.GetLogConfig().File, config.GetLogConfig().Level, config.GetLogConfig().SaveFile)
} }
func main() { func main() {
log.Print("gid is", os.Getegid())
InitConfig() InitConfig()
InitLogs() InitLogs()
InitRedisConfig() InitRedisConfig()
@ -162,11 +165,18 @@ func main() {
api.POST("/delmemo", controller.DeleteMemos) //删除备忘录 api.POST("/delmemo", controller.DeleteMemos) //删除备忘录
api.GET("/memo", controller.GetMemo) // 单独读取 api.GET("/memo", controller.GetMemo) // 单独读取
api.GET("doc_groups", controller.GetDocGroup) // 获取所有的文章分组 api.GET("doc_groups", controller.GetDocGroup) // 获取所有的文章分组
api.GET("templates", controller.GetDocTemplate) // 获取所有文章的模板
api.GET("doc_versions", nil) // 获取文章的某个版本
} }
hookapi := r.Group("hookapi") hookapi := r.Group("hookapi")
{ {
hookapi.POST("/push_hook/:repo", webhookController.PushHook) hookapi.POST("/push_hook/:repo", webhookController.PushHook)
} }
openapi := r.Group("openapi")
{
openapi.POST("negotiate")
}
e := r.Run(":" + strconv.Itoa(config.GetPort())) e := r.Run(":" + strconv.Itoa(config.GetPort()))
if nil != e { if nil != e {
log.Print(e.Error()) log.Print(e.Error())

View File

@ -4,8 +4,9 @@ import (
"background/db" "background/db"
"background/logs" "background/logs"
"fmt" "fmt"
"qiniupkg.com/x/log.v7"
"strings" "strings"
"qiniupkg.com/x/log.v7"
) )
type Doc struct { type Doc struct {