ImageModal.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <template>
  2. <div class="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4" @click="$emit('close')">
  3. <div class="bg-white rounded-lg border-2 border-[#0A0910] max-w-4xl max-h-[90vh] overflow-hidden" @click.stop>
  4. <!-- 头部 -->
  5. <div class="bg-blue-500 text-white p-4 flex items-center justify-between">
  6. <div>
  7. <h3 class="font-bold text-lg">{{ image.recipeName }}</h3>
  8. <p class="text-blue-100 text-sm">{{ image.cuisine }} • {{ formatDate(image.generatedAt) }}</p>
  9. </div>
  10. <button @click="$emit('close')" class="text-white hover:text-gray-200 text-2xl">×</button>
  11. </div>
  12. <!-- 图片 -->
  13. <div class="relative">
  14. <img :src="image.url" :alt="image.recipeName" class="w-full max-h-[60vh] object-contain" />
  15. </div>
  16. <!-- 详情信息 -->
  17. <div class="p-4 max-h-48 overflow-y-auto">
  18. <!-- 食材 -->
  19. <div class="mb-4">
  20. <h4 class="font-bold text-gray-800 mb-2 flex items-center gap-1">🥬 食材</h4>
  21. <div class="flex flex-wrap gap-1">
  22. <span v-for="ingredient in image.ingredients" :key="ingredient" class="bg-yellow-100 text-yellow-800 px-2 py-1 rounded text-sm border">
  23. {{ ingredient }}
  24. </span>
  25. </div>
  26. </div>
  27. <!-- 生成提示词 -->
  28. <div v-if="image.prompt" class="mb-4">
  29. <h4 class="font-bold text-gray-800 mb-2 flex items-center gap-1">🎨 生成提示</h4>
  30. <p class="text-gray-600 text-sm bg-gray-50 p-3 rounded border">
  31. {{ image.prompt }}
  32. </p>
  33. </div>
  34. </div>
  35. <!-- 操作按钮 -->
  36. <div class="bg-gray-50 border-t border-gray-200 p-4 flex items-center justify-between">
  37. <div class="text-sm text-gray-500">生成于 {{ new Date(image.generatedAt).toLocaleString('zh-CN') }}</div>
  38. <div class="flex items-center gap-2">
  39. <button
  40. @click="$emit('download', image)"
  41. class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg text-sm font-medium border-2 border-[#0A0910] transition-all duration-200 hover:scale-105"
  42. >
  43. 📥 下载
  44. </button>
  45. <button
  46. @click="$emit('delete', image.id)"
  47. class="px-4 py-2 bg-red-500 hover:bg-red-600 text-white rounded-lg text-sm font-medium border-2 border-[#0A0910] transition-all duration-200 hover:scale-105"
  48. >
  49. 🗑️ 删除
  50. </button>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </template>
  56. <script setup lang="ts">
  57. import type { GalleryImage } from '@/services/galleryService'
  58. interface Props {
  59. image: GalleryImage
  60. }
  61. defineProps<Props>()
  62. defineEmits<{
  63. close: []
  64. delete: [imageId: string]
  65. download: [image: GalleryImage]
  66. }>()
  67. // 格式化日期
  68. const formatDate = (dateString: string) => {
  69. const date = new Date(dateString)
  70. const now = new Date()
  71. const diffTime = now.getTime() - date.getTime()
  72. const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))
  73. if (diffDays === 0) {
  74. return '今天'
  75. } else if (diffDays === 1) {
  76. return '昨天'
  77. } else if (diffDays < 7) {
  78. return `${diffDays}天前`
  79. } else {
  80. return date.toLocaleDateString('zh-CN', {
  81. year: 'numeric',
  82. month: 'short',
  83. day: 'numeric'
  84. })
  85. }
  86. }
  87. </script>
  88. <style scoped>
  89. /* 确保弹窗在最顶层 */
  90. .z-50 {
  91. z-index: 50;
  92. }
  93. </style>