From 9fcd686fda694ed99fb6a2de91fc366e202b1a4c Mon Sep 17 00:00:00 2001 From: RockYang Date: Thu, 12 Oct 2023 18:09:50 +0800 Subject: [PATCH] feat: image wall page is ready --- README.md | 4 +- api/handler/mj_handler.go | 22 +++++-- web/package-lock.json | 11 ++++ web/package.json | 3 +- web/src/assets/css/images-wall.css | 46 ++++++++++++++ web/src/assets/css/images-wall.styl | 69 ++++++++++++++++++++ web/src/main.js | 3 + web/src/router.js | 6 +- web/src/views/Home.vue | 2 +- web/src/views/ImageMj.vue | 5 +- web/src/views/Images.vue | 41 ------------ web/src/views/ImagesWall.vue | 98 +++++++++++++++++++++++++++++ 12 files changed, 254 insertions(+), 56 deletions(-) create mode 100644 web/src/assets/css/images-wall.css create mode 100644 web/src/assets/css/images-wall.styl delete mode 100644 web/src/views/Images.vue create mode 100644 web/src/views/ImagesWall.vue diff --git a/README.md b/README.md index 19afbc4d..b018e773 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # ChatGPT-Plus **ChatGPT-PLUS** 基于 AI 大语言模型 API 实现的 AI 助手全套开源解决方案,自带运营管理后台,开箱即用。集成了 OpenAI, Azure, -ChatGLM,讯飞星火,文心一言等多个平台的大语言模型。主要有如下特性: +ChatGLM,讯飞星火,文心一言等多个平台的大语言模型。集成了 MidJourney 和 Stable Diffusion AI绘画功能。主要有如下特性: * 完整的开源系统,前端应用和后台管理系统皆可开箱即用。 * 聊天体验跟 ChatGPT 官方版本完全一致。 * 内置了各种预训练好的角色,比如小红书写手,英语翻译大师,苏格拉底,孔子,乔布斯,周报助手等。轻松满足你的各种聊天和应用需求。 -* 支持 MidJourney AI 绘画集成,开箱即用。 +* 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。 * 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。(可定制开发其他支付通道支持) * 集成插件 API 功能,可结合 GPT 开发各种强大的插件,已内置实现了微博热搜,今日头条,今日早报和 AI 绘画函数插件。 diff --git a/api/handler/mj_handler.go b/api/handler/mj_handler.go index 77d6e9ff..97d8a6a4 100644 --- a/api/handler/mj_handler.go +++ b/api/handler/mj_handler.go @@ -315,14 +315,26 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) { // JobList 获取 MJ 任务列表 func (h *MidJourneyHandler) JobList(c *gin.Context) { status := h.GetInt(c, "status", 0) - var items []model.MidJourneyJob - var res *gorm.DB - userId, _ := c.Get(types.LoginUserID) + userId := h.GetInt(c, "user_id", 0) + page := h.GetInt(c, "page", 0) + pageSize := h.GetInt(c, "page_size", 0) + + session := h.db.Session(&gorm.Session{}) if status == 1 { - res = h.db.Where("user_id = ? AND progress = 100", userId).Order("id DESC").Find(&items) + session = session.Where("progress = ?", 100).Order("id DESC") } else { - res = h.db.Where("user_id = ? AND progress < 100", userId).Order("id ASC").Find(&items) + session = session.Where("progress < ?", 100).Order("id ASC") } + if userId > 0 { + session = session.Where("user_id = ?", userId) + } + if page > 0 && pageSize > 0 { + offset := (page - 1) * pageSize + session = session.Offset(offset).Limit(pageSize) + } + + var items []model.MidJourneyJob + res := session.Find(&items) if res.Error != nil { resp.ERROR(c, types.NoData) return diff --git a/web/package-lock.json b/web/package-lock.json index 0badd7e7..20193ad2 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -23,6 +23,7 @@ "pinia": "^2.1.4", "qs": "^6.11.1", "sortablejs": "^1.15.0", + "v3-waterfall": "^1.2.1", "vant": "^4.5.0", "vue": "^3.2.13", "vue-router": "^4.0.15" @@ -10459,6 +10460,11 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v3-waterfall": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.2.1.tgz", + "integrity": "sha512-zjfT1FuHupsAahvS4mr3Yb8k2SHB8srW6st+/cBXwrsyhbCcj8Qhb1QtNUuEIx/tbpLQrMpxtJunZXkaKBfAEA==" + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -19518,6 +19524,11 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, + "v3-waterfall": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.2.1.tgz", + "integrity": "sha512-zjfT1FuHupsAahvS4mr3Yb8k2SHB8srW6st+/cBXwrsyhbCcj8Qhb1QtNUuEIx/tbpLQrMpxtJunZXkaKBfAEA==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", diff --git a/web/package.json b/web/package.json index 275e71ac..bcd14835 100644 --- a/web/package.json +++ b/web/package.json @@ -17,14 +17,15 @@ "good-storage": "^1.1.1", "highlight.js": "^11.7.0", "json-bigint": "^1.0.0", + "lodash": "^4.17.21", "markdown-it": "^13.0.1", "md-editor-v3": "^2.2.1", "pinia": "^2.1.4", "qs": "^6.11.1", "sortablejs": "^1.15.0", + "v3-waterfall": "^1.2.1", "vant": "^4.5.0", "vue": "^3.2.13", - "lodash": "^4.17.21", "vue-router": "^4.0.15" }, "devDependencies": { diff --git a/web/src/assets/css/images-wall.css b/web/src/assets/css/images-wall.css new file mode 100644 index 00000000..f6ea6bee --- /dev/null +++ b/web/src/assets/css/images-wall.css @@ -0,0 +1,46 @@ +.page-images-wall { + display: flex; + background-color: #282c34; +} +.page-images-wall .inner { + width: 100%; + color: #fff; + overflow: hidden; +} +.page-images-wall .inner .header { + display: flex; + padding: 0 40px; +} +.page-images-wall .inner .header h2 { + width: 300px; +} +.page-images-wall .inner .header .settings { + width: 100%; + display: flex; + justify-content: right; +} +.page-images-wall .inner .header .settings .el-radio-group { + font-size: 16px; +} +.page-images-wall .inner .header .settings .el-radio-group .el-radio { + color: #fff; +} +.page-images-wall .inner .waterfall { + position: relative; + margin: 0 auto; + overflow-y: auto; + overflow-x: hidden; +} +.page-images-wall .custom-scroll ::-webkit-scrollbar { + width: 10px; /* 滚动条宽度 */ +} +.page-images-wall .custom-scroll ::-webkit-scrollbar-track { + background-color: #282c34; +} +.page-images-wall .custom-scroll ::-webkit-scrollbar-thumb { + background-color: #444; + border-radius: 10px; +} +.page-images-wall .custom-scroll ::-webkit-scrollbar-thumb:hover { + background-color: #666; +} diff --git a/web/src/assets/css/images-wall.styl b/web/src/assets/css/images-wall.styl new file mode 100644 index 00000000..f89890d6 --- /dev/null +++ b/web/src/assets/css/images-wall.styl @@ -0,0 +1,69 @@ +.page-images-wall { + display: flex; + background-color: #282c34; + + .inner { + width 100% + color #ffffff + overflow hidden + + .header { + display flex + padding 0 40px + + h2 { + width 300px + } + + .settings { + width 100% + display flex + justify-content right + + .el-radio-group { + font-size 16px + + .el-radio { + color #ffffff + } + + } + } + } + + .waterfall { + position: relative; + margin: 0 auto; + overflow-y auto + overflow-x hidden + } + + } + + .custom-scroll { + /* 修改滚动条的颜色 */ + + ::-webkit-scrollbar { + width: 10px; /* 滚动条宽度 */ + } + + /* 修改滚动条轨道的背景颜色 */ + + ::-webkit-scrollbar-track { + background-color: #282C34; + } + + /* 修改滚动条的滑块颜色 */ + + ::-webkit-scrollbar-thumb { + background-color: #444444; + border-radius 10px + } + + /* 修改滚动条的滑块的悬停颜色 */ + + ::-webkit-scrollbar-thumb:hover { + background-color: #666666; + } + } +} \ No newline at end of file diff --git a/web/src/main.js b/web/src/main.js index d386f3ad..5db4c31e 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -33,6 +33,8 @@ import { Uploader } from "vant"; import router from "@/router"; +import 'v3-waterfall/dist/style.css' +import V3waterfall from "v3-waterfall"; const app = createApp(App) app.use(createPinia()) @@ -62,6 +64,7 @@ app.use(ShareSheet); app.use(Switch); app.use(Uploader); app.use(Tag); +app.use(V3waterfall) app.use(router).use(ElementPlus).mount('#app') diff --git a/web/src/router.js b/web/src/router.js index fabe8397..669dbf0d 100644 --- a/web/src/router.js +++ b/web/src/router.js @@ -40,9 +40,9 @@ const routes = [ }, { name: 'images', - path: '/images', - meta: {title: '绘画社区'}, - component: () => import('@/views/Images.vue'), + path: '/images-wall', + meta: {title: '作品展示'}, + component: () => import('@/views/ImagesWall.vue'), }, { name: 'user-invitation', diff --git a/web/src/views/Home.vue b/web/src/views/Home.vue index b00fe88f..8dfc3737 100644 --- a/web/src/views/Home.vue +++ b/web/src/views/Home.vue @@ -45,7 +45,7 @@ const navs = ref([ {path: "/mj", icon: "image", title: "MJ 绘画"}, {path: "/sd", icon: "palette", title: "SD 绘画"}, {path: "/apps", icon: "menu", title: "应用中心"}, - {path: "/images", icon: "image-list", title: "绘画社区"}, + {path: "/images-wall", icon: "image-list", title: "作品展示"}, {path: "/knowledge", icon: "book", title: "我的知识库"}, {path: "/member", icon: "vip-user", title: "会员计划"}, {path: "/invite", icon: "share", title: "推广计划"}, diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index 8f8cf33a..ccc198cc 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -379,7 +379,6 @@ import {getSessionId, getUserToken} from "@/store/session"; const listBoxHeight = ref(window.innerHeight - 40) const mjBoxHeight = ref(window.innerHeight - 150) - window.onresize = () => { listBoxHeight.value = window.innerHeight - 40 mjBoxHeight.value = window.innerHeight - 150 @@ -476,14 +475,14 @@ onMounted(() => { checkSession().then(user => { imgCalls.value = user['img_calls'] // 获取运行中的任务 - httpGet("/api/mj/jobs?status=0").then(res => { + httpGet(`/api/mj/jobs?status=0&user_id=${user['id']}`).then(res => { runningJobs.value = res.data }).catch(e => { ElMessage.error("获取任务失败:" + e.message) }) // 获取运行中的任务 - httpGet("/api/mj/jobs?status=1").then(res => { + httpGet(`/api/mj/jobs?status=1&user_id=${user['id']}`).then(res => { finishedJobs.value = res.data previewImgList.value = [] for (let index in finishedJobs.value) { diff --git a/web/src/views/Images.vue b/web/src/views/Images.vue deleted file mode 100644 index f44ea305..00000000 --- a/web/src/views/Images.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/web/src/views/ImagesWall.vue b/web/src/views/ImagesWall.vue new file mode 100644 index 00000000..6d4f51e2 --- /dev/null +++ b/web/src/views/ImagesWall.vue @@ -0,0 +1,98 @@ + + + + +