diff --git a/vblog/apps/blog/impl/impl.go b/vblog/apps/blog/impl/impl.go index 435205f..4f26e62 100644 --- a/vblog/apps/blog/impl/impl.go +++ b/vblog/apps/blog/impl/impl.go @@ -3,6 +3,7 @@ package impl import ( "context" "fmt" + "time" "github.com/infraboard/mcube/v2/ioc" "github.com/infraboard/mcube/v2/ioc/config/datasource" @@ -26,7 +27,7 @@ func (i *BlogServiceImpl) Name() string { // CreateBlog implements blog.Service. func (b *BlogServiceImpl) CreateBlog(ctx context.Context, in *blog.CreateBlogRequest) (*blog.Blog, error) { - ins, err := blog.NewBook(in) + ins, err := blog.NewBlog(in) if err != nil { return nil, err } @@ -77,13 +78,23 @@ func (b *BlogServiceImpl) QueryBlog(ctx context.Context, in *blog.QueryBlogReque } // DeleteBlog implements blog.Service. -func (b *BlogServiceImpl) DeleteBlog(context.Context, *blog.DeleteBlogRequest) error { - panic("unimplemented") +func (b *BlogServiceImpl) DeleteBlog(ctx context.Context, in *blog.DeleteBlogRequest) error { + time.Sleep(3 * time.Second) + ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id)) + if err != nil { + return err + } + return datasource.DBFromCtx(ctx).Where("id = ?", ins.Id).Delete(ins).Error } // DescribeBlog implements blog.Service. -func (b *BlogServiceImpl) DescribeBlog(context.Context, *blog.DescribeBlogRequest) (*blog.Blog, error) { - panic("unimplemented") +func (b *BlogServiceImpl) DescribeBlog(ctx context.Context, in *blog.DescribeBlogRequest) (*blog.Blog, error) { + ins := &blog.Blog{} + err := datasource.DBFromCtx(ctx).Where("id = ?", in.Id).First(ins).Error + if err != nil { + return nil, err + } + return ins, nil } // PublishBlog implements blog.Service. diff --git a/vblog/apps/blog/interface.go b/vblog/apps/blog/interface.go index 8f427d0..1daaa63 100644 --- a/vblog/apps/blog/interface.go +++ b/vblog/apps/blog/interface.go @@ -63,6 +63,12 @@ type UpdateBlogRequest struct { CreateBlogRequest } +func NewDescribeBlogRequest(id uint) *DescribeBlogRequest { + return &DescribeBlogRequest{ + GetRequest: *utils.NewGetRequest(id), + } +} + type DescribeBlogRequest struct { utils.GetRequest } diff --git a/vblog/apps/blog/model.go b/vblog/apps/blog/model.go index 3362341..e240981 100644 --- a/vblog/apps/blog/model.go +++ b/vblog/apps/blog/model.go @@ -20,7 +20,7 @@ type BlogSet struct { Items []*Blog `json:"items"` } -func NewBook(in *CreateBlogRequest) (*Blog, error) { +func NewBlog(in *CreateBlogRequest) (*Blog, error) { if err := in.Validate(); err != nil { return nil, exception.NewBadRequest("参数异常: %s", err) } diff --git a/vblog/etc/application.toml b/vblog/etc/application.toml index 6e52559..42f84b1 100644 --- a/vblog/etc/application.toml +++ b/vblog/etc/application.toml @@ -1,7 +1,7 @@ [app] name = "vblog" description = "app desc" - address = "http://127.0.0.1" + address = "http://localhost/" [http] # HTTP服务Host diff --git a/vblog/logs/vblog.log b/vblog/logs/vblog.log index a32b2d9..efe3d9c 100644 --- a/vblog/logs/vblog.log +++ b/vblog/logs/vblog.log @@ -246,3 +246,80 @@ {"level":"info","component":"server","time":"2025-01-12T14:57:03+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} {"level":"info","component":"server","time":"2025-01-12T14:57:03+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} {"level":"info","component":"http","time":"2025-01-12T14:57:03+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"info","component":"server","time":"2025-01-12T17:22:29+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T17:22:29+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T17:22:29+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T17:22:29+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T17:22:32+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T17:22:32+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T17:22:32+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-12T17:22:32+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T17:22:32+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T17:22:32+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T17:22:32+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"debug","time":"2025-01-12T17:32:36+08:00","caller":"token/api/api.go:57","message":"cookie domain: 127.0.0.1"} +{"level":"error","time":"2025-01-12T18:05:41+08:00","caller":"vblog/middleware/auth.go:36","message":"get cookie error, http: named cookie not present"} +{"level":"error","time":"2025-01-12T18:05:49+08:00","caller":"vblog/middleware/auth.go:36","message":"get cookie error, http: named cookie not present"} +{"level":"info","component":"server","time":"2025-01-12T18:06:23+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:06:23+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:06:23+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:06:23+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T18:06:26+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T18:06:26+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T18:06:26+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-12T18:06:26+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:06:26+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:06:26+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T18:06:26+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"error","time":"2025-01-12T18:06:48+08:00","caller":"vblog/middleware/auth.go:36","message":"get cookie error, http: named cookie not present"} +{"level":"debug","time":"2025-01-12T18:07:57+08:00","caller":"token/api/api.go:57","message":"cookie domain: 127.0.0.1"} +{"level":"error","time":"2025-01-12T18:08:03+08:00","caller":"vblog/middleware/auth.go:36","message":"get cookie error, http: named cookie not present"} +{"level":"info","component":"server","time":"2025-01-12T18:11:49+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:11:49+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:11:49+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:11:49+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T18:11:51+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T18:11:51+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T18:11:51+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-12T18:11:51+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:11:51+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:11:51+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T18:11:51+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"debug","time":"2025-01-12T18:12:03+08:00","caller":"token/api/api.go:57","message":"cookie domain: localhost"} +{"level":"info","component":"server","time":"2025-01-12T18:17:07+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:17:07+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:17:07+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:17:07+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T18:17:10+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T18:17:10+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T18:17:10+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-12T18:17:10+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:17:10+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:17:10+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T18:17:10+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"info","component":"server","time":"2025-01-12T18:19:23+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:19:23+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:19:23+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:19:23+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T18:19:25+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T18:19:25+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T18:19:25+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-12T18:19:25+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:19:25+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:19:25+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T18:19:25+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"info","component":"server","time":"2025-01-12T18:27:47+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:27:47+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:27:47+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:27:47+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} +{"level":"info","component":"gin_webframework","time":"2025-01-12T18:27:51+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"} +{"level":"debug","time":"2025-01-12T18:27:51+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"} +{"level":"info","component":"server","time":"2025-01-12T18:27:51+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-12T18:27:51+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:27:51+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"} +{"level":"info","component":"server","time":"2025-01-12T18:27:51+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"} +{"level":"info","component":"http","time":"2025-01-12T18:27:51+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"} +{"level":"info","component":"server","time":"2025-01-12T18:30:18+08:00","caller":"ioc/server/server.go:101","message":"receive signal 'interrupt', start graceful shutdown"} +{"level":"info","component":"http","time":"2025-01-12T18:30:18+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"} +{"level":"error","component":"http","time":"2025-01-12T18:30:18+08:00","caller":"config/http/http.go:146","message":"http: Server closed"} +{"level":"info","component":"server","time":"2025-01-12T18:30:18+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"} diff --git a/vblog/utils/request.go b/vblog/utils/request.go index 1dbaa17..9eebead 100644 --- a/vblog/utils/request.go +++ b/vblog/utils/request.go @@ -1,5 +1,11 @@ package utils +func NewGetRequest(id uint) *GetRequest { + return &GetRequest{ + Id: id, + } +} + type GetRequest struct { Id uint `json:"id"` } diff --git a/vblog/web/README.md b/vblog/web/README.md index b8e7994..b44e9ee 100644 --- a/vblog/web/README.md +++ b/vblog/web/README.md @@ -444,3 +444,127 @@ const pageSizeChanged = (pageSize) => { queryData() } ``` + +## Menu状态保存 + +```js +import { useStorage } from '@vueuse/core' + +export const systemConfig = useStorage( + 'system_config', + { + selected_current_menu_item_key: '', + }, + localStorage, + { + mergeDefaults: true, + }, +) +``` + +点击时,保存这个状态 + +```js +const handleMenuItemClick = (key) => { + // https://router.vuejs.org/zh/guide/essentials/navigation.html + router.push({ name: key }) + systemConfig.value.selected_current_menu_item_key = key +} +``` + +```html + + +``` + +## 文章删除 + +1. 准备好你的后端接口: + +```go +// DeleteBlog implements blog.Service. +func (b *BlogServiceImpl) DeleteBlog(ctx context.Context, in *blog.DeleteBlogRequest) error { + ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id)) + if err != nil { + return err + } + return datasource.DBFromCtx(ctx).Where("id = ?", ins.Id).Delete(ins).Error +} + +// DescribeBlog implements blog.Service. +func (b *BlogServiceImpl) DescribeBlog(ctx context.Context, in *blog.DescribeBlogRequest) (*blog.Blog, error) { + ins := &blog.Blog{} + err := datasource.DBFromCtx(ctx).Where("id = ?", in.Id).First(ins).Error + if err != nil { + return nil, err + } + return ins, nil +} +``` + +```go +r.DELETE(":id", h.DeleteBlog) + +func (h *BlogApiHandler) DeleteBlog(ctx *gin.Context) { + in := blog.NewDeleteBlogRequest(ctx.Param("id")) + + err := h.blog.DeleteBlog(ctx.Request.Context(), in) + if err != nil { + response.Failed(ctx, err) + return + } + response.Success(ctx, "ok") +} +``` + +2. SetCookie的问题: localhost + +```go + // 打印下日志, ioc + domain := application.Get().Domain() + log.L().Debug().Msgf("cookie domain: %s", domain) + + // 设置Cookie + ctx.SetCookie(token.COOKIE_NAME, ins.AccessToken, ins.AccessTokenExpireTTL(), "/", domain, false, true) +``` + +```toml +[app] + name = "vblog" + description = "app desc" + address = "http://localhost/" +``` + +3. 调用API, 实现删除, 刷新页面(2个操作的先后关系) + +```js +// 删除函数 +const delteLoadding = ref(0) +const deleteBlog = async (id) => { + try { + delteLoadding.value = id + // 等待这个操作执行完成 + await DELTE_BLOG(id) + // 刷新数据 + queryData() + } finally { + delteLoadding.value = 0 + } +} +``` + +4. 删除按钮Loadding控制: + +```html + + + 删除 + +``` diff --git a/vblog/web/src/api/blog.js b/vblog/web/src/api/blog.js index cb487e7..d380c92 100644 --- a/vblog/web/src/api/blog.js +++ b/vblog/web/src/api/blog.js @@ -10,3 +10,9 @@ export const QUERY_BLOG = (params) => // params: params params, }) + +export const DELTE_BLOG = (blog_id) => + client({ + url: `/api/vblog/v1/blogs/${blog_id}`, + method: 'DELETE', + }) diff --git a/vblog/web/src/stores/system.js b/vblog/web/src/stores/system.js new file mode 100644 index 0000000..f81bd03 --- /dev/null +++ b/vblog/web/src/stores/system.js @@ -0,0 +1,12 @@ +import { useStorage } from '@vueuse/core' + +export const systemConfig = useStorage( + 'system_config', + { + selected_current_menu_item_key: '', + }, + localStorage, + { + mergeDefaults: true, + }, +) diff --git a/vblog/web/src/views/backend/BackendLayout.vue b/vblog/web/src/views/backend/BackendLayout.vue index bfe0d2e..8726a59 100644 --- a/vblog/web/src/views/backend/BackendLayout.vue +++ b/vblog/web/src/views/backend/BackendLayout.vue @@ -17,7 +17,8 @@ - + 发布 - + @@ -78,7 +78,7 @@