Files
dbx/apps/desktop/src/components/generate/params/BarcodeParams.vue
T

105 lines
3.6 KiB
Vue

<script setup lang="ts">
import { computed, ref } from "vue";
import { Button } from "@/components/ui/button";
import { RefreshCw } from "@lucide/vue";
import type { GeneratorParams } from "@/lib/dataGrid/dataGenerate";
import CommonOptions from "./CommonOptions.vue";
import { useI18n } from "vue-i18n";
const props = defineProps<{ params: GeneratorParams }>();
const { t } = useI18n();
const barcodeTypes = [
{ value: "ean8", label: "EAN8", regex: "[0-9]{8}" },
{ value: "ean13", label: "EAN13", regex: "[0-9]{13}" },
{ value: "upca", label: "UPCA", regex: "[0-9]{12}" },
{ value: "upce", label: "UPCE", regex: "[0-9]{6}" },
{ value: "isbn", label: "ISBN", regex: "[0-9]{13}" },
{ value: "code39", label: "Code39", regex: "[A-Z]{3}-[0-9]{4}" },
];
if (!props.params.barcodeTypes) {
props.params.barcodeTypes = ["ean13"];
}
function pick<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
function randDigits(n: number): string {
return Array.from({ length: n }, () => Math.floor(Math.random() * 10).toString()).join("");
}
function generateByType(type: string): string {
switch (type) {
case "ean8":
return randDigits(8);
case "ean13":
return randDigits(13);
case "upca":
return randDigits(12);
case "upce":
return randDigits(6);
case "isbn":
return `978${randDigits(10)}`;
case "code39": {
const letters = Array.from({ length: 3 }, () => String.fromCharCode(65 + Math.floor(Math.random() * 26))).join("");
return `${letters}-${randDigits(4)}`;
}
default:
return randDigits(13);
}
}
function toggleBarcode(val: string) {
if (!props.params.barcodeTypes) props.params.barcodeTypes = [];
const idx = props.params.barcodeTypes.indexOf(val);
if (idx >= 0) props.params.barcodeTypes.splice(idx, 1);
else props.params.barcodeTypes.push(val);
}
const currentRegex = computed(() => {
if (!props.params.barcodeTypes?.length) return "";
const chosen = pick(props.params.barcodeTypes);
const bt = barcodeTypes.find((b) => b.value === chosen);
return bt?.regex ?? "";
});
const previewKey = ref(0);
const previewVal = computed(() => {
void previewKey.value;
const selected = props.params.barcodeTypes?.length ? props.params.barcodeTypes : ["ean13"];
return generateByType(pick(selected));
});
function refresh() {
previewKey.value++;
}
</script>
<template>
<div class="space-y-3">
<div class="rounded-md border bg-muted/10 p-3">
<div class="text-xs text-muted-foreground mb-2">{{ t("dataGenerate.typeLabel") }}</div>
<div class="flex flex-wrap gap-1.5">
<button v-for="b in barcodeTypes" :key="b.value" type="button" class="px-2 py-1 rounded border text-xs" :class="(params.barcodeTypes ?? []).includes(b.value) ? 'bg-primary text-primary-foreground border-primary' : 'bg-background'" @click="toggleBarcode(b.value)">{{ b.label }}</button>
</div>
</div>
<div class="rounded-md border bg-muted/10 p-3">
<div class="text-xs text-muted-foreground mb-1">{{ t("dataGenerate.regex") }}</div>
<div class="font-mono text-xs bg-background rounded border px-2 py-1 break-all">{{ currentRegex }}</div>
</div>
<div class="rounded-md border bg-muted/10 p-3">
<div class="flex items-center gap-2 text-xs">
<span class="text-muted-foreground shrink-0">{{ t("dataGenerate.preview") }}</span>
<span :key="previewKey" class="font-mono text-sm">{{ previewVal }}</span>
<Button variant="ghost" size="icon" class="h-5 w-5 ml-auto" @click="refresh">
<RefreshCw class="h-3 w-3" />
</Button>
</div>
</div>
<CommonOptions :params="params" />
</div>
</template>