fix: Corregir configuración de estilos y componentes
- Agregar imports de Tailwind CSS v4 y Nuxt UI en main.css - Renombrar QueueActions.vue -> Actions.vue y QueueItem.vue -> Item.vue para evitar conflictos de nombres de componentes - Crear composable useMediaQuery para manejo de responsive - Corregir referencias a componentes en index.vue y PrintQueue.vue - Actualizar imports de servidor a rutas relativas - Instalar @iconify-json/heroicons y @iconify-json/lucide - Actualizar Jimp a sintaxis v1.x
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
@import "@nuxt/ui";
|
||||||
|
|
||||||
/* Safe area para PWA en iOS */
|
/* Safe area para PWA en iOS */
|
||||||
.safe-area-bottom {
|
.safe-area-bottom {
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
@@ -19,11 +22,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
@apply bg-gray-300 dark:bg-gray-700 rounded-full;
|
background: rgb(209 213 219); /* gray-300 */
|
||||||
|
border-radius: 9999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
@apply bg-gray-400 dark:bg-gray-600;
|
background: rgb(156 163 175); /* gray-400 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark ::-webkit-scrollbar-thumb {
|
||||||
|
background: rgb(55 65 81); /* gray-700 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark ::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgb(75 85 99); /* gray-600 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset básico */
|
/* Reset básico */
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const queue = usePrintQueue()
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TransitionGroup name="list" tag="div" class="space-y-2">
|
<TransitionGroup name="list" tag="div" class="space-y-2">
|
||||||
<QueueQueueItem
|
<QueueItem
|
||||||
v-for="(op, index) in queue.operations.value"
|
v-for="(op, index) in queue.operations.value"
|
||||||
:key="index"
|
:key="index"
|
||||||
:operation="op"
|
:operation="op"
|
||||||
|
|||||||
20
app/composables/useMediaQuery.ts
Normal file
20
app/composables/useMediaQuery.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export function useMediaQuery(query: string) {
|
||||||
|
const matches = ref(false)
|
||||||
|
|
||||||
|
if (import.meta.client) {
|
||||||
|
const mediaQuery = window.matchMedia(query)
|
||||||
|
matches.value = mediaQuery.matches
|
||||||
|
|
||||||
|
const handler = (e: MediaQueryListEvent) => {
|
||||||
|
matches.value = e.matches
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaQuery.addEventListener('change', handler)
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
mediaQuery.removeEventListener('change', handler)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ const queue = usePrintQueue()
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 border-t border-gray-200 dark:border-gray-800">
|
<div class="p-4 border-t border-gray-200 dark:border-gray-800">
|
||||||
<QueueQueueActions />
|
<QueueActions />
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ const queue = usePrintQueue()
|
|||||||
|
|
||||||
<template v-else-if="activeTab === 'queue'">
|
<template v-else-if="activeTab === 'queue'">
|
||||||
<QueuePrintQueue />
|
<QueuePrintQueue />
|
||||||
<QueueQueueActions class="mt-4" />
|
<QueueActions class="mt-4" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="activeTab === 'templates'">
|
<template v-else-if="activeTab === 'templates'">
|
||||||
|
|||||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -14,6 +14,10 @@
|
|||||||
"nuxt": "^4.2.1",
|
"nuxt": "^4.2.1",
|
||||||
"vue": "^3.5.24",
|
"vue": "^3.5.24",
|
||||||
"vue-router": "^4.6.3"
|
"vue-router": "^4.6.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@iconify-json/heroicons": "^1.2.3",
|
||||||
|
"@iconify-json/lucide": "^1.2.75"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ai-sdk/gateway": {
|
"node_modules/@ai-sdk/gateway": {
|
||||||
@@ -2236,6 +2240,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@iconify-json/heroicons": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@iconify-json/heroicons/-/heroicons-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-n+vmCEgTesRsOpp5AB5ILB6srsgsYK+bieoQBNlafvoEhjVXLq8nIGN4B0v/s4DUfa0dOrjwE/cKJgIKdJXOEg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@iconify/types": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@iconify-json/lucide": {
|
||||||
|
"version": "1.2.75",
|
||||||
|
"resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.75.tgz",
|
||||||
|
"integrity": "sha512-sWBN0t/rTo1FxWG/46xKgkIcDerHpsjyNgMH48nvtC4/kUG88sFQXI+7mxX3SD8eSUaQQ2kS9C7ZKWm2DKgBlw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@iconify/types": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@iconify/collections": {
|
"node_modules/@iconify/collections": {
|
||||||
"version": "1.0.616",
|
"version": "1.0.616",
|
||||||
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.616.tgz",
|
"resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.616.tgz",
|
||||||
|
|||||||
@@ -17,5 +17,9 @@
|
|||||||
"nuxt": "^4.2.1",
|
"nuxt": "^4.2.1",
|
||||||
"vue": "^3.5.24",
|
"vue": "^3.5.24",
|
||||||
"vue-router": "^4.6.3"
|
"vue-router": "^4.6.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@iconify-json/heroicons": "^1.2.3",
|
||||||
|
"@iconify-json/lucide": "^1.2.75"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Endpoint para cortar papel
|
// Endpoint para cortar papel
|
||||||
import { buildFromOperations } from '~/server/utils/eposBuilder'
|
import { buildFromOperations } from '../../utils/eposBuilder'
|
||||||
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '~/server/utils/printer'
|
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Endpoint para imprimir imágenes usando Jimp
|
// Endpoint para imprimir imágenes usando Jimp
|
||||||
import Jimp from 'jimp'
|
import { Jimp } from 'jimp'
|
||||||
import { EposMessageBuilder } from '~/server/utils/eposBuilder'
|
import { EposMessageBuilder } from '../../utils/eposBuilder'
|
||||||
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '~/server/utils/printer'
|
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
@@ -29,14 +29,15 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
// Leer y procesar imagen
|
// Leer y procesar imagen
|
||||||
const img = await Jimp.read(path)
|
const img = await Jimp.read(path)
|
||||||
let targetWidth = width || img.bitmap.width
|
let targetWidth = width || img.width
|
||||||
if (targetWidth <= 0) targetWidth = img.bitmap.width
|
if (targetWidth <= 0) targetWidth = img.width
|
||||||
|
|
||||||
const scale = targetWidth / img.bitmap.width
|
const scale = targetWidth / img.width
|
||||||
const targetHeight = Math.max(1, Math.round(img.bitmap.height * scale))
|
const targetHeight = Math.max(1, Math.round(img.height * scale))
|
||||||
|
|
||||||
img.resize(targetWidth, targetHeight, Jimp.RESIZE_BILINEAR)
|
// Resize y convertir a escala de grises
|
||||||
img.grayscale()
|
img.resize({ w: targetWidth, h: targetHeight })
|
||||||
|
img.greyscale()
|
||||||
|
|
||||||
// Empaquetar bits MSB first por byte
|
// Empaquetar bits MSB first por byte
|
||||||
const bytesPerRow = Math.ceil(targetWidth / 8)
|
const bytesPerRow = Math.ceil(targetWidth / 8)
|
||||||
@@ -49,13 +50,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
let rowBytes = 0
|
let rowBytes = 0
|
||||||
|
|
||||||
for (let x = 0; x < targetWidth; x++) {
|
for (let x = 0; x < targetWidth; x++) {
|
||||||
const idx = (y * targetWidth + x) * 4
|
const color = img.getPixelColor(x, y)
|
||||||
const rgba = img.bitmap.data
|
// Extraer componente rojo (ya es greyscale, todos los canales son iguales)
|
||||||
const r = rgba[idx]
|
const r = (color >> 24) & 0xFF
|
||||||
const g = rgba[idx + 1]
|
const isBlack = r < threshold
|
||||||
const b = rgba[idx + 2]
|
|
||||||
const lum = 0.299 * r + 0.587 * g + 0.114 * b
|
|
||||||
const isBlack = lum < threshold
|
|
||||||
|
|
||||||
if (isBlack) byte |= (1 << bit)
|
if (isBlack) byte |= (1 << bit)
|
||||||
bit--
|
bit--
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Endpoint genérico de impresión que acepta una lista de operaciones
|
// Endpoint genérico de impresión que acepta una lista de operaciones
|
||||||
import { buildFromOperations, type Operation } from '~/server/utils/eposBuilder'
|
import { buildFromOperations, type Operation } from '../../utils/eposBuilder'
|
||||||
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '~/server/utils/printer'
|
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Endpoint para abrir cajón de dinero
|
// Endpoint para abrir cajón de dinero
|
||||||
import { buildFromOperations } from '~/server/utils/eposBuilder'
|
import { buildFromOperations } from '../../utils/eposBuilder'
|
||||||
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '~/server/utils/printer'
|
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Endpoint de conveniencia para imprimir texto con opciones
|
// Endpoint de conveniencia para imprimir texto con opciones
|
||||||
import { buildFromOperations, type Operation } from '~/server/utils/eposBuilder'
|
import { buildFromOperations, type Operation } from '../../utils/eposBuilder'
|
||||||
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '~/server/utils/printer'
|
import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user