Skip to content

Commit fef1993

Browse files
committed
feat(new tools): Barcode Reader and Generator
Fix CorentinTh#437 and CorentinTh#805
1 parent e876d03 commit fef1993

File tree

9 files changed

+297
-10
lines changed

9 files changed

+297
-10
lines changed

components.d.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ declare module '@vue/runtime-core' {
1313
About: typeof import('./src/pages/About.vue')['default']
1414
App: typeof import('./src/App.vue')['default']
1515
AsciiTextDrawer: typeof import('./src/tools/ascii-text-drawer/ascii-text-drawer.vue')['default']
16+
BarcodeGenerator: typeof import('./src/tools/barcode-generator/barcode-generator.vue')['default']
17+
BarcodeReader: typeof import('./src/tools/barcode-reader/barcode-reader.vue')['default']
1618
'Base.layout': typeof import('./src/layouts/base.layout.vue')['default']
1719
Base64FileConverter: typeof import('./src/tools/base64-file-converter/base64-file-converter.vue')['default']
1820
Base64StringConverter: typeof import('./src/tools/base64-string-converter/base64-string-converter.vue')['default']
@@ -127,24 +129,25 @@ declare module '@vue/runtime-core' {
127129
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
128130
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
129131
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
132+
NCheckbox: typeof import('naive-ui')['NCheckbox']
130133
NCode: typeof import('naive-ui')['NCode']
131134
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
135+
NColorPicker: typeof import('naive-ui')['NColorPicker']
132136
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
133137
NDivider: typeof import('naive-ui')['NDivider']
134138
NEllipsis: typeof import('naive-ui')['NEllipsis']
139+
NForm: typeof import('naive-ui')['NForm']
135140
NFormItem: typeof import('naive-ui')['NFormItem']
136141
NGi: typeof import('naive-ui')['NGi']
137142
NGrid: typeof import('naive-ui')['NGrid']
138143
NH1: typeof import('naive-ui')['NH1']
139144
NH3: typeof import('naive-ui')['NH3']
140145
NIcon: typeof import('naive-ui')['NIcon']
141146
NInputNumber: typeof import('naive-ui')['NInputNumber']
142-
NLabel: typeof import('naive-ui')['NLabel']
143147
NLayout: typeof import('naive-ui')['NLayout']
144148
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
145149
NMenu: typeof import('naive-ui')['NMenu']
146150
NScrollbar: typeof import('naive-ui')['NScrollbar']
147-
NSpin: typeof import('naive-ui')['NSpin']
148151
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
149152
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
150153
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"release": "node ./scripts/release.mjs"
3636
},
3737
"dependencies": {
38+
"@chenfengyuan/vue-barcode": "^2.0.2",
3839
"@it-tools/bip39": "^0.0.4",
3940
"@it-tools/oggen": "^1.3.0",
4041
"@sindresorhus/slugify": "^2.2.1",
@@ -47,6 +48,7 @@
4748
"@vueuse/core": "^10.3.0",
4849
"@vueuse/head": "^1.0.0",
4950
"@vueuse/router": "^10.0.0",
51+
"@zxing/library": "^0.21.0",
5052
"bcryptjs": "^2.4.3",
5153
"change-case": "^4.1.2",
5254
"colord": "^2.9.3",
@@ -64,6 +66,7 @@
6466
"highlight.js": "^11.7.0",
6567
"iarna-toml-esm": "^3.0.5",
6668
"ibantools": "^4.3.3",
69+
"jsbarcode": "^3.11.6",
6770
"json5": "^2.2.3",
6871
"jwt-decode": "^3.1.2",
6972
"libphonenumber-js": "^1.10.28",

pnpm-lock.yaml

Lines changed: 50 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/composable/queryParams.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useRouteQuery } from '@vueuse/router';
22
import { computed } from 'vue';
3+
import { useStorage } from '@vueuse/core';
34

4-
export { useQueryParam };
5+
export { useQueryParam, useQueryParamOrStorage };
56

67
const transformers = {
78
number: {
@@ -33,3 +34,31 @@ function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue:
3334
},
3435
});
3536
}
37+
38+
function useQueryParamOrStorage<T>({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) {
39+
const type = typeof defaultValue;
40+
const transformer = transformers[type as keyof typeof transformers] ?? transformers.string;
41+
42+
const storageRef = useStorage(storageName, defaultValue);
43+
const storageDefaultValue = storageRef.value ?? defaultValue;
44+
45+
const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never));
46+
47+
const ref = computed<T>({
48+
get() {
49+
return transformer.fromQuery(proxy.value) as unknown as T;
50+
},
51+
set(value) {
52+
proxy.value = transformer.toQuery(value as never);
53+
},
54+
});
55+
56+
watch(
57+
ref,
58+
(newValue) => {
59+
storageRef.value = newValue;
60+
},
61+
);
62+
63+
return ref;
64+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<script setup lang="ts">
2+
import VueBarcode from '@chenfengyuan/vue-barcode';
3+
import JsBarcode from 'jsbarcode';
4+
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
5+
import { useQueryParamOrStorage } from '@/composable/queryParams';
6+
7+
const foreground = useQueryParamOrStorage({ name: 'fg', storageName: 'barcode-gen:fg', defaultValue: '#000000ff' });
8+
const background = useQueryParamOrStorage({ name: 'bg', storageName: 'barcode-gen:bg', defaultValue: '#ffffffff' });
9+
const width = useQueryParamOrStorage({ name: 'width', storageName: 'barcode-gen:width', defaultValue: 2 });
10+
const height = useQueryParamOrStorage({ name: 'height', storageName: 'barcode-gen:height', defaultValue: 100 });
11+
const margin = useQueryParamOrStorage({ name: 'margin', storageName: 'barcode-gen:margin', defaultValue: 10 });
12+
const format = useQueryParamOrStorage({ name: 'format', storageName: 'barcode-gen:format', defaultValue: 'auto' });
13+
const displayValue = useQueryParamOrStorage({ name: 'display', storageName: 'barcode-gen:display', defaultValue: true });
14+
const ean128 = useQueryParamOrStorage({ name: 'ean128', storageName: 'barcode-gen:ean128', defaultValue: false });
15+
const value = ref('123456789');
16+
17+
const options = computed(() => ({
18+
lineColor: foreground.value,
19+
background: background.value,
20+
width: width.value,
21+
height: height.value,
22+
margin: margin.value,
23+
format: format.value === 'auto' ? 'CODE128' : format.value,
24+
displayValue: displayValue.value,
25+
ean128: ean128.value,
26+
text: value.value,
27+
}));
28+
29+
const formats = [
30+
'auto',
31+
'CODE39',
32+
'CODE128', 'CODE128A', 'CODE128B', 'CODE128C',
33+
'EAN13', 'EAN8', 'EAN5', 'EAN2', 'UPC', 'UPCE',
34+
'ITF14',
35+
'ITF',
36+
'MSI', 'MSI10', 'MSI11', 'MSI1010', 'MSI1110',
37+
'pharmacode',
38+
'codabar',
39+
'GenericBarcode',
40+
];
41+
42+
const barcodePNG = computed(() => {
43+
const canvas = document.createElement('canvas');
44+
JsBarcode(canvas, value.value, options.value);
45+
return canvas.toDataURL('image/png');
46+
});
47+
48+
const { download } = useDownloadFileFromBase64({ source: barcodePNG, filename: 'barcode.png' });
49+
</script>
50+
51+
<template>
52+
<c-card>
53+
<n-grid x-gap="12" y-gap="12" cols="1 600:3">
54+
<n-gi span="2">
55+
<c-input-text
56+
v-model:value="value"
57+
label-position="left"
58+
label-width="130px"
59+
label-align="right"
60+
label="Text:"
61+
multiline
62+
rows="1"
63+
autosize
64+
placeholder="Your text..."
65+
mb-6
66+
/>
67+
<n-form label-width="130" label-placement="left">
68+
<n-form-item label="Foreground color:">
69+
<n-color-picker v-model:value="foreground" :modes="['hex']" />
70+
</n-form-item>
71+
<n-form-item label="Background color:">
72+
<n-color-picker v-model:value="background" :modes="['hex']" />
73+
</n-form-item>
74+
<n-form-item label="Width:">
75+
<n-input-number v-model:value="width" :min="0" />
76+
</n-form-item>
77+
<n-form-item label="Height:">
78+
<n-input-number v-model:value="height" :min="0" />
79+
</n-form-item>
80+
<n-form-item label="Margin:">
81+
<n-input-number v-model:value="margin" :min="0" />
82+
</n-form-item>
83+
<n-form-item label="Display text:">
84+
<n-checkbox v-model:checked="displayValue" />
85+
</n-form-item>
86+
<c-select
87+
v-model:value="format"
88+
label="Format:"
89+
label-position="left"
90+
label-width="130px"
91+
label-align="right"
92+
:options="formats.map((value) => ({ label: value, value }))"
93+
/>
94+
</n-form>
95+
</n-gi>
96+
<n-gi>
97+
<div flex flex-col items-center gap-3>
98+
<VueBarcode
99+
:options="options"
100+
:value="value"
101+
/>
102+
<c-button @click="download">
103+
Download barcode
104+
</c-button>
105+
</div>
106+
</n-gi>
107+
</n-grid>
108+
</c-card>
109+
</template>

src/tools/barcode-generator/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Barcode } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Barcode Generator',
6+
path: '/barcode-generator',
7+
description: 'Barcode generator',
8+
keywords: ['barcode', 'generator'],
9+
component: () => import('./barcode-generator.vue'),
10+
icon: Barcode,
11+
createdAt: new Date('2024-04-20'),
12+
});

0 commit comments

Comments
 (0)