From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/ai/image/index/components/ImageList.vue |  208 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 208 insertions(+), 0 deletions(-)

diff --git a/src/views/ai/image/index/components/ImageList.vue b/src/views/ai/image/index/components/ImageList.vue
new file mode 100644
index 0000000..5169e45
--- /dev/null
+++ b/src/views/ai/image/index/components/ImageList.vue
@@ -0,0 +1,208 @@
+<template>
+  <el-card
+    class="wh-full"
+    :body-style="{ margin: 0, padding: 0, height: '100%', position: 'relative' }"
+    shadow="never"
+  >
+    <template #header>
+      缁樼敾浠诲姟
+      <!-- TODO @fan锛氱湅鐪嬶紝鎬庝箞浼樺寲涓嬭繖涓牱瀛愬搱銆� -->
+      <el-button @click="handleViewPublic">缁樼敾浣滃搧</el-button>
+    </template>
+    <!-- 鍥剧墖鍒楄〃 -->
+    <div
+      class="relative flex flex-row flex-wrap content-start h-full overflow-auto p-5 pb-[140px] box-border [&>div]:mr-5 [&>div]:mb-5"
+      ref="imageListRef"
+    >
+      <ImageCard
+        v-for="image in imageList"
+        :key="image.id"
+        :detail="image"
+        @on-btn-click="handleImageButtonClick"
+        @on-mj-btn-click="handleImageMidjourneyButtonClick"
+      />
+    </div>
+    <div
+      class="absolute bottom-[60px] h-[50px] leading-[90px] w-full z-[999] bg-white flex flex-row justify-center items-center"
+    >
+      <Pagination
+        :total="pageTotal"
+        v-model:page="queryParams.pageNo"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getImageList"
+      />
+    </div>
+  </el-card>
+
+  <!-- 鍥剧墖璇︽儏 -->
+  <ImageDetail
+    :show="isShowImageDetail"
+    :id="showImageDetailId"
+    @handle-drawer-close="handleDetailClose"
+  />
+</template>
+<script setup lang="ts">
+import {
+  ImageApi,
+  ImageVO,
+  ImageMidjourneyActionVO,
+  ImageMidjourneyButtonsVO
+} from '@/api/ai/image'
+import ImageDetail from './ImageDetail.vue'
+import ImageCard from './ImageCard.vue'
+import { ElLoading, LoadingOptionsResolved } from 'element-plus'
+import { AiImageStatusEnum } from '@/views/ai/utils/constants'
+import download from '@/utils/download'
+
+const message = useMessage() // 娑堟伅寮圭獥
+const router = useRouter() // 璺敱
+
+// 鍥剧墖鍒嗛〉鐩稿叧鐨勫弬鏁�
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10
+})
+const pageTotal = ref<number>(0) // page size
+const imageList = ref<ImageVO[]>([]) // image 鍒楄〃
+const imageListLoadingInstance = ref<any>() // image 鍒楄〃鏄惁姝e湪鍔犺浇涓�
+const imageListRef = ref<any>() // ref
+// 鍥剧墖杞鐩稿叧鐨勫弬鏁帮紙姝e湪鐢熸垚涓殑锛�
+const inProgressImageMap = ref<{}>({}) // 鐩戝惉鐨� image 鏄犲皠锛屼竴鑸槸鐢熸垚涓紙闇�瑕佽疆璇級锛宬ey 涓� image 缂栧彿锛寁alue 涓� image
+const inProgressTimer = ref<any>() // 鐢熸垚涓殑 image 瀹氭椂鍣紝杞鐢熸垚杩涘睍
+// 鍥剧墖璇︽儏鐩稿叧鐨勫弬鏁�
+const isShowImageDetail = ref<boolean>(false) // 鍥剧墖璇︽儏鏄惁灞曠ず
+const showImageDetailId = ref<number>(0) // 鍥剧墖璇︽儏鐨勫浘鐗囩紪鍙�
+
+/** 澶勭悊鏌ョ湅缁樺浘浣滃搧 */
+const handleViewPublic = () => {
+  router.push({
+    name: 'AiImageSquare'
+  })
+}
+
+/** 鏌ョ湅鍥剧墖鐨勮鎯�  */
+const handleDetailOpen = async () => {
+  isShowImageDetail.value = true
+}
+
+/** 鍏抽棴鍥剧墖鐨勮鎯�  */
+const handleDetailClose = async () => {
+  isShowImageDetail.value = false
+}
+
+/** 鑾峰緱 image 鍥剧墖鍒楄〃 */
+const getImageList = async () => {
+  try {
+    // 1. 鍔犺浇鍥剧墖鍒楄〃
+    imageListLoadingInstance.value = ElLoading.service({
+      target: imageListRef.value,
+      text: '鍔犺浇涓�...'
+    } as LoadingOptionsResolved)
+    const { list, total } = await ImageApi.getImagePageMy(queryParams)
+    imageList.value = list
+    pageTotal.value = total
+
+    // 2. 璁$畻闇�瑕佽疆璇㈢殑鍥剧墖
+    const newWatImages = {}
+    imageList.value.forEach((item) => {
+      if (item.status === AiImageStatusEnum.IN_PROGRESS) {
+        newWatImages[item.id] = item
+      }
+    })
+    inProgressImageMap.value = newWatImages
+  } finally {
+    // 鍏抽棴姝e湪鈥滃姞杞戒腑鈥濈殑 Loading
+    if (imageListLoadingInstance.value) {
+      imageListLoadingInstance.value.close()
+      imageListLoadingInstance.value = null
+    }
+  }
+}
+
+/** 杞鐢熸垚涓殑 image 鍒楄〃 */
+const refreshWatchImages = async () => {
+  const imageIds = Object.keys(inProgressImageMap.value).map(Number)
+  if (imageIds.length == 0) {
+    return
+  }
+  const list = (await ImageApi.getImageListMyByIds(imageIds)) as ImageVO[]
+  const newWatchImages = {}
+  list.forEach((image) => {
+    if (image.status === AiImageStatusEnum.IN_PROGRESS) {
+      newWatchImages[image.id] = image
+    } else {
+      const index = imageList.value.findIndex((oldImage) => image.id === oldImage.id)
+      if (index >= 0) {
+        // 鏇存柊 imageList
+        imageList.value[index] = image
+      }
+    }
+  })
+  inProgressImageMap.value = newWatchImages
+}
+
+/** 鍥剧墖鐨勭偣鍑讳簨浠� */
+const handleImageButtonClick = async (type: string, imageDetail: ImageVO) => {
+  // 璇︽儏
+  if (type === 'more') {
+    showImageDetailId.value = imageDetail.id
+    await handleDetailOpen()
+    return
+  }
+  // 鍒犻櫎
+  if (type === 'delete') {
+    await message.confirm(`鏄惁鍒犻櫎鐓х墖?`)
+    await ImageApi.deleteImageMy(imageDetail.id)
+    await getImageList()
+    message.success('鍒犻櫎鎴愬姛!')
+    return
+  }
+  // 涓嬭浇
+  if (type === 'download') {
+    download.image({ url: imageDetail.picUrl })
+    return
+  }
+  // 閲嶆柊鐢熸垚
+  if (type === 'regeneration') {
+    emits('onRegeneration', imageDetail)
+    return
+  }
+}
+
+/** 澶勭悊 Midjourney 鎸夐挳鐐瑰嚮浜嬩欢  */
+const handleImageMidjourneyButtonClick = async (
+  button: ImageMidjourneyButtonsVO,
+  imageDetail: ImageVO
+) => {
+  // 1. 鏋勫缓 params 鍙傛暟
+  const data = {
+    id: imageDetail.id,
+    customId: button.customId
+  } as ImageMidjourneyActionVO
+  // 2. 鍙戦�� action
+  await ImageApi.midjourneyAction(data)
+  // 3. 鍒锋柊鍒楄〃
+  await getImageList()
+}
+
+defineExpose({ getImageList }) // 鏆撮湶缁勪欢鏂规硶
+
+const emits = defineEmits(['onRegeneration'])
+
+/** 缁勪欢鎸傚湪鐨勬椂鍊� */
+onMounted(async () => {
+  // 鑾峰彇 image 鍒楄〃
+  await getImageList()
+  // 鑷姩鍒锋柊 image 鍒楄〃
+  inProgressTimer.value = setInterval(async () => {
+    await refreshWatchImages()
+  }, 1000 * 3)
+})
+
+/** 缁勪欢鍙栨秷鎸傚湪鐨勬椂鍊� */
+onUnmounted(async () => {
+  if (inProgressTimer.value) {
+    clearInterval(inProgressTimer.value)
+  }
+})
+</script>

--
Gitblit v1.8.0