diff --git a/app/package-lock.json b/app/package-lock.json
index 8201281..923306a 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -28,7 +28,9 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3",
"prettier": "^2.4.1",
- "typescript": "~4.5.5"
+ "typescript": "~4.5.5",
+ "unplugin-auto-import": "^0.17.5",
+ "unplugin-vue-components": "^0.26.0"
}
},
"node_modules/@achrinza/node-ipc": {
@@ -60,6 +62,16 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@antfu/utils": {
+ "version": "0.7.10",
+ "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz",
+ "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.26.2.tgz",
@@ -2105,6 +2117,42 @@
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
+ "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/@sideway/address": {
"version": "4.1.5",
"resolved": "https://registry.npmmirror.com/@sideway/address/-/address-4.1.5.tgz",
@@ -4802,6 +4850,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/confbox": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
+ "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/connect-history-api-fallback": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
@@ -6718,6 +6773,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/exsolve": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz",
+ "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -8299,6 +8361,23 @@
"json5": "lib/cli.js"
}
},
+ "node_modules/local-pkg": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz",
+ "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mlly": "^1.7.3",
+ "pkg-types": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
@@ -8887,6 +8966,19 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/mlly": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
+ "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "pathe": "^2.0.1",
+ "pkg-types": "^1.3.0",
+ "ufo": "^1.5.4"
+ }
+ },
"node_modules/module-alias": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz",
@@ -9532,6 +9624,13 @@
"node": ">=8"
}
},
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@@ -9564,6 +9663,18 @@
"node": ">=8"
}
},
+ "node_modules/pkg-types": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
+ "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.1.8",
+ "mlly": "^1.7.4",
+ "pathe": "^2.0.1"
+ }
+ },
"node_modules/portfinder": {
"version": "1.0.35",
"resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.35.tgz",
@@ -10424,6 +10535,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/quansync": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
+ "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -10859,6 +10987,13 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/scule": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",
+ "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz",
@@ -11490,6 +11625,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strip-literal": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz",
+ "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/strip-literal/node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -12017,6 +12172,13 @@
"node": ">=4.2.0"
}
},
+ "node_modules/ufo": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
+ "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.20.0.tgz",
@@ -12068,6 +12230,102 @@
"node": ">=4"
}
},
+ "node_modules/unimport": {
+ "version": "3.14.6",
+ "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.14.6.tgz",
+ "integrity": "sha512-CYvbDaTT04Rh8bmD8jz3WPmHYZRG/NnvYVzwD6V1YAlvvKROlAeNDUBhkBGzNav2RKaeuXvlWYaa1V4Lfi/O0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rollup/pluginutils": "^5.1.4",
+ "acorn": "^8.14.0",
+ "escape-string-regexp": "^5.0.0",
+ "estree-walker": "^3.0.3",
+ "fast-glob": "^3.3.3",
+ "local-pkg": "^1.0.0",
+ "magic-string": "^0.30.17",
+ "mlly": "^1.7.4",
+ "pathe": "^2.0.1",
+ "picomatch": "^4.0.2",
+ "pkg-types": "^1.3.0",
+ "scule": "^1.3.0",
+ "strip-literal": "^2.1.1",
+ "unplugin": "^1.16.1"
+ }
+ },
+ "node_modules/unimport/node_modules/confbox": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.1.tgz",
+ "integrity": "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unimport/node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/unimport/node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/unimport/node_modules/local-pkg": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
+ "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mlly": "^1.7.4",
+ "pkg-types": "^2.0.1",
+ "quansync": "^0.2.8"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/unimport/node_modules/local-pkg/node_modules/pkg-types": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",
+ "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.2.1",
+ "exsolve": "^1.0.1",
+ "pathe": "^2.0.3"
+ }
+ },
+ "node_modules/unimport/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
@@ -12088,6 +12346,165 @@
"node": ">= 0.8"
}
},
+ "node_modules/unplugin": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz",
+ "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "webpack-virtual-modules": "^0.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/unplugin-auto-import": {
+ "version": "0.17.8",
+ "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.17.8.tgz",
+ "integrity": "sha512-CHryj6HzJ+n4ASjzwHruD8arhbdl+UXvhuAIlHDs15Y/IMecG3wrf7FVg4pVH/DIysbq/n0phIjNHAjl7TG7Iw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/utils": "^0.7.10",
+ "@rollup/pluginutils": "^5.1.0",
+ "fast-glob": "^3.3.2",
+ "local-pkg": "^0.5.0",
+ "magic-string": "^0.30.10",
+ "minimatch": "^9.0.4",
+ "unimport": "^3.7.2",
+ "unplugin": "^1.11.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@nuxt/kit": "^3.2.2",
+ "@vueuse/core": "*"
+ },
+ "peerDependenciesMeta": {
+ "@nuxt/kit": {
+ "optional": true
+ },
+ "@vueuse/core": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/unplugin-auto-import/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/unplugin-auto-import/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/unplugin-vue-components": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.26.0.tgz",
+ "integrity": "sha512-s7IdPDlnOvPamjunVxw8kNgKNK8A5KM1YpK5j/p97jEKTjlPNrA0nZBiSfAKKlK1gWZuyWXlKL5dk3EDw874LQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/utils": "^0.7.6",
+ "@rollup/pluginutils": "^5.0.4",
+ "chokidar": "^3.5.3",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.1",
+ "local-pkg": "^0.4.3",
+ "magic-string": "^0.30.3",
+ "minimatch": "^9.0.3",
+ "resolve": "^1.22.4",
+ "unplugin": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@babel/parser": "^7.15.8",
+ "@nuxt/kit": "^3.2.2",
+ "vue": "2 || 3"
+ },
+ "peerDependenciesMeta": {
+ "@babel/parser": {
+ "optional": true
+ },
+ "@nuxt/kit": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/unplugin-vue-components/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/unplugin-vue-components/node_modules/local-pkg": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
+ "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/unplugin-vue-components/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/unplugin/node_modules/webpack-virtual-modules": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
diff --git a/app/package.json b/app/package.json
index 5246abd..d064b27 100644
--- a/app/package.json
+++ b/app/package.json
@@ -28,6 +28,8 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3",
"prettier": "^2.4.1",
- "typescript": "~4.5.5"
+ "typescript": "~4.5.5",
+ "unplugin-auto-import": "^0.17.5",
+ "unplugin-vue-components": "^0.26.0"
}
}
diff --git a/app/public/favicon.ico b/app/public/favicon.ico
deleted file mode 100644
index df36fcf..0000000
Binary files a/app/public/favicon.ico and /dev/null differ
diff --git a/app/public/protocol.svg b/app/public/favicon.svg
similarity index 100%
rename from app/public/protocol.svg
rename to app/public/favicon.svg
diff --git a/app/public/iconfont.css b/app/public/iconfont.css
index 5d91fb7..15fcef9 100644
--- a/app/public/iconfont.css
+++ b/app/public/iconfont.css
@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 4870215 */
- src: url('iconfont.woff2?t=1742911403305') format('woff2'),
- url('iconfont.woff?t=1742911403305') format('woff'),
- url('iconfont.ttf?t=1742911403305') format('truetype');
+ src: url('iconfont.woff2?t=1742978562991') format('woff2'),
+ url('iconfont.woff?t=1742978562991') format('woff'),
+ url('iconfont.ttf?t=1742978562991') format('truetype');
}
.iconfont {
@@ -13,6 +13,38 @@
-moz-osx-font-smoothing: grayscale;
}
+.icon-company:before {
+ content: "\e6f5";
+}
+
+.icon-token:before {
+ content: "\e68f";
+}
+
+.icon-url-line:before {
+ content: "\ea38";
+}
+
+.icon-llm:before {
+ content: "\e8be";
+}
+
+.icon-bg-colors:before {
+ content: "\e800";
+}
+
+.icon-i18n:before {
+ content: "\e601";
+}
+
+.icon-weixin:before {
+ content: "\e600";
+}
+
+.icon-QQ:before {
+ content: "\e882";
+}
+
.icon-debug:before {
content: "\e76d";
}
diff --git a/app/public/iconfont.woff2 b/app/public/iconfont.woff2
index 1e4dc17..f45d776 100644
Binary files a/app/public/iconfont.woff2 and b/app/public/iconfont.woff2 differ
diff --git a/app/public/images/deepseek.com.ico b/app/public/images/deepseek.com.ico
new file mode 100644
index 0000000..8e78c0b
Binary files /dev/null and b/app/public/images/deepseek.com.ico differ
diff --git a/app/public/images/grok.com.png b/app/public/images/grok.com.png
new file mode 100644
index 0000000..e854e05
Binary files /dev/null and b/app/public/images/grok.com.png differ
diff --git a/app/public/images/gstatic.com.svg b/app/public/images/gstatic.com.svg
new file mode 100644
index 0000000..4a94330
--- /dev/null
+++ b/app/public/images/gstatic.com.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/public/images/kimichat.cn.png b/app/public/images/kimichat.cn.png
new file mode 100644
index 0000000..75d1244
Binary files /dev/null and b/app/public/images/kimichat.cn.png differ
diff --git a/app/public/images/mistral.ai.ico b/app/public/images/mistral.ai.ico
new file mode 100644
index 0000000..6f5b731
Binary files /dev/null and b/app/public/images/mistral.ai.ico differ
diff --git a/app/public/images/ollama.png b/app/public/images/ollama.png
new file mode 100644
index 0000000..f938b51
Binary files /dev/null and b/app/public/images/ollama.png differ
diff --git a/app/public/images/openai.com.ico b/app/public/images/openai.com.ico
new file mode 100644
index 0000000..0b6b8a6
Binary files /dev/null and b/app/public/images/openai.com.ico differ
diff --git a/app/public/images/openmcp-qq-qrcode.jpg b/app/public/images/openmcp-qq-qrcode.jpg
new file mode 100644
index 0000000..003b4cb
Binary files /dev/null and b/app/public/images/openmcp-qq-qrcode.jpg differ
diff --git a/app/public/images/openmcp.svg b/app/public/images/openmcp.svg
new file mode 100644
index 0000000..885bcdd
--- /dev/null
+++ b/app/public/images/openmcp.svg
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/public/images/perplexity.ai.ico b/app/public/images/perplexity.ai.ico
new file mode 100644
index 0000000..a17ffc4
Binary files /dev/null and b/app/public/images/perplexity.ai.ico differ
diff --git a/app/public/index.html b/app/public/index.html
index cefc281..38e5d7c 100644
--- a/app/public/index.html
+++ b/app/public/index.html
@@ -5,7 +5,7 @@
-
+
diff --git a/app/src/App.vue b/app/src/App.vue
index 850d81c..8465e98 100644
--- a/app/src/App.vue
+++ b/app/src/App.vue
@@ -11,12 +11,17 @@ import { Connection } from './components/sidebar/sidebar';
import Sidebar from '@/components/sidebar/index.vue';
import MainPanel from '@/components/main-panel/index.vue';
+import { setDefaultCss } from './hook/css';
+import { pinkLog } from './views/setting/util';
onMounted(() => {
+ setDefaultCss();
document.addEventListener('click', () => {
Connection.showPanel = false;
});
+
+ pinkLog('OpenMCP Client 启动');
})
diff --git a/app/src/components/main-panel/index.vue b/app/src/components/main-panel/index.vue
index 15f0fbb..e9879a0 100644
--- a/app/src/components/main-panel/index.vue
+++ b/app/src/components/main-panel/index.vue
@@ -31,6 +31,7 @@ defineComponent({ name: 'main-panel' });
justify-content: center;
flex-direction: column;
width: 100%;
+ min-width: 800px;
height: 100%;
margin-left: 20px;
}
diff --git a/app/src/components/sidebar/mcp-title.vue b/app/src/components/sidebar/mcp-title.vue
index 7033605..9edc574 100644
--- a/app/src/components/sidebar/mcp-title.vue
+++ b/app/src/components/sidebar/mcp-title.vue
@@ -1,6 +1,6 @@
-
+
OpenMCP
diff --git a/app/src/components/sidebar/sidebar-item-container.vue b/app/src/components/sidebar/sidebar-item-container.vue
index 6ff5119..92a8390 100644
--- a/app/src/components/sidebar/sidebar-item-container.vue
+++ b/app/src/components/sidebar/sidebar-item-container.vue
@@ -8,13 +8,14 @@
@click="gotoOption(item.ident)"
>
- {{ item.name }}
+ {{ t(item.ident) }}
\ No newline at end of file
diff --git a/app/src/views/debug/welcome.vue b/app/src/views/debug/welcome.vue
index f225449..c66364f 100644
--- a/app/src/views/debug/welcome.vue
+++ b/app/src/views/debug/welcome.vue
@@ -1,6 +1,6 @@
-
选择一个项目进行调试
+
{{ t('choose-a-project-debug') }}
\ No newline at end of file
diff --git a/app/src/views/setting/api.vue b/app/src/views/setting/api.vue
new file mode 100644
index 0000000..8a50108
--- /dev/null
+++ b/app/src/views/setting/api.vue
@@ -0,0 +1,94 @@
+
+
+
{{ "API" }}
+
+
+
+ {{ t('server-provider') }}
+
+
+
+
+
+
+
+
{{ option.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('model') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('api-root-url') }}
+
+
+
+
+
+
+
+
+
+ {{ t('api-token') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/views/setting/appearance.vue b/app/src/views/setting/appearance.vue
new file mode 100644
index 0000000..c05daba
--- /dev/null
+++ b/app/src/views/setting/appearance.vue
@@ -0,0 +1,42 @@
+
+
+
{{ t('general-setting') }}
+
+
+
+ {{ t('language-setting') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/views/setting/color.ts b/app/src/views/setting/color.ts
new file mode 100644
index 0000000..1c460c6
--- /dev/null
+++ b/app/src/views/setting/color.ts
@@ -0,0 +1,45 @@
+import { reactive } from 'vue';
+
+import i18n from '@/i18n';
+import { parseColor } from '@/hook/color';
+import { globalSetting } from '@/hook/global';
+
+const { t, locale } = i18n.global;
+locale.value = globalSetting.language;
+
+export const colorManager = reactive({
+ mainColor: 'white',
+
+ initColor() {
+ const rootStyles = getComputedStyle(document.documentElement);
+ this.mainColor = rootStyles.getPropertyValue('--main-color');
+ }
+});
+
+/**
+ * @description 通用颜色设置发生变时
+ * @param {string} colorString 用户选择的颜色的字符串
+ */
+export function onGeneralColorChange(colorString: string) {
+ const color = parseColor(colorString);
+ if (!color) {
+ return;
+ }
+ const { r, g, b } = color;
+
+ document.documentElement.style.setProperty(
+ '--main-color', `rgb(${r}, ${g}, ${b})`);
+
+ document.documentElement.style.setProperty(
+ '--main-light-color', `rgba(${r}, ${g}, ${b}, 0.7)`);
+}
+
+export const predefinedColors = [
+ '#ff4500',
+ '#ff8c00',
+ '#ffd700',
+ '#90ee90',
+ '#00ced1',
+ '#1e90ff',
+ '#c71585'
+];
\ No newline at end of file
diff --git a/app/src/views/setting/general.vue b/app/src/views/setting/general.vue
new file mode 100644
index 0000000..42ae8dd
--- /dev/null
+++ b/app/src/views/setting/general.vue
@@ -0,0 +1,29 @@
+
+
+
{{ t('appearance-setting') }}
+
+
+
+
+ {{ t('setting.general-color-setting') }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/views/setting/index.vue b/app/src/views/setting/index.vue
index efbf924..ecfeaca 100644
--- a/app/src/views/setting/index.vue
+++ b/app/src/views/setting/index.vue
@@ -1,12 +1,116 @@
-
+
\ No newline at end of file
diff --git a/app/src/views/setting/language.ts b/app/src/views/setting/language.ts
new file mode 100644
index 0000000..23f0c17
--- /dev/null
+++ b/app/src/views/setting/language.ts
@@ -0,0 +1,42 @@
+import { reactive } from 'vue';
+
+export const languageSetting = reactive({
+ options: [
+ {
+ value: 'en',
+ text: 'English'
+ },
+ {
+ value: 'zh',
+ text: '简体中文'
+ },
+ {
+ value: 'zhTw',
+ text: '繁體中文'
+ },
+ {
+ value: 'ja',
+ text: '日本語'
+ },
+ {
+ value: 'ko',
+ text: '한국어'
+ },
+ {
+ value: 'de',
+ text: 'Deutsch'
+ },
+ {
+ value: 'fr',
+ text: 'Français'
+ },
+ {
+ value: 'ru',
+ text: 'Русский'
+ },
+ {
+ value: 'ar',
+ text: 'العربية'
+ }
+ ]
+});
diff --git a/app/src/views/setting/llm.ts b/app/src/views/setting/llm.ts
new file mode 100644
index 0000000..8e5850c
--- /dev/null
+++ b/app/src/views/setting/llm.ts
@@ -0,0 +1,114 @@
+import { reactive } from 'vue';
+
+export const llms = reactive([
+ {
+ id: 'deepseek',
+ name: 'DeepSeek',
+ baseUrl: 'https://api.deepseek.com/v1',
+ models: ['deepseek-chat', 'deepseek-coder', 'deepseek-math'],
+ icon: '/images/deepseek.com.ico',
+ provider: 'DeepSeek',
+ isOpenAICompatible: true,
+ description: '深度求索推出的大模型,擅长中文和代码',
+ website: 'https://www.deepseek.com',
+ userToken: '',
+ userModel: 'deepseek-chat'
+ },
+ {
+ id: 'openai',
+ name: 'OpenAI',
+ baseUrl: 'https://api.openai.com/v1',
+ models: ['gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo'],
+ icon: '/images/openai.com.ico',
+ provider: 'OpenAI',
+ isOpenAICompatible: true,
+ description: 'OpenAI官方API',
+ website: 'https://openai.com',
+ userToken: '',
+ userModel: 'gpt-4-turbo'
+ },
+ {
+ id: 'mistral',
+ name: 'Mistral',
+ baseUrl: 'https://api.mistral.ai/v1',
+ models: ['mistral-tiny', 'mistral-small', 'mistral-medium'],
+ icon: '/images/mistral.ai.ico',
+ provider: 'Mistral AI',
+ isOpenAICompatible: true,
+ description: '欧洲开源大模型代表',
+ website: 'https://mistral.ai',
+ userToken: '',
+ userModel: 'mistral-tiny'
+ },
+ {
+ id: 'ollama',
+ name: 'Ollama (Local)',
+ baseUrl: 'http://localhost:11434/v1',
+ models: ['llama2', 'mistral', 'codellama'],
+ icon: '/images/ollama.png',
+ provider: 'Ollama',
+ isOpenAICompatible: true,
+ description: '本地运行的大模型',
+ website: 'https://ollama.com',
+ userToken: '',
+ userModel: 'llama2'
+ },
+ {
+ id: 'groq',
+ name: 'Groq',
+ baseUrl: 'https://api.groq.com/openai/v1',
+ models: ['mixtral-8x7b-32768', 'llama2-70b-4096'],
+ icon: '/images/grok.com.png',
+ provider: 'Groq',
+ isOpenAICompatible: true,
+ description: '超高速推理API',
+ website: 'https://groq.com',
+ userToken: '',
+ userModel: 'mixtral-8x7b-32768'
+ },
+ {
+ id: 'perplexity',
+ name: 'Perplexity',
+ baseUrl: 'https://api.perplexity.ai/v1',
+ models: ['pplx-7b-online', 'pplx-70b-online'],
+ icon: '/images/perplexity.ai.ico',
+ provider: 'Perplexity AI',
+ isOpenAICompatible: true,
+ description: '联网搜索增强的大模型',
+ website: 'https://www.perplexity.ai',
+ userToken: '',
+ userModel: 'pplx-7b-online'
+ },
+ {
+ id: 'kimi',
+ name: 'Kimi Chat',
+ baseUrl: 'https://api.moonshot.cn/v1',
+ models: ['moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k'],
+ icon: '/images/kimichat.cn.png',
+ provider: '月之暗面 (Moonshot AI)',
+ isOpenAICompatible: true,
+ description: '支持超长上下文的中文大模型,上下文窗口高达128K',
+ website: 'https://kimi.moonshot.cn',
+ userToken: '',
+ userModel: 'moonshot-v1-8k'
+ }
+]);
+
+export const llmManager = reactive({
+ currentModelIndex: 0,
+});
+
+export function onmodelchange() {
+ console.log();
+
+}
+
+export async function save() {
+ console.log();
+
+}
+
+export async function load() {
+ console.log();
+
+}
\ No newline at end of file
diff --git a/app/src/views/setting/util.ts b/app/src/views/setting/util.ts
new file mode 100644
index 0000000..7531abd
--- /dev/null
+++ b/app/src/views/setting/util.ts
@@ -0,0 +1,10 @@
+const pinkLogStyle = 'background-color: #CB81DA; color: white; padding: 3px; border-radius: 3px;';
+const redLogStyle = 'background-color:rgb(227, 91, 49); color: white; padding: 3px; border-radius: 3px;';
+
+export function pinkLog(message: string) {
+ console.log('%c' + message, pinkLogStyle);
+}
+
+export function redLog(message: string) {
+ console.log('%c' + message, redLogStyle);
+}
\ No newline at end of file
diff --git a/app/tsconfig.json b/app/tsconfig.json
index b047527..6e25c86 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -1,41 +1,41 @@
{
- "compilerOptions": {
- "target": "esnext",
- "module": "esnext",
- "strict": true,
- "jsx": "preserve",
- "moduleResolution": "node",
- "skipLibCheck": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "forceConsistentCasingInFileNames": true,
- "resolveJsonModule": true,
- "useDefineForClassFields": true,
- "sourceMap": true,
- "baseUrl": ".",
- "types": [
- "webpack-env"
- ],
- "paths": {
- "@/*": [
- "src/*"
- ]
- },
- "lib": [
- "esnext",
- "dom",
- "dom.iterable",
- "scripthost"
- ]
- },
- "include": [
- "src/**/*.ts",
- "src/**/*.tsx",
- "src/**/*.vue",
- "tests/**/*.ts",
- "tests/**/*.tsx"
- ],
- "exclude": [
- "node_modules"
- ]
-}
+ "compilerOptions": {
+ "target": "esnext",
+ "module": "esnext",
+ "strict": true,
+ "jsx": "preserve",
+ "moduleResolution": "node",
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "useDefineForClassFields": true,
+ "sourceMap": true,
+ "baseUrl": ".",
+ "types": [
+ "webpack-env"
+ ],
+ "paths": {
+ "@/*": [
+ "src/*"
+ ]
+ },
+ "lib": [
+ "esnext",
+ "dom",
+ "dom.iterable",
+ "scripthost"
+ ]
+ },
+ "include": [
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ "src/**/*.vue",
+ "tests/**/*.ts",
+ "tests/**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/app/webpack.config.js b/app/webpack.config.js
new file mode 100644
index 0000000..f942304
--- /dev/null
+++ b/app/webpack.config.js
@@ -0,0 +1,22 @@
+const AutoImport = require('unplugin-auto-import/webpack')
+const Components = require('unplugin-vue-components/webpack')
+const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
+
+module.exports = {
+ plugins: [
+ AutoImport({
+ resolvers: [ElementPlusResolver()],
+ }),
+ Components({
+ resolvers: [ElementPlusResolver()],
+ }),
+ new webpack.DefinePlugin({
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
+ })
+ ],
+ resolve: {
+ fallback: {
+ "stream": false
+ }
+ },
+};
\ No newline at end of file