Browse Source

add

develop
谢亚昕 1 week ago
parent
commit
f1833df97b
  1. 2
      electron.vite.config.ts
  2. 3
      package.json
  3. 10
      packages/helper/updater/main/index.ts
  4. 86
      pnpm-lock.yaml
  5. 57
      src/common/event/Updater/hook.ts
  6. 6
      src/renderer/about.html
  7. 2
      src/renderer/components.d.ts
  8. 1
      src/renderer/src/assets/style/_common.scss
  9. 5
      src/renderer/src/assets/style/global/_index.scss
  10. 4
      src/renderer/src/main.ts
  11. 7
      src/renderer/src/pages/index/index.vue
  12. 130
      src/renderer/src/pages/setting/index.vue
  13. 31
      src/renderer/src/ui/NavBar.vue
  14. 78
      src/renderer/src/ui/Update.vue
  15. 4
      src/types/global.d.ts

2
electron.vite.config.ts

@ -50,7 +50,7 @@ export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/style/global" as *;\n`,
additionalData: `@use "@/assets/style/global/_index.scss";\n`,
api: "modern-compiler",
},
},

3
package.json

@ -51,6 +51,7 @@
"@vue/eslint-config-typescript": "^13.0.0",
"@vueuse/core": "^12.7.0",
"base": "workspace:*",
"bulma": "^1.0.4",
"debug": "^4.4.0",
"electron": "^31.7.7",
"electron-builder": "^24.13.3",
@ -73,12 +74,12 @@
"simplebar-vue": "^2.4.0",
"typescript": "^5.7.3",
"unocss": "^0.64.1",
"utils": "workspace:*",
"unplugin-auto-import": "^19.1.0",
"unplugin-icons": "^22.1.0",
"unplugin-vue-components": "^28.4.0",
"unplugin-vue-macros": "^2.14.2",
"unplugin-vue-router": "^0.11.2",
"utils": "workspace:*",
"vite": "^5.4.14",
"vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-vue-layouts": "^0.11.0",

10
packages/helper/updater/main/index.ts

