使用常量标记状态和Redis的key,增加了文件管理功能,修改tinymce页面增加文件上传功能
This commit is contained in:
parent
e1d0017257
commit
a2d868d354
|
@ -1,6 +1,7 @@
|
|||
package async
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/blog"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
|
@ -27,7 +28,7 @@ func init() {
|
|||
database.GormTemplate.Table("blog_articles").Where("id = ?", id).UpdateColumn("publish_time", time)
|
||||
database.GormTemplate.Table("blog_articles").Where("id = ?", id).First(article)
|
||||
|
||||
database.RedisTemplate.ZAdd(ctx, "blog:article:latest", redis.Z{Score: float64(article.PublishTime), Member: article})
|
||||
database.RedisTemplate.ZAdd(ctx, consts.REDIS_BLOG_ARTICLE_LATEST, redis.Z{Score: float64(article.PublishTime), Member: article})
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package async
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/blog"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
|
@ -22,7 +23,7 @@ func init() {
|
|||
|
||||
var diary blog.BlogDiary
|
||||
database.GormTemplate.Table("blog_diaries").Where("id = ?", id).First(&diary)
|
||||
database.RedisTemplate.ZAdd(ctx, "blog:diary:latest", redis.Z{Score: float64(diary.PublishTime), Member: diary})
|
||||
database.RedisTemplate.ZAdd(ctx, consts.REDIS_BLOG_DIARY_LATEST, redis.Z{Score: float64(diary.PublishTime), Member: diary})
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package async
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
"log"
|
||||
|
@ -30,7 +31,7 @@ func init() {
|
|||
record.Id = uuid.NewString()
|
||||
database.GormTemplate.Table("blog_view_record").Create(&record)
|
||||
ctx := context.Background()
|
||||
database.RedisTemplate.HIncrBy(ctx, "blog:view:record", relId, 1)
|
||||
database.RedisTemplate.HIncrBy(ctx, consts.REDIS_BLOG_VIEW_RECORD, relId, 1)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package consts
|
||||
|
||||
//文章状态常量
|
||||
const ARTICLE_STATE_PUBLISH string = "publish"
|
||||
const ARTICLE_STATE_DRAFT string = "draft"
|
||||
|
||||
const ARTICLE_CONTENT_TYPE_MARKDOWN string = "markdown"
|
||||
const ARTICLE_CONTENT_TYPE_TINYMCE string = "tinymce"
|
|
@ -0,0 +1,6 @@
|
|||
package consts
|
||||
|
||||
//文本状态常量
|
||||
|
||||
const CONTENT_STATE_PUBLISH string = "publish"
|
||||
const CONTENT_STATE_DOWN string = "down"
|
|
@ -0,0 +1,21 @@
|
|||
package consts
|
||||
|
||||
//Redis
|
||||
|
||||
//文章相关Key常量
|
||||
const REDIS_BLOG_ARTICLE string = "blog:article:"
|
||||
const REDIS_BLOG_ARTICLE_LATEST string = "blog:article:latest"
|
||||
|
||||
//日记相关Key常量
|
||||
const REDIS_BLOG_DIARY string = "blog:diary:"
|
||||
const REDIS_BLOG_DIARY_LATEST string = "blog:diary:latest"
|
||||
|
||||
//文件相关Key常量
|
||||
const REDIS_FILE string = "blog:file:"
|
||||
const REDIS_FILE_BYTES string = "blog:file:bytes"
|
||||
|
||||
//文本相关Key常量
|
||||
const REDIS_BLOG_CONTENT string = "blog:content:"
|
||||
|
||||
//点击量相关Key常量
|
||||
const REDIS_BLOG_VIEW_RECORD string = "blog:view:record"
|
|
@ -2,6 +2,7 @@ package controller
|
|||
|
||||
import (
|
||||
"blog/internal/async"
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/AjaxResult"
|
||||
"blog/internal/model/blog"
|
||||
"blog/internal/service"
|
||||
|
@ -28,7 +29,7 @@ func (ctrl *ArticleController) Get() {
|
|||
func (ctrl *ArticleController) GetLatest() {
|
||||
ctx := context.Background()
|
||||
var slices []blog.BlogArticle
|
||||
err := database.RedisTemplate.ZRevRange(ctx, "blog:article:latest", 0, 10).ScanSlice(&slices)
|
||||
err := database.RedisTemplate.ZRevRange(ctx, consts.REDIS_BLOG_ARTICLE_LATEST, 0, 10).ScanSlice(&slices)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ctrl.Ctx.JSON(AjaxResult.Error("加载错误"))
|
||||
|
@ -38,7 +39,7 @@ func (ctrl *ArticleController) GetLatest() {
|
|||
for i := range slices {
|
||||
article := &slices[i]
|
||||
id := article.Id
|
||||
viewRecord, _ := database.RedisTemplate.HGet(ctx, "blog:view:record", id).Int()
|
||||
viewRecord, _ := database.RedisTemplate.HGet(ctx, consts.REDIS_BLOG_VIEW_RECORD, id).Int()
|
||||
article.ViewRecord = viewRecord
|
||||
}
|
||||
|
||||
|
@ -58,7 +59,7 @@ func (ctrl *ArticleController) ViewArticle() {
|
|||
content := service.ContentService.GetContentByCache(articleId)
|
||||
ctrl.Ctx.ViewData("article", article)
|
||||
ctrl.Ctx.ViewData("content", content)
|
||||
if article.ContentType == "markdown" {
|
||||
if article.ContentType == consts.ARTICLE_CONTENT_TYPE_MARKDOWN {
|
||||
ctrl.Ctx.View("blog/article/article_md.html")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/AjaxResult"
|
||||
"blog/internal/model/blog"
|
||||
"blog/internal/service"
|
||||
|
@ -24,7 +25,7 @@ func (ctrl *DiaryController) Get() {
|
|||
func (ctrl *DiaryController) GetLatest() {
|
||||
ctx := context.Background()
|
||||
var slices []blog.BlogDiary
|
||||
err := database.RedisTemplate.ZRevRange(ctx, "blog:diary:latest", 0, 5).ScanSlice(&slices)
|
||||
err := database.RedisTemplate.ZRevRange(ctx, consts.REDIS_BLOG_DIARY_LATEST, 0, 5).ScanSlice(&slices)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ctrl.Ctx.JSON(AjaxResult.Error("加载错误"))
|
||||
|
|
|
@ -2,6 +2,7 @@ package controller
|
|||
|
||||
import (
|
||||
"blog/internal/service"
|
||||
"net/url"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/kataras/iris/v12/mvc"
|
||||
|
@ -14,10 +15,13 @@ type FileController struct {
|
|||
}
|
||||
|
||||
func (ctrl *FileController) ViewFile() {
|
||||
relId := ctrl.Ctx.Params().Get("id")
|
||||
bytes := service.FileService.GetFile(relId)
|
||||
ctrl.Ctx.Write(bytes)
|
||||
|
||||
id := ctrl.Ctx.Params().Get("id")
|
||||
file, err := service.FileService.GetFile(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctrl.Ctx.Header("Content-Disposition", "attachment;filename="+url.QueryEscape(file.FileName))
|
||||
ctrl.Ctx.Write(file.Data)
|
||||
}
|
||||
|
||||
func (ctrl *FileController) BeforeActivation(activation mvc.BeforeActivation) {
|
||||
|
|
|
@ -2,6 +2,8 @@ package admin
|
|||
|
||||
import (
|
||||
"blog/internal/model/admin"
|
||||
"blog/internal/service"
|
||||
"blog/third_party/SessionUtil"
|
||||
"blog/third_party/database"
|
||||
"time"
|
||||
|
||||
|
@ -23,6 +25,18 @@ type uploadResponse struct {
|
|||
Location string `json:"location"`
|
||||
}
|
||||
|
||||
func (ctrl *FileController) Get() {
|
||||
ctrl.Ctx.View("/admin/file/index.html")
|
||||
}
|
||||
|
||||
func (ctrl *FileController) GetList() {
|
||||
page := ctrl.Ctx.URLParamIntDefault("page", 0)
|
||||
itemsPerPage := ctrl.Ctx.URLParamIntDefault("itemsPerPage", 10)
|
||||
pages := service.FileService.PageSysFiles(page, itemsPerPage)
|
||||
|
||||
ctrl.Ctx.JSON(pages)
|
||||
}
|
||||
|
||||
func (ctrl *FileController) PostUpload() {
|
||||
file, fileHeader, err := ctrl.Ctx.FormFile("editormd-image-file")
|
||||
if err != nil {
|
||||
|
@ -31,13 +45,22 @@ func (ctrl *FileController) PostUpload() {
|
|||
return
|
||||
}
|
||||
}
|
||||
user := SessionUtil.GetUser(ctrl.Session)
|
||||
fileId := uuid.NewString()
|
||||
fileName := fileHeader.Filename
|
||||
fileSize := fileHeader.Size
|
||||
var bytes []byte = make([]byte, fileSize)
|
||||
file.Read(bytes)
|
||||
|
||||
sysFile := admin.SysFile{Id: fileId, FileName: fileName, FileSize: fileSize, CreateTime: time.Now().UnixMilli(), Data: bytes, State: "1", Del: 0}
|
||||
sysFile := admin.SysFile{
|
||||
Id: fileId,
|
||||
FileName: fileName,
|
||||
FileSize: fileSize,
|
||||
CreateBy: user.Username,
|
||||
CreateTime: time.Now().UnixMilli(),
|
||||
Data: bytes, State: "1",
|
||||
Del: 0,
|
||||
}
|
||||
err = database.GormTemplate.Transaction(func(tx *gorm.DB) error {
|
||||
err2 := tx.Table("common_files").Create(sysFile).Error
|
||||
return err2
|
||||
|
|
|
@ -5,7 +5,7 @@ import "encoding/json"
|
|||
type CommonFiles struct {
|
||||
Id string `json:"id" gorm:"primary_key"`
|
||||
FileName string `json:"fileName"`
|
||||
Data []byte
|
||||
Data []byte `json:"-"`
|
||||
Sort int32 `json:"sort"`
|
||||
CreateBy string `json:"-"`
|
||||
CreateTime int64 `json:"-"`
|
||||
|
@ -15,11 +15,11 @@ type CommonFiles struct {
|
|||
Del int `json:"-"`
|
||||
}
|
||||
|
||||
func (article *CommonFiles) MarshalBinary() (data []byte, err error) {
|
||||
func (file *CommonFiles) MarshalBinary() (data []byte, err error) {
|
||||
// encoding.BinaryMarshaler
|
||||
return json.Marshal(article)
|
||||
return json.Marshal(file)
|
||||
}
|
||||
|
||||
func (article *CommonFiles) UnmarshalBinary(data []byte) (err error) {
|
||||
return json.Unmarshal(data, article)
|
||||
func (file *CommonFiles) UnmarshalBinary(data []byte) (err error) {
|
||||
return json.Unmarshal(data, file)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/admin"
|
||||
"blog/internal/model/blog"
|
||||
"blog/internal/model/vo"
|
||||
|
@ -23,13 +24,13 @@ var ArticleService articleService
|
|||
|
||||
func (*articleService) InitArticleData() {
|
||||
var articleSlice []blog.BlogArticle
|
||||
result := database.GormTemplate.Where("state = ?", "publish").Find(&articleSlice)
|
||||
result := database.GormTemplate.Where("state = ?", consts.ARTICLE_STATE_PUBLISH).Find(&articleSlice)
|
||||
log.Println("文章初始化数据加载量:", result.RowsAffected)
|
||||
ctx := context.Background()
|
||||
for _, article := range articleSlice {
|
||||
// log.Println(article)
|
||||
publishTime := article.PublishTime
|
||||
err := database.RedisTemplate.ZAdd(ctx, "blog:article:latest", redis.Z{Score: float64(publishTime), Member: &article}).Err()
|
||||
err := database.RedisTemplate.ZAdd(ctx, consts.REDIS_BLOG_ARTICLE_LATEST, redis.Z{Score: float64(publishTime), Member: &article}).Err()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
@ -43,14 +44,14 @@ func (*articleService) InitArticleData() {
|
|||
database.GormTemplate.Table("blog_view_record").Select("rel_id ,count(1) counts").Group("rel_id").Find(&records)
|
||||
|
||||
for _, val := range records {
|
||||
database.RedisTemplate.HSet(ctx, "blog:view:record", map[string]any{val.RelId: val.Counts})
|
||||
database.RedisTemplate.HSet(ctx, consts.REDIS_BLOG_VIEW_RECORD, map[string]any{val.RelId: val.Counts})
|
||||
}
|
||||
}
|
||||
|
||||
func (*articleService) GetBlogArticle(id string) blog.BlogArticle {
|
||||
ctx := context.Background()
|
||||
var article blog.BlogArticle
|
||||
key := "blog:article:" + id
|
||||
key := consts.REDIS_BLOG_ARTICLE + id
|
||||
err := database.RedisTemplate.HGetAll(ctx, key).Scan(&article)
|
||||
if err != nil || article.Id == "" {
|
||||
database.GormTemplate.Table("blog_articles").Where("id = ?", id).First(&article)
|
||||
|
@ -93,7 +94,7 @@ func (*articleService) CreateArticle(articel *admin.AdminArticle) (string, error
|
|||
articel.CreateTime = time
|
||||
articel.UpdateTime = time
|
||||
articel.Del = 0
|
||||
articel.State = "draft"
|
||||
articel.State = consts.ARTICLE_STATE_DRAFT
|
||||
|
||||
err := database.GormTemplate.Transaction(func(tx *gorm.DB) error {
|
||||
contentId := uuid.NewString()
|
||||
|
@ -134,19 +135,19 @@ func (*articleService) PublishArticle(id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if article.State != "draft" {
|
||||
if article.State != consts.ARTICLE_STATE_DRAFT {
|
||||
return errors.New("发布失败,文章状态不是起草状态,无法发布")
|
||||
}
|
||||
|
||||
article.PublishTime = now
|
||||
article.State = "publish"
|
||||
article.State = consts.ARTICLE_STATE_PUBLISH
|
||||
|
||||
err = database.GormTemplate.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error = tx.Table("blog_articles").Updates(&article).Error
|
||||
if txErr != nil {
|
||||
return errors.New("文章更新错误")
|
||||
}
|
||||
txErr = ContentService.UpdataState(id, "publish")
|
||||
txErr = ContentService.UpdataState(id, consts.CONTENT_STATE_PUBLISH)
|
||||
if txErr != nil {
|
||||
return errors.New("文本状态更新错误")
|
||||
}
|
||||
|
@ -156,11 +157,11 @@ func (*articleService) PublishArticle(id string) error {
|
|||
}
|
||||
|
||||
ctx := context.Background()
|
||||
txErr = database.RedisTemplate.ZAdd(ctx, "blog:article:latest", redis.Z{Score: float64(article.PublishTime), Member: &article}).Err()
|
||||
txErr = database.RedisTemplate.ZAdd(ctx, consts.REDIS_BLOG_ARTICLE_LATEST, redis.Z{Score: float64(article.PublishTime), Member: &article}).Err()
|
||||
if txErr != nil {
|
||||
return errors.New("缓存错误")
|
||||
}
|
||||
txErr = database.RedisTemplate.Set(ctx, "blog:content:"+id, content.Content, time.Duration(0)).Err()
|
||||
txErr = database.RedisTemplate.Set(ctx, consts.REDIS_BLOG_CONTENT+id, content.Content, time.Duration(0)).Err()
|
||||
|
||||
return txErr
|
||||
})
|
||||
|
@ -175,14 +176,14 @@ func (*articleService) UnPublishArticle(id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if article.State != "publish" {
|
||||
if article.State != consts.CONTENT_STATE_PUBLISH {
|
||||
return errors.New("撤下失败,文章状态不是已发布状态,无法撤下")
|
||||
}
|
||||
|
||||
err = database.GormTemplate.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
ctx := context.Background()
|
||||
txErr = database.RedisTemplate.ZRemRangeByScore(ctx, "blog:article:latest",
|
||||
txErr = database.RedisTemplate.ZRemRangeByScore(ctx, consts.REDIS_BLOG_ARTICLE_LATEST,
|
||||
strconv.FormatFloat(float64(article.PublishTime), 'E', -1, 64),
|
||||
strconv.FormatFloat(float64(article.PublishTime), 'E', -1, 64),
|
||||
).Err()
|
||||
|
@ -191,18 +192,18 @@ func (*articleService) UnPublishArticle(id string) error {
|
|||
return errors.New("缓存错误")
|
||||
}
|
||||
|
||||
txErr = database.RedisTemplate.Del(ctx, "blog:content:"+id).Err()
|
||||
txErr = database.RedisTemplate.Del(ctx, consts.REDIS_BLOG_CONTENT+id).Err()
|
||||
if txErr != nil {
|
||||
return errors.New("缓存错误")
|
||||
}
|
||||
|
||||
article.State = "draft"
|
||||
article.State = consts.ARTICLE_STATE_DRAFT
|
||||
article.PublishTime = -1
|
||||
txErr = tx.Table("blog_articles").Updates(&article).Error
|
||||
if txErr != nil {
|
||||
return errors.New("文章状态更新错误")
|
||||
}
|
||||
txErr = ContentService.UpdataState(id, "down")
|
||||
txErr = ContentService.UpdataState(id, consts.CONTENT_STATE_DOWN)
|
||||
|
||||
return txErr
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/vo"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
|
@ -15,12 +16,12 @@ var ContentService contentService
|
|||
|
||||
func (*contentService) InitContentData() {
|
||||
var contentSlice []vo.CommonContent
|
||||
result := database.GormTemplate.Table("common_contents").Where("state = ?", "publish").Find(&contentSlice)
|
||||
result := database.GormTemplate.Table("common_contents").Where("state = ?", consts.CONTENT_STATE_PUBLISH).Find(&contentSlice)
|
||||
log.Println("大文本初始化数据加载量:", result.RowsAffected)
|
||||
ctx := context.Background()
|
||||
|
||||
for _, content := range contentSlice {
|
||||
database.RedisTemplate.Set(ctx, "blog:content:"+content.RelId, content.Content, time.Duration(0))
|
||||
database.RedisTemplate.Set(ctx, consts.REDIS_BLOG_CONTENT+content.RelId, content.Content, time.Duration(0))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ func (*contentService) InitContentData() {
|
|||
func (*contentService) GetContentByCache(relId string) string {
|
||||
ctx := context.Background()
|
||||
var content string
|
||||
database.RedisTemplate.Get(ctx, "blog:content:"+relId).Scan(&content)
|
||||
database.RedisTemplate.Get(ctx, consts.REDIS_BLOG_CONTENT+relId).Scan(&content)
|
||||
return content
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/blog"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
|
@ -23,7 +24,7 @@ func (*diaryService) InitDiaryData() {
|
|||
for _, diary := range diarySlice {
|
||||
// log.Println(article)
|
||||
publishTime := diary.PublishTime
|
||||
err := database.RedisTemplate.ZAdd(ctx, "blog:diary:latest", redis.Z{Score: float64(publishTime), Member: &diary}).Err()
|
||||
err := database.RedisTemplate.ZAdd(ctx, consts.REDIS_BLOG_DIARY_LATEST, redis.Z{Score: float64(publishTime), Member: &diary}).Err()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"blog/internal/consts"
|
||||
"blog/internal/model/admin"
|
||||
"blog/internal/model/vo"
|
||||
"blog/third_party/database"
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -12,15 +15,46 @@ type fileService struct {
|
|||
|
||||
var FileService fileService
|
||||
|
||||
func (*fileService) GetFile(relId string) []byte {
|
||||
func (*fileService) GetFile(id string) (vo.CommonFiles, error) {
|
||||
ctx := context.Background()
|
||||
key := "blog:file:" + relId
|
||||
bytes, err := database.RedisTemplate.Get(ctx, key).Bytes()
|
||||
if err != nil {
|
||||
var file vo.CommonFiles
|
||||
database.GormTemplate.Table("common_files").Where("id = ?", relId).First(&file)
|
||||
var bytes []byte
|
||||
err := database.RedisTemplate.Get(ctx, consts.REDIS_FILE+id).Scan(&file)
|
||||
//如果缓存不存在,则查数据库并存入Redis
|
||||
if err != nil || file.Id == "" {
|
||||
database.GormTemplate.Table("common_files").Where("id = ?", id).First(&file)
|
||||
bytes = file.Data
|
||||
database.RedisTemplate.Set(ctx, key, bytes, time.Duration(0))
|
||||
err = database.RedisTemplate.Set(ctx, consts.REDIS_FILE+id, &file, time.Duration(0)).Err()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return bytes
|
||||
err = database.RedisTemplate.Set(ctx, consts.REDIS_FILE_BYTES+id, bytes, time.Duration(0)).Err()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
bytes, err = database.RedisTemplate.Get(ctx, consts.REDIS_FILE_BYTES+id).Bytes()
|
||||
file.Data = bytes
|
||||
return file, err
|
||||
}
|
||||
|
||||
func (*fileService) PageSysFiles(page int, itemsPerPage int) vo.Page[admin.SysFile] {
|
||||
var content []admin.SysFile
|
||||
var totalElements int64
|
||||
database.GormTemplate.Table("common_files").Count(&totalElements)
|
||||
database.GormTemplate.Table("common_files").
|
||||
Where("del != ?", 1).
|
||||
Offset((page - 1) * itemsPerPage).
|
||||
Limit(itemsPerPage).
|
||||
Order("create_time DESC").
|
||||
Find(&content)
|
||||
|
||||
pre := int(totalElements) % itemsPerPage
|
||||
if pre > 0 {
|
||||
pre = 1
|
||||
}
|
||||
var totalPages int = int(totalElements)/itemsPerPage + pre
|
||||
|
||||
return vo.Page[admin.SysFile]{TotalElements: totalElements, TotalPages: totalPages, Number: totalPages, Content: content}
|
||||
}
|
||||
|
|
2
main.go
2
main.go
|
@ -21,6 +21,8 @@ import (
|
|||
// func main() {
|
||||
// i := time.Now().UnixMilli()
|
||||
// log.Println(i)
|
||||
// b, _ := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost)
|
||||
// log.Println(string(b))
|
||||
// }
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Admin Console</title>
|
||||
<link rel="icon" href="/assets/favicon.ico" type="image/x-icon"/>
|
||||
<link rel="bookmark" href="/assets/favicon.ico" type="image/x-icon"/>
|
||||
<link href="/assets/vuetify-v2.6.9/vuetify-v2.6.9.min.css" rel="stylesheet"/>
|
||||
<link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />
|
||||
<link rel="bookmark" href="/assets/favicon.ico" type="image/x-icon" />
|
||||
<link href="/assets/vuetify-v2.6.9/vuetify-v2.6.9.min.css" rel="stylesheet" />
|
||||
<link href="/assets/vuetify-v2.6.9/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/input.css" rel="stylesheet">
|
||||
|
||||
|
@ -15,8 +16,9 @@
|
|||
<script src="/assets/axios/axios.min.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script type="text/x-template" id="app-template">
|
||||
<v-app id="inspire">
|
||||
|
@ -49,6 +51,7 @@
|
|||
<v-col cols="12" sm="10">
|
||||
<v-sheet min-height="100%">
|
||||
<textarea id="tinyMceEditor"></textarea>
|
||||
<input id="i-files" name="file" type="file" style="display:none"/>
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
@ -65,8 +68,8 @@
|
|||
new Vue({
|
||||
el: '#app',
|
||||
template: '#app-template',
|
||||
computed:{
|
||||
tags:{
|
||||
computed: {
|
||||
tags: {
|
||||
get() {
|
||||
let result = []
|
||||
if (this.article.tags.length == 0) {
|
||||
|
@ -144,16 +147,36 @@
|
|||
],*/
|
||||
fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
|
||||
font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;知乎配置=BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif;小米配置=Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif',
|
||||
link_list: [
|
||||
// { title: '预置链接1', value: 'http://www.tinymce.com' },
|
||||
// { title: '预置链接2', value: 'http://tinymce.ax-z.cn' }
|
||||
],
|
||||
// link_list: [
|
||||
// // { title: '预置链接1', value: 'http://www.tinymce.com' },
|
||||
// // { title: '预置链接2', value: 'http://tinymce.ax-z.cn' }
|
||||
// ],
|
||||
|
||||
//importcss_append: true,
|
||||
//自定义文件选择器的回调内容
|
||||
file_picker_callback: function (callback, value, meta) {
|
||||
let files = document.getElementById('i-files')
|
||||
files.click()
|
||||
files.onchange = () => {
|
||||
let formData = new FormData();
|
||||
console.log(files.files);
|
||||
for (let index = 0; index < files.files.length; index++) {
|
||||
const element = files.files[index];
|
||||
formData.append("file", element);
|
||||
}
|
||||
axios.post('/admin/file/upload', formData, { headers: { "Content-Type": "multipart/form-data" } }).then(res => {
|
||||
let data = res.data
|
||||
console.log(data)
|
||||
// location.href = '/diary'
|
||||
callback(`${data.url}`, { text: '附件下载' });
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// if (meta.filetype === 'file') {
|
||||
// callback('https://www.baidu.com/img/bd_logo1.png', { text: 'My text' });
|
||||
// callback('https://www.baidu.com/img/bd_logo1.png', {val:"value", text: 'My text',alt: 'My alt text' });
|
||||
// }
|
||||
// if (meta.filetype === 'image') {
|
||||
// callback('https://www.baidu.com/img/bd_logo1.png', { alt: 'My alt text' });
|
||||
|
@ -177,8 +200,8 @@
|
|||
// { title: '预置图片2', value: 'https://www.baidu.com/img/bd_logo1.png' }
|
||||
],
|
||||
image_class_list: [
|
||||
{title: 'None', value: ''},
|
||||
{title: 'Some class', value: 'class-name'}
|
||||
{ title: 'None', value: '' },
|
||||
{ title: 'Some class', value: 'class-name' }
|
||||
],
|
||||
convert_urls: false,
|
||||
images_upload_credentials: true,
|
||||
|
@ -207,4 +230,5 @@
|
|||
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,201 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Admin Console</title>
|
||||
<link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />
|
||||
<link rel="bookmark" href="/assets/favicon.ico" type="image/x-icon" />
|
||||
<link href="/assets/vuetify-v2.6.9/vuetify-v2.6.9.min.css" rel="stylesheet" />
|
||||
<link href="/assets/vuetify-v2.6.9/materialdesignicons.min.css" rel="stylesheet">
|
||||
|
||||
<script src="/assets/vue/vue.min.js"></script>
|
||||
<script src="/assets/vuetify-v2.6.9/vuetify-v2.6.9.min.js"></script>
|
||||
<script src="/assets/axios/axios.min.js"></script>
|
||||
<script src="/assets/moment/moment.js"></script>
|
||||
<script src="/assets/qs/qs.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
|
||||
<style>
|
||||
.over-display {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script type="text/x-template" id="app-template">
|
||||
<v-app id="inspire">
|
||||
#{ render "common/bar-admin.html" . }
|
||||
<!-- <#include "../../common/drawer-admin.ftl"> -->
|
||||
|
||||
<v-dialog v-model="dialog.show" width="500" v-if="dialog.obj">
|
||||
<v-card>
|
||||
<v-card-title class="text-h5 grey lighten-2">{{dialog.title}}</v-card-title>
|
||||
<v-card-text>{{dialog.context}}</v-card-text>
|
||||
<v-divider></v-divider>
|
||||
<v-card-actions>
|
||||
<v-btn text @click="dialog.show = false">取消</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" text @click="confirm">确认</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
|
||||
<v-main class="grey lighten-3">
|
||||
<v-container style="height: 100%">
|
||||
<v-row style="height: 100%">
|
||||
<!-- <v-col cols="12" sm="2" class="">
|
||||
<v-sheet min-height="100%">
|
||||
</v-sheet>
|
||||
</v-col> -->
|
||||
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-sheet min-height="100%">
|
||||
|
||||
<v-data-table class="elevation-1"
|
||||
:headers="headers"
|
||||
:items="itemList"
|
||||
height="700px"
|
||||
:page.sync="pageable.page"
|
||||
:items-per-page="pageable.itemsPerPage"
|
||||
:loading="loading"
|
||||
loading-text="数据加载中"
|
||||
hide-default-footer>
|
||||
<template #item.createTime="{ item }">
|
||||
{{item.createTime?moment(item.createTime).format('YYYY/MM/DD HH:mm:ss'):''}}
|
||||
</template>
|
||||
<template #item.fileName="{ item }">
|
||||
<span class="over-display">{{item.fileName}}</span>
|
||||
</template>
|
||||
<template #item.fileSize="{ item }">
|
||||
{{Math.round(item.fileSize/1024)}}KB
|
||||
</template>
|
||||
|
||||
<template #item.actions="{ item }">
|
||||
<v-btn text color="primary" :href="`/file/${item.id}`" target="_blank">下载</v-btn>
|
||||
</template>
|
||||
</v-data-table>
|
||||
<div class="pt-2 float-right" style="display: flex">
|
||||
<v-pagination v-model="pageable.page" :length="pageable.totalPages" :total-visible="7"
|
||||
style="min-width: 200px;" @previous="previousPage" @next="nextPage"
|
||||
@input="goPage"></v-pagination>
|
||||
<v-select :items="[5,10,20,50,100]" label="分页大小" style="width: 100px"
|
||||
v-model="pageable.itemsPerPage" outlined dense
|
||||
@input="pageSizeChange"></v-select>
|
||||
</div>
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
|
||||
<!-- <v-col cols="12" sm="2">
|
||||
<v-sheet min-height="100%">
|
||||
</v-sheet>
|
||||
</v-col> -->
|
||||
|
||||
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
var qs = Qs
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: '#app-template',
|
||||
data: {
|
||||
group: null,
|
||||
drawer: false,
|
||||
loading: false,
|
||||
dialog: {
|
||||
show: false,
|
||||
title: '',
|
||||
context: '',
|
||||
obj: null
|
||||
},
|
||||
pageable: {
|
||||
page: 1,
|
||||
itemsPerPage: 20,
|
||||
totalElements: 0,
|
||||
totalPages: 1
|
||||
},
|
||||
param: {
|
||||
id: null,
|
||||
title: null,
|
||||
subTitle: null,
|
||||
},
|
||||
|
||||
headers: [
|
||||
{ text: 'ID', value: 'id', align: 'start', sortable: false },
|
||||
{ text: '文件名', value: 'fileName', align: 'start', sortable: false },
|
||||
{ text: '文件大小', value: 'fileSize', align: 'start', sortable: false },
|
||||
{ text: '上传人', value: 'createBy', align: 'start', sortable: false },
|
||||
{ text: '上传时间', value: 'createTime', align: 'start', sortable: false },
|
||||
{ text: '操作', value: 'actions', align: 'center', sortable: false },
|
||||
],
|
||||
itemList: [],
|
||||
},
|
||||
methods: {
|
||||
pageSizeChange(size) {
|
||||
this.pageable.page = 1
|
||||
this.list()
|
||||
},
|
||||
nextPage() {
|
||||
this.pageable.page = this.pageable.page + 1
|
||||
// this.list()
|
||||
},
|
||||
previousPage() {
|
||||
this.pageable.page = this.pageable.page - 1
|
||||
// this.list()
|
||||
},
|
||||
goPage(num) {
|
||||
this.pageable.page = num
|
||||
this.list()
|
||||
},
|
||||
list() {
|
||||
let ths = this;
|
||||
this.loading = true;
|
||||
let { page, itemsPerPage } = this.pageable;
|
||||
let pageQuery = qs.stringify({ page, itemsPerPage, ...this.param }, { skipNulls: true });
|
||||
// let paramQuery = qs.stringify(this.param, {skipNulls: true});
|
||||
axios.get('/admin/file/list?' + pageQuery).then(function (response) {
|
||||
// console.log(response);
|
||||
let data = response.data;
|
||||
ths.itemList = data.content;
|
||||
ths.pageable.totalElements = data.totalElements
|
||||
ths.pageable.totalPages = data.totalPages
|
||||
ths.pageable.page = data.number + 1
|
||||
|
||||
ths.loading = false;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
ths.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
download(id) {
|
||||
console.log(id);
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.list();
|
||||
|
||||
},
|
||||
|
||||
vuetify: new Vuetify(),
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue