diff --git a/api/core/app_server.go b/api/core/app_server.go index 3dd27bfb..a29c32d9 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -336,9 +336,11 @@ func staticResourceMiddleware() gin.HandlerFunc { log.Fatal(err) } + // 设置图片缓存有效期为一年 (365天) + c.Header("Cache-Control", "max-age=31536000, public") // 直接输出图像数据流 c.Data(http.StatusOK, "image/jpeg", buffer.Bytes()) - return + c.Abort() // 中断请求 } c.Next() } diff --git a/api/main.go b/api/main.go index c6e5b6bf..9d76db9c 100644 --- a/api/main.go +++ b/api/main.go @@ -165,6 +165,11 @@ func main() { // MidJourney service pool fx.Provide(mj.NewServicePool), + fx.Invoke(func(pool *mj.ServicePool) { + if pool.HasAvailableService() { + pool.DownloadImages() + } + }), // Stable Diffusion 机器人 fx.Provide(sd.NewServicePool), diff --git a/api/service/mj/pool.go b/api/service/mj/pool.go index 38289760..6fd5fd48 100644 --- a/api/service/mj/pool.go +++ b/api/service/mj/pool.go @@ -4,7 +4,9 @@ import ( "chatplus/core/types" "chatplus/service/oss" "chatplus/store" + "chatplus/store/model" "fmt" + "time" "github.com/go-redis/redis/v8" "gorm.io/gorm" @@ -12,8 +14,10 @@ import ( // ServicePool Mj service pool type ServicePool struct { - services []*Service - taskQueue *store.RedisQueue + services []*Service + taskQueue *store.RedisQueue + db *gorm.DB + uploaderManager *oss.UploaderManager } func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderManager, appConfig *types.AppConfig) *ServicePool { @@ -29,7 +33,7 @@ func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderMa name := fmt.Sprintf("MjService-%d", k) // create mj service - service := NewService(name, queue, 4, 600, db, client, manager, appConfig.ProxyURL) + service := NewService(name, queue, 4, 600, db, client) botName := fmt.Sprintf("MjBot-%d", k) bot, err := NewBot(botName, appConfig.ProxyURL, &config, service) if err != nil { @@ -50,11 +54,39 @@ func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderMa } return &ServicePool{ - taskQueue: queue, - services: services, + taskQueue: queue, + services: services, + uploaderManager: manager, + db: db, } } +func (p *ServicePool) DownloadImages() { + go func() { + var items []model.MidJourneyJob + for { + res := p.db.Where("img_url = ? AND progress = ?", "", 100).Find(&items) + if res.Error != nil { + continue + } + + // download images + for _, item := range items { + imgURL, err := p.uploaderManager.GetUploadHandler().PutImg(item.OrgURL, true) + if err != nil { + logger.Error("error with download image: ", err) + continue + } + + item.ImgURL = imgURL + p.db.Updates(&item) + } + + time.Sleep(time.Second * 5) + } + }() +} + // PushTask push a new mj task in to task queue func (p *ServicePool) PushTask(task types.MjTask) { logger.Debugf("add a new MidJourney task to the task list: %+v", task) diff --git a/api/service/mj/service.go b/api/service/mj/service.go index 49d94edc..3b3d6e7c 100644 --- a/api/service/mj/service.go +++ b/api/service/mj/service.go @@ -2,7 +2,6 @@ package mj import ( "chatplus/core/types" - "chatplus/service/oss" "chatplus/store" "chatplus/store/model" "gorm.io/gorm" @@ -17,24 +16,20 @@ type Service struct { client *Client // MJ client taskQueue *store.RedisQueue db *gorm.DB - uploadManager *oss.UploaderManager - proxyURL string maxHandleTaskNum int32 // max task number current service can handle handledTaskNum int32 // already handled task number taskStartTimes map[int]time.Time // task start time, to check if the task is timeout taskTimeout int64 } -func NewService(name string, queue *store.RedisQueue, maxTaskNum int32, timeout int64, db *gorm.DB, client *Client, manager *oss.UploaderManager, proxy string) *Service { +func NewService(name string, queue *store.RedisQueue, maxTaskNum int32, timeout int64, db *gorm.DB, client *Client) *Service { return &Service{ name: name, db: db, taskQueue: queue, client: client, - uploadManager: manager, taskTimeout: timeout, maxHandleTaskNum: maxTaskNum, - proxyURL: proxy, taskStartTimes: make(map[int]time.Time, 0), } } @@ -146,17 +141,6 @@ func (s *Service) Notify(data CBReq) { return } - // upload image - if data.Status == Finished { - imgURL, err := s.uploadManager.GetUploadHandler().PutImg(data.Image.URL, true) - if err != nil { - logger.Error("error with download img: ", err.Error()) - return - } - job.ImgURL = imgURL - s.db.Updates(&job) - } - if data.Status == Finished { // release lock task atomic.AddInt32(&s.handledTaskNum, -1) diff --git a/web/src/assets/iconfont/iconfont.css b/web/src/assets/iconfont/iconfont.css index f9fb659a..a16a9c4e 100644 --- a/web/src/assets/iconfont/iconfont.css +++ b/web/src/assets/iconfont/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 4125778 */ - src: url('iconfont.woff2?t=1702024026523') format('woff2'), - url('iconfont.woff?t=1702024026523') format('woff'), - url('iconfont.ttf?t=1702024026523') format('truetype'); + src: url('iconfont.woff2?t=1703124384910') format('woff2'), + url('iconfont.woff?t=1703124384910') format('woff'), + url('iconfont.ttf?t=1703124384910') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-loading:before { + content: "\e627"; +} + .icon-alipay:before { content: "\e634"; } diff --git a/web/src/assets/iconfont/iconfont.js b/web/src/assets/iconfont/iconfont.js index ab90b064..6521c8f0 100644 --- a/web/src/assets/iconfont/iconfont.js +++ b/web/src/assets/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_4125778='',function(a){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var t,o,i,h,e,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}t=function(){var l,c=document.createElement("div");c.innerHTML=a._iconfont_svg_string_4125778,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),t()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(i=t,h=a.document,e=!1,z(),h.onreadystatechange=function(){"complete"==h.readyState&&(h.onreadystatechange=null,m())})}function m(){e||(e=!0,i())}function z(){try{h.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}m()}}(window); \ No newline at end of file +window._iconfont_svg_string_4125778='',function(a){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var t,o,i,h,e,s=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}t=function(){var l,c=document.createElement("div");c.innerHTML=a._iconfont_svg_string_4125778,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?s(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),t()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(i=t,h=a.document,e=!1,z(),h.onreadystatechange=function(){"complete"==h.readyState&&(h.onreadystatechange=null,m())})}function m(){e||(e=!0,i())}function z(){try{h.documentElement.doScroll("left")}catch(l){return void setTimeout(z,50)}m()}}(window); \ No newline at end of file diff --git a/web/src/assets/iconfont/iconfont.json b/web/src/assets/iconfont/iconfont.json index 6e99ab74..ea413f94 100644 --- a/web/src/assets/iconfont/iconfont.json +++ b/web/src/assets/iconfont/iconfont.json @@ -5,6 +5,13 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "1278349", + "name": "loading", + "font_class": "loading", + "unicode": "e627", + "unicode_decimal": 58919 + }, { "icon_id": "1486848", "name": "支付宝支付", diff --git a/web/src/assets/iconfont/iconfont.ttf b/web/src/assets/iconfont/iconfont.ttf index df9a3753..70c1c350 100644 Binary files a/web/src/assets/iconfont/iconfont.ttf and b/web/src/assets/iconfont/iconfont.ttf differ diff --git a/web/src/assets/iconfont/iconfont.woff b/web/src/assets/iconfont/iconfont.woff index abfc99eb..bba70a0d 100644 Binary files a/web/src/assets/iconfont/iconfont.woff and b/web/src/assets/iconfont/iconfont.woff differ diff --git a/web/src/assets/iconfont/iconfont.woff2 b/web/src/assets/iconfont/iconfont.woff2 index 3f951f4d..5264eadc 100644 Binary files a/web/src/assets/iconfont/iconfont.woff2 and b/web/src/assets/iconfont/iconfont.woff2 differ diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index c6fa70df..c5d0e960 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -359,7 +359,7 @@