- Nuevo layout responsivo mobile-first con tabs inferiores - Sidebar colapsable en desktop con cola de impresión - Sistema de templates reutilizables con localStorage - Soporte Dark/Light mode con UColorModeButton - Composables usePrintQueue y useTemplates para estado global - Componentes modulares: CommandBuilder, QuickActions, PrintQueue, QueueItem - Navegación por tabs: Constructor | Cola | Templates
188 lines
5.7 KiB
Vue
188 lines
5.7 KiB
Vue
<script setup lang="ts">
|
|
const queue = usePrintQueue()
|
|
|
|
// Estado del formulario
|
|
const text = ref('')
|
|
const align = ref('')
|
|
const font = ref('')
|
|
const width = ref<number | undefined>()
|
|
const height = ref<number | undefined>()
|
|
const bold = ref(false)
|
|
const underline = ref(false)
|
|
const reverse = ref(false)
|
|
const smooth = ref(false)
|
|
const color = ref('')
|
|
const feedLines = ref<number | undefined>()
|
|
const cut = ref('')
|
|
|
|
// Opciones para selects
|
|
const alignOptions = [
|
|
{ label: '(sin cambio)', value: '' },
|
|
{ label: 'Izquierda', value: 'left' },
|
|
{ label: 'Centro', value: 'center' },
|
|
{ label: 'Derecha', value: 'right' }
|
|
]
|
|
|
|
const fontOptions = [
|
|
{ label: '(sin cambio)', value: '' },
|
|
{ label: 'Font A', value: 'font_a' },
|
|
{ label: 'Font B', value: 'font_b' },
|
|
{ label: 'Font C', value: 'font_c' },
|
|
{ label: 'Font D', value: 'font_d' },
|
|
{ label: 'Font E', value: 'font_e' },
|
|
{ label: 'Special A', value: 'special_a' },
|
|
{ label: 'Special B', value: 'special_b' }
|
|
]
|
|
|
|
const colorOptions = [
|
|
{ label: '(default)', value: '' },
|
|
{ label: 'Color 1', value: 'color_1' },
|
|
{ label: 'Color 2', value: 'color_2' },
|
|
{ label: 'Color 3', value: 'color_3' },
|
|
{ label: 'Color 4', value: 'color_4' }
|
|
]
|
|
|
|
const cutOptions = [
|
|
{ label: '(no cortar)', value: '' },
|
|
{ label: 'Sin feed', value: 'no_feed' },
|
|
{ label: 'Con feed', value: 'feed' },
|
|
{ label: 'Reservar', value: 'reserve' },
|
|
{ label: 'Full sin feed', value: 'no_feed_fullcut' },
|
|
{ label: 'Full con feed', value: 'feed_fullcut' },
|
|
{ label: 'Full reservar', value: 'reserve_fullcut' }
|
|
]
|
|
|
|
const formatSections = [
|
|
{ label: 'Alineación y Fuente', value: 'alignment', icon: 'i-heroicons-bars-3-bottom-left' },
|
|
{ label: 'Tamaño', value: 'size', icon: 'i-heroicons-arrows-pointing-out' },
|
|
{ label: 'Estilo', value: 'style', icon: 'i-heroicons-paint-brush' },
|
|
{ label: 'Acciones finales', value: 'actions', icon: 'i-heroicons-scissors' }
|
|
]
|
|
|
|
function resetForm() {
|
|
text.value = ''
|
|
align.value = ''
|
|
font.value = ''
|
|
width.value = undefined
|
|
height.value = undefined
|
|
bold.value = false
|
|
underline.value = false
|
|
reverse.value = false
|
|
smooth.value = false
|
|
color.value = ''
|
|
feedLines.value = undefined
|
|
cut.value = ''
|
|
}
|
|
|
|
function queueText() {
|
|
const ops: any[] = []
|
|
|
|
if (align.value) ops.push({ op: 'textAlign', align: align.value })
|
|
if (font.value) ops.push({ op: 'textFont', font: font.value })
|
|
if (width.value || height.value) {
|
|
ops.push({ op: 'textSize', width: width.value, height: height.value })
|
|
}
|
|
ops.push({
|
|
op: 'textStyle',
|
|
em: bold.value,
|
|
ul: underline.value,
|
|
reverse: reverse.value,
|
|
...(color.value ? { color: color.value } : {})
|
|
})
|
|
if (text.value) ops.push({ op: 'text', value: text.value })
|
|
if (feedLines.value != null && feedLines.value !== 0) {
|
|
ops.push({ op: 'feedLine', line: Number(feedLines.value) })
|
|
}
|
|
if (cut.value) ops.push({ op: 'cut', type: cut.value })
|
|
|
|
queue.addOperations(ops)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<UCard>
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
|
Constructor de Comandos
|
|
</h2>
|
|
<UButton
|
|
icon="i-heroicons-arrow-path"
|
|
variant="ghost"
|
|
size="sm"
|
|
@click="resetForm"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Textarea principal -->
|
|
<UFormField label="Texto a imprimir" class="mb-4">
|
|
<UTextarea
|
|
v-model="text"
|
|
:rows="4"
|
|
autoresize
|
|
placeholder="Escribe el texto a imprimir..."
|
|
/>
|
|
</UFormField>
|
|
|
|
<!-- Controles de formato con Accordion -->
|
|
<UAccordion :items="formatSections" type="multiple">
|
|
<template #alignment>
|
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3 p-3">
|
|
<UFormField label="Alineación">
|
|
<USelect v-model="align" :items="alignOptions" placeholder="Seleccionar" />
|
|
</UFormField>
|
|
<UFormField label="Fuente">
|
|
<USelect v-model="font" :items="fontOptions" placeholder="Seleccionar" />
|
|
</UFormField>
|
|
<UFormField label="Color">
|
|
<USelect v-model="color" :items="colorOptions" placeholder="Seleccionar" />
|
|
</UFormField>
|
|
</div>
|
|
</template>
|
|
|
|
<template #size>
|
|
<div class="grid grid-cols-2 gap-3 p-3">
|
|
<UFormField label="Ancho (1-8)">
|
|
<UInput v-model.number="width" type="number" :min="1" :max="8" placeholder="1" />
|
|
</UFormField>
|
|
<UFormField label="Alto (1-8)">
|
|
<UInput v-model.number="height" type="number" :min="1" :max="8" placeholder="1" />
|
|
</UFormField>
|
|
</div>
|
|
</template>
|
|
|
|
<template #style>
|
|
<div class="flex flex-wrap gap-4 p-3">
|
|
<UCheckbox v-model="bold" label="Negrita" />
|
|
<UCheckbox v-model="underline" label="Subrayado" />
|
|
<UCheckbox v-model="reverse" label="Invertido" />
|
|
<UCheckbox v-model="smooth" label="Suavizado" />
|
|
</div>
|
|
</template>
|
|
|
|
<template #actions>
|
|
<div class="grid grid-cols-2 gap-3 p-3">
|
|
<UFormField label="Líneas de feed">
|
|
<UInput v-model.number="feedLines" type="number" :min="0" :max="255" placeholder="0" />
|
|
</UFormField>
|
|
<UFormField label="Corte de papel">
|
|
<USelect v-model="cut" :items="cutOptions" placeholder="Seleccionar" />
|
|
</UFormField>
|
|
</div>
|
|
</template>
|
|
</UAccordion>
|
|
|
|
<template #footer>
|
|
<div class="flex gap-2">
|
|
<UButton color="primary" @click="queueText">
|
|
Agregar a cola
|
|
</UButton>
|
|
<UButton variant="ghost" @click="resetForm">
|
|
Limpiar formulario
|
|
</UButton>
|
|
</div>
|
|
</template>
|
|
</UCard>
|
|
</template>
|