mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	feat: add remove action to remove task and images for MJ and SD task list page
This commit is contained in:
		@@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"chatplus/core/types"
 | 
			
		||||
	"chatplus/service"
 | 
			
		||||
	"chatplus/service/mj"
 | 
			
		||||
	"chatplus/service/oss"
 | 
			
		||||
	"chatplus/store/model"
 | 
			
		||||
	"chatplus/store/vo"
 | 
			
		||||
	"chatplus/utils"
 | 
			
		||||
@@ -22,13 +23,15 @@ type MidJourneyHandler struct {
 | 
			
		||||
	db        *gorm.DB
 | 
			
		||||
	pool      *mj.ServicePool
 | 
			
		||||
	snowflake *service.Snowflake
 | 
			
		||||
	uploader  *oss.UploaderManager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMidJourneyHandler(app *core.AppServer, db *gorm.DB, snowflake *service.Snowflake, pool *mj.ServicePool) *MidJourneyHandler {
 | 
			
		||||
func NewMidJourneyHandler(app *core.AppServer, db *gorm.DB, snowflake *service.Snowflake, pool *mj.ServicePool, manager *oss.UploaderManager) *MidJourneyHandler {
 | 
			
		||||
	h := MidJourneyHandler{
 | 
			
		||||
		db:        db,
 | 
			
		||||
		snowflake: snowflake,
 | 
			
		||||
		pool:      pool,
 | 
			
		||||
		uploader:  manager,
 | 
			
		||||
	}
 | 
			
		||||
	h.App = app
 | 
			
		||||
	return &h
 | 
			
		||||
@@ -306,3 +309,30 @@ func (h *MidJourneyHandler) JobList(c *gin.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c, jobs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove remove task image
 | 
			
		||||
func (h *MidJourneyHandler) Remove(c *gin.Context) {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		Id     uint   `json:"id"`
 | 
			
		||||
		ImgURL string `json:"img_url"`
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.ShouldBindJSON(&data); err != nil {
 | 
			
		||||
		resp.ERROR(c, types.InvalidArgs)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// remove job recode
 | 
			
		||||
	res := h.db.Delete(&model.MidJourneyJob{Id: data.Id})
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, res.Error.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// remove image
 | 
			
		||||
	err := h.uploader.GetUploadHandler().Delete(data.ImgURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("remove image failed: ", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package handler
 | 
			
		||||
import (
 | 
			
		||||
	"chatplus/core"
 | 
			
		||||
	"chatplus/core/types"
 | 
			
		||||
	"chatplus/service/oss"
 | 
			
		||||
	"chatplus/service/sd"
 | 
			
		||||
	"chatplus/store/model"
 | 
			
		||||
	"chatplus/store/vo"
 | 
			
		||||
@@ -19,15 +20,17 @@ import (
 | 
			
		||||
 | 
			
		||||
type SdJobHandler struct {
 | 
			
		||||
	BaseHandler
 | 
			
		||||
	redis *redis.Client
 | 
			
		||||
	db    *gorm.DB
 | 
			
		||||
	pool  *sd.ServicePool
 | 
			
		||||
	redis    *redis.Client
 | 
			
		||||
	db       *gorm.DB
 | 
			
		||||
	pool     *sd.ServicePool
 | 
			
		||||
	uploader *oss.UploaderManager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSdJobHandler(app *core.AppServer, db *gorm.DB, pool *sd.ServicePool) *SdJobHandler {
 | 
			
		||||
func NewSdJobHandler(app *core.AppServer, db *gorm.DB, pool *sd.ServicePool, manager *oss.UploaderManager) *SdJobHandler {
 | 
			
		||||
	h := SdJobHandler{
 | 
			
		||||
		db:   db,
 | 
			
		||||
		pool: pool,
 | 
			
		||||
		db:       db,
 | 
			
		||||
		pool:     pool,
 | 
			
		||||
		uploader: manager,
 | 
			
		||||
	}
 | 
			
		||||
	h.App = app
 | 
			
		||||
	return &h
 | 
			
		||||
@@ -189,3 +192,30 @@ func (h *SdJobHandler) JobList(c *gin.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c, jobs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove remove task image
 | 
			
		||||
func (h *SdJobHandler) Remove(c *gin.Context) {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		Id     uint   `json:"id"`
 | 
			
		||||
		ImgURL string `json:"img_url"`
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.ShouldBindJSON(&data); err != nil {
 | 
			
		||||
		resp.ERROR(c, types.InvalidArgs)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// remove job recode
 | 
			
		||||
	res := h.db.Delete(&model.SdJob{Id: data.Id})
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, res.Error.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// remove image
 | 
			
		||||
	err := h.uploader.GetUploadHandler().Delete(data.ImgURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("remove image failed: ", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -233,11 +233,13 @@ func main() {
 | 
			
		||||
			group.POST("upscale", h.Upscale)
 | 
			
		||||
			group.POST("variation", h.Variation)
 | 
			
		||||
			group.GET("jobs", h.JobList)
 | 
			
		||||
			group.POST("remove", h.Remove)
 | 
			
		||||
		}),
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, h *handler.SdJobHandler) {
 | 
			
		||||
			group := s.Engine.Group("/api/sd")
 | 
			
		||||
			group.POST("image", h.Image)
 | 
			
		||||
			group.GET("jobs", h.JobList)
 | 
			
		||||
			group.POST("remove", h.Remove)
 | 
			
		||||
		}),
 | 
			
		||||
 | 
			
		||||
		// 管理后台控制器
 | 
			
		||||
 
 | 
			
		||||
@@ -299,6 +299,7 @@
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border-radius: 6px;
 | 
			
		||||
  transition: all 0.3s ease; /* 添加过渡效果 */
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .finish-job-list .job-item .opt .opt-line {
 | 
			
		||||
  margin: 6px 0;
 | 
			
		||||
@@ -327,6 +328,15 @@
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .finish-job-list .job-item .remove {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 10px;
 | 
			
		||||
  top: 10px;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .finish-job-list .job-item:hover .remove {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .finish-job-list .animate:hover {
 | 
			
		||||
  box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */
 | 
			
		||||
  transform: translateY(-10px); /* 向上移动10像素 */
 | 
			
		||||
 
 | 
			
		||||
@@ -184,6 +184,7 @@
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border-radius: 6px;
 | 
			
		||||
  transition: all 0.3s ease; /* 添加过渡效果 */
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .finish-job-list .job-item .opt .opt-line {
 | 
			
		||||
  margin: 6px 0;
 | 
			
		||||
@@ -212,6 +213,15 @@
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .finish-job-list .job-item .remove {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 10px;
 | 
			
		||||
  top: 10px;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .finish-job-list .job-item:hover .remove {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .finish-job-list .animate:hover {
 | 
			
		||||
  box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */
 | 
			
		||||
  transform: translateY(-10px); /* 向上移动10像素 */
 | 
			
		||||
 
 | 
			
		||||
@@ -148,6 +148,7 @@
 | 
			
		||||
      overflow hidden
 | 
			
		||||
      border-radius 6px
 | 
			
		||||
      transition: all 0.3s ease; /* 添加过渡效果 */
 | 
			
		||||
      position relative
 | 
			
		||||
 | 
			
		||||
      .opt {
 | 
			
		||||
        .opt-line {
 | 
			
		||||
@@ -183,6 +184,19 @@
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .remove {
 | 
			
		||||
        display none
 | 
			
		||||
        position absolute
 | 
			
		||||
        right 10px
 | 
			
		||||
        top 10px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:hover{
 | 
			
		||||
        .remove {
 | 
			
		||||
          display block
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .animate {
 | 
			
		||||
 
 | 
			
		||||
@@ -417,6 +417,10 @@
 | 
			
		||||
                      </ul>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  <div class="remove">
 | 
			
		||||
                    <el-button type="danger" :icon="Delete" @click="removeImage(scope.item)" circle/>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </template>
 | 
			
		||||
            </ItemList>
 | 
			
		||||
@@ -434,7 +438,7 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, ref} from "vue"
 | 
			
		||||
import {
 | 
			
		||||
  ChromeFilled,
 | 
			
		||||
  ChromeFilled, Delete,
 | 
			
		||||
  DeleteFilled,
 | 
			
		||||
  DocumentCopy,
 | 
			
		||||
  InfoFilled,
 | 
			
		||||
@@ -444,7 +448,7 @@ import {
 | 
			
		||||
} from "@element-plus/icons-vue";
 | 
			
		||||
import Compressor from "compressorjs";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {ElMessage, ElNotification} from "element-plus";
 | 
			
		||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
 | 
			
		||||
import ItemList from "@/components/ItemList.vue";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
@@ -581,10 +585,11 @@ const fetchRunningJobs = (userId) => {
 | 
			
		||||
    }
 | 
			
		||||
    runningJobs.value = _jobs
 | 
			
		||||
 | 
			
		||||
    setTimeout(() => fetchRunningJobs(userId), 3000)
 | 
			
		||||
    setTimeout(() => fetchRunningJobs(userId), 1000)
 | 
			
		||||
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取任务失败:" + e.message)
 | 
			
		||||
    setTimeout(() => fetchRunningJobs(userId), 5000)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -592,9 +597,10 @@ const fetchFinishJobs = (userId) => {
 | 
			
		||||
  // 获取已完成的任务
 | 
			
		||||
  httpGet(`/api/mj/jobs?status=1&user_id=${userId}`).then(res => {
 | 
			
		||||
    finishedJobs.value = res.data
 | 
			
		||||
    setTimeout(() => fetchFinishJobs(userId), 3000)
 | 
			
		||||
    setTimeout(() => fetchFinishJobs(userId), 1000)
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取任务失败:" + e.message)
 | 
			
		||||
    setTimeout(() => fetchFinishJobs(userId), 5000)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -674,6 +680,25 @@ const send = (url, index, item) => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const removeImage = (item) => {
 | 
			
		||||
  ElMessageBox.confirm(
 | 
			
		||||
      '此操作将会删除任务和图片,继续操作码?',
 | 
			
		||||
      '删除提示',
 | 
			
		||||
      {
 | 
			
		||||
        confirmButtonText: '确认',
 | 
			
		||||
        cancelButtonText: '取消',
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
      }
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    httpPost("/api/mj/remove", {id: item.id, img_url: item.img_url}).then(() => {
 | 
			
		||||
      ElMessage.success("任务删除成功")
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("任务删除失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
@@ -371,6 +371,10 @@
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </template>
 | 
			
		||||
                  </el-image>
 | 
			
		||||
 | 
			
		||||
                  <div class="remove">
 | 
			
		||||
                    <el-button type="danger" :icon="Delete" @click="removeImage($event,scope.item)" circle/>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </template>
 | 
			
		||||
            </ItemList>
 | 
			
		||||
@@ -498,9 +502,9 @@
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, ref} from "vue"
 | 
			
		||||
import {DocumentCopy, InfoFilled, Orange, Picture, Refresh} from "@element-plus/icons-vue";
 | 
			
		||||
import {Delete, DocumentCopy, InfoFilled, Orange, Picture, Refresh} from "@element-plus/icons-vue";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {ElMessage, ElNotification} from "element-plus";
 | 
			
		||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
 | 
			
		||||
import ItemList from "@/components/ItemList.vue";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
@@ -598,9 +602,10 @@ onMounted(() => {
 | 
			
		||||
      }
 | 
			
		||||
      runningJobs.value = _jobs
 | 
			
		||||
 | 
			
		||||
      setTimeout(() => fetchRunningJobs(userId), 3000)
 | 
			
		||||
      setTimeout(() => fetchRunningJobs(userId), 1000)
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("获取任务失败:" + e.message)
 | 
			
		||||
      setTimeout(() => fetchRunningJobs(userId), 5000)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -608,9 +613,10 @@ onMounted(() => {
 | 
			
		||||
  const fetchFinishJobs = (userId) => {
 | 
			
		||||
    httpGet(`/api/sd/jobs?status=1&user_id=${userId}`).then(res => {
 | 
			
		||||
      finishedJobs.value = res.data
 | 
			
		||||
      setTimeout(() => fetchFinishJobs(userId), 3000)
 | 
			
		||||
      setTimeout(() => fetchFinishJobs(userId), 1000)
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("获取任务失败:" + e.message)
 | 
			
		||||
      setTimeout(() => fetchFinishJobs(userId), 5000)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -654,6 +660,26 @@ const copyParams = (row) => {
 | 
			
		||||
  showTaskDialog.value = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const removeImage = (event, item) => {
 | 
			
		||||
  event.stopPropagation()
 | 
			
		||||
  ElMessageBox.confirm(
 | 
			
		||||
      '此操作将会删除任务和图片,继续操作码?',
 | 
			
		||||
      '删除提示',
 | 
			
		||||
      {
 | 
			
		||||
        confirmButtonText: '确认',
 | 
			
		||||
        cancelButtonText: '取消',
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
      }
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    httpPost("/api/sd/remove", {id: item.id, img_url: item.img_url}).then(() => {
 | 
			
		||||
      ElMessage.success("任务删除成功")
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("任务删除失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user