@ -83,7 +83,7 @@ class _Updater extends BaseSingleton {
this.autoUpdater.on("update-available", info => {
logger.debug("Update available:", info)
this.events.emit("update-available", info)
this.promptUserToUpdate()
this.promptUserToUpdate(info.releaseNotes)
})
// 没有可用更新
@ -134,18 +134,18 @@ class _Updater extends BaseSingleton {
async checkForUpdates() {
try {
this.autoUpdater.checkForUpdates()
logger.debug("Updater初始化检查成功.")
logger.debug("Update开始检查更新.")
await this.autoUpdater.checkForUpdates()
} catch (error) {
logger.debug("Failed to check for updates:", error)
}
}
private async promptUserToUpdate() {
private async promptUserToUpdate(releaseNotes) {
const result = await dialog.showMessageBox({
type: "info",
title: "发现新版本",
message: "是否下载新版本?",
message: releaseNotes, // "是否下载新版本?",
buttons: ["下载", "暂不更新"],
defaultId: 0,
})

86
pnpm-lock.yaml

@ -81,6 +81,9 @@ importers:
base:
specifier: workspace:*
version: link:packages/base
bulma:
specifier: ^1.0.4
version: 1.0.4
debug:
specifier: ^4.4.0
version: 4.4.0
@ -146,7 +149,7 @@ importers:
version: 5.7.3
unocss:
specifier: ^0.64.1
version: 0.64.1(postcss@8.4.49)(rollup@4.26.0)(vite@5.4.14(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))
version: 0.64.1(postcss@8.5.4)(rollup@4.26.0)(vite@5.4.14(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))
unplugin-auto-import:
specifier: ^19.1.0
version: 19.1.0(@nuxt/kit@3.16.2)(@vueuse/core@12.7.0(typescript@5.7.3))
@ -773,20 +776,20 @@ packages:
resolution: {integrity: sha512-4iEsUZ3aF7jXY19CJFN5VP+pPyLITD9FVsjB13z9TU1UxaZLlFsmNhvRxlPDSOfHAP5RpNF2QKKdZ3DHVf4Yzw==}
engines: {node: '>= 16'}
'@intlify/message-compiler@12.0.0-alpha.2':
resolution: {integrity: sha512-PD9C+oQbb7BF52hec0+vLnScaFkvnfX+R7zSbODYuRo/E2niAtGmHd0wPvEMsDhf9Z9b8f/qyDsVeZnD/ya9Ug==}
'@intlify/message-compiler@12.0.0-alpha.3':
resolution: {integrity: sha512-mDDTN3gfYOHhBnpnlby19UHyvMaOnzdlpsIrxUfs44R/vCATfn8pMOkE8PXD2t410xkocEj3FpDcC9XC/0v4Dg==}
engines: {node: '>= 16'}
'@intlify/shared@11.1.1':
resolution: {integrity: sha512-2kGiWoXaeV8HZlhU/Nml12oTbhv7j2ufsJ5vQaa0VTjzUmZVdd/nmKFRAOJ/FtjO90Qba5AnZDwsrY7ZND5udA==}
engines: {node: '>= 16'}
'@intlify/shared@11.1.5':
resolution: {integrity: sha512-+I4vRzHm38VjLr/CAciEPJhGYFzWWW4HMTm+6H3WqknXLh0ozNX9oC8ogMUwTSXYR/wGUb1/lTpNziiCH5MybQ==}
'@intlify/shared@11.1.11':
resolution: {integrity: sha512-RIBFTIqxZSsxUqlcyoR7iiC632bq7kkOwYvZlvcVObHfrF4NhuKc4FKvu8iPCrEO+e3XsY7/UVpfgzg+M7ETzA==}
engines: {node: '>= 16'}
'@intlify/shared@12.0.0-alpha.2':
resolution: {integrity: sha512-P2DULVX9nz3y8zKNqLw9Es1aAgQ1JGC+kgpx5q7yLmrnAKkPR5MybQWoEhxanefNJgUY5ehsgo+GKif59SrncA==}
'@intlify/shared@12.0.0-alpha.3':
resolution: {integrity: sha512-ryaNYBvxQjyJUmVuBBg+HHUsmGnfxcEUPR0NCeG4/K9N2qtyFE35C80S15IN6iYFE2MGWLN7HfOSyg0MXZIc9w==}
engines: {node: '>= 16'}
'@intlify/unplugin-vue-i18n@6.0.3':
@ -904,25 +907,21 @@ packages:
resolution: {integrity: sha512-eEwxY+0Cf76HnQwr1+Qy48qwf4dAebTHaKhzEgxLqLK6szbglnK6SThjY95YHrYWwsH1GujWiFoX51jwZNYfSw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-arm64-musl@3.0.3':
resolution: {integrity: sha512-LdxbLv8qVkzro4/ZoP9MuytIL6NOVsbhoZ5Wl1KXOa/2DSxBiksrAPMSChCTyeLy6P3ebSHxQSb52ku18t1LBA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-linux-x64-gnu@3.0.3':
resolution: {integrity: sha512-bN8elR9AV/DZZPdcteOWWElkz8KyxLtOvmfVl7Dnehcs6f9e+fWYKyqiKvva1jsxG4znGKCPT1gfMhpYW8QuKg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-x64-musl@3.0.3':
resolution: {integrity: sha512-Zy1U49BjriwbAds2ho6CGjZIk2KVn0+lrc/G5bvhQg7UJYxEkAueMGBuA5rULIhx9xVtIPsT9Q+J5Xhb4ffVNw==}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-wasm32-wasi@3.0.3':
resolution: {integrity: sha512-7rteQnn7i5f9nkFZs1VRdBqFhvOx3zWavyKkWjXYVxc9vsSLTg0moh2MRZw5dw5m/bEi1u/p3YAKJ9gdHyBhNQ==}
@ -968,42 +967,36 @@ packages:
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-arm-musl@2.5.0':
resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
libc: [musl]
'@parcel/watcher-linux-arm64-glibc@2.5.0':
resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-arm64-musl@2.5.0':
resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@parcel/watcher-linux-x64-glibc@2.5.0':
resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-x64-musl@2.5.0':
resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
'@parcel/watcher-win32-arm64@2.5.0':
resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==}
@ -1090,55 +1083,46 @@ packages:
resolution: {integrity: sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.26.0':
resolution: {integrity: sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.26.0':
resolution: {integrity: sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.26.0':
resolution: {integrity: sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-powerpc64le-gnu@4.26.0':
resolution: {integrity: sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.26.0':
resolution: {integrity: sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.26.0':
resolution: {integrity: sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.26.0':
resolution: {integrity: sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.26.0':
resolution: {integrity: sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.26.0':
resolution: {integrity: sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==}
@ -1853,6 +1837,9 @@ packages:
builder-util@24.13.1:
resolution: {integrity: sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==}
bulma@1.0.4:
resolution: {integrity: sha512-Ffb6YGXDiZYX3cqvSbHWqQ8+LkX6tVoTcZuVB3lm93sbAVXlO0D6QlOTMnV6g18gILpAXqkG2z9hf9z4hCjz2g==}
bundle-require@5.0.0:
resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -2890,6 +2877,11 @@ packages:
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@ -3068,6 +3060,10 @@ packages:
resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
engines: {node: ^10 || ^12 || >=14}
postcss@8.5.4:
resolution: {integrity: sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==}
engines: {node: ^10 || ^12 || >=14}
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@ -4331,8 +4327,8 @@ snapshots:
'@intlify/bundle-utils@10.0.0(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))':
dependencies:
'@intlify/message-compiler': 12.0.0-alpha.2
'@intlify/shared': 12.0.0-alpha.2
'@intlify/message-compiler': 12.0.0-alpha.3
'@intlify/shared': 12.0.0-alpha.3
acorn: 8.14.0
escodegen: 2.1.0
estree-walker: 2.0.2
@ -4353,23 +4349,23 @@ snapshots:
'@intlify/shared': 11.1.1
source-map-js: 1.2.1
'@intlify/message-compiler@12.0.0-alpha.2':
'@intlify/message-compiler@12.0.0-alpha.3':
dependencies:
'@intlify/shared': 12.0.0-alpha.2
'@intlify/shared': 12.0.0-alpha.3
source-map-js: 1.2.1
'@intlify/shared@11.1.1': {}
'@intlify/shared@11.1.5': {}
'@intlify/shared@11.1.11': {}
'@intlify/shared@12.0.0-alpha.2': {}
'@intlify/shared@12.0.0-alpha.3': {}
'@intlify/unplugin-vue-i18n@6.0.3(@vue/compiler-dom@3.5.13)(eslint@8.57.1)(rollup@4.26.0)(typescript@5.7.3)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
'@intlify/bundle-utils': 10.0.0(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))
'@intlify/shared': 11.1.5
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.5)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
'@intlify/shared': 11.1.11
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.11)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
'@rollup/pluginutils': 5.1.4(rollup@4.26.0)
'@typescript-eslint/scope-manager': 8.25.0
'@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3)
@ -4391,11 +4387,11 @@ snapshots:
- supports-color
- typescript
'@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.5)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))':
'@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.11)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@babel/parser': 7.26.9
optionalDependencies:
'@intlify/shared': 11.1.5
'@intlify/shared': 11.1.11
'@vue/compiler-dom': 3.5.13
vue: 3.5.13(typescript@5.7.3)
vue-i18n: 11.1.1(vue@3.5.13(typescript@5.7.3))
@ -4902,13 +4898,13 @@ snapshots:
transitivePeerDependencies:
- vue
'@unocss/postcss@0.64.1(postcss@8.4.49)':
'@unocss/postcss@0.64.1(postcss@8.5.4)':
dependencies:
'@unocss/config': 0.64.1
'@unocss/core': 0.64.1
'@unocss/rule-utils': 0.64.1
css-tree: 3.0.1
postcss: 8.4.49
postcss: 8.5.4
tinyglobby: 0.2.10
transitivePeerDependencies:
- supports-color
@ -5674,6 +5670,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
bulma@1.0.4: {}
bundle-require@5.0.0(esbuild@0.21.5):
dependencies:
esbuild: 0.21.5
@ -6837,6 +6835,8 @@ snapshots:
muggle-string@0.4.1: {}
nanoid@3.3.11: {}
nanoid@3.3.7: {}
natural-compare@1.4.0: {}
@ -7015,6 +7015,12 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
postcss@8.5.4:
dependencies:
nanoid: 3.3.11
picocolors: 1.1.1
source-map-js: 1.2.1
prelude-ls@1.2.1: {}
prettier-linter-helpers@1.0.0:
@ -7476,12 +7482,12 @@ snapshots:
universalify@2.0.1: {}
unocss@0.64.1(postcss@8.4.49)(rollup@4.26.0)(vite@5.4.14(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)):
unocss@0.64.1(postcss@8.5.4)(rollup@4.26.0)(vite@5.4.14(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3)):
dependencies:
'@unocss/astro': 0.64.1(rollup@4.26.0)(vite@5.4.14(@types/node@20.17.19)(sass@1.85.0))(vue@3.5.13(typescript@5.7.3))
'@unocss/cli': 0.64.1(rollup@4.26.0)
'@unocss/core': 0.64.1
'@unocss/postcss': 0.64.1(postcss@8.4.49)
'@unocss/postcss': 0.64.1(postcss@8.5.4)
'@unocss/preset-attributify': 0.64.1
'@unocss/preset-icons': 0.64.1
'@unocss/preset-mini': 0.64.1

57
src/common/event/Updater/hook.ts

@ -1,39 +1,66 @@
import { EventMaps, UpdaterCommand } from "helper/updater/common"
import { defineStore } from "pinia"
export const enum UpdaterStatus {
Idle = "idle",
Checking = "checking",
StartChecking = "start-checking",
UpdateAvailable = "update-available",
UpdateNotAvailable = "update-not-available",
Downloading = "downloading",
Error = "error",
}
export const useUpdaterStore = defineStore(
"Updater",
() => {
const curStatus = ref(UpdaterStatus.Idle)
const speed = ref(0)
const percent = ref(0)
const all = ref(0)
const now = ref(0)
const isNeedUpdate = ref(false)
const isChecking = ref(false)
const api = getApi<UpdaterCommand, EventMaps, "UpdaterCommand">()
api.on("error", (_, data) => {
isChecking.value = false
curStatus.value = UpdaterStatus.Error
console.log(data)
})
api.on("update-not-available", (_, data) => {
isChecking.value = false
console.log(data)
api.on("update-not-available", () => {
curStatus.value = UpdaterStatus.UpdateNotAvailable
isNeedUpdate.value = false
})
api.on("update-available", (_, data) => {
isChecking.value = false
api.on("update-available", () => {
curStatus.value = UpdaterStatus.UpdateAvailable
isNeedUpdate.value = true
console.log(data)
})
api.on("update-progress", (_, data) => {
console.log(data)
curStatus.value = UpdaterStatus.Downloading
speed.value = +(data.speed / 1000).toFixed(2) // Convert to KB/s
percent.value = data.percent
all.value = data.all
now.value = data.now
isNeedUpdate.value = false
})
api.on("checking-for-update", () => {
isChecking.value = true
curStatus.value = UpdaterStatus.Checking
})
api.call("UpdaterCommand.checkForUpdates")
if (import.meta.env.PROD) {
api.callLong("UpdaterCommand.checkForUpdates")
}
return {
isChecking,
status: curStatus,
speed: speed,
percent: percent,
all: all,
now: now,
isNeedUpdate,
checkForUpdates() {
if (isChecking.value) return
api.call("UpdaterCommand.checkForUpdates")
if (curStatus.value === UpdaterStatus.Checking) return
if (curStatus.value === UpdaterStatus.Downloading) return
curStatus.value = UpdaterStatus.StartChecking
api.callLong("UpdaterCommand.checkForUpdates")
},
}
},

6
src/renderer/about.html

@ -4,7 +4,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>关于</title>
<title>关于本应用</title>
<style>
html,
body {
@ -22,9 +22,9 @@
<body>
<article>
<h1>环境</h1>
<h1>关于</h1>
<ul>
<li>111</li>
<li>MIT开源</li>
</ul>
</article>
</body>

2
src/renderer/components.d.ts

@ -10,6 +10,7 @@ declare module 'vue' {
export interface GlobalComponents {
AdjustLine: typeof import('./src/components/AdjustLine.vue')['default']
CodeEditor: typeof import('./src/components/CodeEditor/code-editor.vue')['default']
'IconBxs:error': typeof import('~icons/bxs/error')['default']
IconFluentCollections24Regular: typeof import('~icons/fluent/collections24-regular')['default']
'IconGrommetIcons:update': typeof import('~icons/grommet-icons/update')['default']
IconHugeiconsInbox: typeof import('~icons/hugeicons/inbox')['default']
@ -20,6 +21,7 @@ declare module 'vue' {
NavBar: typeof import('./src/ui/NavBar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Update: typeof import('./src/ui/Update.vue')['default']
Versions: typeof import('./src/components/Versions.vue')['default']
}
}

1
src/renderer/src/assets/style/_common.scss

@ -11,6 +11,7 @@ html {
--text-hover: #000000;
height: 100%;
color: var(--text-normal);
overflow: hidden;
}
body {

5
src/renderer/src/assets/style/global/_index.scss

@ -0,0 +1,5 @@
@use "bulma/sass/base";
@use "bulma/sass/themes";
@use "bulma/sass/elements/button";
@use "bulma/sass/form/input-textarea";

4
src/renderer/src/main.ts

@ -1,9 +1,9 @@
import 'logger/renderer-error'
import "logger/renderer-error"
import "simplebar-vue/dist/simplebar.min.css"
import "@unocss/reset/normalize.css"
import "@/assets/style/_common.scss"
import "virtual:uno.css"
import 'nprogress/nprogress.css';
import "nprogress/nprogress.css"
import { createApp } from "vue"
import App from "./App.vue"

7
src/renderer/src/pages/index/index.vue

@ -6,15 +6,16 @@
<template>
<div gap="20px" h-full>
<div p="20px" flex flex-wrap items-start gap="20px" justify-start>
<div w="calc((100%-4*20px)/5)" shadow v-for="i in 10" :key="i">
<div p-2 text-lg font-bold>导航站</div>
<div p="20px" flex flex-wrap items-start gap="20px" justify-start rounded>
<div class="w-[calc((100%-4*20px)/5)] <lg:w-[calc((100%-2*20px)/3)]" shadow v-for="i in 20" :key="i">
<div p-2 text-lg font-bold>MarkdownUtils</div>
<div p-2 pt-0 text-sm>这是一个导航站</div>
<div flex gap="10px" px-4 py-2 tex border-t="1px solid #E5E5E5">
<div cursor="pointer" text-sm leading-1 py-2 px-3 border="1px solid #E5E5E5" rounded>查看</div>
<div cursor="pointer" text-sm leading-1 py-2 px-3 border="1px solid #E5E5E5" rounded>访问</div>
</div>
</div>
<button class="button">Button</button>
<button @click="UpdaterStore.checkForUpdates()">更新</button>
</div>
</div>

130
src/renderer/src/pages/setting/index.vue

@ -1,18 +1,126 @@
<script setup lang="ts">
import Simplebar from "simplebar-vue"
import { useSettingStore } from "common/event/Setting/hook"
const settingStore = useSettingStore()
console.log(settingStore.config)
</script>
<template>
<div h-full flex>
<div w="200px" border-r="#E5E5E5 solid 1px">左侧菜单</div>
<Simplebar w="100px" border-r="#E5E5E5 solid 1px">
<div py-2 hover:bg-gray-100 cursor-pointer text-center text-sm>基础设置</div>
<div py-2 hover:bg-gray-100 cursor-pointer text-center text-sm>更新设置</div>
</Simplebar>
<div flex="1" w="0">
{{ settingStore.isSame }}--{{ settingStore.diffKeys }}
<input v-model="settingStore.config['update.repo']" type="text" />
{{ settingStore.config["update.repo"] }}
<button v-if="!settingStore.isSame" :disabled="settingStore.isSaving" @click="settingStore.save()">保存</button>
<div class="form">
<div class="form-item" :class="{ ['not-save']: settingStore.diffKeys.includes('storagePath') }">
<div class="form-item__label">存储地址</div>
<div class="form-item__value">
<div class="input-wrapper">
<input v-model="settingStore.config['storagePath']" class="input" readonly type="text" placeholder="请输入存储地址" />
</div>
</div>
</div>
<div class="form-item" :class="{ ['not-save']: settingStore.diffKeys.includes('common.theme') }">
<div class="form-item__label">主题</div>
<div class="form-item__value">
<div class="radio-group">
<div
class="radio"
:class="{ active: settingStore.config['common.theme'] === 'auto' }"
@click="settingStore.config['common.theme'] = 'auto'"
>
Auto
</div>
<div
class="radio"
:class="{ active: settingStore.config['common.theme'] === 'light' }"
@click="settingStore.config['common.theme'] = 'light'"
>
亮色
</div>
<div
class="radio"
:class="{ active: settingStore.config['common.theme'] === 'dark' }"
@click="settingStore.config['common.theme'] = 'dark'"
>
暗色
</div>
</div>
</div>
</div>
</div>
<div v-if="!settingStore.isSame" text-center>
<button class="submit" :disabled="settingStore.isSaving" @click="settingStore.save()">保存</button>
<button :disabled="settingStore.isSaving" @click="settingStore.reset()">重置</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useSettingStore } from "common/event/Setting/hook"
const settingStore = useSettingStore()
console.log(settingStore.config)
</script>
<style lang="scss" scoped>
.form {
padding: 20px;
.form-item {
display: flex;
align-items: center;
+ .form-item {
margin-top: 15px;
}
.form-item__label {
width: 100px;
font-weight: bold;
flex-basis: 100px;
}
.form-item__value {
width: 300px;
}
}
}
.submit {
margin: 20px;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
&:disabled {
background-color: #ccc;
cursor: not-allowed;
}
}
// .input-wrapper {
// .input {
// width: 100%;
// padding: 8px;
// border: 1px solid #ccc;
// border-radius: 4px;
// }
// }
.radio-group {
display: inline-flex;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
.radio {
flex: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
&:hover {
background-color: #f0f0f0;
}
&.active {
background-color: #e0e0e0;
font-weight: bold;
}
+ .radio {
border-left: 1px solid #ccc;
}
}
}
</style>

31
src/renderer/src/ui/NavBar.vue

@ -19,20 +19,7 @@
</div>
</div>
<div float-right h-full flex items-center relative style="-webkit-app-region: no-drag">
<div
v-if="UpdaterStore.isNeedUpdate"
text-sm
px-2
py-1
flex
items-center
hover:bg-gray-2
hover:cursor-pointer
text="hover:hover"
@click="UpdaterStore.checkForUpdates"
>
<icon-grommet-icons:update :class="{ rotate: UpdaterStore.isChecking }"></icon-grommet-icons:update>
</div>
<Update />
<div
v-if="!isHome"
text-sm
@ -48,19 +35,6 @@
>
<icon-stash:arrow-reply-duotone></icon-stash:arrow-reply-duotone>
</div>
<!-- <div
v-if="!isHome"
text-sm
px-2
hover:rounded-md
hover:bg-gray-2
hover:cursor-pointer
text="hover:hover"
title="返回首页"
@click="backHome"
>
🏠
</div> -->
<div text-sm px-2 hover:rounded-md hover:bg-gray-2 hover:cursor-pointer text="hover:hover" @click="onClickAbout">关于</div>
</div>
</div>
@ -73,10 +47,9 @@
import { PopupMenu } from "@/bridge/PopupMenu"
import { usePlatForm } from "common/event/PlatForm/hook"
import { LogLevel } from "logger/common"
import { useUpdaterStore } from "common/event/Updater/hook"
import Update from "./Update.vue"
const PlatForm = usePlatForm()
const UpdaterStore = useUpdaterStore()
const router = useRouter()
const route = useRoute()

78
src/renderer/src/ui/Update.vue

@ -0,0 +1,78 @@
<template>
<div
v-if="UpdaterStore.isNeedUpdate"
text-sm
px-2
py-1
flex
items-center
hover:bg-gray-2
hover:cursor-pointer
text="hover:hover"
@click="UpdaterStore.checkForUpdates"
>
<icon-grommet-icons:update
v-if="
UpdaterStore.status === UpdaterStatus.StartChecking ||
UpdaterStore.status === UpdaterStatus.Checking ||
UpdaterStore.status === UpdaterStatus.UpdateAvailable
"
:class="{ rotate: UpdaterStore.status === UpdaterStatus.Checking }"
></icon-grommet-icons:update>
<icon-bxs:error v-if="UpdaterStore.status === UpdaterStatus.Error" title="更新失败" class="text-red-400"></icon-bxs:error>
</div>
<div
v-if="UpdaterStore.status === UpdaterStatus.Downloading"
class="progress"
style="font-size: 12px"
px-2
flex
items-center
bg-gray-2
hover:cursor-pointer
text="hover:hover"
>
<div class="line" :style="{ width: UpdaterStore.percent + '%' }"></div>
<div class="speed">{{ UpdaterStore.speed }} KB/s</div>
</div>
</template>
<script lang="ts" setup>
import { UpdaterStatus, useUpdaterStore } from "common/event/Updater/hook"
const UpdaterStore = useUpdaterStore()
</script>
<style lang="scss" scoped>
.rotate {
animation: rotate 1.5s linear infinite forwards running;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.progress {
background-color: rgba(229, 231, 235, 100);
position: relative;
.speed {
position: relative;
z-index: 3;
color: red;
}
.line {
content: "";
z-index: 2;
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0;
background-color: rgb(239, 156, 156);
}
}
</style>

4
src/types/global.d.ts

@ -2,8 +2,8 @@ type FireFN = (...argu: any[]) => void
type Api<M extends Record<string, (...argu: any[]) => void>, T extends Record<string, FireFN>, N extends string> = {
call: <S extends keyof M>(command: `${N}${N extends string ? "." : ""}${S}`, ...args: Parameters<M[S]>) => any
callLong: <S extends keyof M>(command: string, ...args: Parameters<T[S]>) => any
callSync: <S extends keyof M>(command: string, ...args: Parameters<M[S]>) => any
callLong: <S extends keyof M>(command: `${N}${N extends string ? "." : ""}${S}`, ...args: Parameters<M[S]>) => any
callSync: <S extends keyof M>(command: `${N}${N extends string ? "." : ""}${S}`, ...args: Parameters<M[S]>) => any
send: <S extends keyof M>(command: string, ...argu: Parameters<M[S]>) => any
sendSync: <S extends keyof M>(command: string, ...argu: Parameters<M[S]>) => any
on: <S extends keyof T>(command: S, cb: (event: IpcRendererEventIpcRendererEvent, ...args: Parameters<T[S]>) => void) => () => void

Loading…
Cancel
Save