@ramathibodi/nuxt-commons 0.1.73 → 0.1.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -55
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -0
- package/dist/runtime/components/Alert.vue +4 -0
- package/dist/runtime/components/BarcodeReader.vue +8 -0
- package/dist/runtime/components/ExportCSV.vue +13 -5
- package/dist/runtime/components/FileBtn.vue +17 -5
- package/dist/runtime/components/ImportCSV.vue +14 -2
- package/dist/runtime/components/MrzReader.vue +168 -0
- package/dist/runtime/components/SplitterPanel.vue +9 -1
- package/dist/runtime/components/TabsGroup.vue +9 -1
- package/dist/runtime/components/TextBarcode.vue +13 -1
- package/dist/runtime/components/device/IdCardButton.vue +15 -3
- package/dist/runtime/components/device/IdCardWebSocket.vue +18 -6
- package/dist/runtime/components/device/Scanner.vue +18 -6
- package/dist/runtime/components/dialog/Confirm.vue +20 -8
- package/dist/runtime/components/dialog/Host.vue +4 -0
- package/dist/runtime/components/dialog/Index.vue +17 -5
- package/dist/runtime/components/dialog/Loading.vue +14 -2
- package/dist/runtime/components/dialog/default/Confirm.vue +20 -8
- package/dist/runtime/components/dialog/default/Loading.vue +14 -2
- package/dist/runtime/components/dialog/default/Notify.vue +18 -6
- package/dist/runtime/components/dialog/default/Printing.vue +14 -2
- package/dist/runtime/components/dialog/default/VerifyUser.vue +20 -8
- package/dist/runtime/components/document/Form.vue +10 -2
- package/dist/runtime/components/document/TemplateBuilder.vue +14 -2
- package/dist/runtime/components/form/ActionPad.vue +19 -7
- package/dist/runtime/components/form/Birthdate.vue +15 -3
- package/dist/runtime/components/form/CheckboxGroup.vue +17 -5
- package/dist/runtime/components/form/CodeEditor.vue +11 -3
- package/dist/runtime/components/form/Date.vue +23 -11
- package/dist/runtime/components/form/DateTime.vue +29 -17
- package/dist/runtime/components/form/Dialog.vue +21 -9
- package/dist/runtime/components/form/EditPad.vue +20 -8
- package/dist/runtime/components/form/File.vue +18 -6
- package/dist/runtime/components/form/Hidden.vue +15 -3
- package/dist/runtime/components/form/Iterator.vue +43 -31
- package/dist/runtime/components/form/Login.vue +18 -6
- package/dist/runtime/components/form/Pad.vue +24 -12
- package/dist/runtime/components/form/SignPad.vue +13 -5
- package/dist/runtime/components/form/System.vue +10 -2
- package/dist/runtime/components/form/Table.vue +31 -19
- package/dist/runtime/components/form/TableData.vue +21 -9
- package/dist/runtime/components/form/Time.vue +16 -4
- package/dist/runtime/components/form/images/Capture.vue +17 -9
- package/dist/runtime/components/form/images/Edit.vue +16 -4
- package/dist/runtime/components/form/images/Field.vue +21 -10
- package/dist/runtime/components/form/images/Pad.vue +12 -0
- package/dist/runtime/components/label/Date.vue +12 -4
- package/dist/runtime/components/label/DateAgo.vue +13 -5
- package/dist/runtime/components/label/DateCount.vue +13 -5
- package/dist/runtime/components/label/Field.vue +14 -6
- package/dist/runtime/components/label/FormatMoney.vue +11 -3
- package/dist/runtime/components/label/Mask.vue +11 -3
- package/dist/runtime/components/label/Object.vue +11 -3
- package/dist/runtime/components/master/Autocomplete.vue +19 -11
- package/dist/runtime/components/master/Combobox.vue +19 -11
- package/dist/runtime/components/master/RadioGroup.vue +17 -5
- package/dist/runtime/components/master/Select.vue +18 -10
- package/dist/runtime/components/master/label.vue +14 -6
- package/dist/runtime/components/model/Autocomplete.vue +24 -12
- package/dist/runtime/components/model/Combobox.vue +24 -12
- package/dist/runtime/components/model/Pad.vue +15 -3
- package/dist/runtime/components/model/Select.vue +19 -7
- package/dist/runtime/components/model/Table.vue +30 -18
- package/dist/runtime/components/model/iterator.vue +36 -28
- package/dist/runtime/components/model/label.vue +16 -8
- package/dist/runtime/components/pdf/Print.vue +17 -5
- package/dist/runtime/components/pdf/View.vue +18 -6
- package/dist/runtime/composables/alert.d.ts +4 -0
- package/dist/runtime/composables/api.d.ts +4 -0
- package/dist/runtime/composables/document/templateFormHidden.d.ts +4 -0
- package/dist/runtime/composables/localStorageModel.d.ts +4 -0
- package/dist/runtime/composables/lookupList.d.ts +4 -0
- package/dist/runtime/composables/menu.d.ts +4 -0
- package/dist/runtime/composables/useMrzReader.d.ts +48 -0
- package/dist/runtime/composables/useMrzReader.js +423 -0
- package/dist/runtime/composables/useTesseract.d.ts +16 -0
- package/dist/runtime/composables/useTesseract.js +45 -0
- package/dist/runtime/utils/asset.d.ts +2 -0
- package/dist/runtime/utils/asset.js +49 -0
- package/package.json +12 -3
- package/scripts/enrich-vue-docs-from-ai.mjs +197 -0
- package/scripts/generate-ai-summary.mjs +321 -0
- package/scripts/generate-composables-md.mjs +129 -0
- package/templates/public/tesseract/mrz.traineddata.gz +0 -0
- package/templates/public/tesseract/ocrb.traineddata.gz +0 -0
package/README.md
CHANGED
|
@@ -1,45 +1,54 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Get your module up and running quickly.
|
|
3
|
-
|
|
4
|
-
Find and replace all on all files (CMD+SHIFT+F):
|
|
5
|
-
- Name: Ramahis Common Component
|
|
6
|
-
- Package name: @ramahis/common-components
|
|
7
|
-
-->
|
|
8
|
-
|
|
9
1
|
# @ramathibodi/nuxt-commons
|
|
10
2
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
Nuxt 3 module that provides shared runtime building blocks for Rama projects:
|
|
4
|
+
- globally auto-imported UI components
|
|
5
|
+
- auto-imported composables
|
|
6
|
+
- runtime plugins for permission/dialog/default behavior
|
|
7
|
+
- utility and lab exports
|
|
16
8
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
1. Add `'@ramathibodi/nuxt-commons'` dependency to your project
|
|
9
|
+
## Install
|
|
20
10
|
|
|
21
11
|
```bash
|
|
22
|
-
#
|
|
12
|
+
# pnpm
|
|
23
13
|
pnpm add -D @ramathibodi/nuxt-commons
|
|
24
14
|
|
|
25
|
-
#
|
|
15
|
+
# yarn
|
|
26
16
|
yarn add --dev @ramathibodi/nuxt-commons
|
|
27
17
|
|
|
28
|
-
#
|
|
18
|
+
# npm
|
|
29
19
|
npm install --save-dev @ramathibodi/nuxt-commons
|
|
30
20
|
```
|
|
31
21
|
|
|
32
|
-
|
|
22
|
+
## Nuxt Setup
|
|
33
23
|
|
|
34
|
-
```
|
|
24
|
+
```ts
|
|
25
|
+
// nuxt.config.ts
|
|
35
26
|
export default defineNuxtConfig({
|
|
36
|
-
modules: [
|
|
37
|
-
'@ramathibodi/nuxt-commons'
|
|
38
|
-
]
|
|
27
|
+
modules: ['@ramathibodi/nuxt-commons'],
|
|
39
28
|
})
|
|
40
29
|
```
|
|
41
30
|
|
|
42
|
-
|
|
31
|
+
## What The Module Registers
|
|
32
|
+
|
|
33
|
+
Configured in `src/module.ts`:
|
|
34
|
+
- Components from `src/runtime/components` (global + prefixed)
|
|
35
|
+
- Composables from `src/runtime/composables/**` (auto-imported)
|
|
36
|
+
- Plugins:
|
|
37
|
+
- `src/runtime/plugins/permission.ts`
|
|
38
|
+
- `src/runtime/plugins/dialogManager.ts` (client)
|
|
39
|
+
- `src/runtime/plugins/clientConfig.ts` (client)
|
|
40
|
+
- `src/runtime/plugins/default.ts` (client)
|
|
41
|
+
- Type templates from `src/runtime/types/*.d.ts`
|
|
42
|
+
|
|
43
|
+
## Runtime Config
|
|
44
|
+
|
|
45
|
+
This module uses public runtime config at:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
runtimeConfig.public['nuxt-commons']
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Module options are merged into this key by module setup.
|
|
43
52
|
|
|
44
53
|
## Development
|
|
45
54
|
|
|
@@ -47,50 +56,60 @@ That's it! You can now use My Module in your Nuxt app ✨
|
|
|
47
56
|
# Install dependencies
|
|
48
57
|
npm install
|
|
49
58
|
|
|
50
|
-
#
|
|
59
|
+
# Prepare stubs/types
|
|
51
60
|
npm run dev:prepare
|
|
52
61
|
|
|
53
|
-
#
|
|
62
|
+
# Run playground
|
|
54
63
|
npm run dev
|
|
55
64
|
|
|
56
|
-
# Build
|
|
65
|
+
# Build playground
|
|
57
66
|
npm run dev:build
|
|
58
67
|
|
|
59
|
-
#
|
|
68
|
+
# Lint and test
|
|
60
69
|
npm run lint
|
|
61
|
-
|
|
62
|
-
# Run Vitest
|
|
63
70
|
npm run test
|
|
64
|
-
npm run test:watch
|
|
65
|
-
|
|
66
|
-
# Release new version
|
|
67
|
-
npm run release
|
|
68
71
|
```
|
|
69
72
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
- จะส่ง link url มาให้เข้าไปที่ url login npm
|
|
73
|
+
## Documentation
|
|
74
|
+
|
|
75
|
+
Generate documentation artifacts from source:
|
|
75
76
|
|
|
76
|
-
## NPM PUBLISH
|
|
77
77
|
```bash
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
# Vue component API docs (vue-docgen)
|
|
79
|
+
npm run docs:api:components
|
|
80
|
+
|
|
81
|
+
# Composable API docs (typedoc)
|
|
82
|
+
npm run docs:api:composables
|
|
83
|
+
|
|
84
|
+
# Both API docs
|
|
85
|
+
npm run docs:api
|
|
86
|
+
|
|
87
|
+
# AI-focused summary + type index
|
|
88
|
+
npm run docs:ai:summary
|
|
83
89
|
```
|
|
84
90
|
|
|
85
|
-
|
|
86
|
-
[npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
87
|
-
[npm-version-href]: https://npmjs.com/package/my-module
|
|
91
|
+
`docs:api:components` now runs a post-process step that enriches missing prop/event descriptions and missing type/default cells in generated markdown using `docs/ai-summary.json`.
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
[
|
|
93
|
+
Documentation config files:
|
|
94
|
+
- [`docs/vue-docgen.config.cjs`](docs/vue-docgen.config.cjs) for component docs generation
|
|
95
|
+
- [`docs/typedoc.json`](docs/typedoc.json) for composable docs generation
|
|
96
|
+
- [`docs/typedoc.tsconfig.json`](docs/typedoc.tsconfig.json) for docs-only TypeScript scope
|
|
91
97
|
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
Generated outputs:
|
|
99
|
+
- [`docs/components/`](docs/components/) (vue-docgen output)
|
|
100
|
+
- [`docs/composables/`](docs/composables/) (typedoc output)
|
|
101
|
+
- [`docs/ai-summary.md`](docs/ai-summary.md) (compact AI-oriented markdown summary)
|
|
102
|
+
- [`docs/ai-summary.json`](docs/ai-summary.json) (machine-readable component/composable metadata)
|
|
103
|
+
- [`docs/type-index.json`](docs/type-index.json) (type index for tooling/AI pipelines)
|
|
94
104
|
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
`docs:ai:summary` generates:
|
|
106
|
+
- `docs/ai-summary.md`
|
|
107
|
+
- `docs/ai-summary.json`
|
|
108
|
+
- `docs/type-index.json`
|
|
109
|
+
|
|
110
|
+
## Publish Notes
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run dev:build
|
|
114
|
+
npm publish --access public
|
|
115
|
+
```
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* Alert displays runtime alert messages and bridges alert-store entries to a consistent UI variant system.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import { ref, watch } from 'vue'
|
|
3
7
|
import { isEmpty } from 'lodash-es'
|
|
4
8
|
import { useAlert } from '../composables/alert'
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* BarcodeReader starts and stops barcode scans, then emits parsed scan results back to parent workflows.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import {BrowserMultiFormatReader} from '@zxing/browser'
|
|
3
7
|
import {type IScannerControls} from '@zxing/browser/esm'
|
|
4
8
|
import type {Exception, Result} from '@zxing/library'
|
|
@@ -12,6 +16,10 @@ const barcodeReaderControl = ref()
|
|
|
12
16
|
const alert = useAlert()
|
|
13
17
|
const isLoading = ref<boolean>(false)
|
|
14
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Custom events emitted by BarcodeReader.
|
|
21
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
22
|
+
*/
|
|
15
23
|
const emit = defineEmits<{
|
|
16
24
|
(event: 'decode', barcodeValue: string): void
|
|
17
25
|
(event: 'error', error: string | unknown): void
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* ExportCSV exports array data to spreadsheet files, flattening nested fields before file generation.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import { ref } from 'vue'
|
|
3
7
|
import * as XLSX from 'xlsx'
|
|
4
8
|
import { VBtn } from 'vuetify/components/VBtn'
|
|
5
9
|
import { useAlert } from '../composables/alert'
|
|
6
10
|
|
|
7
11
|
interface ExportButtonProps extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
|
|
8
|
-
fileName?: string
|
|
9
|
-
sheetName?: string
|
|
10
|
-
modelValue?: object[]
|
|
11
|
-
stringFields?: Array<string>
|
|
12
|
-
tooltip?: string | Record<string,any> | undefined
|
|
12
|
+
fileName?: string // File name used when downloading or printing generated files.
|
|
13
|
+
sheetName?: string // Configuration option used by ExportCSV.
|
|
14
|
+
modelValue?: object[] // Bound value for v-model synchronization with the parent component.
|
|
15
|
+
stringFields?: Array<string> // Field paths that must stay as string values (no nested object conversion).
|
|
16
|
+
tooltip?: string | Record<string,any> | undefined // Tooltip text or config object shown for the action control.
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Public props accepted by ExportCSV.
|
|
21
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
22
|
+
*/
|
|
15
23
|
const props = withDefaults(defineProps<ExportButtonProps>(), {
|
|
16
24
|
fileName: 'download',
|
|
17
25
|
sheetName: 'Sheet1',
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* FileBtn wraps file selection behavior into a reusable button interface that works with form and upload flows.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import {ref} from 'vue'
|
|
3
7
|
import {VBtn} from 'vuetify/components/VBtn'
|
|
4
8
|
|
|
5
9
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
|
|
6
|
-
accept?: string
|
|
7
|
-
multiple?: boolean
|
|
8
|
-
iconOnly?: boolean
|
|
9
|
-
modelValue?: File | File[] | undefined
|
|
10
|
-
tooltip?: string | Record<string,any> | undefined
|
|
10
|
+
accept?: string // Accepted file MIME types or extensions for file selection.
|
|
11
|
+
multiple?: boolean // Allows selecting or uploading more than one file.
|
|
12
|
+
iconOnly?: boolean // icon name/class used in UI rendering
|
|
13
|
+
modelValue?: File | File[] | undefined // Bound value for v-model synchronization with the parent component.
|
|
14
|
+
tooltip?: string | Record<string,any> | undefined // Tooltip text or config object shown for the action control.
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Public props accepted by FileBtn.
|
|
19
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
20
|
+
*/
|
|
13
21
|
const props = withDefaults(defineProps<Props>(), {
|
|
14
22
|
multiple: false,
|
|
15
23
|
accept: '*',
|
|
16
24
|
tooltip: 'Upload File',
|
|
17
25
|
})
|
|
18
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Custom events emitted by FileBtn.
|
|
29
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
30
|
+
*/
|
|
19
31
|
const emit = defineEmits<{
|
|
20
32
|
(event: 'update:modelValue', value: File | File[] | undefined): void
|
|
21
33
|
}>()
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* ImportCSV imports spreadsheet rows, maps nested object keys, and emits normalized records for downstream processing.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import * as XLSX from 'xlsx'
|
|
3
7
|
import { ref } from 'vue'
|
|
4
8
|
import { useAlert } from '../composables/alert'
|
|
5
9
|
import { VBtn } from 'vuetify/components/VBtn'
|
|
6
10
|
|
|
7
11
|
interface ImportButtonProps extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
|
|
8
|
-
stringFields?: Array<string>
|
|
9
|
-
tooltip?: string | Record<string,any> | undefined
|
|
12
|
+
stringFields?: Array<string> // Field paths that must stay as string values (no nested object conversion).
|
|
13
|
+
tooltip?: string | Record<string,any> | undefined // Tooltip text or config object shown for the action control.
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Public props accepted by ImportCSV.
|
|
18
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
19
|
+
*/
|
|
12
20
|
const props = withDefaults(defineProps<ImportButtonProps>(), {
|
|
13
21
|
stringFields: ()=>[],
|
|
14
22
|
tooltip: ()=>({text: 'Import', location: 'bottom'}),
|
|
15
23
|
})
|
|
16
24
|
|
|
17
25
|
const alert = useAlert()
|
|
26
|
+
/**
|
|
27
|
+
* Custom events emitted by ImportCSV.
|
|
28
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
29
|
+
*/
|
|
18
30
|
const emit = defineEmits<{
|
|
19
31
|
(e: 'import', value: object[]): void
|
|
20
32
|
}>()
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* MrzReader captures passport/ID images from camera or upload, runs OCR + MRZ parsing,
|
|
4
|
+
* and emits normalized MRZ data once checksum validation passes.
|
|
5
|
+
*/
|
|
6
|
+
import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue'
|
|
7
|
+
import { useDevicesList, useUserMedia } from '@vueuse/core'
|
|
8
|
+
import { useAlert } from '../composables/alert'
|
|
9
|
+
import { useMrzReader, type MrzResult } from '../composables/useMrzReader'
|
|
10
|
+
|
|
11
|
+
const mrzReaderControl = ref<number | null>(null)
|
|
12
|
+
|
|
13
|
+
const alert = useAlert()
|
|
14
|
+
const isLoading = ref(false)
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
intervalMs?: number // Scan interval (ms) for periodic camera-frame OCR attempts.
|
|
18
|
+
scaleFactor?: number // Upscale factor applied before OCR to improve small-text readability.
|
|
19
|
+
useOpenCv?: boolean // Enables OpenCV-assisted region detection before OCR.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
23
|
+
intervalMs: 900,
|
|
24
|
+
scaleFactor: 2,
|
|
25
|
+
useOpenCv: true,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const emit = defineEmits<{
|
|
29
|
+
(event: 'decode', value: MrzResult): void // Emitted when a valid MRZ payload is parsed.
|
|
30
|
+
(event: 'error', error: string | unknown): void // Emitted when camera/OCR/parsing fails.
|
|
31
|
+
}>()
|
|
32
|
+
|
|
33
|
+
const videoScreen = ref<HTMLVideoElement>()
|
|
34
|
+
|
|
35
|
+
const currentCameraId = ref<ConstrainDOMString | undefined>()
|
|
36
|
+
const { videoInputs: cameras } = useDevicesList({
|
|
37
|
+
requestPermissions: true,
|
|
38
|
+
constraints: { audio: false, video: true },
|
|
39
|
+
onUpdated() {
|
|
40
|
+
if (!cameras.value.find(camera => camera.deviceId === currentCameraId.value))
|
|
41
|
+
currentCameraId.value = cameras.value[0]?.deviceId
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const hasCamera = computed(() => !!currentCameraId.value)
|
|
46
|
+
|
|
47
|
+
const { stream, start: cameraStart, stop: cameraStop, enabled: cameraEnabled } = useUserMedia({
|
|
48
|
+
constraints: { video: { deviceId: currentCameraId.value } },
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
watchEffect(() => {
|
|
52
|
+
if (videoScreen.value)
|
|
53
|
+
videoScreen.value.srcObject = stream.value ?? null
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const mrzReader = useMrzReader({
|
|
57
|
+
scaleFactor: props.scaleFactor,
|
|
58
|
+
useOpenCv: props.useOpenCv,
|
|
59
|
+
lang: 'ocrb',
|
|
60
|
+
langPath: '/tesseract/',
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
async function scanOnce() {
|
|
64
|
+
if (!videoScreen.value || !cameraEnabled.value) return
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const parsed = await mrzReader.decodeFromVideoElement(videoScreen.value)
|
|
68
|
+
if (parsed) {
|
|
69
|
+
emit('decode', parsed)
|
|
70
|
+
stopCamera()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
emit('error', err)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function startCamera() {
|
|
79
|
+
if (cameraEnabled.value) return
|
|
80
|
+
|
|
81
|
+
isLoading.value = true
|
|
82
|
+
cameraStart()
|
|
83
|
+
.then(() => {
|
|
84
|
+
if (mrzReaderControl.value) {
|
|
85
|
+
window.clearInterval(mrzReaderControl.value)
|
|
86
|
+
mrzReaderControl.value = null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
mrzReaderControl.value = window.setInterval(() => {
|
|
90
|
+
void scanOnce()
|
|
91
|
+
}, props.intervalMs)
|
|
92
|
+
})
|
|
93
|
+
.catch((err) => {
|
|
94
|
+
emit('error', err)
|
|
95
|
+
})
|
|
96
|
+
.finally(() => {
|
|
97
|
+
isLoading.value = false
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stopCamera() {
|
|
102
|
+
if (mrzReaderControl.value) {
|
|
103
|
+
window.clearInterval(mrzReaderControl.value)
|
|
104
|
+
mrzReaderControl.value = null
|
|
105
|
+
}
|
|
106
|
+
if (cameraEnabled.value)
|
|
107
|
+
cameraStop()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function scanImageFile(selectedFile: File | File[] | undefined) {
|
|
111
|
+
if (!selectedFile) {
|
|
112
|
+
alert?.addAlert({ message: 'No file selected.', alertType: 'error' })
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const file = Array.isArray(selectedFile) ? selectedFile[0] : selectedFile
|
|
117
|
+
|
|
118
|
+
void mrzReader.decodeFromImageFile(file)
|
|
119
|
+
.then((parsed) => {
|
|
120
|
+
if (parsed)
|
|
121
|
+
emit('decode', parsed)
|
|
122
|
+
else
|
|
123
|
+
alert?.addAlert({ message: 'MRZ not found or checksum invalid.', alertType: 'warning' })
|
|
124
|
+
})
|
|
125
|
+
.catch((err) => {
|
|
126
|
+
emit('error', err)
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
onMounted(() => {
|
|
131
|
+
void mrzReader.ensureOpenCvReady()
|
|
132
|
+
startCamera()
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
onBeforeUnmount(() => {
|
|
136
|
+
stopCamera()
|
|
137
|
+
})
|
|
138
|
+
</script>
|
|
139
|
+
|
|
140
|
+
<template>
|
|
141
|
+
<v-card flat>
|
|
142
|
+
<v-card-text class="d-flex justify-center" v-if="isLoading">
|
|
143
|
+
<v-progress-circular indeterminate />
|
|
144
|
+
</v-card-text>
|
|
145
|
+
<v-card-text v-else>
|
|
146
|
+
<v-col v-if="hasCamera">
|
|
147
|
+
<div style="position: relative; display: inline-block; width: 100%;" :style="{ maxWidth: '1024px' }">
|
|
148
|
+
<video autoplay ref="videoScreen" width="100%" :style="{ maxWidth: '1024px' }"></video>
|
|
149
|
+
<div style="position: absolute; bottom: 10px; right: 10px; z-index: 2000;">
|
|
150
|
+
<FileBtn
|
|
151
|
+
accept="image/*"
|
|
152
|
+
icon="mdi mdi-image-plus"
|
|
153
|
+
icon-only
|
|
154
|
+
@update:model-value="scanImageFile"
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</v-col>
|
|
159
|
+
<v-col v-else>
|
|
160
|
+
<FileBtn
|
|
161
|
+
accept="image/*"
|
|
162
|
+
text="Upload Image"
|
|
163
|
+
@update:model-value="scanImageFile"
|
|
164
|
+
/>
|
|
165
|
+
</v-col>
|
|
166
|
+
</v-card-text>
|
|
167
|
+
</v-card>
|
|
168
|
+
</template>
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SplitterPanel provides a resizable split layout panel for flexible, user-adjustable page composition.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import { ref } from 'vue'
|
|
3
7
|
import { VCard } from 'vuetify/components/VCard'
|
|
4
8
|
|
|
@@ -6,8 +10,12 @@ const isResizing = ref(false)
|
|
|
6
10
|
const pane1Width = ref('50%')
|
|
7
11
|
const containerRef = ref<HTMLElement>()
|
|
8
12
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VCard['$props']> {
|
|
9
|
-
height?: number | string
|
|
13
|
+
height?: number | string // Fixed or minimum height applied to the component container.
|
|
10
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Public props accepted by SplitterPanel.
|
|
17
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
18
|
+
*/
|
|
11
19
|
const props = defineProps<Props>()
|
|
12
20
|
|
|
13
21
|
const startResize = () => {
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* TabsGroup renders grouped tab content and keeps tab state consistent across controlled and uncontrolled usage.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import {VTabs} from 'vuetify/components'
|
|
3
7
|
|
|
4
8
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VTabs['$props']> {
|
|
5
|
-
flat?: boolean
|
|
9
|
+
flat?: boolean // Uses a flatter tab style with reduced elevation and borders.
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
defineOptions({
|
|
9
13
|
inheritAttrs: false,
|
|
10
14
|
})
|
|
11
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Public props accepted by TabsGroup.
|
|
18
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
19
|
+
*/
|
|
12
20
|
const props = defineProps<Props>()
|
|
13
21
|
const currentTab = defineModel<string|number>()
|
|
14
22
|
</script>
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* TextBarcode renders barcode output from plain text and updates when bound values change.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import {ref, watch} from 'vue'
|
|
3
7
|
import {useAlert} from '../composables/alert'
|
|
4
8
|
|
|
5
9
|
interface Props {
|
|
6
|
-
modelValue?: string
|
|
10
|
+
modelValue?: string // Bound value for v-model synchronization with the parent component.
|
|
7
11
|
}
|
|
8
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Public props accepted by TextBarcode.
|
|
15
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
16
|
+
*/
|
|
9
17
|
const props = defineProps<Props>()
|
|
18
|
+
/**
|
|
19
|
+
* Custom events emitted by TextBarcode.
|
|
20
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
21
|
+
*/
|
|
10
22
|
const emit = defineEmits<{
|
|
11
23
|
(event: 'update:modelValue', value: string | undefined): void
|
|
12
24
|
(event: 'decode', value: string | undefined): void
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* DeviceIdCardButton bridges UI actions with host-agent hardware/device operations and emits runtime scan/read results.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import { computed, ref, useAttrs } from 'vue'
|
|
3
7
|
import { VBtn } from 'vuetify/components/VBtn'
|
|
4
8
|
import { useAlert } from '../../composables/alert'
|
|
@@ -6,19 +10,27 @@ import { useHostAgent, type PatientRegisterPayload } from '../../composables/hos
|
|
|
6
10
|
|
|
7
11
|
interface Props extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
|
|
8
12
|
/** If true -> call /idcard/infoAndPhoto, else /idcard/info */
|
|
9
|
-
withPhoto?: boolean
|
|
13
|
+
withPhoto?: boolean // Includes portrait/photo data in ID card read results.
|
|
10
14
|
/** Optional reader name/query string */
|
|
11
|
-
reader?: string | null
|
|
15
|
+
reader?: string | null // Preferred hardware reader identifier to connect or switch to.
|
|
12
16
|
/** Auto-disable button while reading */
|
|
13
|
-
disableWhileLoading?: boolean
|
|
17
|
+
disableWhileLoading?: boolean // Disables the trigger button while a read operation is in progress.
|
|
14
18
|
}
|
|
15
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Public props accepted by DeviceIdCardButton.
|
|
22
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
23
|
+
*/
|
|
16
24
|
const props = withDefaults(defineProps<Props>(), {
|
|
17
25
|
withPhoto: false,
|
|
18
26
|
reader: null,
|
|
19
27
|
disableWhileLoading: true,
|
|
20
28
|
})
|
|
21
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Custom events emitted by DeviceIdCardButton.
|
|
32
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
33
|
+
*/
|
|
22
34
|
const emit = defineEmits<{
|
|
23
35
|
(e: 'read', payload: PatientRegisterPayload): void
|
|
24
36
|
(e: 'error', err: unknown): void
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* DeviceIdCardWebSocket bridges UI actions with host-agent hardware/device operations and emits runtime scan/read results.
|
|
4
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
5
|
+
*/
|
|
2
6
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
7
|
import { type IdCardWsServerMessage, type PatientRegisterPayload } from '../../composables/hostAgent'
|
|
4
8
|
import { useHostAgentWs } from "../../composables/hostAgentWs";
|
|
5
9
|
|
|
6
10
|
interface Props {
|
|
7
11
|
/** Subscribe withPhoto=true => server will push payload that includes photo when available */
|
|
8
|
-
withPhoto?: boolean
|
|
12
|
+
withPhoto?: boolean // Includes portrait/photo data in ID card read results.
|
|
9
13
|
/** Optional reader name; null/undefined means "any/default" */
|
|
10
|
-
reader?: string | null
|
|
14
|
+
reader?: string | null // Preferred hardware reader identifier to connect or switch to.
|
|
11
15
|
/** Auto-connect on mount (default true) */
|
|
12
|
-
autoConnect?: boolean
|
|
16
|
+
autoConnect?: boolean // Connects to the device WebSocket automatically on mount.
|
|
13
17
|
/** Auto-subscribe after connect (default true) */
|
|
14
|
-
autoSubscribe?: boolean
|
|
18
|
+
autoSubscribe?: boolean // Subscribes to live reader events automatically after connect.
|
|
15
19
|
/** If true, try to reconnect when socket closes unexpectedly */
|
|
16
|
-
autoReconnect?: boolean
|
|
20
|
+
autoReconnect?: boolean // Retries connection automatically when the socket closes unexpectedly.
|
|
17
21
|
/** Reconnect delay in ms */
|
|
18
|
-
reconnectDelayMs?: number
|
|
22
|
+
reconnectDelayMs?: number // Delay in milliseconds before each reconnect attempt.
|
|
19
23
|
}
|
|
20
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Public props accepted by DeviceIdCardWebSocket.
|
|
27
|
+
* Document each prop field with intent, defaults, and side effects for clear generated docs.
|
|
28
|
+
*/
|
|
21
29
|
const props = withDefaults(defineProps<Props>(), {
|
|
22
30
|
withPhoto: false,
|
|
23
31
|
reader: null,
|
|
@@ -27,6 +35,10 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
27
35
|
reconnectDelayMs: 1000,
|
|
28
36
|
})
|
|
29
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Custom events emitted by DeviceIdCardWebSocket.
|
|
40
|
+
* Parents can listen to these events to react to user actions and internal state changes.
|
|
41
|
+
*/
|
|
30
42
|
const emit = defineEmits<{
|
|
31
43
|
(e: 'connected'): void
|
|
32
44
|
(e: 'disconnected', info?: { code?: number; reason?: string }): void
|