Skip to content

Commit c8118b0

Browse files
committed
Merge branch 'feat/barcodes' into chore/all-my-stuffs
# Conflicts: # components.d.ts # package.json # pnpm-lock.yaml
2 parents 5413ede + 15f6c91 commit c8118b0

File tree

7 files changed

+216
-23
lines changed

7 files changed

+216
-23
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
},
3838
"dependencies": {
3939
"@github/paste-markdown": "^1.5.3",
40+
"@chenfengyuan/vue-barcode": "^2.0.2",
4041
"@it-tools/bip39": "^0.0.4",
4142
"@it-tools/oggen": "^1.3.0",
4243
"@regexper/render": "^1.0.0",
@@ -52,6 +53,7 @@
5253
"@vueuse/core": "^10.3.0",
5354
"@vueuse/head": "^1.0.0",
5455
"@vueuse/router": "^10.0.0",
56+
"@zxing/library": "^0.21.0",
5557
"bcryptjs": "^2.4.3",
5658
"change-case": "^4.1.2",
5759
"chatgpt-prompt-splitter": "^1.0.5",
@@ -71,7 +73,8 @@
7173
"highlight.js": "^11.7.0",
7274
"iarna-toml-esm": "^3.0.5",
7375
"ibantools": "^4.3.3",
74-
"js-base64": "^3.7.6",
76+
"js-base64": "^3.7.7",
77+
"jsbarcode": "^3.11.6",
7578
"json5": "^2.2.3",
7679
"jwt-decode": "^3.1.2",
7780
"libphonenumber-js": "^1.10.28",

pnpm-lock.yaml

Lines changed: 3 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
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+
});
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<script setup lang="ts">
2+
import { BarcodeFormat, BrowserMultiFormatReader } from '@zxing/library';
3+
import TextareaCopyable from '@/components/TextareaCopyable.vue';
4+
5+
const imageBase64 = ref('');
6+
const barCode = computedAsync(async () => {
7+
if (imageBase64.value === '') {
8+
return { text: '', format: '', error: '' };
9+
}
10+
try {
11+
const barcodeReader = new BrowserMultiFormatReader();
12+
const result = (await barcodeReader.decodeFromImageUrl(imageBase64.value));
13+
return { text: result.getText(), format: BarcodeFormat[result.getBarcodeFormat()], error: '' };
14+
}
15+
catch (e: any) {
16+
return { error: e.toString(), text: '', format: '' };
17+
}
18+
});
19+
20+
function blobToBase64(blob: Blob) {
21+
if (blob === null) {
22+
return Promise.resolve('');
23+
}
24+
return new Promise<string>((resolve, _reject) => {
25+
const reader = new FileReader();
26+
reader.onloadend = () => resolve(reader.result as string);
27+
reader.readAsDataURL(blob);
28+
});
29+
}
30+
31+
async function onUpload(file: File) {
32+
if (file) {
33+
imageBase64.value = await blobToBase64(file);
34+
}
35+
}
36+
</script>
37+
38+
<template>
39+
<div>
40+
<c-file-upload
41+
title="Drag and drop a BarCode here, or click to select a file"
42+
:paste-image="true"
43+
mb-3
44+
@file-upload="onUpload"
45+
/>
46+
47+
<div v-if="barCode?.text">
48+
<n-divider />
49+
50+
<h3>Decoded <span v-if="barCode?.format">({{ barCode?.format }})</span></h3>
51+
<TextareaCopyable
52+
:value="barCode?.text"
53+
:word-wrap="true"
54+
/>
55+
</div>
56+
<c-alert v-if="barCode?.error">
57+
{{ barCode?.error }}
58+
</c-alert>
59+
</div>
60+
</template>
61+
62+
<style lang="less" scoped>
63+
::v-deep(.n-upload-trigger) {
64+
width: 100%;
65+
}
66+
</style>

src/tools/barcode-reader/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 Reader',
6+
path: '/barcode-reader',
7+
description: 'Barcode reader',
8+
keywords: ['barcode', 'reader'],
9+
component: () => import('./barcode-reader.vue'),
10+
icon: Barcode,
11+
createdAt: new Date('2024-04-20'),
12+
});

src/tools/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ import { tool as uuidGenerator } from './uuid-generator';
9090
import { tool as macAddressLookup } from './mac-address-lookup';
9191
import { tool as xmlFormatter } from './xml-formatter';
9292
import { tool as yamlViewer } from './yaml-viewer';
93+
import { tool as barcodeReader } from './barcode-reader';
94+
import { tool as barcodeGenerator } from './barcode-generator';
9395

9496
export const toolsByCategory: ToolCategory[] = [
9597
{
@@ -145,7 +147,14 @@ export const toolsByCategory: ToolCategory[] = [
145147
},
146148
{
147149
name: 'Images and videos',
148-
components: [qrCodeGenerator, wifiQrCodeGenerator, svgPlaceholderGenerator, cameraRecorder],
150+
components: [
151+
qrCodeGenerator,
152+
wifiQrCodeGenerator,
153+
svgPlaceholderGenerator,
154+
cameraRecorder,
155+
barcodeReader,
156+
barcodeGenerator,
157+
],
149158
},
150159
{
151160
name: 'Development',

0 commit comments

Comments
 (0)