diff --git a/vblog/apps/blog/api/api.go b/vblog/apps/blog/api/api.go
index 30b1011..1637902 100644
--- a/vblog/apps/blog/api/api.go
+++ b/vblog/apps/blog/api/api.go
@@ -55,6 +55,7 @@ func (h *BlogApiHandler) Init() error {
r.POST("", h.CreateBlog)
r.PUT(":id", h.UpdateBlog)
r.DELETE(":id", h.DeleteBlog)
+ r.POST(":id/publish", h.PublishBlog)
return nil
}
@@ -96,6 +97,27 @@ func (h *BlogApiHandler) QueryBlog(ctx *gin.Context) {
response.Success(ctx, ins)
}
+func (h *BlogApiHandler) PublishBlog(ctx *gin.Context) {
+ idInt, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
+ if err != nil {
+ response.Failed(ctx, err)
+ return
+ }
+
+ req := blog.NewPublishBlogRequest(uint(idInt))
+ if err := ctx.BindJSON(req); err != nil {
+ response.Failed(ctx, err)
+ return
+ }
+
+ ins, err := h.blog.PublishBlog(ctx.Request.Context(), req)
+ if err != nil {
+ response.Failed(ctx, err)
+ return
+ }
+ response.Success(ctx, ins)
+}
+
func (h *BlogApiHandler) DescribeBlog(ctx *gin.Context) {
idInt, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
if err != nil {
@@ -131,6 +153,11 @@ func (h *BlogApiHandler) UpdateBlog(ctx *gin.Context) {
}
in := blog.NewUpdateBlogRequest(uint(idInt))
+ if err := ctx.BindJSON(in); err != nil {
+ response.Failed(ctx, err)
+ return
+ }
+
ins, err := h.blog.UpdateBlog(ctx.Request.Context(), in)
if err != nil {
response.Failed(ctx, err)
diff --git a/vblog/apps/blog/enum.go b/vblog/apps/blog/enum.go
index b8ee1ab..6b067f4 100644
--- a/vblog/apps/blog/enum.go
+++ b/vblog/apps/blog/enum.go
@@ -1,7 +1,43 @@
package blog
+import (
+ "fmt"
+ "strings"
+)
+
type STAGE int
+func (s STAGE) String() string {
+ return STAGE_MAPPING[s]
+}
+
+// 自定义 类型的序列化方式
+// "草稿"
+func (s STAGE) MarshalJSON() ([]byte, error) {
+ return []byte(`"` + s.String() + `"`), nil
+}
+
+// UnmarshalJSON([]byte) error
+func (s *STAGE) UnmarshalJSON(data []byte) error {
+ str := strings.Trim(string(data), `"`)
+ switch str {
+ case "草稿":
+ *s = STAGE_DRAFT
+ // v := STAGE_DRAFT
+ // s = &v
+ case "已发布":
+ *s = STAGE_PUBLISHED
+ default:
+ return fmt.Errorf("不支持的发布类型")
+ }
+ return nil
+}
+
+var STAGE_MAPPING = map[STAGE]string{
+ STAGE_DRAFT: "草稿",
+ STAGE_PUBLISHED: "已发布",
+}
+
const (
STAGE_DRAFT STAGE = iota
STAGE_PUBLISHED
diff --git a/vblog/apps/blog/impl/dao.go b/vblog/apps/blog/impl/dao.go
new file mode 100644
index 0000000..cbc9939
--- /dev/null
+++ b/vblog/apps/blog/impl/dao.go
@@ -0,0 +1,17 @@
+package impl
+
+import (
+ "context"
+
+ "github.com/infraboard/mcube/v2/ioc/config/datasource"
+ "gitlab.com/go-course-project/go17/vblog/apps/blog"
+)
+
+func (b *BlogServiceImpl) update(ctx context.Context, ins *blog.Blog) error {
+ err := datasource.DBFromCtx(ctx).Where("id = ?", ins.Id).Updates(ins).Error
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vblog/apps/blog/impl/impl.go b/vblog/apps/blog/impl/impl.go
index aa3c634..24e8c3b 100644
--- a/vblog/apps/blog/impl/impl.go
+++ b/vblog/apps/blog/impl/impl.go
@@ -100,11 +100,38 @@ func (b *BlogServiceImpl) DescribeBlog(ctx context.Context, in *blog.DescribeBlo
}
// PublishBlog implements blog.Service.
-func (b *BlogServiceImpl) PublishBlog(context.Context, *blog.PublishBlogRequest) (*blog.Blog, error) {
- panic("unimplemented")
+func (b *BlogServiceImpl) PublishBlog(ctx context.Context, in *blog.PublishBlogRequest) (*blog.Blog, error) {
+ ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
+ if err != nil {
+ return nil, err
+ }
+
+ ins.Stage = in.Stage
+
+ err = b.update(ctx, ins)
+ if err != nil {
+ return nil, err
+ }
+ return ins, nil
}
// UpdateBlog implements blog.Service.
-func (b *BlogServiceImpl) UpdateBlog(context.Context, *blog.UpdateBlogRequest) (*blog.Blog, error) {
- panic("unimplemented")
+func (b *BlogServiceImpl) UpdateBlog(ctx context.Context, in *blog.UpdateBlogRequest) (*blog.Blog, error) {
+ ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
+ if err != nil {
+ return nil, err
+ }
+
+ // 全量更新
+ ins.CreateBlogRequest = in.CreateBlogRequest
+ if err := ins.Validate(); err != nil {
+ return nil, err
+ }
+
+ err = b.update(ctx, ins)
+ if err != nil {
+ return nil, err
+ }
+
+ return ins, nil
}
diff --git a/vblog/apps/blog/impl_test.go b/vblog/apps/blog/impl_test.go
index 9c03795..b2de1fc 100644
--- a/vblog/apps/blog/impl_test.go
+++ b/vblog/apps/blog/impl_test.go
@@ -29,6 +29,23 @@ func TestCreateBlog(t *testing.T) {
t.Log(ins)
}
+func TestUpdateBlog(t *testing.T) {
+ ins, err := blog.GetService().DescribeBlog(ctx, blog.NewDescribeBlogRequest(31))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req := blog.NewUpdateBlogRequest(31)
+ req.CreateBlogRequest = ins.CreateBlogRequest
+ req.Summary = "for update"
+
+ ins, err = blog.GetService().UpdateBlog(ctx, req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(ins)
+}
+
// SELECT * FROM `blogs` ORDER BY created_at DESC LIMIT 20
func TestQueryBlog(t *testing.T) {
req := blog.NewQueryBlogRequest()
@@ -42,6 +59,25 @@ func TestQueryBlog(t *testing.T) {
t.Log(ins)
}
+func TestDescribeBlog(t *testing.T) {
+ req := blog.NewDescribeBlogRequest(31)
+ ins, err := blog.GetService().DescribeBlog(ctx, req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(ins)
+}
+
+func TestPublishBlog(t *testing.T) {
+ req := blog.NewPublishBlogRequest(31)
+ req.Stage = blog.STAGE_PUBLISHED
+ ins, err := blog.GetService().PublishBlog(ctx, req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(ins)
+}
+
func TestNewQueryBlogRequest(t *testing.T) {
req := blog.NewQueryBlogRequest()
req.SetTag("key1=value1,key2=value2")
diff --git a/vblog/apps/blog/interface.go b/vblog/apps/blog/interface.go
index a381c47..ec2c5b9 100644
--- a/vblog/apps/blog/interface.go
+++ b/vblog/apps/blog/interface.go
@@ -53,6 +53,12 @@ type DeleteBlogRequest struct {
utils.GetRequest
}
+func NewPublishBlogRequest(id uint) *PublishBlogRequest {
+ return &PublishBlogRequest{
+ GetRequest: *utils.NewGetRequest(id),
+ }
+}
+
type PublishBlogRequest struct {
utils.GetRequest
StatusSpec
diff --git a/vblog/logs/vblog.log b/vblog/logs/vblog.log
index 8e26778..ece4c5a 100644
--- a/vblog/logs/vblog.log
+++ b/vblog/logs/vblog.log
@@ -386,3 +386,106 @@
{"level":"info","component":"server","time":"2025-01-19T11:59:44+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
{"level":"info","component":"server","time":"2025-01-19T11:59:44+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
{"level":"info","component":"http","time":"2025-01-19T11:59:44+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:40+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:14:40+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:14:40+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:40+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:14:42+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:14:42+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:42+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:42+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:42+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:14:42+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:14:42+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:02+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:16:02+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:16:02+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:02+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:16:04+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:16:04+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:04+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:04+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:04+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:16:04+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:16:04+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:36+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:24:36+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:24:36+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:36+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:24:39+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:24:39+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:39+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:39+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:39+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:24:39+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:24:39+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:25+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:26:25+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:26:25+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:25+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:26:28+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:26:28+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:28+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:28+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:28+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:26:28+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:26:28+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:10+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:27:10+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:27:10+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:10+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:27:12+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:27:12+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:12+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:12+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:12+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:27:12+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:27:12+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:57+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:32:57+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:32:57+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:57+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:32:59+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:32:59+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:59+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:59+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:59+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:32:59+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:32:59+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:39:58+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:39:58+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:39:58+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:39:58+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:40:00+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:40:00+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:40:00+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:40:00+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:40:00+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:40:00+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:40:00+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:34+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:41:34+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:41:34+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:34+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:41:36+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:41:36+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:36+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:36+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:36+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:41:36+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:41:36+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:34+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:45:34+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:45:34+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:34+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
+{"level":"info","component":"gin_webframework","time":"2025-01-19T14:45:36+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
+{"level":"debug","time":"2025-01-19T14:45:36+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:36+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:36+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:36+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
+{"level":"info","component":"server","time":"2025-01-19T14:45:36+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
+{"level":"info","component":"http","time":"2025-01-19T14:45:36+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
+{"level":"info","component":"server","time":"2025-01-19T14:50:39+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"}
+{"level":"info","component":"http","time":"2025-01-19T14:50:39+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
+{"level":"error","component":"http","time":"2025-01-19T14:50:39+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
+{"level":"info","component":"server","time":"2025-01-19T14:50:39+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
diff --git a/vblog/web/README.md b/vblog/web/README.md
index dcbb774..3f0dffe 100644
--- a/vblog/web/README.md
+++ b/vblog/web/README.md
@@ -587,7 +587,7 @@ const deleteBlog = async (id) => {
```
-## 文章的创建
+## 文章的创建和更新
选择一个mardown的编辑器: https://www.npmjs.com/package/md-editor-v3
@@ -598,3 +598,168 @@ const deleteBlog = async (id) => {
```
创建成功后,进入到保存模式
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+ 软件开发
+ 系统运维
+ 软件测试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## 文章的发布
+
+后端如何自定义状态展示
+
+```go
+type STAGE int
+
+func (s STAGE) String() string {
+ return STAGE_MAPPING[s]
+}
+
+// 自定义 类型的序列化方式
+// "草稿"
+func (s STAGE) MarshalJSON() ([]byte, error) {
+ return []byte(`"` + s.String() + `"`), nil
+}
+
+// UnmarshalJSON([]byte) error
+func (s *STAGE) UnmarshalJSON(data []byte) error {
+ str := strings.Trim(string(data), `"`)
+ switch str {
+ case "草稿":
+ *s = STAGE_DRAFT
+ case "已发布":
+ *s = STAGE_PUBLISHED
+ default:
+ return fmt.Errorf("不支持的发布类型")
+ }
+ return nil
+}
+
+var STAGE_MAPPING = map[STAGE]string{
+ STAGE_DRAFT: "草稿",
+ STAGE_PUBLISHED: "已发布",
+}
+
+const (
+ STAGE_DRAFT STAGE = iota
+ STAGE_PUBLISHED
+)
+```
diff --git a/vblog/web/src/api/blog.js b/vblog/web/src/api/blog.js
index 05649d9..f51b53f 100644
--- a/vblog/web/src/api/blog.js
+++ b/vblog/web/src/api/blog.js
@@ -31,6 +31,13 @@ export const UPDATE_BLOG = (blog_id, data) =>
data,
})
+export const PUBLISH_BLOG = (blog_id, data) =>
+ client({
+ url: `/api/vblog/v1/blogs/${blog_id}/publish`,
+ method: 'POST',
+ data,
+ })
+
export const DELTE_BLOG = (blog_id) =>
client({
url: `/api/vblog/v1/blogs/${blog_id}`,
diff --git a/vblog/web/src/views/backend/blog/ListPage.vue b/vblog/web/src/views/backend/blog/ListPage.vue
index 5c9c58b..c5b62aa 100644
--- a/vblog/web/src/views/backend/blog/ListPage.vue
+++ b/vblog/web/src/views/backend/blog/ListPage.vue
@@ -35,6 +35,7 @@
+
{{ dayjs(record.updated_at).format('YYYY-MM-DD HH:mm:ss') }}
@@ -49,7 +50,7 @@
编辑
-
+
@@ -81,7 +82,7 @@