mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	feat: add image preview for mobile chat page
This commit is contained in:
		@@ -1,4 +1,8 @@
 | 
			
		||||
# 更新日志
 | 
			
		||||
## v3.2.8
 | 
			
		||||
* 功能优化:SD 绘画页面采用 websocket 替换 http 轮询机制,节省带宽
 | 
			
		||||
* 功能优化:移动端聊天页面图片支持预览和放大功能
 | 
			
		||||
 | 
			
		||||
## v3.2.7
 | 
			
		||||
* 功能重构:采用 Vant 重构移动页面,新增 MidJourney 功能
 | 
			
		||||
* 功能优化:优化 PC 端 MidJourney 页面布局,新增融图和换脸功能
 | 
			
		||||
 
 | 
			
		||||
@@ -233,6 +233,7 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
 | 
			
		||||
	const translatePromptTemplate = "Translate the following painting prompt words into English keyword phrases. Without any explanation, directly output the keyword phrases separated by commas. The content to be translated is: [%s]"
 | 
			
		||||
	pt, err := utils.OpenAIRequest(h.db, fmt.Sprintf(translatePromptTemplate, params["prompt"]), h.App.Config.ProxyURL)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		logger.Debugf("翻译绘画提示词,原文:%s,译文:%s", prompt, pt)
 | 
			
		||||
		prompt = pt
 | 
			
		||||
	}
 | 
			
		||||
	imgNum := chatConfig.DallImgNum
 | 
			
		||||
 
 | 
			
		||||
@@ -109,19 +109,10 @@
 | 
			
		||||
  background-color: #4e5058;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .el-image {
 | 
			
		||||
.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .van-image {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 200px;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .el-image .image-slot {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .el-image .image-slot .iconfont {
 | 
			
		||||
  margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .upscale {
 | 
			
		||||
  height: 260px;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
 
 | 
			
		||||
@@ -150,20 +150,9 @@
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              .el-image {
 | 
			
		||||
              .van-image {
 | 
			
		||||
                width 100%
 | 
			
		||||
                height 200px
 | 
			
		||||
 | 
			
		||||
                .image-slot {
 | 
			
		||||
                  height 100%
 | 
			
		||||
                  display flex
 | 
			
		||||
                  justify-content center
 | 
			
		||||
                  align-items center
 | 
			
		||||
 | 
			
		||||
                  .iconfont {
 | 
			
		||||
                    margin-right 5px
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              .upscale {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
    <div class="chat-item">
 | 
			
		||||
      <div class="triangle"></div>
 | 
			
		||||
      <div class="content-box">
 | 
			
		||||
      <div class="content-box" ref="contentRef">
 | 
			
		||||
        <div :data-clipboard-text="orgContent" class="content content-mobile" v-html="content"></div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
@@ -17,8 +17,7 @@
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, ref} from "vue"
 | 
			
		||||
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import {showNotify} from "vant";
 | 
			
		||||
import {showImagePreview} from "vant";
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  content: {
 | 
			
		||||
@@ -34,6 +33,20 @@ const props = defineProps({
 | 
			
		||||
    default: '/images/gpt-icon.png',
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const contentRef = ref(null)
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  const imgs = contentRef.value.querySelectorAll('img')
 | 
			
		||||
  for (let i = 0; i < imgs.length; i++) {
 | 
			
		||||
    if (!imgs[i].src) {
 | 
			
		||||
      continue
 | 
			
		||||
    }
 | 
			
		||||
    imgs[i].addEventListener('click', (e) => {
 | 
			
		||||
      e.stopPropagation()
 | 
			
		||||
      showImagePreview([imgs[i].src]);
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
@@ -143,29 +143,16 @@
 | 
			
		||||
        <van-grid :gutter="10" :column-num="2" v-else>
 | 
			
		||||
          <van-grid-item v-for="item in finishedJobs">
 | 
			
		||||
            <div class="job-item">
 | 
			
		||||
              <el-image
 | 
			
		||||
              <van-image
 | 
			
		||||
                  :src="item['thumb_url']"
 | 
			
		||||
                  :class="item['can_opt'] ? '' : 'upscale'" :zoom-rate="1.2"
 | 
			
		||||
                  :preview-src-list="[item['img_url']]" fit="cover" :initial-index="0"
 | 
			
		||||
                  loading="lazy" v-if="item.progress > 0">
 | 
			
		||||
                <template #placeholder>
 | 
			
		||||
                  <div class="image-slot">
 | 
			
		||||
                    正在加载图片
 | 
			
		||||
                  </div>
 | 
			
		||||
                  :class="item['can_opt'] ? '' : 'upscale'"
 | 
			
		||||
                  lazy-load
 | 
			
		||||
                  @click="imageView(item)"
 | 
			
		||||
                  fit="cover">
 | 
			
		||||
                <template v-slot:loading>
 | 
			
		||||
                  <van-loading type="spinner" size="20"/>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template #error>
 | 
			
		||||
                  <div class="image-slot" v-if="item['img_url'] === ''">
 | 
			
		||||
                    <i class="iconfont icon-loading"></i>
 | 
			
		||||
                    <span>正在下载图片</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="image-slot" v-else>
 | 
			
		||||
                    <el-icon>
 | 
			
		||||
                      <Picture/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-image>
 | 
			
		||||
              </van-image>
 | 
			
		||||
 | 
			
		||||
              <div class="opt" v-if="item['can_opt']">
 | 
			
		||||
 | 
			
		||||
@@ -205,7 +192,7 @@
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, ref} from "vue";
 | 
			
		||||
import {showConfirmDialog, showFailToast, showNotify, showToast, showDialog} from "vant";
 | 
			
		||||
import {showConfirmDialog, showFailToast, showNotify, showToast, showDialog, showImagePreview} from "vant";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import Compressor from "compressorjs";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
@@ -478,6 +465,10 @@ const showPrompt = (item) => {
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const imageView = (item) => {
 | 
			
		||||
  showImagePreview([item['img_url']]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user