21
21
</div >
22
22
<!-- Modal body -->
23
23
<div class =" p-4 md:p-5 space-y-4" >
24
- <textarea id =" message" rows =" 3" class =" block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
25
- :placeholder =" $t('Prompt which will be passed to AI network')" v-model =" prompt"
24
+ <!-- PROMPT TEXTAREA -->
25
+ <!-- Textarea -->
26
+ <textarea
27
+ id =" message"
28
+ rows =" 3"
29
+ class =" block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
30
+ :placeholder =" $t('Prompt which will be passed to AI network')"
31
+ v-model =" prompt"
26
32
:title =" $t('Prompt which will be passed to AI network')"
27
- ></textarea >
33
+ ></textarea >
34
+
35
+ <!-- Thumbnails -->
36
+ <div class =" mt-2 flex flex-wrap gap-2" >
37
+ <img
38
+ v-for =" (img, idx) in attachmentFiles"
39
+ :key =" idx"
40
+ :src =" img"
41
+ class =" w-20 h-20 object-cover rounded cursor-pointer border hover:border-blue-500 transition"
42
+ :alt =" `Generated image ${idx + 1}`"
43
+ @click =" zoomImage(img)"
44
+ />
45
+ </div >
46
+
47
+ <!-- Fullscreen Modal -->
48
+ <div
49
+ v-if =" zoomedImage"
50
+ class =" fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-80"
51
+ @click.self =" closeZoom"
52
+ >
53
+ <img
54
+ :src =" zoomedImage"
55
+ ref =" zoomedImg"
56
+ class =" max-w-full max-h-full rounded-lg object-contain cursor-grab"
57
+ />
58
+ </div >
28
59
29
60
<div class =" flex flex-col items-center justify-center w-full relative" >
30
61
<div
144
175
145
176
<script setup lang="ts">
146
177
147
- import { ref , onMounted , nextTick , Ref , h , computed } from ' vue'
178
+ import { ref , onMounted , nextTick , Ref , h , computed , watch , reactive } from ' vue'
148
179
import { Carousel } from ' flowbite' ;
149
180
import { callAdminForthApi } from ' @/utils' ;
150
181
import { useI18n } from ' vue-i18n' ;
@@ -158,6 +189,7 @@ const emit = defineEmits(['close', 'uploadImage']);
158
189
const props = defineProps ([' meta' , ' record' ]);
159
190
const images = ref ([]);
160
191
const loading = ref (false );
192
+ const attachmentFiles = ref <string []>([])
161
193
162
194
function minifyField(field : string ): string {
163
195
if (field .length > 100 ) {
@@ -167,7 +199,7 @@ function minifyField(field: string): string {
167
199
}
168
200
169
201
const caurosel = ref (null );
170
- onMounted (() => {
202
+ onMounted (async () => {
171
203
// Initialize carousel
172
204
const context = {
173
205
field: props .meta .pathColumnLabel ,
@@ -203,7 +235,24 @@ onMounted(() => {
203
235
prompt .value = template .replace (regex , (_ , field ) => {
204
236
return context [field .trim ()] || ' ' ;
205
237
});
238
+
239
+ const recordId = props .record [props .meta .recorPkFieldName ];
240
+ if (! recordId ) return ;
241
+
242
+ try {
243
+ const resp = await callAdminForthApi ({
244
+ path: ` /plugin/${props .meta .pluginInstanceId }/get_attachment_files ` ,
245
+ method: ' POST' ,
246
+ body: { recordId },
247
+ });
206
248
249
+ if (resp ?.files ?.length ) {
250
+ attachmentFiles .value = resp .files ;
251
+ console .log (' attachmentFiles' , attachmentFiles .value );
252
+ }
253
+ } catch (err ) {
254
+ console .error (' Failed to fetch attachment files' , err );
255
+ }
207
256
});
208
257
209
258
async function slide(direction : number ) {
@@ -357,6 +406,27 @@ async function generateImages() {
357
406
loading .value = false ;
358
407
}
359
408
409
+ import mediumZoom from ' medium-zoom'
360
410
411
+ const zoomedImage = ref (null )
412
+ const zoomedImg = ref (null )
413
+
414
+ function zoomImage(img ) {
415
+ zoomedImage .value = img
416
+ }
361
417
418
+ function closeZoom() {
419
+ zoomedImage .value = null
420
+ }
421
+
422
+ watch (zoomedImage , async (val ) => {
423
+ await nextTick ()
424
+ if (val && zoomedImg .value ) {
425
+ mediumZoom (zoomedImg .value , {
426
+ margin: 24 ,
427
+ background: ' rgba(0, 0, 0, 0.9)' ,
428
+ scrollOffset: 150
429
+ }).show ()
430
+ }
431
+ })
362
432
</script >
0 commit comments