diff --git a/package-lock.json b/package-lock.json index 554918e..22df8bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,15 @@ "name": "vue-project", "version": "0.0.0", "dependencies": { - "element-plus": "^2.6.1", + "@vueuse/core": "^10.9.0", + "ansi_up": "^6.0.2", + "element-plus": "^2.7.3", "mitt": "^3.0.1", "pinia": "^2.1.7", "vue": "^3.4.21", "vue-i18n": "^9.10.2", - "vue-router": "^4.3.0" + "vue-router": "^4.3.0", + "vuetify": "^3.6.5" }, "devDependencies": { "@rushstack/eslint-patch": "^1.3.3", @@ -38,6 +41,7 @@ "vite-plugin-css-injected-by-js": "^3.5.0", "vite-plugin-html": "^3.2.2", "vite-plugin-singlefile": "^2.0.1", + "vite-plugin-vuetify": "^2.0.3", "vite-svg-loader": "^5.1.0", "vue-tsc": "^2.0.6" } @@ -106,7 +110,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "aix" @@ -122,7 +125,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -138,7 +140,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -154,7 +155,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -170,7 +170,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -186,7 +185,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -202,7 +200,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -218,7 +215,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -234,7 +230,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -250,7 +245,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -266,7 +260,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -282,7 +275,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -298,7 +290,6 @@ "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -314,7 +305,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -330,7 +320,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -346,7 +335,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -362,7 +350,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -378,7 +365,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -394,7 +380,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -410,7 +395,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -426,7 +410,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -442,7 +425,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -458,7 +440,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -711,7 +692,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -725,7 +706,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -734,7 +715,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -743,7 +724,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -758,7 +739,7 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -860,7 +841,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -873,7 +853,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -886,7 +865,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -899,7 +877,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -912,7 +889,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -925,7 +901,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -938,7 +913,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -951,7 +925,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -964,7 +937,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -977,7 +949,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -990,7 +961,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1003,7 +973,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1016,7 +985,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1047,7 +1015,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "devOptional": true }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -1072,7 +1040,7 @@ "version": "20.11.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", - "dev": true, + "devOptional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1084,9 +1052,9 @@ "dev": true }, "node_modules/@types/web-bluetooth": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", - "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.21.0", @@ -1487,15 +1455,28 @@ "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", "dev": true }, - "node_modules/@vueuse/core": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", - "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "node_modules/@vuetify/loader-shared": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.0.3.tgz", + "integrity": "sha512-Ss3GC7eJYkp2SF6xVzsT7FAruEmdihmn4OCk2+UocREerlXKWgOKKzTN5PN3ZVN5q05jHHrsNhTuWbhN61Bpdg==", + "devOptional": true, "dependencies": { - "@types/web-bluetooth": "^0.0.16", - "@vueuse/metadata": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "upath": "^2.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, + "node_modules/@vueuse/core": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -1527,19 +1508,19 @@ } }, "node_modules/@vueuse/metadata": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", - "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", - "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", "dependencies": { - "vue-demi": "*" + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -1574,7 +1555,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -1607,6 +1588,14 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi_up": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-6.0.2.tgz", + "integrity": "sha512-3G3vKvl1ilEp7J1u6BmULpMA0xVoW/f4Ekqhl8RTrJrhEBkonKn5k3bUc5Xt+qDayA6iDX0jyUh3AbZjB/l0tw==", + "engines": { + "node": "*" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1800,7 +1789,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "devOptional": true }, "node_modules/callsites": { "version": "3.1.0", @@ -2094,7 +2083,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "devOptional": true, "dependencies": { "ms": "2.1.2" }, @@ -2117,7 +2106,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, + "devOptional": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -2275,9 +2264,9 @@ "dev": true }, "node_modules/element-plus": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.6.1.tgz", - "integrity": "sha512-6VRpLjwtIVdtUuITJPPKtpOH1NM6nuAkRE3q5O4Lrx0N1bYMhTkiqb2Jy7zfQuDPbOIkkF2OABTzegpNnzgsnQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.7.3.tgz", + "integrity": "sha512-OaqY1kQ2xzNyRFyge3fzM7jqMwux+464RBEqd+ybRV9xPiGxtgnj/sVK4iEbnKnzQIa9XK03DOIFzoToUhu1DA==", "dependencies": { "@ctrl/tinycolor": "^3.4.1", "@element-plus/icons-vue": "^2.3.1", @@ -2299,6 +2288,94 @@ "vue": "^3.2.0" } }, + "node_modules/element-plus/node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "node_modules/element-plus/node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/element-plus/node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2320,7 +2397,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -2807,7 +2884,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3265,7 +3341,7 @@ "version": "1.24.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.24.1.tgz", "integrity": "sha512-kUpHOLiH5GB0ERSv4pxqlL0RYKnOXtgGtVe7shDGfhS0AZ4D1ouKFYAcLcZhql8aMspDNzaUCumGHZ78tb2fTg==", - "dev": true, + "devOptional": true, "dependencies": { "detect-libc": "^1.0.3" }, @@ -3295,7 +3371,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3315,7 +3390,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3335,7 +3409,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -3355,7 +3428,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3375,7 +3447,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3395,7 +3466,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3415,7 +3485,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3435,7 +3504,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3455,7 +3523,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3659,7 +3726,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "devOptional": true }, "node_modules/muggle-string": { "version": "0.4.1", @@ -4480,7 +4547,7 @@ "version": "4.13.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/estree": "1.0.5" }, @@ -4607,7 +4674,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -4624,7 +4691,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, + "devOptional": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4903,7 +4970,7 @@ "version": "5.29.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -4921,7 +4988,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "devOptional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -5033,7 +5100,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "devOptional": true }, "node_modules/unimport": { "version": "3.7.1", @@ -5184,6 +5251,16 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "devOptional": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -5233,7 +5310,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.2.tgz", "integrity": "sha512-FWZbz0oSdLq5snUI0b6sULbz58iXFXdvkZfZWR/F0ZJuKTSPO7v72QPXt6KqYeMFb0yytNp6kZosxJ96Nr/wDQ==", - "dev": true, + "devOptional": true, "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.36", @@ -5351,6 +5428,25 @@ "vite": "^5.1.4" } }, + "node_modules/vite-plugin-vuetify": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-2.0.3.tgz", + "integrity": "sha512-HbYajgGgb/noaVKNRhnnXIiQZrNXfNIeanUGAwXgOxL6h/KULS40Uf51Kyz8hNmdegF+DwjgXXI/8J1PNS83xw==", + "devOptional": true, + "dependencies": { + "@vuetify/loader-shared": "^2.0.3", + "debug": "^4.3.3", + "upath": "^2.0.1" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": ">=5", + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, "node_modules/vite-svg-loader": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-5.1.0.tgz", @@ -5467,6 +5563,39 @@ "typescript": "*" } }, + "node_modules/vuetify": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.6.5.tgz", + "integrity": "sha512-YrHTM1vb7UllAtfH9tWfTo1wYMjyCSybu4WtXrfMRpMwAaZWgfrMmqD/4Tc+0KqDsDsYMXaYs0nJ6HtdMJZbyA==", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=1.0.0", + "vue": "^3.3.0", + "vue-i18n": "^9.0.0", + "webpack-plugin-vuetify": ">=2.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "vue-i18n": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", diff --git a/package.json b/package.json index 136e716..83255d9 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "type": "module", "scripts": { "dev": ". ./set_env.sh && vite", + "devh": ". ./set_env.sh && vite --host", "build": "run-p type-check \"build-only {@}\" --", "preview": ". ./set_env.sh && vite preview", "build-only": ". ./set_env.sh && vite build", @@ -14,11 +15,14 @@ "format": "prettier --write src/" }, "dependencies": { - "element-plus": "^2.6.1", + "@vueuse/core": "^10.9.0", + "ansi_up": "^6.0.2", + "element-plus": "^2.7.3", "mitt": "^3.0.1", "pinia": "^2.1.7", "vue": "^3.4.21", "vue-i18n": "^9.10.2", + "vuetify": "^3.6.5", "vue-router": "^4.3.0" }, "devDependencies": { @@ -44,6 +48,7 @@ "vite-plugin-css-injected-by-js": "^3.5.0", "vite-plugin-html": "^3.2.2", "vite-plugin-singlefile": "^2.0.1", + "vite-plugin-vuetify": "^2.0.3", "vite-svg-loader": "^5.1.0", "vue-tsc": "^2.0.6" } diff --git a/src/api/apiDataFlow.ts b/src/api/apiDataFlow.ts new file mode 100644 index 0000000..9e380f4 --- /dev/null +++ b/src/api/apiDataFlow.ts @@ -0,0 +1,47 @@ +import {type ApiJsonMsg} from '@/api' +import * as api from "@/api/index"; + +export enum WtDataFlowCmd { + UNKNOWN = 0, + GET_INS_LIST = 1, + GET_CUR_INS = 2, + GET_CUR_ATTACH_LIST = 3, + GET_ATTACH_LIST = 4, + ATTACH = 5, + ATTACH_CUR_TO_RECVER = 6, + ATTACH_CUR_TO_SENDER = 7, + DETACH_SINGLE = 8, + DETACH_CUR_FROM = 9, + SET_DATA_TYPE = 10, +} + +export interface IWtDataFlowJsonMsg extends ApiJsonMsg { + data_type?: 3 | 4, + ins_idx?: number, +} + +export function wt_data_flow_get_instance_list() { + const jsonMsg: IWtDataFlowJsonMsg = { + cmd: WtDataFlowCmd.GET_INS_LIST, + module: api.WtModuleID.DATA_FLOW, + } + api.sendJsonMsg(jsonMsg); +} + +export function wt_data_flow_attach_cur_to_sender(instance_index: number) { + const jsonMsg: IWtDataFlowJsonMsg = { + cmd: WtDataFlowCmd.ATTACH_CUR_TO_SENDER, + module: api.WtModuleID.DATA_FLOW, + data_type: 3, + ins_idx: instance_index, + } + api.sendJsonMsg(jsonMsg); +} + +export function wt_data_flow_get_attach_list() { + const jsonMsg: IWtDataFlowJsonMsg = { + cmd: WtDataFlowCmd.GET_ATTACH_LIST, + module: api.WtModuleID.DATA_FLOW, + } + api.sendJsonMsg(jsonMsg); +} diff --git a/src/api/apiUart.ts b/src/api/apiUart.ts new file mode 100644 index 0000000..52a75b1 --- /dev/null +++ b/src/api/apiUart.ts @@ -0,0 +1,96 @@ +import type {ApiBinaryMsg} from "@/api/binDataDef"; +import {WtDataType} from "@/api/binDataDef"; +import {type ApiJsonMsg, sendBinMsg, sendJsonMsg, WtModuleID} from "@/api/index"; + +export enum WtUartCmd { + UNKNOWN = 0, + + /* UART PERIPHERAL */ + GET_AVAILABLE_NUMS = 1, + GET_BAUD = 4, + SET_BAUD = 5, + GET_CONFIG = 6, /* data bits, parity and stop bits */ + SET_CONFIG = 7, + GET_FLOW_CTRL, /* flow control function RTS/CTS*/ + SET_FLOW_CTRL, + GET_PINS_NUM, /* not implemented change pinout function */ + SET_PINS_NUM, /* not implemented */ + GET_MODE, /* not implemented UART/RS485/IrDA */ + SET_MODE, /* not implemented UART/RS485/IrDA */ + + GET_STATUS = 20, /* is uart enabled and other information */ + SET_STATUS, /* set specific uart port disable */ + GET_DATA_TYPE = 22, // 0x03 or 0x04 + SET_DATA_TYPE = 23, // 0x03 or 0x04 +} + +enum ANSI_ESCAPE_CODE { + REFRESH_WINDOW = '\x1b[7t', + CLEAR_WINDOW = '\x1b[2J' +} + +export interface IUartConfig { + data_bits: 5 | 6 | 7 | 8; + parity : 0 | 1 | 2; + stop_bits: 1 | 15 | 2; +} + +export interface IUartMsgConfig extends ApiJsonMsg, IUartConfig { + sub_mod: number; +} + +export interface IUartMsgBaud extends ApiJsonMsg { + sub_mod: number; + baud: number; +} + +export function uart_send_msg(payload: Uint8Array, sub_mod: number = 1) { + /* hard code uart num for now */ + const msg: ApiBinaryMsg = { + sub_mod: sub_mod, + data_type: WtDataType.RAW, + module: WtModuleID.UART, + payload: payload, + } + sendBinMsg(msg); +} + +export function uart_get_baud(uart_num: number = 1) { + const cmd = { + cmd: WtUartCmd.GET_BAUD, + module: WtModuleID.UART, + sub_mod: uart_num, + } + sendJsonMsg(cmd); +} + +export function uart_set_baud(baud: number, uart_num: number = 1) { + const cmd: IUartMsgBaud = { + cmd: WtUartCmd.SET_BAUD, + module: WtModuleID.UART, + baud: baud, + sub_mod: uart_num, + } + sendJsonMsg(cmd); +} + +export function uart_get_config(uart_num: number = 1) { + const cmd = { + cmd: WtUartCmd.GET_CONFIG, + module: WtModuleID.UART, + sub_mod: uart_num, + } + sendJsonMsg(cmd); +} + +export function uart_set_config(uart_config: IUartConfig, uart_num: number = 1) { + const cmd: IUartMsgConfig = { + cmd: WtUartCmd.SET_CONFIG, + module: WtModuleID.UART, + sub_mod: uart_num, + data_bits: uart_config.data_bits, + parity: uart_config.parity, + stop_bits: uart_config.stop_bits, + } + sendJsonMsg(cmd); +} \ No newline at end of file diff --git a/src/assets/icon/arrow_drop_down.svg b/src/assets/icon/arrow_drop_down.svg new file mode 100644 index 0000000..88e7bf1 --- /dev/null +++ b/src/assets/icon/arrow_drop_down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icon/arrow_drop_up.svg b/src/assets/icon/arrow_drop_up.svg new file mode 100644 index 0000000..10c71f5 --- /dev/null +++ b/src/assets/icon/arrow_drop_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icon/close-fullscreen.svg b/src/assets/icon/close-fullscreen.svg new file mode 100644 index 0000000..36f90c5 --- /dev/null +++ b/src/assets/icon/close-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icon/open-in-full.svg b/src/assets/icon/open-in-full.svg new file mode 100644 index 0000000..a757944 --- /dev/null +++ b/src/assets/icon/open-in-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icon/trash.svg b/src/assets/icon/trash.svg new file mode 100644 index 0000000..d1d3899 --- /dev/null +++ b/src/assets/icon/trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 5841e0b..5689295 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,8 @@ import '@/assets/page.css' import '@/assets/navigation.css' import 'element-plus/dist/index.css'; +import 'vuetify/styles' +import { createVuetify } from 'vuetify' import { createApp } from 'vue' import { createPinia } from 'pinia' @@ -17,5 +19,6 @@ const app = createApp(App) app.use(createPinia()) app.use(i18n); app.use(router) +app.use(createVuetify()) app.mount('#app') diff --git a/src/stores/dataViewerStore.ts b/src/stores/dataViewerStore.ts new file mode 100644 index 0000000..bd0aea9 --- /dev/null +++ b/src/stores/dataViewerStore.ts @@ -0,0 +1,553 @@ +import {defineStore} from "pinia"; +import {computed, type Ref, ref, shallowReactive} from "vue"; +import {AnsiUp} from 'ansi_up' +import {debouncedWatch} from "@vueuse/core"; +import {type IUartConfig, uart_send_msg} from "@/api/apiUart"; + +interface IDataArchive { + time: number; + isRX: boolean; + data: Uint8Array; +} + +export interface IDataBuf { + time: string; + isRX: boolean; + data: Uint8Array; + str: string; + hex: string; + hexdump: string; +} + +function decodeUtf8(u8Arr: Uint8Array) { + try { + const decoder = new TextDecoder(); + const decodedText = decoder.decode(u8Arr); // Attempt to decode + return decodedText.replace(/\uFFFD/g, ''); // Remove all � characters + } catch (error) { + return ""; + } +} + +function escapeHTML(text: string) { + const element = document.createElement('p'); + element.textContent = text; + return element.innerHTML; +} + +function unescapeString(str: string) { + return str.replace(/\\(u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|[0-7]{1,3}|.)/g, (_, escapeChar) => { + switch (escapeChar[0]) { + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'b': + return '\b'; + case 'v': + return '\v'; + case '0': + return '\0'; + case 'x': + return String.fromCharCode(parseInt(escapeChar.slice(1), 16)); + case 'u': + return String.fromCharCode(parseInt(escapeChar.slice(1), 16)); + default: + if (/^[0-7]{1,3}$/.test(escapeChar)) { + return String.fromCharCode(parseInt(escapeChar, 8)); + } + return escapeChar; + } + }); +} + +const zeroPad = (num: number, places: number) => String(num).padStart(places, '0'); +const ansi_up = new AnsiUp(); +ansi_up.escape_html = false; + +/* quick HEX lookup table */ +const byteToHex: string[] = new Array(256); +for (let n = 0; n <= 0xff; ++n) { + byteToHex[n] = n.toString(16).padStart(2, "0").toUpperCase(); +} + +function u8toHexString(buff: Uint8Array) { + const hexOctets = []; // new Array(buff.length) is even faster (preallocates necessary array size), then use hexOctets[i] instead of .push() + if (buff.length === 0) { + return "" + } + + for (let i = 0; i < buff.length; ++i) + hexOctets.push(byteToHex[buff[i]]); + + return hexOctets.join(" "); +} + +function u8toHexdump(buffer: Uint8Array) { + const lines: string[] = []; + const bytesPerRow = 16; + + for (let lineStart = 0; lineStart < buffer.length; lineStart += bytesPerRow) { + let result = lineStart.toString(16).padStart(4, '0') + ": "; + let ascii = ""; + + // Process each byte in the row + for (let i = 0; i < bytesPerRow; i++) { + const byteIndex = lineStart + i; + if (byteIndex >= buffer.length) { + // Pad the row if it's shorter than the full width + result += " "; + } else { + const byte = buffer[byteIndex]; + result += byteToHex[byte] + " "; + + // Prepare the ASCII representation, non-printable as '.' + if (byte >= 32 && byte <= 126) { + ascii += String.fromCharCode(byte); + } else { + ascii += "."; + } + } + if (i === 8) { + result += " " + } + } + + result += "|" + ascii + "|" + " ".repeat(16 - ascii.length); + lines.push(result); + } + + return strToHTML(escapeHTML(lines.join('\n'))); +} + +function strToHTML(str: string) { + return str.replace(/\n/g, '
') // Replace newline with
tag + .replace(/\t/g, ' ') // Replace tab with spaces (or you could use ' ' for single spaces) + .replace(/ /g, ' '); +} + +function isArrayContained(subArray: Uint8Array, mainArray: Uint8Array) { + if (subArray.length === 0) return -1; + outerLoop: for (let i = 0; i <= mainArray.length - subArray.length; i++) { + // Check if subArray is found starting at position i in mainArray + for (let j = 0; j < subArray.length; j++) { + if (mainArray[i + j] !== subArray[j]) { + continue outerLoop; // Continue the outer loop if mismatch found + } + } + return i; // subArray is found within mainArray + } + return -1; +} + +const baudArr = [ + { + start: 300, + count: 9, + }, { + start: 14400, + count: 9, + } +] + +function generateBaudArr(results: { baud: number;}[]) { + for (let i = 0; i < baudArr.length; ++i) { + let start = baudArr[i].start; + for (let j = 0; j < baudArr[i].count; ++j) { + results.push({baud: start}); + start += start; + } + } + + results.sort((a, b) => { + return a.baud - b.baud; + }); +} + +export const useDataViewerStore = defineStore('text-viewer', () => { + /* private value */ + const predefineColors = [ + '#f0f9eb', + '#ecf4ff', + 'rgba(255, 69, 0, 0.68)', + 'rgb(255, 120, 0)', + 'hsv(51, 100, 98)', + 'hsva(120, 40, 94, 0.5)', + 'hsl(181, 100%, 37%)', + 'hsla(209, 100%, 56%, 0.73)', + 'rgba(85,155,197,0.44)', + ] + + const predefinedUartBaudFrequent = Object.freeze([ + { + baud: 115200, + }, { + baud: 921600, + }, { + baud: 9600, + } + ]) + + const uartBaudList: { baud: number; }[] = []; + generateBaudArr(uartBaudList); + + /* public value */ + const configPanelTab = ref("second"); + const configPanelShow = ref(true); + const quickAccessPanelShow = ref(true); + const enableAnsiDecode = ref(true); + const frameBreakSequence = ref("\\n"); + const frameBreakSequenceNormalized = ref(new Uint8Array(0)); + const frameBreakDelay = ref(0); + + const showText = ref(true); + const showHex = ref(false); + const showHexdump = ref(false); + const enableLineWrap = ref(true); + const showTimestamp = ref(true); + + const pauseAutoRefresh = ref(false); + + const RxHexdumpColor = ref("#f0f9eb"); + const RxTotalByteCount = ref(0); + const RxByteCount = ref(0); + + const TxHexdumpColor = ref("#ecf4ff"); + const TxTotalByteCount = ref(0); + const TxByteCount = ref(0); + + const enableFilter = ref(true); + const enableMatch = ref(false); + const forceToBottom = ref(true); + const filterChanged = ref(false); + + const textSuffixValue = ref("") + const textPrefixValue = ref("") + + const uartBaud = ref(115200); + const uartBaudReal = ref(115200); + const uartConfig: Ref = ref({ + data_bits: 8, + parity: 0, + stop_bits: 1, + }); + + const filterValue = ref(""); + const computedFilterValue = computed(() => { + const str = unescapeString(filterValue.value); + const encoder = new TextEncoder(); + return encoder.encode(str); + }) + + const computedSuffixValue = computed(() => { + const str = unescapeString(textSuffixValue.value); + const encoder = new TextEncoder(); + return encoder.encode(str); + }) + + const computedPrefixValue = computed(() => { + const str = unescapeString(textPrefixValue.value); + const encoder = new TextEncoder(); + return encoder.encode(str); + }) + + debouncedWatch(() => frameBreakSequence.value, (newValue) => { + const unescapedStr = unescapeString(newValue); + const encoder = new TextEncoder(); + frameBreakSequenceNormalized.value = encoder.encode(unescapedStr); + }, {debounce: 300, immediate: true}); + + debouncedWatch(() => frameBreakDelay.value, (newValue) => { + if (newValue < 0) { + frameBreakReady = false; + clearTimeout(frameBreakTimeoutID); + } else if (newValue === 0) { + frameBreakReady = true; + clearTimeout(frameBreakTimeoutID); + } else { + refreshTimeout(); + } + }, {debounce: 300, immediate: true}); + + const dataArchive: IDataArchive[] = []; + const dataBuf: IDataBuf[] = []; + const dataBufLength = ref(0); + + /* actual data shown on screen */ + const dataFiltered: IDataBuf[] = shallowReactive([]); + const dataFilteredLength = ref(0); + + + let frameBreakReady = false; + let frameBreakTimeoutID = setTimeout(() => { + }, 0); + + debouncedWatch(computedFilterValue, () => { + dataFiltered.length = 0; // Clear the array efficiently + if (computedFilterValue.value.length === 0) { + dataFiltered.push(...dataBuf); + filterChanged.value = true; + return; + } + + const index = dataFiltered.length; + for (const item of dataBuf) { + const index = isArrayContained(computedFilterValue.value, item.data); + if (index >= 0) { + dataFiltered.push(item); + } + filterChanged.value = true; + } + }, {debounce: 300}); + + function addString(item: string, isRX: boolean = false, doSend: boolean = false) { + const encoder = new TextEncoder(); + item = unescapeString(item); + const encodedStr = encoder.encode(item); + return addItem(encodedStr, isRX, doSend); + } + + function addHexString(item: string, isRX: boolean = false, doSend: boolean = false){ + if (item === "") { + return addItem(new Uint8Array(0), isRX); + } + const hexArray = item.split(' '); + // Map each hex value to a decimal (integer) and create a Uint8Array from these integers + const uint8Array = new Uint8Array(hexArray.map(hex => parseInt(hex, 16))); + return addItem(uint8Array, isRX, doSend); + } + + function addItem(item: Uint8Array, isRX: boolean, doSend: boolean = false){ + const t = new Date(); + + // dataArchive.push({ + // time: t.getMilliseconds(), + // isRX: isRX, + // data: u8arr, + // }); + + if (isRX) { + RxTotalByteCount.value += item.length; + RxByteCount.value = item.length; + } else { + /* append prefix and suffix */ + if (computedPrefixValue.value.length || computedSuffixValue.value.length) { + const newArr = new Uint8Array(computedPrefixValue.value.length + + computedSuffixValue.value.length + item.length); + newArr.set(computedPrefixValue.value); + newArr.set(item, computedPrefixValue.value.length); + newArr.set(computedSuffixValue.value, computedPrefixValue.value.length + item.length); + item = newArr; + } + if (doSend) { + /* INFO: hard coded for the moment */ + uart_send_msg(item); + } + TxTotalByteCount.value += item.length; + TxByteCount.value = item.length; + } + + let str = decodeUtf8(item); + str = escapeHTML(str); + str = strToHTML(str); + + /* unescape data \n */ + if (enableAnsiDecode.value) { + /* ansi_to_html will escape HTML sequence */ + str = ansi_up.ansi_to_html("\x1b[0m" + str); + } + + dataBuf.push({ + time: "[" + + zeroPad(t.getHours(), 2) + ":" + + zeroPad(t.getMinutes(), 2) + ":" + + zeroPad(t.getSeconds(), 2) + ":" + + zeroPad(t.getMilliseconds(), 3) + + "]", + data: item, + isRX: isRX, + str: str, + hex: u8toHexString(item), + hexdump: u8toHexdump(item), + }); + + if (dataBuf.length >= 20000) { + dataBuf.splice(0, 5000); + } + + if (!enableFilter.value || computedFilterValue.value.length === 0) { + dataFiltered.push(dataBuf[dataBuf.length - 1]); + if (dataFiltered.length >= 20000) { + dataFiltered.splice(0, 5000); + } + } else if (enableFilter.value && isArrayContained(computedFilterValue.value, dataBuf[dataBuf.length - 1].data) >= 0) { + dataFiltered.push(dataBuf[dataBuf.length - 1]); + if (dataFiltered.length >= 20000) { + dataFiltered.splice(0, 5000); + } + } + + dataBufLength.value = dataBuf.length; + } + + function popItem() { + dataBuf.pop(); + dataFiltered.pop(); + } + + function doFrameBreak() { + frameBreakReady = true; + } + + + function refreshTimeout() { + /* always break */ + // if (frameBreakDelay.value === 0) { + // frameBreakReady = true; + // } + + + if (!frameBreakReady && frameBreakDelay.value > 0) { + clearTimeout(frameBreakTimeoutID); + frameBreakTimeoutID = setTimeout(doFrameBreak, frameBreakDelay.value); + } + } + + function addChunk(item: Uint8Array, isRX: boolean) { + let newArray: Uint8Array; + + if (frameBreakSequence.value === "") { + if (frameBreakReady || dataBuf.length === 0 || dataBuf[dataBuf.length - 1].isRX != isRX) { + addItem(item, isRX); + frameBreakReady = false; + } else { + /* TODO: append item to last */ + newArray = new Uint8Array(dataBuf[dataBuf.length - 1].data.length + item.length + 1); + newArray.set(dataBuf[dataBuf.length - 1].data); + newArray.set(item, dataBuf[dataBuf.length - 1].data.length); + popItem(); + addItem(newArray, isRX); + } + refreshTimeout(); + return; + } + + + if (frameBreakReady) { + newArray = item; + } else { + if (dataBuf.length) { + newArray = new Uint8Array(dataBuf[dataBuf.length - 1].data.length + item.length + 1); + newArray.set(dataBuf[dataBuf.length - 1].data); + newArray.set(item, dataBuf[dataBuf.length - 1].data.length); + popItem(); + } else { + newArray = item; + } + } + + console.log(newArray) + console.log(frameBreakSequenceNormalized.value) + + /* break frame at sequence match */ + let matchIndex = isArrayContained(frameBreakSequenceNormalized.value, newArray); + while (matchIndex < 0) { + console.log(matchIndex) + /* update last buf item */ + addItem(newArray.slice(0, matchIndex + frameBreakSequenceNormalized.value.length), isRX); + newArray = newArray.slice(matchIndex + frameBreakSequenceNormalized.value.length); + matchIndex = isArrayContained(frameBreakSequenceNormalized.value, newArray); + } + addItem(newArray.slice(0, matchIndex + frameBreakSequenceNormalized.value.length), isRX); + } + + function clearByteCount(isRX: boolean) { + if (isRX) { + RxTotalByteCount.value = 0; + } else { + TxTotalByteCount.value = 0; + } + } + + function clearDataBuff() { + dataBuf.length = 0; + dataFiltered.length = 0; + dataBufLength.value = 0; + + RxByteCount.value = 0; + RxTotalByteCount.value = 0; + + TxByteCount.value = 0; + TxTotalByteCount.value = 0; + } + + function clearFilteredBuff() { + dataFiltered.length = 0; + } + + function refreshFilteredBuff() { + const oldValue = filterValue.value; + filterValue.value += "66"; + filterValue.value = oldValue; + } + + function setUartBaud(baud: number) { + uartBaudReal.value = baud; + for (let i = 0; i < uartBaudList.length; i++) { + const difference = Math.abs(uartBaudList[i].baud - baud); + const percentageDifference = (difference / baud); + if (percentageDifference !== 0 && percentageDifference < 0.001) { + uartBaud.value = uartBaudList[i].baud; + return; + } + } + uartBaud.value = baud; + } + + return { + addItem, + addChunk, + addString, + addHexString, + clearFilteredBuff, + clearDataBuff, + refreshFilteredBuff, + textSuffixValue, + textPrefixValue, + clearByteCount, + dataBufLength, + configPanelTab, + configPanelShow, + pauseAutoRefresh, + quickAccessPanelShow, + dataFiltered, + filterValue, + enableAnsiDecode, + showHex, + showHexdump, + showText, + showTimestamp, + enableLineWrap, + RxHexdumpColor, + TxHexdumpColor, + predefineColors, + RxByteCount, + RxTotalByteCount, + TxByteCount, + TxTotalByteCount, + forceToBottom, + frameBreakSequence, + frameBreakDelay, + filterChanged, + + /* UART */ + predefinedUartBaudFrequent, + uartBaudList, + uartBaud, + uartConfig, + uartBaudReal, + setUartBaud, + } +}); diff --git a/src/views/Uart.vue b/src/views/Uart.vue index 51dbd02..f41624a 100644 --- a/src/views/Uart.vue +++ b/src/views/Uart.vue @@ -1,9 +1,497 @@ + + - + diff --git a/src/views/text-data-viewer/textDataConfig.vue b/src/views/text-data-viewer/textDataConfig.vue new file mode 100644 index 0000000..6b345bb --- /dev/null +++ b/src/views/text-data-viewer/textDataConfig.vue @@ -0,0 +1,304 @@ + + + + + \ No newline at end of file diff --git a/src/views/text-data-viewer/textDataMacro.vue b/src/views/text-data-viewer/textDataMacro.vue new file mode 100644 index 0000000..7d1dd4c --- /dev/null +++ b/src/views/text-data-viewer/textDataMacro.vue @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/src/views/text-data-viewer/textDataViewer.vue b/src/views/text-data-viewer/textDataViewer.vue new file mode 100644 index 0000000..e58ff60 --- /dev/null +++ b/src/views/text-data-viewer/textDataViewer.vue @@ -0,0 +1,376 @@ + + + diff --git a/vite.config.ts b/vite.config.ts index 26066a8..73291a7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,7 @@ import vue from '@vitejs/plugin-vue' import svgLoader from "vite-svg-loader"; import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js"; import { viteSingleFile } from 'vite-plugin-singlefile' - +import vuetify from 'vite-plugin-vuetify' // https://vitejs.dev/config/ export default ({mode}: ConfigEnv) => { @@ -25,6 +25,7 @@ export default ({mode}: ConfigEnv) => { svgLoader(), cssInjectedByJsPlugin(), viteSingleFile(), + vuetify(), ], define: {}, resolve: {