@@ -7,6 +7,7 @@ export interface BulkCanvasItem {
77 featureImage : string
88 title : string
99 subtitle : string
10+ fileTitle : string
1011 params : Record < string , string >
1112 previewHtml : string
1213 selected : boolean
@@ -25,11 +26,23 @@ interface TemplateInfo {
2526let nextId = 1
2627function uid ( ) { return `bulk-${ nextId ++ } ` }
2728
29+ // Remove Vietnamese diacritics and slugify
30+ function slugify ( text : string ) : string {
31+ return text
32+ . normalize ( 'NFD' ) . replace ( / [ \u0300 - \u036f ] / g, '' )
33+ . replace ( / [ đ Đ ] / g, 'd' )
34+ . toLowerCase ( )
35+ . replace ( / [ ^ a - z 0 - 9 ] + / g, '-' )
36+ . replace ( / ^ - | - $ / g, '' )
37+ || 'banner'
38+ }
39+
2840export function useBulkCanvas ( ) {
2941 const mediaStore = useMediaStore ( )
3042
3143 const templates = ref < TemplateInfo [ ] > ( [ ] )
3244 const selectedTemplateId = ref ( '' )
45+ const globalTitle = ref ( '' )
3346 const items = ref < BulkCanvasItem [ ] > ( [ ] )
3447 const editingItemId = ref < string | null > ( null )
3548 const renderQueue = ref ( 0 )
@@ -57,13 +70,20 @@ export function useBulkCanvas() {
5770 featureImage,
5871 title,
5972 subtitle : '' ,
73+ fileTitle : '' ,
6074 params : { } ,
6175 previewHtml : '' ,
6276 selected : true ,
6377 loading : false ,
6478 }
6579 }
6680
81+ // Generate export filename for an item at given index (1-based)
82+ function exportFilename ( item : BulkCanvasItem , index : number ) : string {
83+ const base = slugify ( item . fileTitle || globalTitle . value )
84+ return `${ base } -${ index } .png`
85+ }
86+
6787 async function addImages ( files : File [ ] ) {
6888 const uploads = files . map ( async ( file ) => {
6989 const media = await mediaStore . uploadFile ( file )
@@ -140,7 +160,8 @@ export function useBulkCanvas() {
140160 const item = items . value . find ( i => i . id === id )
141161 if ( ! item ) return
142162
143- // Handle special keys
163+ // Handle special keys — auto-slugify fileTitle
164+ if ( key === 'fileTitle' ) { item . fileTitle = slugify ( value ) ; return }
144165 if ( key === 'title' ) item . title = value
145166 else if ( key === 'subtitle' ) item . subtitle = value
146167 else if ( key === 'feature_image' ) item . featureImage = value
@@ -182,11 +203,12 @@ export function useBulkCanvas() {
182203
183204 return {
184205 templates, selectedTemplateId, selectedTemplate,
206+ globalTitle,
185207 items, editingItemId, editingItem, renderQueue,
186208 loadTemplates,
187209 addImages, addImageUrls, removeItem,
188210 renderItem, renderAll,
189- updateItemParam,
211+ updateItemParam, exportFilename ,
190212 toggleItem, selectAll, deselectAll, toggleSelectAll, selectedItems,
191213 openEditor, closeEditor,
192214 }
0 commit comments