diff --git a/web/auto-imports.d.ts b/web/auto-imports.d.ts
new file mode 100644
index 0000000..669b072
--- /dev/null
+++ b/web/auto-imports.d.ts
@@ -0,0 +1,80 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+// biome-ignore lint: disable
+export {}
+declare global {
+ const EffectScope: typeof import('vue').EffectScope
+ const ElMessage: typeof import('element-plus/es').ElMessage
+ const ElMessageBox: typeof import('element-plus/es').ElMessageBox
+ const computed: typeof import('vue').computed
+ const createApp: typeof import('vue').createApp
+ const customRef: typeof import('vue').customRef
+ const defineAsyncComponent: typeof import('vue').defineAsyncComponent
+ const defineComponent: typeof import('vue').defineComponent
+ const effectScope: typeof import('vue').effectScope
+ const getCurrentInstance: typeof import('vue').getCurrentInstance
+ const getCurrentScope: typeof import('vue').getCurrentScope
+ const getCurrentWatcher: typeof import('vue').getCurrentWatcher
+ const h: typeof import('vue').h
+ const inject: typeof import('vue').inject
+ const isProxy: typeof import('vue').isProxy
+ const isReactive: typeof import('vue').isReactive
+ const isReadonly: typeof import('vue').isReadonly
+ const isRef: typeof import('vue').isRef
+ const isShallow: typeof import('vue').isShallow
+ const markRaw: typeof import('vue').markRaw
+ const nextTick: typeof import('vue').nextTick
+ const onActivated: typeof import('vue').onActivated
+ const onBeforeMount: typeof import('vue').onBeforeMount
+ const onBeforeRouteLeave: typeof import('vue-router').onBeforeRouteLeave
+ const onBeforeRouteUpdate: typeof import('vue-router').onBeforeRouteUpdate
+ const onBeforeUnmount: typeof import('vue').onBeforeUnmount
+ const onBeforeUpdate: typeof import('vue').onBeforeUpdate
+ const onDeactivated: typeof import('vue').onDeactivated
+ const onErrorCaptured: typeof import('vue').onErrorCaptured
+ const onMounted: typeof import('vue').onMounted
+ const onRenderTracked: typeof import('vue').onRenderTracked
+ const onRenderTriggered: typeof import('vue').onRenderTriggered
+ const onScopeDispose: typeof import('vue').onScopeDispose
+ const onServerPrefetch: typeof import('vue').onServerPrefetch
+ const onUnmounted: typeof import('vue').onUnmounted
+ const onUpdated: typeof import('vue').onUpdated
+ const onWatcherCleanup: typeof import('vue').onWatcherCleanup
+ const provide: typeof import('vue').provide
+ const reactive: typeof import('vue').reactive
+ const readonly: typeof import('vue').readonly
+ const ref: typeof import('vue').ref
+ const resolveComponent: typeof import('vue').resolveComponent
+ const shallowReactive: typeof import('vue').shallowReactive
+ const shallowReadonly: typeof import('vue').shallowReadonly
+ const shallowRef: typeof import('vue').shallowRef
+ const toRaw: typeof import('vue').toRaw
+ const toRef: typeof import('vue').toRef
+ const toRefs: typeof import('vue').toRefs
+ const toValue: typeof import('vue').toValue
+ const triggerRef: typeof import('vue').triggerRef
+ const unref: typeof import('vue').unref
+ const useAttrs: typeof import('vue').useAttrs
+ const useCssModule: typeof import('vue').useCssModule
+ const useCssVars: typeof import('vue').useCssVars
+ const useId: typeof import('vue').useId
+ const useLink: typeof import('vue-router').useLink
+ const useModel: typeof import('vue').useModel
+ const useRoute: typeof import('vue-router').useRoute
+ const useRouter: typeof import('vue-router').useRouter
+ const useSlots: typeof import('vue').useSlots
+ const useTemplateRef: typeof import('vue').useTemplateRef
+ const watch: typeof import('vue').watch
+ const watchEffect: typeof import('vue').watchEffect
+ const watchPostEffect: typeof import('vue').watchPostEffect
+ const watchSyncEffect: typeof import('vue').watchSyncEffect
+}
+// for type re-export
+declare global {
+ // @ts-ignore
+ export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
+ import('vue')
+}
diff --git a/web/components.d.ts b/web/components.d.ts
new file mode 100644
index 0000000..ebbc46f
--- /dev/null
+++ b/web/components.d.ts
@@ -0,0 +1,39 @@
+/* eslint-disable */
+// @ts-nocheck
+// biome-ignore lint: disable
+// oxlint-disable
+// ------
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+
+export {}
+
+/* prettier-ignore */
+declare module 'vue' {
+ export interface GlobalComponents {
+ AddDataDialog: typeof import('./src/components/AddDataDialog.vue')['default']
+ ElButton: typeof import('element-plus/es')['ElButton']
+ ElDialog: typeof import('element-plus/es')['ElDialog']
+ ElDropdown: typeof import('element-plus/es')['ElDropdown']
+ ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
+ ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
+ ElHeader: typeof import('element-plus/es')['ElHeader']
+ ElIcon: typeof import('element-plus/es')['ElIcon']
+ ElInput: typeof import('element-plus/es')['ElInput']
+ ElMain: typeof import('element-plus/es')['ElMain']
+ ElOption: typeof import('element-plus/es')['ElOption']
+ ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
+ ElProgress: typeof import('element-plus/es')['ElProgress']
+ ElSelect: typeof import('element-plus/es')['ElSelect']
+ ElSpace: typeof import('element-plus/es')['ElSpace']
+ ElTable: typeof import('element-plus/es')['ElTable']
+ ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+ ElTag: typeof import('element-plus/es')['ElTag']
+ ElText: typeof import('element-plus/es')['ElText']
+ RouterLink: typeof import('vue-router')['RouterLink']
+ RouterView: typeof import('vue-router')['RouterView']
+ }
+ export interface GlobalDirectives {
+ vLoading: typeof import('element-plus/es')['ElLoadingDirective']
+ }
+}
diff --git a/web/package.json b/web/package.json
index a94149e..3b3ba4a 100644
--- a/web/package.json
+++ b/web/package.json
@@ -28,6 +28,8 @@
"@vue/tsconfig": "^0.9.1",
"npm-run-all2": "^8.0.4",
"typescript": "~6.0.3",
+ "unplugin-auto-import": "^21.0.0",
+ "unplugin-vue-components": "^32.1.0",
"vite": "^8.0.16",
"vite-plugin-vue-devtools": "^8.1.2",
"vue-tsc": "^3.3.3"
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index 9f91232..1508468 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -54,6 +54,12 @@ importers:
typescript:
specifier: ~6.0.3
version: 6.0.3
+ unplugin-auto-import:
+ specifier: ^21.0.0
+ version: 21.0.0(@vueuse/core@14.3.0(vue@3.5.35(typescript@6.0.3)))
+ unplugin-vue-components:
+ specifier: ^32.1.0
+ version: 32.1.0(vue@3.5.35(typescript@6.0.3))
vite:
specifier: ^8.0.16
version: 8.0.16(@types/node@24.12.4)(jiti@2.7.0)(yaml@2.9.0)
@@ -483,6 +489,9 @@ packages:
'@tybys/wasm-util@0.10.2':
resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==}
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
'@types/jsesc@2.5.1':
resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==}
@@ -788,9 +797,16 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
exsolve@1.0.8:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
@@ -898,6 +914,9 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -1205,6 +1224,9 @@ packages:
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
engines: {node: '>=0.10.0'}
+ strip-literal@3.1.0:
+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+
superjson@2.2.6:
resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==}
engines: {node: '>=16'}
@@ -1238,10 +1260,40 @@ packages:
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+ unimport@5.7.0:
+ resolution: {integrity: sha512-njnL6sp8lEA8QQbZrt+52p/g4X0rw3bnGGmUcJnt1jeG8+iiqO779aGz0PirCtydAIVcuTBRlJ52F0u46z309Q==}
+ engines: {node: '>=18.12.0'}
+
+ unplugin-auto-import@21.0.0:
+ resolution: {integrity: sha512-vWuC8SwqJmxZFYwPojhOhOXDb5xFhNNcEVb9K/RFkyk/3VnfaOjzitWN7v+8DEKpMjSsY2AEGXNgt6I0yQrhRQ==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@nuxt/kit': ^4.0.0
+ '@vueuse/core': '*'
+ peerDependenciesMeta:
+ '@nuxt/kit':
+ optional: true
+ '@vueuse/core':
+ optional: true
+
unplugin-utils@0.3.1:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
+ unplugin-vue-components@32.1.0:
+ resolution: {integrity: sha512-YiUkSxuRjab18XFOrX5VsIxXzccrfmHVGsGeJgSgklb829DQmCy9E4vvDUE4tuvZZdxyFJZX0Oc4TPnnxiiMyg==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@nuxt/kit': ^3.2.2 || ^4.0.0
+ vue: ^3.0.0
+ peerDependenciesMeta:
+ '@nuxt/kit':
+ optional: true
+
+ unplugin@2.3.11:
+ resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
+ engines: {node: '>=18.12.0'}
+
unplugin@3.0.0:
resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1795,6 +1847,8 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@types/estree@1.0.9': {}
+
'@types/jsesc@2.5.1': {}
'@types/lodash-es@4.17.12':
@@ -2149,8 +2203,14 @@ snapshots:
escalade@3.2.0: {}
+ escape-string-regexp@5.0.0: {}
+
estree-walker@2.0.2: {}
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+
exsolve@1.0.8: {}
fdir@6.5.0(picomatch@4.0.4):
@@ -2237,6 +2297,8 @@ snapshots:
js-tokens@4.0.0: {}
+ js-tokens@9.0.1: {}
+
jsesc@3.1.0: {}
json-parse-even-better-errors@4.0.0: {}
@@ -2488,6 +2550,10 @@ snapshots:
speakingurl@14.0.1: {}
+ strip-literal@3.1.0:
+ dependencies:
+ js-tokens: 9.0.1
+
superjson@2.2.6:
dependencies:
copy-anything: 4.0.5
@@ -2512,11 +2578,59 @@ snapshots:
undici-types@7.16.0: {}
+ unimport@5.7.0:
+ dependencies:
+ acorn: 8.16.0
+ escape-string-regexp: 5.0.0
+ estree-walker: 3.0.3
+ local-pkg: 1.2.1
+ magic-string: 0.30.21
+ mlly: 1.8.2
+ pathe: 2.0.3
+ picomatch: 4.0.4
+ pkg-types: 2.3.1
+ scule: 1.3.0
+ strip-literal: 3.1.0
+ tinyglobby: 0.2.17
+ unplugin: 2.3.11
+ unplugin-utils: 0.3.1
+
+ unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.35(typescript@6.0.3))):
+ dependencies:
+ local-pkg: 1.2.1
+ magic-string: 0.30.21
+ picomatch: 4.0.4
+ unimport: 5.7.0
+ unplugin: 2.3.11
+ unplugin-utils: 0.3.1
+ optionalDependencies:
+ '@vueuse/core': 14.3.0(vue@3.5.35(typescript@6.0.3))
+
unplugin-utils@0.3.1:
dependencies:
pathe: 2.0.3
picomatch: 4.0.4
+ unplugin-vue-components@32.1.0(vue@3.5.35(typescript@6.0.3)):
+ dependencies:
+ chokidar: 5.0.0
+ local-pkg: 1.2.1
+ magic-string: 0.30.21
+ mlly: 1.8.2
+ obug: 2.1.1
+ picomatch: 4.0.4
+ tinyglobby: 0.2.17
+ unplugin: 3.0.0
+ unplugin-utils: 0.3.1
+ vue: 3.5.35(typescript@6.0.3)
+
+ unplugin@2.3.11:
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ acorn: 8.16.0
+ picomatch: 4.0.4
+ webpack-virtual-modules: 0.6.2
+
unplugin@3.0.0:
dependencies:
'@jridgewell/remapping': 2.3.5
diff --git a/web/src/App.vue b/web/src/App.vue
index a5d277c..9c1bfe1 100644
--- a/web/src/App.vue
+++ b/web/src/App.vue
@@ -1,6 +1,4 @@
diff --git a/web/src/components/AddDataDialog.vue b/web/src/components/AddDataDialog.vue
index 489d188..06e3fe1 100644
--- a/web/src/components/AddDataDialog.vue
+++ b/web/src/components/AddDataDialog.vue
@@ -1,7 +1,5 @@