Feature(custom): support theme system and add a new theme hub for piclist

This commit is contained in:
Kuingsmile
2026-01-14 23:00:07 +08:00
parent d98f955a76
commit 50a59a124a
55 changed files with 1440 additions and 1621 deletions

View File

@@ -31,6 +31,7 @@
"lint:dpdm:renderer": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/renderer/main.ts",
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src/ scripts/ .",
"lint:style": "stylelint \"src/**/*.(vue|less|scss|css)\" --fix",
"lint:style:themes": "stylelint \"resources/theme/*.css\" --fix",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps",
"prebuild": "electron-vite build",
@@ -50,6 +51,7 @@
"@piclist/store": "^3.0.1",
"@smithy/node-http-handler": "^4.4.7",
"@vueuse/core": "^14.1.0",
"adm-zip": "^0.5.16",
"ali-oss": "^6.23.0",
"axios": "^1.13.2",
"chalk": "^5.6.2",
@@ -89,6 +91,7 @@
"@headlessui/vue": "^1.7.23",
"@highlightjs/vue-plugin": "^2.1.2",
"@intlify/unplugin-vue-i18n": "^11.0.3",
"@types/adm-zip": "^0.5.7",
"@types/ali-oss": "^6.23.0",
"@types/fs-extra": "^11.0.4",
"@types/js-yaml": "^4.0.9",
@@ -118,9 +121,9 @@
"eslint-plugin-unicorn": "^62.0.0",
"eslint-plugin-vue": "^10.6.2",
"globals": "^16.5.0",
"js-yaml": "^4.1.1",
"highlight.js": "^11.11.1",
"husky": "^9.1.7",
"js-yaml": "^4.1.1",
"lucide-vue-next": "^0.562.0",
"node-bump-version": "^2.0.0",
"pinia": "^3.0.4",

49
resources/theme/360.css Normal file
View File

@@ -0,0 +1,49 @@
/* 360 */
.dark, [data-theme="dark"] {
--color-text-primary: #f5f5f7 !important;
--color-text-secondary: #a1a1a6 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #1c1c1e !important;
--color-background-secondary: #2c2c2e !important;
--color-background-tertiary: #3a3a3c !important;
--color-surface: rgb(44 44 46 / 80%) !important;
--color-surface-elevated: rgb(58 58 60 / 95%) !important;
--color-border: rgb(255 255 255 / 10%) !important;
--color-border-secondary: rgb(255 255 255 / 5%) !important;
--color-primary: #19b400 !important;
--color-primary-hover: #23d100 !important;
--color-accent: #19b400 !important;
--color-accent-hover: #23d100 !important;
--accent-rgb: 25, 180, 0 !important;
--color-blue-common: #19b400 !important;
--color-light-blue: rgb(25 180 0 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}
.light, [data-theme="light"] {
--color-text-primary: #1d1d1f !important;
--color-text-secondary: #6e6e73 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f5f5f7 !important;
--color-background-tertiary: #fbfbfd !important;
--color-surface: rgb(255 255 255 / 80%) !important;
--color-surface-elevated: rgb(255 255 255 / 95%) !important;
--color-border: rgb(0 0 0 / 10%) !important;
--color-border-secondary: rgb(0 0 0 / 5%) !important;
--color-primary: #19b400 !important;
--color-primary-hover: #159400 !important;
--color-accent: #19b400 !important;
--color-accent-hover: #159400 !important;
--accent-rgb: 25, 180, 0 !important;
--color-blue-common: #19b400 !important;
--color-light-blue: rgb(25 180 0 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}

View File

@@ -0,0 +1,50 @@
/* Catppuccin */
.dark, [data-theme="dark"] {
--color-text-primary: #cdd6f4 !important;
--color-text-secondary: #a6adc8 !important;
--color-text-tertiary: #a6adc8 !important;
--color-background-primary: #1e1e2e !important;
--color-background-secondary: #181825 !important;
--color-background-tertiary: #11111b !important;
--color-surface: rgb(49 50 68 / 80%) !important;
--color-surface-elevated: rgb(49 50 68 / 95%) !important;
--color-border: #45475a !important;
--color-border-secondary: rgb(69 71 90 / 50%) !important;
--color-primary: #89b4fa !important;
--color-primary-hover: #b4befe !important;
--color-accent: #cba6f7 !important;
--color-accent-hover: #f5c2e7 !important;
--accent-rgb: 203, 166, 247 !important;
--color-blue-common: #89b4fa !important;
--color-light-blue: rgb(137 180 250 / 10%) !important;
--color-success: #a6e3a1 !important;
--color-warning: #f9e2af !important;
--color-danger: #f38ba8 !important;
--color-error: #f38ba8 !important;
--color-error-surface: rgb(243 139 168 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #4c4f69 !important;
--color-text-secondary: #5c5f77 !important;
--color-text-tertiary: #6c6f85 !important;
--color-background-primary: #eff1f5 !important;
--color-background-secondary: #e6e9ef !important;
--color-background-tertiary: #dce0e8 !important;
--color-surface: rgb(255 255 255 / 80%) !important;
--color-surface-elevated: rgb(255 255 255 / 95%) !important;
--color-border: #bcc0cc !important;
--color-border-secondary: rgb(188 192 204 / 50%) !important;
--color-primary: #1e66f5 !important;
--color-primary-hover: #7287fd !important;
--color-accent: #8839ef !important;
--color-accent-hover: #ea76cb !important;
--accent-rgb: 136, 57, 239 !important;
--color-blue-common: #1e66f5 !important;
--color-light-blue: rgb(30 102 245 / 10%) !important;
--color-success: #40a02b !important;
--color-warning: #df8e1d !important;
--color-danger: #d20f39 !important;
--color-error: #d20f39 !important;
--color-error-surface: rgb(210 15 57 / 10%) !important;
}

View File

@@ -0,0 +1,48 @@
/* CoolApk */
.dark, [data-theme="dark"] {
--color-text-primary: #f5f5f7 !important;
--color-text-secondary: #a1a1a6 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #1c1c1e !important;
--color-background-secondary: #2c2c2e !important;
--color-background-tertiary: #3a3a3c !important;
--color-surface: rgb(44 44 46 / 80%) !important;
--color-surface-elevated: rgb(58 58 60 / 95%) !important;
--color-border: rgb(255 255 255 / 10%) !important;
--color-border-secondary: rgb(255 255 255 / 5%) !important;
--color-primary: #0bb976 !important;
--color-primary-hover: #20df94 !important;
--color-accent: #0bb976 !important;
--color-accent-hover: #20df94 !important;
--accent-rgb: 11, 185, 118 !important;
--color-blue-common: #0bb976 !important;
--color-light-blue: rgb(11 185 118 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}
.light, [data-theme="light"] {
--color-text-primary: #1d1d1f !important;
--color-text-secondary: #6e6e73 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f5f5f7 !important;
--color-background-tertiary: #fbfbfd !important;
--color-surface: rgb(255 255 255 / 80%) !important;
--color-surface-elevated: rgb(255 255 255 / 95%) !important;
--color-border: rgb(0 0 0 / 10%) !important;
--color-border-secondary: rgb(0 0 0 / 5%) !important;
--color-primary: #0bb976 !important;
--color-primary-hover: #078c58 !important;
--color-accent: #0bb976 !important;
--color-accent-hover: #078c58 !important;
--accent-rgb: 11, 185, 118 !important;
--color-blue-common: #0bb976 !important;
--color-light-blue: rgb(11 185 118 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}

View File

@@ -0,0 +1,51 @@
/* Cupertino */
.dark, [data-theme="dark"] {
--color-text-primary: #ffffff !important;
--color-text-secondary: #ebebf5 !important;
--color-text-tertiary: #ebebf5 !important;
--color-background-primary: #1e1e1e !important;
--color-background-secondary: #2c2c2e !important;
--color-background-tertiary: #3a3a3c !important;
--color-surface: rgb(44 44 46 / 90%) !important;
--color-surface-elevated: rgb(58 58 60 / 95%) !important;
--color-border: #38383a !important;
--color-border-secondary: rgb(56 56 58 / 50%) !important;
--color-primary: #0a84ff !important;
--color-primary-hover: #409cff !important;
--color-accent: #0a84ff !important;
--color-accent-hover: #409cff !important;
--accent-rgb: 10, 132, 255 !important;
--color-blue-common: #0a84ff !important;
--color-light-blue: rgb(10 132 255 / 10%) !important;
--color-success: #32d74b !important;
--color-warning: #ff9f0a !important;
--color-danger: #ff453a !important;
--color-error: #ff453a !important;
--color-error-surface: rgb(255 69 58 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #000000 !important;
--color-text-secondary: #3c3c43 !important;
--color-text-tertiary: #3c3c43 !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f2f2f7 !important;
--color-background-tertiary: #ffffff !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(255 255 255 / 100%) !important;
--color-border: #d1d1d6 !important;
--color-border-secondary: rgb(209 209 214 / 50%) !important;
--color-primary: #007aff !important;
--color-primary-hover: #0051a8 !important;
--color-accent: #007aff !important;
--color-accent-hover: #0051a8 !important;
--accent-rgb: 0, 122, 255 !important;
--color-blue-common: #007aff !important;
--color-light-blue: rgb(0 122 255 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #ff9500 !important;
--color-danger: #ff3b30 !important;
--color-error: #ff3b30 !important;
--color-error-surface: rgb(255 59 48 / 10%) !important;
}

View File

@@ -0,0 +1,49 @@
/* 火绒 */
.dark, [data-theme="dark"] {
--color-text-primary: #f5f5f7 !important;
--color-text-secondary: #a1a1a6 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #1c1c1e !important;
--color-background-secondary: #2c2c2e !important;
--color-background-tertiary: #3a3a3c !important;
--color-surface: rgb(44 44 46 / 80%) !important;
--color-surface-elevated: rgb(58 58 60 / 95%) !important;
--color-border: rgb(255 255 255 / 10%) !important;
--color-border-secondary: rgb(255 255 255 / 5%) !important;
--color-primary: #fa8b15 !important;
--color-primary-hover: #ff9f38 !important;
--color-accent: #fa8b15 !important;
--color-accent-hover: #ff9f38 !important;
--accent-rgb: 250, 139, 21 !important;
--color-blue-common: #fa8b15 !important;
--color-light-blue: rgb(250 139 21 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}
.light, [data-theme="light"] {
--color-text-primary: #1d1d1f !important;
--color-text-secondary: #6e6e73 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f5f5f7 !important;
--color-background-tertiary: #fbfbfd !important;
--color-surface: rgb(255 255 255 / 80%) !important;
--color-surface-elevated: rgb(255 255 255 / 95%) !important;
--color-border: rgb(0 0 0 / 10%) !important;
--color-border-secondary: rgb(0 0 0 / 5%) !important;
--color-primary: #fa8b15 !important;
--color-primary-hover: #d9770e !important;
--color-accent: #fa8b15 !important;
--color-accent-hover: #d9770e !important;
--accent-rgb: 250, 139, 21 !important;
--color-blue-common: #fa8b15 !important;
--color-light-blue: rgb(250 139 21 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
}

View File

@@ -0,0 +1,51 @@
/* Adwaita */
.dark, [data-theme="dark"] {
--color-text-primary: #eeeeec !important;
--color-text-secondary: #9a9996 !important;
--color-text-tertiary: #77767b !important;
--color-background-primary: #242424 !important;
--color-background-secondary: #303030 !important;
--color-background-tertiary: #1e1e1e !important;
--color-surface: rgb(48 48 48 / 90%) !important;
--color-surface-elevated: rgb(56 56 56 / 95%) !important;
--color-border: #1b1b1b !important;
--color-border-secondary: rgb(27 27 27 / 50%) !important;
--color-primary: #3584e4 !important;
--color-primary-hover: #62a0ea !important;
--color-accent: #3584e4 !important;
--color-accent-hover: #62a0ea !important;
--accent-rgb: 53, 132, 228 !important;
--color-blue-common: #3584e4 !important;
--color-light-blue: rgb(53 132 228 / 10%) !important;
--color-success: #33d17a !important;
--color-warning: #f29c37 !important;
--color-danger: #e01b24 !important;
--color-error: #c01c28 !important;
--color-error-surface: rgb(192 28 40 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #2e3436 !important;
--color-text-secondary: #5e5c64 !important;
--color-text-tertiary: #9a9996 !important;
--color-background-primary: #fafafa !important;
--color-background-secondary: #f6f5f4 !important;
--color-background-tertiary: #ffffff !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(255 255 255 / 100%) !important;
--color-border: #cdc7c2 !important;
--color-border-secondary: rgb(205 199 194 / 50%) !important;
--color-primary: #3584e4 !important;
--color-primary-hover: #1c71d8 !important;
--color-accent: #3584e4 !important;
--color-accent-hover: #1c71d8 !important;
--accent-rgb: 53, 132, 228 !important;
--color-blue-common: #3584e4 !important;
--color-light-blue: rgb(53 132 228 / 10%) !important;
--color-success: #26a269 !important;
--color-warning: #e66100 !important;
--color-danger: #c01c28 !important;
--color-error: #a51d2d !important;
--color-error-surface: rgb(165 29 45 / 10%) !important;
}

57
resources/theme/anime.css Normal file
View File

@@ -0,0 +1,57 @@
/* 二次元 */
.dark, [data-theme="dark"] {
--background-image: url("https://w.wallhaven.cc/full/gj/wallhaven-gje69q.png") !important;
--background-image-opacity: 0.7 !important;
--background-blur: blur(5px) !important;
--color-text-primary: #f2cee2 !important;
--color-text-secondary: #d4a5c0 !important;
--color-text-tertiary: #b080a0 !important;
--color-background-primary: transparent !important;
--color-background-secondary: transparent !important;
--color-background-tertiary: #402834 !important;
--color-surface: #4f3d47cd !important;
--color-surface-elevated: rgb(220 220 220 / 50%) !important;
--color-border: #6d4c5e !important;
--color-border-secondary: #efd0d671 !important;
--color-primary: #ffb7c5 !important;
--color-primary-hover: #ffcfd8 !important;
--color-accent: #23ade0 !important;
--color-accent-hover: #0c9bcb !important;
--accent-rgb: 255, 183, 197 !important;
--color-blue-common: #a0e6ff !important;
--color-light-blue: rgb(160 230 255 / 10%) !important;
--color-success: #98e8b1 !important;
--color-warning: #ffe69c !important;
--color-danger: #ff99aa !important;
--color-error: #ff99aa !important;
--color-error-surface: rgb(255 153 170 / 10%) !important;
}
.light, [data-theme="light"] {
--background-image: url("https://w.wallhaven.cc/full/2k/wallhaven-2ky11m.png") !important;
--background-image-opacity: 0.7 !important;
--background-blur: blur(5px) !important;
--color-text-primary: #5c3a49 !important;
--color-text-secondary: #8c6075 !important;
--color-text-tertiary: #b080a0 !important;
--color-background-primary: transparent !important;
--color-background-secondary: transparent !important;
--color-background-tertiary: #ffe0eb !important;
--color-surface: rgb(255 255 255 / 60%) !important;
--color-surface-elevated: rgb(255 255 255 / 90%) !important;
--color-border: #f8c2d6 !important;
--color-border-secondary: rgb(248 194 214 / 50%) !important;
--color-primary: #ff85a2 !important;
--color-primary-hover: #ff6085 !important;
--color-accent: #60c3eb !important;
--color-accent-hover: #3daade !important;
--accent-rgb: 255, 133, 162 !important;
--color-blue-common: #60c3eb !important;
--color-light-blue: rgb(96 195 235 / 10%) !important;
--color-success: #55c97b !important;
--color-warning: #ffcf5c !important;
--color-danger: #ff6b85 !important;
--color-error: #ff6b85 !important;
--color-error-surface: rgb(255 107 133 / 10%) !important;
}

View File

@@ -0,0 +1,51 @@
/* Bilibili */
.dark, [data-theme="dark"] {
--color-text-primary: #ffffff !important;
--color-text-secondary: #eeeeee !important;
--color-text-tertiary: #999999 !important;
--color-background-primary: #222222 !important;
--color-background-secondary: #333333 !important;
--color-background-tertiary: #1a1a1a !important;
--color-surface: rgb(51 51 51 / 90%) !important;
--color-surface-elevated: rgb(60 60 60 / 95%) !important;
--color-border: #444444 !important;
--color-border-secondary: rgb(68 68 68 / 50%) !important;
--color-primary: #fb7299 !important;
--color-primary-hover: #ff85a7 !important;
--color-accent: #fb7299 !important;
--color-accent-hover: #ff85a7 !important;
--accent-rgb: 251, 114, 153 !important;
--color-blue-common: #fb7299 !important;
--color-light-blue: rgb(251 114 153 / 10%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
--color-error-surface: rgb(255 59 48 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #18191c !important;
--color-text-secondary: #61666d !important;
--color-text-tertiary: #9499a0 !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f6f7f8 !important;
--color-background-tertiary: #f1f2f3 !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(255 255 255 / 100%) !important;
--color-border: #e3e5e7 !important;
--color-border-secondary: rgb(227 229 231 / 50%) !important;
--color-primary: #fb7299 !important;
--color-primary-hover: #c45674 !important;
--color-accent: #fb7299 !important;
--color-accent-hover: #c45674 !important;
--accent-rgb: 251, 114, 153 !important;
--color-blue-common: #fb7299 !important;
--color-light-blue: rgb(251 114 153 / 5%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
--color-error-surface: rgb(255 59 48 / 10%) !important;
}

View File

@@ -0,0 +1,51 @@
/* 默认 */
.dark, [data-theme="dark"] {
--color-text-primary: #f5f5f7 !important;
--color-text-secondary: #a1a1a6 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #000000 !important;
--color-background-secondary: #1c1c1e !important;
--color-background-tertiary: #2c2c2e !important;
--color-surface: rgb(28 28 30 / 80%) !important;
--color-surface-elevated: rgb(44 44 46 / 95%) !important;
--color-border: rgb(255 255 255 / 10%) !important;
--color-border-secondary: rgb(255 255 255 / 5%) !important;
--color-primary: #6366f1 !important;
--color-primary-hover: #818cf8 !important;
--color-accent: #0a84ff !important;
--color-accent-hover: #409cff !important;
--accent-rgb: #449af7 !important;
--color-blue-common: #409eff !important;
--color-light-blue: rgb(0 122 255 / 5%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
--color-error-surface: rgb(255 59 48 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #1d1d1f !important;
--color-text-secondary: #6e6e73 !important;
--color-text-tertiary: #86868b !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f5f5f7 !important;
--color-background-tertiary: #fbfbfd !important;
--color-surface: rgb(255 255 255 / 80%) !important;
--color-surface-elevated: rgb(255 255 255 / 95%) !important;
--color-border: rgb(0 0 0 / 10%) !important;
--color-border-secondary: rgb(0 0 0 / 5%) !important;
--color-primary: #6366f1 !important;
--color-primary-hover: #4f46e5 !important;
--color-accent: #007aff !important;
--color-accent-hover: #3b82f6 !important;
--accent-rgb: #449af7 !important;
--color-blue-common: #409eff !important;
--color-light-blue: rgb(0 122 255 / 5%) !important;
--color-success: #34c759 !important;
--color-warning: #f1930f !important;
--color-danger: #ff3b30 !important;
--color-error: #cb2431 !important;
--color-error-surface: rgb(255 59 48 / 10%) !important;
}

View File

@@ -0,0 +1,50 @@
/* Gemini */
.dark, [data-theme="dark"] {
--color-text-primary: #e3e3e3 !important;
--color-text-secondary: #c4c7c5 !important;
--color-text-tertiary: #a8c7fa !important;
--color-background-primary: #131314 !important;
--color-background-secondary: #1e1f20 !important;
--color-background-tertiary: #2e2f31 !important;
--color-surface: rgb(30 31 32 / 90%) !important;
--color-surface-elevated: rgb(40 41 42 / 95%) !important;
--color-border: #444746 !important;
--color-border-secondary: rgb(68 71 70 / 50%) !important;
--color-primary: #a8c7fa !important;
--color-primary-hover: #d2e3fc !important;
--color-accent: #a8c7fa !important;
--color-accent-hover: #d2e3fc !important;
--accent-rgb: 168, 199, 250 !important;
--color-blue-common: #a8c7fa !important;
--color-light-blue: rgb(168 199 250 / 10%) !important;
--color-success: #6dd58c !important;
--color-warning: #fdc365 !important;
--color-danger: #f28b82 !important;
--color-error: #f28b82 !important;
--color-error-surface: rgb(242 139 130 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #1f1f1f !important;
--color-text-secondary: #444746 !important;
--color-text-tertiary: #0b57d0 !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f0f4f9 !important;
--color-background-tertiary: #e9eef6 !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(240 244 249 / 100%) !important;
--color-border: #e0e3e1 !important;
--color-border-secondary: rgb(224 227 225 / 50%) !important;
--color-primary: #0b57d0 !important;
--color-primary-hover: #0842a0 !important;
--color-accent: #0b57d0 !important;
--color-accent-hover: #0842a0 !important;
--accent-rgb: 11, 87, 208 !important;
--color-blue-common: #0b57d0 !important;
--color-light-blue: rgb(11 87 208 / 10%) !important;
--color-success: #1e8e3e !important;
--color-warning: #e37400 !important;
--color-danger: #d93025 !important;
--color-error: #d93025 !important;
--color-error-surface: rgb(217 48 37 / 10%) !important;
}

View File

@@ -0,0 +1,51 @@
/* 微信 */
.dark, [data-theme="dark"] {
--color-text-primary: #ffffff !important;
--color-text-secondary: #7d7d7d !important;
--color-text-tertiary: #4c4c4c !important;
--color-background-primary: #191919 !important;
--color-background-secondary: #242424 !important;
--color-background-tertiary: #111111 !important;
--color-surface: rgb(36 36 36 / 90%) !important;
--color-surface-elevated: rgb(42 42 42 / 95%) !important;
--color-border: #333333 !important;
--color-border-secondary: rgb(51 51 51 / 50%) !important;
--color-primary: #07c160 !important;
--color-primary-hover: #06ad56 !important;
--color-accent: #07c160 !important;
--color-accent-hover: #06ad56 !important;
--accent-rgb: 7, 193, 96 !important;
--color-blue-common: #07c160 !important;
--color-light-blue: rgb(7 193 96 / 10%) !important;
--color-success: #07c160 !important;
--color-warning: #ffbe00 !important;
--color-danger: #fa5151 !important;
--color-error: #fa5151 !important;
--color-error-surface: rgb(250 81 81 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #000000 !important;
--color-text-secondary: #b2b2b2 !important;
--color-text-tertiary: #999999 !important;
--color-background-primary: #f5f5f5 !important;
--color-background-secondary: #eaeaea !important;
--color-background-tertiary: #ffffff !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(255 255 255 / 100%) !important;
--color-border: #d6d6d6 !important;
--color-border-secondary: rgb(214 214 214 / 50%) !important;
--color-primary: #07c160 !important;
--color-primary-hover: #06ad56 !important;
--color-accent: #07c160 !important;
--color-accent-hover: #06ad56 !important;
--accent-rgb: 7, 193, 96 !important;
--color-blue-common: #07c160 !important;
--color-light-blue: rgb(7 193 96 / 10%) !important;
--color-success: #07c160 !important;
--color-warning: #ffbe00 !important;
--color-danger: #fa5151 !important;
--color-error: #fa5151 !important;
--color-error-surface: rgb(250 81 81 / 10%) !important;
}

51
resources/theme/win11.css Normal file
View File

@@ -0,0 +1,51 @@
/* Windows 11 */
.dark, [data-theme="dark"] {
--color-text-primary: #ffffff !important;
--color-text-secondary: #cccccc !important;
--color-text-tertiary: #999999 !important;
--color-background-primary: #202020 !important;
--color-background-secondary: #2b2b2b !important;
--color-background-tertiary: #1f1f1f !important;
--color-surface: rgb(44 44 44 / 90%) !important;
--color-surface-elevated: rgb(50 50 50 / 95%) !important;
--color-border: #333333 !important;
--color-border-secondary: rgb(51 51 51 / 50%) !important;
--color-primary: #60cdff !important;
--color-primary-hover: #98e7ff !important;
--color-accent: #60cdff !important;
--color-accent-hover: #98e7ff !important;
--accent-rgb: 96, 205, 255 !important;
--color-blue-common: #60cdff !important;
--color-light-blue: rgb(96 205 255 / 10%) !important;
--color-success: #6cc4a1 !important;
--color-warning: #fce100 !important;
--color-danger: #ff99a4 !important;
--color-error: #ff99a4 !important;
--color-error-surface: rgb(255 153 164 / 10%) !important;
}
.light, [data-theme="light"] {
--color-text-primary: #000000 !important;
--color-text-secondary: #5d5d5d !important;
--color-text-tertiary: #767676 !important;
--color-background-primary: #ffffff !important;
--color-background-secondary: #f3f3f3 !important;
--color-background-tertiary: #eeeeee !important;
--color-surface: rgb(255 255 255 / 90%) !important;
--color-surface-elevated: rgb(255 255 255 / 100%) !important;
--color-border: #e5e5e5 !important;
--color-border-secondary: rgb(229 229 229 / 50%) !important;
--color-primary: #005fb8 !important;
--color-primary-hover: #004578 !important;
--color-accent: #005fb8 !important;
--color-accent-hover: #004578 !important;
--accent-rgb: 0, 95, 184 !important;
--color-blue-common: #005fb8 !important;
--color-light-blue: rgb(0 95 184 / 10%) !important;
--color-success: #0f7b0f !important;
--color-warning: #9d5d00 !important;
--color-danger: #c50f1f !important;
--color-error: #c50f1f !important;
--color-error-surface: rgb(197 15 31 / 10%) !important;
}

View File

@@ -0,0 +1,81 @@
import path from 'node:path'
import { themesDir } from '@core/datastore/dirs'
import * as fsWalk from '@nodelib/fs.walk'
import AdmZip from 'adm-zip'
import windowManager from 'apis/app/window/windowManager'
import axios from 'axios'
import fs from 'fs-extra'
import { IWindowList } from '~/utils/enum'
let insertedCSSKeyMain: string | undefined
export async function resolveThemes(): Promise<{ key: string; label: string }[]> {
const files = fsWalk.walkSync(themesDir(), {
followSymbolicLinks: true,
fs,
stats: true,
throwErrorOnBrokenSymbolicLink: false,
})
const result: string[] = []
files.forEach(item => {
if (item.stats?.isFile()) {
result.push(item.path.replace(themesDir() + '/', ''))
}
})
const themes = await Promise.all(
result
.filter(file => file.endsWith('.css'))
.map(async file => {
const css = (await fs.readFile(file, 'utf-8')) || ''
let name = file
if (css.startsWith('/*')) {
name = css.split('\n')[0].replace('/*', '').replace('*/', '').trim() || file
}
return { key: file, label: name }
}),
)
if (themes.find(theme => theme.key === 'default.css')) {
return themes
} else {
return [{ key: 'default.css', label: '默认' }, ...themes]
}
}
export async function fetchThemes(): Promise<void> {
const zipUrl = 'https://github.com/Kuingsmile/piclist-themeHub/releases/download/latest/themes.zip'
const zipData = await axios.get(zipUrl, {
responseType: 'arraybuffer',
headers: { 'Content-Type': 'application/octet-stream' },
})
const zip = new AdmZip(zipData.data as Buffer)
zip.extractAllTo(themesDir(), true)
}
export async function importThemes(files: string[]): Promise<void> {
for (const file of files) {
if (fs.existsSync(file))
await fs.copyFile(file, path.join(themesDir(), `${new Date().getTime().toString(16)}-${path.basename(file)}`))
}
}
export async function readTheme(theme: string): Promise<string> {
if (!fs.existsSync(path.join(themesDir(), theme))) return ''
const result = await fs.readFile(path.join(themesDir(), theme), 'utf-8')
return result
}
export async function applyTheme(theme: string): Promise<void> {
theme = path.basename(theme)
console.log('Applying theme:', theme)
const css = await readTheme(theme)
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
try {
await windowManager.get(IWindowList.SETTING_WINDOW)?.webContents.removeInsertedCSS(insertedCSSKeyMain || '')
insertedCSSKeyMain = await windowManager.get(IWindowList.SETTING_WINDOW)?.webContents.insertCSS(css)
} catch (e) {
console.error(e)
}
}
}

View File

@@ -12,6 +12,7 @@ import { configPaths } from '~/utils/configPaths'
import { IWindowList } from '~/utils/enum'
import logo from '../../../../../resources/logo.png?asset&asarUnpack'
import { applyTheme } from '../theme'
const windowList = new Map<string, IWindowListItem>()
@@ -205,6 +206,10 @@ windowList.set(IWindowList.SETTING_WINDOW, {
})
}
})
window.on('ready-to-show', () => {
const customTheme = picgo.getConfig<string>(configPaths.settings.theme) || 'default.css'
applyTheme(customTheme)
})
bus.emit(CREATE_APP_MENU)
windowManager.create(IWindowList.MINI_WINDOW)
},

View File

@@ -1,8 +1,9 @@
import picgo from '@core/picgo'
import { app, shell } from 'electron'
import { app, nativeTheme, shell } from 'electron'
import { applyTheme, fetchThemes, importThemes, resolveThemes } from '~/apis/app/theme'
import { i18nManager } from '~/i18n'
import { IRPCActionType } from '~/utils/enum'
import { IRPCActionType, IRPCType } from '~/utils/enum'
export default [
{
@@ -32,4 +33,51 @@ export default [
picgo.i18n.setLanguage(lang)
},
},
{
action: IRPCActionType.GET_SYSTEM_THEME,
handler: async () => {
return nativeTheme.shouldUseDarkColors ? 'dark' : 'light'
},
type: IRPCType.INVOKE,
},
{
action: IRPCActionType.SET_SYSTEM_THEME,
handler: async (_: IIPCEvent, args: [theme: 'light' | 'dark' | 'system']) => {
nativeTheme.themeSource = args[0]
},
},
{
action: IRPCActionType.APPLY_THEME,
handler: async (_: IIPCEvent, args: [theme: string]) => {
applyTheme(args[0])
},
},
{
action: IRPCActionType.THEME_RESOLVE_THEMES,
handler: async () => {
return await resolveThemes()
},
type: IRPCType.INVOKE,
},
{
action: IRPCActionType.THEME_FETCH_THEMES,
handler: async () => {
await fetchThemes()
},
type: IRPCType.INVOKE,
},
{
action: IRPCActionType.THEME_IMPORT_THEMES,
handler: async (_: IIPCEvent, args: [files: string[]]) => {
await importThemes(args[0])
},
type: IRPCType.INVOKE,
},
{
action: IRPCActionType.THEME_APPLY_THEME,
handler: async (_: IIPCEvent, args: [theme: string]) => {
await applyTheme(args[0])
},
type: IRPCType.INVOKE,
},
]

View File

@@ -11,7 +11,7 @@ import { createTray, setDockMenu } from 'apis/app/system'
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
import windowManager from 'apis/app/window/windowManager'
import axios from 'axios'
import { app, globalShortcut, Notification, protocol, screen } from 'electron'
import { app, globalShortcut, nativeTheme, Notification, protocol, screen } from 'electron'
import updater from 'electron-updater'
import fs from 'fs-extra'
@@ -180,6 +180,12 @@ class LifeCycle {
windowManager.create(IWindowList.TRAY_WINDOW)
windowManager.create(IWindowList.SETTING_WINDOW)
const isAutoListenClipboard = picgo.getConfig<boolean>(configPaths.settings.isAutoListenClipboard) || false
const systemTheme = picgo.getConfig<'light' | 'dark' | 'system' | undefined>(configPaths.settings.systemTheme)
if (systemTheme) {
nativeTheme.themeSource = systemTheme
} else {
nativeTheme.themeSource = 'system'
}
const ClipboardWatcher = clipboardPoll
if (isAutoListenClipboard) {
picgo.saveConfig({ [configPaths.settings.isListeningClipboard]: true })
@@ -362,7 +368,6 @@ class LifeCycle {
}
async launchApp() {
console.log('launchApp called', app.getPath('exe'))
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()

View File

@@ -2,7 +2,8 @@ import os from 'node:os'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { appConfigPath } from '@core/datastore/dirs'
import { appConfigPath, themesDir } from '@core/datastore/dirs'
import * as fsWalk from '@nodelib/fs.walk'
import fs from 'fs-extra'
import yaml from 'yaml'
@@ -17,6 +18,7 @@ function beforeOpen() {
resolveMacWorkFlow()
}
resolveClipboardImageGenerator()
resolveCss()
resolveOtherI18nFiles()
}
@@ -86,16 +88,50 @@ function resolveClipboardImageGenerator() {
diffFilesAndUpdate(item.origin, item.dest)
})
}
}
function getClipboardFiles() {
const files = ['linux.sh', 'mac.applescript', 'windows.ps1', 'windows10.ps1', 'wsl.sh']
function getClipboardFiles() {
const files = ['linux.sh', 'mac.applescript', 'windows.ps1', 'windows10.ps1', 'wsl.sh']
return files.map(item => {
return {
origin: path.join(dirname, '../../resources', item).replace('app.asar', 'app.asar.unpacked'),
dest: path.join(CONFIG_DIR, item),
return files.map(item => {
return {
origin: path.join(dirname, '../../resources', item).replace('app.asar', 'app.asar.unpacked'),
dest: path.join(CONFIG_DIR, item),
}
})
}
function getFileInCssDir() {
const cssDir = path.join(dirname, '../../resources/theme').replace('app.asar', 'app.asar.unpacked')
const res = fsWalk.walkSync(cssDir, {
followSymbolicLinks: true,
fs,
stats: true,
throwErrorOnBrokenSymbolicLink: false,
})
const result: string[] = []
res.forEach(item => {
if (item.stats?.isFile()) {
result.push(item.path)
}
})
return result
}
function resolveCss() {
try {
fs.ensureDirSync(themesDir())
const css = getFileInCssDir()
css.forEach(item => {
const dest = path.join(themesDir(), path.basename(item))
if (!fs.pathExistsSync(dest)) {
fs.copyFileSync(item, dest)
} else {
diffFilesAndUpdate(item, dest)
}
})
} catch (e) {
console.error(e)
}
}

View File

@@ -30,6 +30,8 @@ export interface IConfigStruct {
}
settings: {
shortKey: Record<string, IShortKeyConfig>
systemTheme: 'light' | 'dark' | 'auto'
customTheme: string
logLevel: string[]
logPath: string
logFileSizeLimit: number
@@ -85,6 +87,7 @@ export interface IConfigStruct {
galleryPicBedFilter: string[]
enableSecondUploader?: boolean
lastSyncTime?: number
theme: string
}
needReload: boolean
picgoPlugins: IPicGoPlugins
@@ -120,6 +123,8 @@ export const configPaths = {
_path: 'settings.shortKey',
'picgo:upload': 'settings.shortKey[picgo:upload]',
},
systemTheme: 'settings.systemTheme',
customTheme: 'settings.customTheme',
logLevel: 'settings.logLevel',
logPath: 'settings.logPath',
logFileSizeLimit: 'settings.logFileSizeLimit',
@@ -175,6 +180,7 @@ export const configPaths = {
galleryPicBedFilter: 'settings.galleryPicBedFilter',
enableSecondUploader: 'settings.enableSecondUploader',
lastSyncTime: 'settings.lastSyncTime',
theme: 'settings.theme',
},
needReload: 'needReload',
picgoPlugins: 'picgoPlugins',

View File

@@ -70,6 +70,13 @@ export const IRPCType = {
export const IRPCActionType = {
// system rpc
GET_SYSTEM_THEME: 'GET_SYSTEM_THEME',
SET_SYSTEM_THEME: 'SET_SYSTEM_THEME',
APPLY_THEME: 'APPLY_THEME',
THEME_RESOLVE_THEMES: 'THEME_RESOLVE_THEMES',
THEME_FETCH_THEMES: 'THEME_FETCH_THEMES',
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
RELOAD_APP: 'RELOAD_APP',
OPEN_URL: 'OPEN_URL',
OPEN_FILE: 'OPEN_FILE',

View File

@@ -1,34 +1,25 @@
<template>
<div id="app" :key="pageReloadCount">
<router-view />
<div class="bg-images" />
<UIServiceProvider />
</div>
</template>
<script lang="ts" setup>
import { onBeforeMount, onMounted } from 'vue'
import { onBeforeMount } from 'vue'
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
import { useAppStore } from '@/hooks/useAppStore'
import { useATagClick } from '@/hooks/useATagClick'
import { pageReloadCount, usePicBed } from '@/hooks/useGlobal'
useATagClick()
const appStore = useAppStore()
const { updatePicBeds } = usePicBed()
onBeforeMount(() => {
updatePicBeds()
})
onMounted(async () => {
try {
appStore.init()
} catch (error) {
console.error('Failed to load settings:', error)
}
})
</script>
<script lang="ts">
@@ -43,7 +34,23 @@ html
padding 0
margin 0
height 100%
#app
height 100%
user-select none
.bg-images {
position: absolute;
inset: 0;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
background-attachment: fixed;
background-image: var(--background-image);
background-repeat: no-repeat, no-repeat;
opacity: var(--background-image-opacity);
filter: var(--background-blur);
z-index: -1;
pointer-events: none;
}
</style>

View File

@@ -125,335 +125,4 @@ export default {
}
</script>
<style scoped>
/* Transitions */
.inputbox-fade-enter-active,
.inputbox-fade-leave-active {
transition: opacity 0.2s ease;
}
.inputbox-fade-enter-from,
.inputbox-fade-leave-to {
opacity: 0;
}
.inputbox-scale-enter-active {
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.inputbox-scale-leave-active {
transition: all 0.2s ease;
}
.inputbox-scale-enter-from {
opacity: 0;
transform: scale(0.9) translateY(-10px);
}
.inputbox-scale-leave-to {
opacity: 0;
transform: scale(0.95);
}
/* Overlay */
.inputbox-overlay {
position: fixed;
inset: 0;
z-index: 2000;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
background: rgb(0 0 0 / 40%);
}
/* Container */
.inputbox-container {
position: relative;
overflow: hidden;
border: 1px solid rgb(229 231 235);
border-radius: 1rem;
width: 100%;
max-width: 28rem;
background: white;
box-shadow:
0 20px 25px -5px rgb(0 0 0 / 10%),
0 10px 10px -5px rgb(0 0 0 / 4%);
}
:root.dark .inputbox-container,
:root.auto.dark .inputbox-container {
border-color: rgb(55 65 81);
background: rgb(31 41 55);
}
/* Close Button */
.inputbox-close {
position: absolute;
top: 1rem;
right: 1rem;
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
border: none;
border-radius: 0.5rem;
padding: 0.375rem;
color: rgb(107 114 128);
background: transparent;
transition: all 0.15s ease;
cursor: pointer;
}
.inputbox-close:hover {
color: rgb(75 85 99);
background: rgb(243 244 246);
}
:root.dark .inputbox-close,
:root.auto.dark .inputbox-close {
color: rgb(156 163 175);
}
:root.dark .inputbox-close:hover,
:root.auto.dark .inputbox-close:hover {
color: rgb(209 213 219);
background: rgb(55 65 81);
}
/* Body */
.inputbox-body {
padding: 1rem 1rem 0.5rem;
}
.inputbox-title {
margin: 0 0 1.25rem;
padding-right: 2rem;
font-size: 1.125rem;
font-weight: 600;
line-height: 1.4;
color: rgb(17 24 39);
}
:root.dark .inputbox-title,
:root.auto.dark .inputbox-title {
color: rgb(243 244 246);
}
.inputbox-content {
position: relative;
}
/* Input */
.inputbox-input {
border: 1.5px solid rgb(229 231 235);
border-radius: 0.625rem;
padding: 0.75rem 1rem;
width: 100%;
font-size: 0.9375rem;
font-family: inherit;
color: rgb(17 24 39);
background: rgb(249 250 251);
outline: none;
transition: all 0.2s ease;
}
.inputbox-input:hover {
border-color: rgb(209 213 219);
background: white;
}
.inputbox-input:focus {
border-color: rgb(59 130 246);
background: white;
box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
}
.inputbox-input::placeholder {
color: rgb(156 163 175);
}
/* Textarea */
.inputbox-textarea {
border: 1.5px solid rgb(229 231 235);
border-radius: 0.625rem;
padding: 0.75rem 1rem;
width: 100%;
min-height: 6rem;
font-size: 0.9375rem;
font-family: inherit;
line-height: 1.6;
color: rgb(17 24 39);
background: rgb(249 250 251);
outline: none;
resize: vertical;
transition: all 0.2s ease;
}
.inputbox-textarea:hover {
border-color: rgb(209 213 219);
background: white;
}
.inputbox-textarea:focus {
border-color: rgb(59 130 246);
background: white;
box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
}
.inputbox-textarea::placeholder {
color: rgb(156 163 175);
}
/* Dark Mode - Input */
:root.dark .inputbox-input,
:root.auto.dark .inputbox-input {
border-color: rgb(55 65 81);
color: rgb(243 244 246);
background: rgb(55 65 81);
}
:root.dark .inputbox-input:hover,
:root.auto.dark .inputbox-input:hover {
border-color: rgb(75 85 99);
background: rgb(55 65 81);
}
:root.dark .inputbox-input:focus,
:root.auto.dark .inputbox-input:focus {
border-color: rgb(59 130 246);
background: rgb(55 65 81);
box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
}
:root.dark .inputbox-input::placeholder,
:root.auto.dark .inputbox-input::placeholder {
color: rgb(107 114 128);
}
/* Dark Mode - Textarea */
:root.dark .inputbox-textarea,
:root.auto.dark .inputbox-textarea {
border-color: rgb(55 65 81);
color: rgb(243 244 246);
background: rgb(55 65 81);
}
:root.dark .inputbox-textarea:hover,
:root.auto.dark .inputbox-textarea:hover {
border-color: rgb(75 85 99);
background: rgb(55 65 81);
}
:root.dark .inputbox-textarea:focus,
:root.auto.dark .inputbox-textarea:focus {
border-color: rgb(59 130 246);
background: rgb(55 65 81);
box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
}
:root.dark .inputbox-textarea::placeholder,
:root.auto.dark .inputbox-textarea::placeholder {
color: rgb(107 114 128);
}
/* Actions */
.inputbox-actions {
display: flex;
border-top: 1px solid rgb(243 244 246);
padding: 1rem 1.5rem;
gap: 0.75rem;
}
:root.dark .inputbox-actions,
:root.auto.dark .inputbox-actions {
border-top-color: rgb(55 65 81);
}
.inputbox-btn {
flex: 1;
border: none;
border-radius: 0.5rem;
padding: 0.625rem 1.25rem;
font-size: 0.875rem;
font-weight: 500;
transition: all 0.15s ease;
cursor: pointer;
}
.inputbox-btn:active {
transform: scale(0.98);
}
.inputbox-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.inputbox-btn:disabled:active {
transform: none;
}
/* Cancel Button */
.cancel-btn {
border: 1px solid rgb(229 231 235);
color: rgb(75 85 99);
background: white;
}
.cancel-btn:hover {
border-color: rgb(209 213 219);
background: rgb(249 250 251);
}
:root.dark .cancel-btn,
:root.auto.dark .cancel-btn {
border-color: rgb(55 65 81);
color: rgb(209 213 219);
background: rgb(55 65 81);
}
:root.dark .cancel-btn:hover,
:root.auto.dark .cancel-btn:hover {
border-color: rgb(75 85 99);
background: rgb(75 85 99);
}
/* Confirm Button */
.confirm-btn {
border: none;
color: white;
background: linear-gradient(135deg, rgb(59 130 246) 0%, rgb(37 99 235) 100%);
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 5%);
}
.confirm-btn:hover:not(:disabled) {
background: linear-gradient(135deg, rgb(37 99 235) 0%, rgb(29 78 216) 100%);
box-shadow: 0 4px 12px rgb(59 130 246 / 40%);
}
/* Responsive */
@media (width <= 640px) {
.inputbox-overlay {
align-items: flex-end;
padding: 0;
}
.inputbox-container {
border-radius: 1rem 1rem 0 0;
max-width: 100%;
}
.inputbox-body {
padding: 1.75rem 1.5rem 1.25rem;
}
.inputbox-actions {
flex-direction: column-reverse;
}
.inputbox-btn {
width: 100%;
}
}
</style>
<style scoped src="./css/InputBox.css"></style>

View File

@@ -5,7 +5,6 @@
height: 100%;
min-height: 100vh;
color: var(--color-text-primary);
background: var(--color-background-primary);
}
/* ==================== Tab Navigation ==================== */
@@ -16,7 +15,6 @@
border: 1px solid var(--color-border);
border-radius: 14px;
padding: 6px;
background: var(--color-background-primary);
box-shadow:
0 2px 12px rgb(0 0 0 / 6%),
inset 0 1px 0 rgb(255 255 255 / 5%);
@@ -29,7 +27,7 @@
z-index: 0;
border-radius: 10px;
height: calc(100% - 12px);
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
background: var(--color-accent);
box-shadow: 0 2px 8px rgb(64 158 255 / 35%);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -383,7 +381,7 @@
}
.switch-input:checked + .switch-slider {
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
background: var(--color-accent);
box-shadow:
inset 0 1px 3px rgb(0 0 0 / 10%),
0 2px 8px rgb(64 158 255 / 30%);
@@ -432,7 +430,7 @@
}
.radio-option:hover {
border-color: #409eff;
border-color: var(--color-accent);
background: rgb(64 158 255 / 8%);
}
@@ -451,7 +449,7 @@
}
.radio-input:checked + .radio-indicator {
border-color: #409eff;
border-color: var(--color-accent);
background: var(--color-background-primary);
}
@@ -462,7 +460,7 @@
border-radius: 50%;
width: 10px;
height: 10px;
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
background: var(--color-accent);
content: '';
transform: translate(-50%, -50%);
}
@@ -656,158 +654,6 @@ small {
}
}
/* ==================== Dark mode adjustments ==================== */
:root.dark .image-process-settings,
:root.auto.dark .image-process-settings {
background: linear-gradient(180deg, var(--color-background-secondary) 0%, var(--color-background-tertiary) 100%);
}
:root.dark .settings-header,
:root.auto.dark .settings-header {
border-color: var(--color-border);
background: linear-gradient(135deg, var(--color-background-tertiary) 0%, var(--color-surface) 100%);
}
:root.dark .tab-navigation,
:root.auto.dark .tab-navigation {
border-color: var(--color-border);
background: var(--color-background-tertiary);
}
:root.dark .settings-section,
:root.auto.dark .settings-section {
border-color: var(--color-border);
background: var(--color-background-tertiary);
}
:root.dark .form-input,
:root.dark .form-textarea,
:root.auto.dark .form-input,
:root.auto.dark .form-textarea {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-surface);
}
:root.dark .form-range,
:root.auto.dark .form-range {
background: linear-gradient(90deg, #409eff 0%, #4a4a52 0%);
}
:root.dark .switch-slider,
:root.auto.dark .switch-slider {
background: linear-gradient(180deg, #4a4a52 0%, #3a3a42 100%);
}
:root.dark .switch-slider::before,
:root.auto.dark .switch-slider::before {
background: linear-gradient(180deg, #e0e0e0 0%, #d0d0d0 100%);
}
:root.dark .btn-secondary,
:root.auto.dark .btn-secondary {
border-color: var(--color-border);
color: var(--color-text-secondary);
background: var(--color-surface);
}
:root.dark .btn-secondary:hover,
:root.auto.dark .btn-secondary:hover {
border-color: var(--color-border-hover);
color: var(--color-text-primary);
background: var(--color-background-tertiary);
}
:root.dark .switch-label,
:root.auto.dark .switch-label {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .switch-label:hover,
:root.auto.dark .switch-label:hover {
border-color: #409eff;
background: var(--color-background-tertiary);
}
:root.dark .switch-title,
:root.auto.dark .switch-title {
color: var(--color-text-primary);
}
:root.dark .switch-description,
:root.auto.dark .switch-description {
color: var(--color-text-secondary);
}
:root.dark .position-button,
:root.auto.dark .position-button {
border-color: var(--color-border);
color: var(--color-text-secondary);
background: var(--color-surface);
}
:root.dark .position-button:hover,
:root.auto.dark .position-button:hover {
border-color: #409eff;
color: var(--color-text-primary);
background: var(--color-background-tertiary);
}
:root.dark .position-button.active,
:root.auto.dark .position-button.active {
border-color: #409eff;
color: white;
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
}
:root.dark .radio-option,
:root.auto.dark .radio-option {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .radio-option:hover,
:root.auto.dark .radio-option:hover {
border-color: #409eff;
background: var(--color-background-tertiary);
}
:root.dark .section-icon,
:root.auto.dark .section-icon {
background: linear-gradient(135deg, #409eff25 0%, #409eff35 100%);
}
:root.dark .section-icon.watermark-icon,
:root.auto.dark .section-icon.watermark-icon {
background: linear-gradient(135deg, #67c23a25 0%, #67c23a35 100%);
}
:root.dark .section-icon.transform-icon,
:root.auto.dark .section-icon.transform-icon {
background: linear-gradient(135deg, #e6a23c25 0%, #e6a23c35 100%);
}
:root.dark .section-icon.rotate-icon,
:root.auto.dark .section-icon.rotate-icon {
background: linear-gradient(135deg, #90939925 0%, #90939935 100%);
}
:root.dark .section-icon.resize-icon,
:root.auto.dark .section-icon.resize-icon {
background: linear-gradient(135deg, #f56c6c25 0%, #f56c6c35 100%);
}
:root.dark .section-icon.percent-icon,
:root.auto.dark .section-icon.percent-icon {
background: linear-gradient(135deg, #b37feb25 0%, #b37feb35 100%);
}
:root.dark small,
:root.auto.dark small {
background: var(--color-surface);
}
/* Placeholder Help Styles */
.placeholder-help {
overflow-y: auto;
@@ -932,43 +778,3 @@ small {
.section-icon.rename-icon {
background: linear-gradient(135deg, #52c41a25 0%, #52c41a35 100%);
}
/* Dark theme adjustments */
:root.dark .placeholder-help,
:root.auto.dark .placeholder-help {
border-color: var(--color-border);
background: var(--color-background-secondary);
box-shadow: 0 2px 8px rgb(0 0 0 / 20%);
}
:root.dark .category-title,
:root.auto.dark .category-title {
border-bottom-color: var(--color-border);
background: linear-gradient(135deg, var(--color-background-tertiary) 0%, var(--color-background-secondary) 100%);
}
:root.dark .placeholder-category,
:root.auto.dark .placeholder-category {
border-bottom-color: var(--color-border);
}
:root.dark .placeholder-item:hover,
:root.auto.dark .placeholder-item:hover {
background: rgb(var(--color-accent-rgb), 0.12);
}
:root.dark .placeholder-item code,
:root.auto.dark .placeholder-item code {
border-color: rgb(255 255 255 / 15%);
background: var(--color-blue-common);
}
:root.dark .rename-toggle-card,
:root.auto.dark .rename-toggle-card {
background: var(--color-background-tertiary);
}
:root.dark .section-icon.rename-icon,
:root.auto.dark .section-icon.rename-icon {
background: linear-gradient(135deg, #52c41a25 0%, #52c41a35 100%);
}

View File

@@ -0,0 +1,232 @@
/* Transitions */
.inputbox-fade-enter-active,
.inputbox-fade-leave-active {
transition: opacity 0.2s ease;
}
.inputbox-fade-enter-from,
.inputbox-fade-leave-to {
opacity: 0;
}
.inputbox-scale-enter-active {
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.inputbox-scale-leave-active {
transition: all 0.2s ease;
}
.inputbox-scale-enter-from {
opacity: 0;
transform: scale(0.9) translateY(-10px);
}
.inputbox-scale-leave-to {
opacity: 0;
transform: scale(0.95);
}
/* Overlay */
.inputbox-overlay {
position: fixed;
inset: 0;
z-index: 2000;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
background: rgb(0 0 0 / 40%);
}
/* Container */
.inputbox-container {
position: relative;
overflow: hidden;
border: 1px solid var(--color-border);
border-radius: 1rem;
width: 100%;
max-width: 28rem;
background: var(--color-background-tertiary);
}
/* Close Button */
.inputbox-close {
position: absolute;
top: 1rem;
right: 1rem;
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
border: none;
border-radius: 0.5rem;
padding: 0.375rem;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
transition: all 0.15s ease;
cursor: pointer;
}
.inputbox-close:hover {
color: var(--color-text-primary);
background: var(--color-surface-elevated);
}
/* Body */
.inputbox-body {
padding: 1rem 1rem 0.5rem;
}
.inputbox-title {
margin: 0 0 1.25rem;
padding-right: 2rem;
font-size: 1.125rem;
font-weight: 600;
line-height: 1.4;
color: var(--color-text-primary);
}
.inputbox-content {
position: relative;
}
/* Input */
.inputbox-input {
border: 1.5px solid var(--color-border);
border-radius: 0.625rem;
padding: 0.75rem 1rem;
width: 100%;
font-size: 0.9375rem;
font-family: inherit;
color: var(--color-text-primary);
background: var(--color-background-tertiary);
outline: none;
transition: all 0.2s ease;
}
.inputbox-input:hover {
border-color: var(--color-border-hover);
background: var(--color-background-elevated);
}
.inputbox-input:focus {
border-color: var(--color-primary);
background: var(--color-background-elevated);
box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
}
.inputbox-input::placeholder {
color: var(--color-text-primary);
}
/* Textarea */
.inputbox-textarea {
border: 1.5px solid var(--color-border);
border-radius: 0.625rem;
padding: 0.75rem 1rem;
width: 100%;
min-height: 6rem;
font-size: 0.9375rem;
font-family: inherit;
line-height: 1.6;
color: var(--color-text-primary);
background: var(--color-background-tertiary);
outline: none;
resize: vertical;
transition: all 0.2s ease;
}
.inputbox-textarea:hover {
border-color: var(--color-border-hover);
background: var(--color-background-elevated);
}
.inputbox-textarea:focus {
border-color: var(--color-primary);
background: var(--color-background-elevated);
}
.inputbox-textarea::placeholder {
color: var(--color-text-primary);
}
/* Actions */
.inputbox-actions {
display: flex;
border-top: 1px solid var(--color-border);
padding: 1rem 1.5rem;
gap: 0.75rem;
}
.inputbox-btn {
flex: 1;
border: none;
border-radius: 0.5rem;
padding: 0.625rem 1.25rem;
font-size: 0.875rem;
font-weight: 500;
transition: all 0.15s ease;
cursor: pointer;
}
.inputbox-btn:active {
transform: scale(0.98);
}
.inputbox-btn:disabled {
opacity: 0.8;
cursor: not-allowed;
}
.inputbox-btn:disabled:active {
transform: none;
}
/* Cancel Button */
.cancel-btn {
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
background: var(--color-background-elevated);
}
.cancel-btn:hover {
border-color: var(--color-border-hover);
background: var(--color-background-elevated-hover);
}
/* Confirm Button */
.confirm-btn {
border: none;
color: var(--color-text-on-primary);
background: var(--color-accent);
}
.confirm-btn:hover:not(:disabled) {
background: var(--color-accent-hover);
}
/* Responsive */
@media (width <= 640px) {
.inputbox-overlay {
align-items: flex-end;
padding: 0;
}
.inputbox-container {
border-radius: 1rem 1rem 0 0;
max-width: 100%;
}
.inputbox-body {
padding: 1.75rem 1.5rem 1.25rem;
}
.inputbox-actions {
flex-direction: column-reverse;
}
.inputbox-btn {
width: 100%;
}
}

View File

@@ -1,7 +1,7 @@
.navigation {
display: flex;
overflow: hidden;
border-right: 1px solid rgb(229 231 235);
border-right: 1px solid var(--color-border-secondary);
width: 150px;
height: 100vh;
background: var(--color-background-secondary);
@@ -13,12 +13,6 @@
width: 60px;
}
:root.dark .navigation,
:root.auto.dark .navigation {
border-right-color: var(--color-background-secondary);
background: var(--color-background-secondary);
}
.title-bar {
position: relative;
display: flex;
@@ -60,12 +54,6 @@
transform: none;
}
:root.dark .title-bar,
:root.auto.dark .title-bar {
border-bottom-color: var(--color-border);
background: var(--color-background-secondary);
}
.app-title {
display: flex;
flex-direction: column;
@@ -92,7 +80,7 @@
font-size: 10px;
font-weight: 500;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-surface);
}
.theme-section {
@@ -103,11 +91,6 @@
padding: 0.75rem;
}
:root.dark .theme-section,
:root.auto.dark .theme-section {
border-bottom-color: var(--color-border);
}
.nav-menu {
overflow-y: auto;
padding: 1rem 0;
@@ -123,7 +106,7 @@
font-size: 0.875rem;
font-weight: 500;
text-decoration: none;
color: rgb(75 85 99);
color: var(--color-text-secondary);
transition: all 0.2s ease;
gap: 0.75rem;
cursor: pointer;
@@ -139,33 +122,15 @@
display: none;
}
:root.dark .nav-item,
:root.auto.dark .nav-item {
color: rgb(209 213 219);
}
.nav-item:hover {
color: rgb(17 24 39);
background: rgb(243 244 246);
}
:root.dark .nav-item:hover,
:root.auto.dark .nav-item:hover {
color: rgb(243 244 246);
background: rgb(55 65 81);
color: var(--color-text-primary);
background: var(--color-surface);
}
.nav-item.router-link-active {
border-right: 3px solid rgb(99 102 241);
color: rgb(99 102 241);
background: rgb(239 246 255);
}
:root.dark .nav-item.router-link-active,
:root.auto.dark .nav-item.router-link-active {
border-right-color: rgb(129 140 248);
color: rgb(129 140 248);
background: rgb(30 58 138 / 20%);
border-right: 3px solid var(--color-accent);
color: var(--color-accent);
background: var(--color-surface);
}
.nav-icon-container {
@@ -190,7 +155,7 @@
border: none;
border-radius: 6px;
padding: 8px;
color: var(--color-text-secondary);
color: var(--color-text-tertiary);
background: transparent;
cursor: pointer;
}
@@ -217,27 +182,16 @@
font-size: 0.875rem;
font-weight: 500;
text-decoration: none;
color: rgb(75 85 99);
color: var(--color-text-secondary);
background: transparent;
transition: all 0.2s ease;
gap: 0.75rem;
cursor: pointer;
}
:root.dark .submenu-trigger,
:root.auto.dark .submenu-trigger {
color: rgb(209 213 219);
}
.submenu-trigger:hover {
color: rgb(17 24 39);
background: rgb(243 244 246);
}
:root.dark .submenu-trigger:hover,
:root.auto.dark .submenu-trigger:hover {
color: rgb(243 244 246);
background: rgb(55 65 81);
color: var(--color-text-primary);
background: var(--color-surface-elevated);
}
.submenu-trigger .nav-icon-container {
@@ -290,14 +244,8 @@
}
.collapsed-picbed:hover {
color: rgb(17 24 39);
background: rgb(243 244 246);
}
:root.dark .collapsed-picbed:hover,
:root.auto.dark .collapsed-picbed:hover {
color: rgb(243 244 246);
background: rgb(55 65 81);
color: var(--color-text-primary);
background: var(--color-surface-elevated);
}
.qr-dialog {
@@ -328,7 +276,7 @@
border-radius: 16px;
width: 100%;
max-width: 500px;
background: var(--color-background-primary);
background: var(--color-background-secondary);
box-shadow: var(--shadow-md);
}

View File

@@ -122,7 +122,7 @@
border-radius: 12px;
width: 44px;
height: 24px;
background: var(--color-border);
background: linear-gradient(180deg, #d0d3d9 0%, #c0c4cc 100%);
transition: all 0.3s ease;
flex-shrink: 0;
}
@@ -141,7 +141,7 @@
}
.switch-input:checked + .switch-slider {
background: var(--color-blue-common);
background: var(--color-accent);
}
.switch-input:checked + .switch-slider::before {
@@ -342,97 +342,3 @@ select.form-input:focus {
align-items: flex-start;
}
}
/* Dark mode styles */
:root.dark .map-settings-panel,
:root.auto.dark .map-settings-panel {
border-color: var(--color-border);
background: var(--color-background-tertiary);
box-shadow: 0 2px 8px rgb(0 0 0 / 30%);
}
:root.dark .picbed-setting-item,
:root.auto.dark .picbed-setting-item {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .picbed-setting-item:hover,
:root.auto.dark .picbed-setting-item:hover {
border-color: var(--color-primary);
box-shadow: 0 2px 4px rgb(0 0 0 / 30%);
}
:root.dark .form-input,
:root.dark .form-color,
:root.auto.dark .form-input,
:root.auto.dark .form-color {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-surface);
}
:root.dark .form-input:focus,
:root.dark .form-color:focus,
:root.auto.dark .form-input:focus,
:root.auto.dark .form-color:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 2px rgb(64 158 255 / 30%);
}
:root.dark .btn-secondary,
:root.auto.dark .btn-secondary {
border-color: var(--color-border);
color: var(--color-text-secondary);
background: var(--color-surface);
}
:root.dark .btn-secondary:hover,
:root.auto.dark .btn-secondary:hover {
border-color: var(--color-border-hover);
color: var(--color-text-primary);
background: var(--color-background-tertiary);
}
:root.dark .switch-slider::before,
:root.auto.dark .switch-slider::before {
background: var(--color-surface);
}
:root.dark .radio-option.small,
:root.auto.dark .radio-option.small {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .radio-option.small:hover,
:root.auto.dark .radio-option.small:hover {
border-color: var(--color-primary);
background: rgb(64 158 255 / 20%);
}
:root.dark .radio-indicator,
:root.auto.dark .radio-indicator {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .radio-input:checked + .radio-indicator,
:root.auto.dark .radio-input:checked + .radio-indicator {
border-color: var(--color-primary);
}
:root.dark .radio-input:checked + .radio-indicator::after,
:root.auto.dark .radio-input:checked + .radio-indicator::after {
background: var(--color-primary);
}
:root.dark select.form-input,
:root.auto.dark select.form-input {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
}
:root.dark select.form-input:focus,
:root.auto.dark select.form-input:focus {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23409eff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
}

View File

@@ -17,7 +17,7 @@
.form-group.required .form-label::after {
content: ' *';
color: var(--color-error, #ef4444);
color: var(--color-error);
}
.form-label-wrapper {
@@ -72,7 +72,7 @@
max-width: 300px;
font-size: 0.75rem;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
box-shadow: var(--shadow-lg);
line-height: 1.4;
}
@@ -86,12 +86,13 @@
font-size: 0.875rem;
font-family: inherit;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
}
.form-input:focus {
border-color: var(--color-accent);
background: var(--color-surface);
outline: none;
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
}
@@ -101,7 +102,7 @@
}
.form-input.error {
border-color: var(--color-error, #ef4444);
border-color: var(--color-error);
}
.form-input.error:focus {
@@ -134,7 +135,7 @@
}
.form-select.error {
border-color: var(--color-error, #ef4444);
border-color: var(--color-error);
}
.form-select.error:focus {
@@ -294,33 +295,7 @@
.error-message {
margin-top: 0.25rem;
font-size: 0.75rem;
color: var(--color-error, #ef4444);
}
/* White theme adjustments */
.white .form-input,
.white .form-select {
border-color: #dddddd;
background: white;
}
.white .form-input:focus,
.white .form-select:focus {
border-color: var(--color-accent);
}
.white .checkbox-custom {
border-color: #dddddd;
background: white;
}
.white .switch-slider {
background: #dddddd;
}
.white .tooltip-content {
border-color: #dddddd;
background: white;
color: var(--color-error);
}
/* Responsive Design */
@@ -344,32 +319,6 @@
}
}
/* Dark mode adjustments */
:root.dark .form-input,
:root.auto.dark .form-input,
:root.dark .form-select,
:root.auto.dark .form-select {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
:root.dark .checkbox-custom,
:root.auto.dark .checkbox-custom {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
:root.dark .switch-slider,
:root.auto.dark .switch-slider {
background: var(--color-border);
}
:root.dark .tooltip-content,
:root.auto.dark .tooltip-content {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
/* Focus styles for accessibility */
.form-input:focus-visible,
.form-select:focus-visible,

View File

@@ -163,12 +163,6 @@ export default {
0 10px 10px -5px rgb(0 0 0 / 4%);
}
:root.dark .messagebox-container,
:root.auto.dark .messagebox-container {
border-color: rgb(55 65 81);
background: rgb(31 41 55);
}
/* Close Button */
.messagebox-close {
position: absolute;
@@ -192,17 +186,6 @@ export default {
background: rgb(243 244 246);
}
:root.dark .messagebox-close,
:root.auto.dark .messagebox-close {
color: rgb(156 163 175);
}
:root.dark .messagebox-close:hover,
:root.auto.dark .messagebox-close:hover {
color: rgb(209 213 219);
background: rgb(55 65 81);
}
/* Body */
.messagebox-body {
padding: 1.75rem 2rem 1.5rem;
@@ -247,45 +230,21 @@ export default {
background: rgb(254 243 199);
}
:root.dark .messagebox-icon-warning,
:root.auto.dark .messagebox-icon-warning {
color: rgb(251 191 36);
background: rgb(120 53 15 / 30%);
}
.messagebox-icon-info {
color: rgb(59 130 246);
background: rgb(219 234 254);
}
:root.dark .messagebox-icon-info,
:root.auto.dark .messagebox-icon-info {
color: rgb(96 165 250);
background: rgb(30 58 138 / 30%);
}
.messagebox-icon-success {
color: rgb(34 197 94);
background: rgb(220 252 231);
}
:root.dark .messagebox-icon-success,
:root.auto.dark .messagebox-icon-success {
color: rgb(74 222 128);
background: rgb(20 83 45 / 30%);
}
.messagebox-icon-error {
color: rgb(239 68 68);
background: rgb(254 226 226);
}
:root.dark .messagebox-icon-error,
:root.auto.dark .messagebox-icon-error {
color: rgb(248 113 113);
background: rgb(127 29 29 / 30%);
}
/* Content */
.messagebox-content {
flex: 1;
@@ -300,11 +259,6 @@ export default {
color: rgb(17 24 39);
}
:root.dark .messagebox-title,
:root.auto.dark .messagebox-title {
color: rgb(243 244 246);
}
.messagebox-message {
margin: 0;
font-size: 0.9375rem;
@@ -312,11 +266,6 @@ export default {
color: rgb(107 114 128);
}
:root.dark .messagebox-message,
:root.auto.dark .messagebox-message {
color: rgb(156 163 175);
}
/* Actions */
.messagebox-actions {
display: flex;
@@ -325,11 +274,6 @@ export default {
gap: 0.75rem;
}
:root.dark .messagebox-actions,
:root.auto.dark .messagebox-actions {
border-top-color: rgb(55 65 81);
}
.messagebox-actions.center {
justify-content: center;
}
@@ -361,19 +305,6 @@ export default {
background: rgb(249 250 251);
}
:root.dark .cancel-btn,
:root.auto.dark .cancel-btn {
border-color: rgb(55 65 81);
color: rgb(209 213 219);
background: rgb(55 65 81);
}
:root.dark .cancel-btn:hover,
:root.auto.dark .cancel-btn:hover {
border-color: rgb(75 85 99);
background: rgb(75 85 99);
}
/* Confirm Buttons */
.confirm-btn {
border: none;

View File

@@ -145,12 +145,6 @@ export default {
overflow-wrap: break-word;
}
:root.dark .message-toast,
:root.auto.dark .message-toast {
border-color: rgb(55 65 81);
background: rgb(31 41 55);
}
.message-info {
border-left: 4px solid rgb(59 130 246);
}
@@ -198,11 +192,6 @@ export default {
hyphens: auto;
}
:root.dark .message-content,
:root.auto.dark .message-content {
color: rgb(209 213 219);
}
.message-close {
display: flex;
justify-content: center;
@@ -222,17 +211,6 @@ export default {
background: rgb(243 244 246);
}
:root.dark .message-close,
:root.auto.dark .message-close {
color: rgb(156 163 175);
}
:root.dark .message-close:hover,
:root.auto.dark .message-close:hover {
color: rgb(209 213 219);
background: rgb(55 65 81);
}
/* Transition animations */
.message-enter-active,
.message-leave-active {

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import { useStorage } from '@vueuse/core'
import { Monitor, Moon, Sun } from 'lucide-vue-next'
import { computed } from 'vue'
import { computed, onBeforeMount, onBeforeUnmount, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAppStore } from '@/hooks/useAppStore'
interface Props {
collapsed?: boolean
}
@@ -12,9 +11,22 @@ interface Props {
defineProps<Props>()
const { t } = useI18n()
const appStore = useAppStore()
const currentTheme = useStorage<'light' | 'dark' | 'system'>('systemTheme', 'system')
const currentTheme = computed(() => appStore.settings.app.theme || 'light')
watch(
currentTheme,
async newTheme => {
document.documentElement.setAttribute('data-theme', newTheme)
document.documentElement.classList.remove('light', 'dark', 'system')
if (newTheme === 'system') {
const systemTheme = (await window.electron.triggerRPC<'light' | 'dark'>('GET_SYSTEM_THEME')) || 'light'
document.documentElement.classList.add(systemTheme)
} else {
document.documentElement.classList.add(newTheme)
}
},
{ immediate: true },
)
const themeOptions = computed(() => [
{
@@ -30,7 +42,7 @@ const themeOptions = computed(() => [
description: t('settings.theme.darkDesc'),
},
{
value: 'auto',
value: 'system',
label: t('settings.theme.auto'),
icon: Monitor,
description: t('settings.theme.autoDesc'),
@@ -41,9 +53,27 @@ const currentThemeOption = computed(
() => themeOptions.value.find(option => option.value === currentTheme.value) || themeOptions.value[0],
)
const toggleTheme = () => {
appStore.toggleTheme()
function toggleTheme() {
const themes = ['light', 'dark', 'system'] as const
const currentIndex = themes.indexOf(currentTheme.value)
const nextTheme = themes[(currentIndex + 1) % themes.length]
currentTheme.value = nextTheme
}
let listenThemeChange: () => void = () => {}
const themUpdateHandler = (value: 'light' | 'dark') => {
const savedTheme = localStorage.getItem('systemTheme') || 'system'
if (savedTheme === 'system') {
currentTheme.value = value
}
}
onBeforeMount(() => {
listenThemeChange = window.electron.ipcRendererOn('theme-update', themUpdateHandler)
})
onBeforeUnmount(() => {
listenThemeChange()
})
</script>
<template>
@@ -70,7 +100,7 @@ const toggleTheme = () => {
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
color: var(--color-text-secondary);
background: rgb(255 255 255 / 10%);
background: var(--color-background-secondary);
transition: all 0.2s ease;
gap: 0.5rem;
cursor: pointer;
@@ -84,7 +114,6 @@ const toggleTheme = () => {
.theme-toggle-btn:hover {
color: var(--color-text-primary);
background: var(--color-surface-elevated);
}
.theme-label {

View File

@@ -114,20 +114,6 @@ onBeforeUnmount(() => {
pointer-events: none;
}
.app-title {
font-size: 14px;
font-weight: 600;
color: var(--color-text-primary);
}
.app-version {
border-radius: 4px;
padding: 2px 6px;
font-size: 12px;
color: var(--color-text-secondary);
background: var(--color-border);
}
.title-center {
flex: 1;
display: flex;

View File

@@ -1,80 +0,0 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useAppStore = defineStore('app', () => {
const settings = ref<IStringKeyMap>({
app: {
theme: 'light',
},
})
const loading = ref(false)
const error = ref<string | undefined>()
function clearError() {
error.value = undefined
}
const loadSettings = () => {
const savedTheme = localStorage.getItem('theme')
if (savedTheme) {
settings.value.app.theme = savedTheme
}
applyTheme(settings.value.app.theme || 'light')
}
function applyTheme(theme: string) {
const root = document.documentElement
root.classList.remove('light', 'dark', 'auto')
if (theme === 'auto') {
root.classList.add('auto')
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
root.classList.add(prefersDark ? 'dark' : 'light')
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', e => {
if (settings.value.app.theme === 'auto') {
root.classList.remove('light', 'dark')
root.classList.add(e.matches ? 'dark' : 'light')
}
})
} else {
root.classList.add(theme)
}
}
function setTheme(theme: 'light' | 'dark' | 'auto') {
settings.value.app.theme = theme
localStorage.setItem('theme', theme)
applyTheme(theme)
}
function toggleTheme() {
const currentTheme = settings.value.app.theme || 'light'
const themes = ['light', 'dark', 'auto'] as const
const currentIndex = themes.indexOf(currentTheme as any)
const nextTheme = themes[(currentIndex + 1) % themes.length]
setTheme(nextTheme)
}
function init() {
try {
loadSettings()
} catch (err) {
console.error('Application initialization failed:', err)
throw err
}
}
return {
init,
loadSettings,
settings,
loading,
error,
clearError,
setTheme,
toggleTheme,
applyTheme,
}
})

View File

@@ -770,13 +770,22 @@
"webdavEndpoint": "WebDAV Endpoint"
},
"system": {
"applyThemeFailed": "Failed to apply theme",
"autoCloseMainWindow": "Close Main Window when Opening Mini Window",
"autoCloseMiniWindow": "Close Mini Window when Opening Main Window",
"autoLaunch": "Auto Launch",
"autoLaunchDesc": "Automatically start PicList when system boots",
"chooseLanguage": "Choose Language",
"chooseTheme": "Choose Theme",
"customMiniIconPath": "Custom Mini Icon Path",
"downloadingThemes": "Downloading...",
"downloadThemes": "Download Themes",
"downloadThemesFailed": "Failed to download themes",
"downloadThemesSuccess": "Themes downloaded successfully",
"hideDockHint": "Cannot hide both dock and tray at the same time",
"importThemes": "Import Themes",
"importThemesFailed": "Failed to import themes",
"importThemesSuccess": "Themes imported successfully",
"isCustomMiniIcon": "Custom Mini Icon",
"isHideDock": "Hide Dock Icon",
"languageAndAppearance": "Language and Appearance",

View File

@@ -765,13 +765,22 @@
"webdavEndpoint": "WebDAV 端点"
},
"system": {
"applyThemeFailed": "应用主题失败",
"autoCloseMainWindow": "打开迷你窗口时关闭主窗口",
"autoCloseMiniWindow": "打开主窗口时关闭迷你窗口",
"autoLaunch": "开机自启",
"autoLaunchDesc": "登录时自动启动 PicList",
"chooseLanguage": "选择语言",
"chooseTheme": "选择主题",
"customMiniIconPath": "自定义迷你窗口图标路径",
"downloadingThemes": "下载中...",
"downloadThemes": "下载主题",
"downloadThemesFailed": "下载主题失败",
"downloadThemesSuccess": "主题下载成功",
"hideDockHint": "不支持同时隐藏 dock 和托盘",
"importThemes": "导入主题",
"importThemesFailed": "导入主题失败",
"importThemesSuccess": "主题导入成功",
"isCustomMiniIcon": "是否自定义迷你窗口图标",
"isHideDock": "是否隐藏 Dock 图标",
"languageAndAppearance": "语言和外观",

View File

@@ -765,13 +765,22 @@
"webdavEndpoint": "WebDAV 端點"
},
"system": {
"applyThemeFailed": "應用主題失敗",
"autoCloseMainWindow": "打開迷你窗口時關閉主窗口",
"autoCloseMiniWindow": "打開主窗口時關閉迷你窗口",
"autoLaunch": "開機自啟",
"autoLaunchDesc": "系統啟動時自動啟動 PicList",
"chooseLanguage": "選擇語言",
"chooseTheme": "選擇主題",
"customMiniIconPath": "自定義迷你窗口圖標路徑",
"downloadingThemes": "下載中...",
"downloadThemes": "下載主題",
"downloadThemesFailed": "下載主題失敗",
"downloadThemesSuccess": "主題下載成功",
"hideDockHint": "不支持同時隱藏 dock 和托盤",
"importThemes": "導入主題",
"importThemesFailed": "導入主題失敗",
"importThemesSuccess": "主題導入成功",
"isCustomMiniIcon": "是否自定義迷你窗口圖標",
"isHideDock": "是否隱藏 Dock 圖標",
"languageAndAppearance": "語言和外觀",

View File

@@ -2,9 +2,6 @@
<div id="main" class="app-container">
<InputBoxDialog />
<TitleBar />
<div class="app-background">
<div class="bg-gradient" />
</div>
<Navigation />
<main class="main-content">
<div class="content-container">
@@ -56,6 +53,8 @@ export default { name: 'MainPage' }
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizelegibility;
--background-image: none;
--background-image-opacity: 1;
--color-text-primary: #1d1d1f;
--color-text-secondary: #6e6e73;
--color-text-tertiary: #86868b;
@@ -92,8 +91,7 @@ export default { name: 'MainPage' }
--transition-slow: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
:root.dark,
:root.auto.dark {
:root.dark {
--color-text-primary: #f5f5f7;
--color-text-secondary: #a1a1a6;
--color-text-tertiary: #86868b;
@@ -108,47 +106,26 @@ export default { name: 'MainPage' }
--color-primary-hover: #818cf8;
--color-accent: #0a84ff;
--color-accent-hover: #409cff;
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--color-text-primary);
}
p,
span,
div {
color: inherit;
}
svg {
color: inherit;
}
input,
select,
textarea {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-surface);
}
input::placeholder,
textarea::placeholder {
color: var(--color-text-tertiary);
}
button {
border-color: var(--color-border);
color: var(--color-text-primary);
}
button:hover {
background: var(--color-surface-elevated);
}
--accent-rgb: #449af7;
--color-blue-common: #409eff;
--color-light-blue: rgb(0 122 255 / 5%);
--color-success: #34c759;
--color-warning: #f1930f;
--color-danger: #ff3b30;
--color-error: #cb2431;
--color-error-surface: rgb(255 59 48 / 10%);
--shadow-sm: 0 1px 3px rgb(0 0 0 / 4%), 0 1px 2px rgb(0 0 0 / 6%);
--shadow-md: 0 4px 6px rgb(0 0 0 / 5%), 0 2px 4px rgb(0 0 0 / 6%);
--shadow-lg: 0 10px 15px rgb(0 0 0 / 8%), 0 4px 6px rgb(0 0 0 / 5%);
--shadow-xl: 0 20px 25px rgb(0 0 0 / 10%), 0 10px 10px rgb(0 0 0 / 4%);
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-2xl: 20px;
--transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
--transition-medium: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
body {
@@ -167,23 +144,6 @@ body {
background-color: var(--color-background-primary);
}
.app-background {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
}
.bg-gradient {
position: absolute;
bottom: -40%;
left: -20%;
border-radius: 50%;
width: 60%;
height: 60%;
background: radial-gradient(circle, rgb(199 131 233 / 5%) 0%, transparent 70%);
}
.main-content {
position: relative;
z-index: 1;

View File

@@ -21,6 +21,9 @@ import db from '@/utils/db'
type MessageSchema = typeof zhCN
window.electron.setVisualZoomLevelLimits(1, 1)
const savedTheme = localStorage.getItem('systemTheme') || 'system'
document.documentElement.setAttribute('data-theme', savedTheme)
document.documentElement.classList.add(savedTheme)
const app = createApp(App)

View File

@@ -62,7 +62,7 @@ const toggleTooltip = () => {
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: 1rem;
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.switch-label-wrapper {
@@ -97,7 +97,7 @@ const toggleTooltip = () => {
.info-icon:hover {
color: var(--color-accent);
background: rgb(0 122 255 / 10%);
background: var(--color-background-secondary);
}
.info-svg {
@@ -145,7 +145,7 @@ const toggleTooltip = () => {
position: absolute;
inset: 0;
border-radius: 0.75rem;
background: var(--color-border);
background: var(--color-primary);
transition: var(--transition-fast);
cursor: pointer;
}
@@ -184,16 +184,4 @@ const toggleTooltip = () => {
.switch-input:checked ~ .switch-text {
color: var(--color-accent);
}
/* Dark mode adjustments */
:root.dark .switch-slider,
:root.auto.dark .switch-slider {
background: var(--color-border);
}
:root.dark .tooltip-content,
:root.auto.dark .tooltip-content {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
</style>

View File

@@ -14,7 +14,7 @@
.bucket-card {
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-xl);
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow: var(--shadow-sm);
transition: var(--transition-medium);
}
@@ -53,7 +53,7 @@
width: 200px;
font-size: 0.875rem;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-tertiary);
transition: var(--transition-fast);
}
@@ -155,8 +155,8 @@
padding: 0.5rem;
font-size: 0.75rem;
font-weight: 500;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
color: var(--color-accent);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.25rem;
cursor: pointer;
@@ -164,14 +164,14 @@
.action-button:hover {
color: white;
background: var(--color-accent);
background: var(--color-accent-hover);
box-shadow: var(--shadow-sm);
transform: translateY(-1px);
}
.action-button.primary {
color: white;
background: var(--color-blue-common);
background: var(--color-accent);
}
.action-button.primary:hover {
@@ -180,7 +180,7 @@
.action-button.secondary {
border: 1px solid var(--color-border);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.action-button.secondary:hover {
@@ -238,7 +238,7 @@
border: 0 solid var(--color-border);
font-size: 0.875rem;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.25rem;
cursor: pointer;
@@ -296,7 +296,7 @@
padding: 0.25rem;
border: 0 solid var(--color-border-secondary);
border-radius: var(--radius-md);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
}
@@ -354,7 +354,7 @@
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.5rem;
cursor: pointer;
@@ -456,7 +456,7 @@
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-lg);
margin: 0;
background: var(--color-surface);
background: var(--color-background-secondary);
cursor: pointer;
transition: var(--transition-medium);
width: 100%;
@@ -472,7 +472,7 @@
}
.virtual-gallery-scroller .file-grid-item.selected {
border-color: var(--color-blue-common);
border-color: var(--color-accent);
box-shadow: 0 0 0 2px rgb(59 130 246 / 20%);
}
@@ -482,7 +482,7 @@
justify-content: center;
align-items: center;
overflow: hidden;
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
flex: 1;
aspect-ratio: auto;
}
@@ -554,7 +554,7 @@
width: 32px;
height: 32px;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
cursor: pointer;
}
@@ -1246,7 +1246,7 @@ input:checked + .switch-slider::before {
align-items: center;
border-bottom: 1px solid var(--color-border-secondary);
padding: 0.75rem 1rem;
background: var(--color-surface);
background: var(--color-background-secondary);
flex-shrink: 0;
}

View File

@@ -83,7 +83,7 @@
text-decoration: none;
white-space: nowrap;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.5rem;
cursor: pointer;
@@ -102,9 +102,9 @@
}
.action-button.primary {
border-color: var(--color-blue-common);
border-color: var(--color-accent);
color: white;
background: var(--color-blue-common);
background: var(--color-accent);
}
.action-button.primary:hover {
@@ -164,7 +164,7 @@
text-decoration: none;
white-space: nowrap;
color: var(--color-text-secondary);
background: var( --color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.5rem;
cursor: pointer;
@@ -238,7 +238,7 @@
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-lg);
padding: 1.25rem;
background: var( --color-surface-elevated);
background: var( --color-background-secondary);
transition: var(--transition-medium);
}
@@ -289,7 +289,7 @@
padding: 0.5rem;
font-size: 0.875rem;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.5rem;
cursor: pointer;

View File

@@ -134,12 +134,13 @@
width: 100%;
font-size: 0.875rem;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
}
.form-input:focus {
border-color: var(--color-accent);
background: var(--color-background-tertiary);
outline: none;
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
}
@@ -233,7 +234,7 @@
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: 0.625rem;
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
gap: 0.75rem;
cursor: pointer;
@@ -399,29 +400,6 @@
gap: 1rem;
}
/* Dark mode adjustments */
:root.dark .manage-setting-container,
:root.auto.dark .manage-setting-container {
background: var(--color-background-secondary);
}
:root.dark .form-input,
:root.auto.dark .form-input {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
:root.dark .radio-custom,
:root.auto.dark .radio-custom {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
:root.dark .pattern-table th,
:root.auto.dark .pattern-table th {
background: var(--color-surface-elevated);
}
.setting-section {
display: flex;
gap: 0.5rem;

View File

@@ -73,6 +73,37 @@
<option value="main">{{ t('pages.settings.system.mainMode') }}</option>
</select>
</div>
<div class="system-option-card">
<div class="system-option-header">
<ImageIcon :size="18" />
<span>{{ t('pages.settings.system.chooseTheme') }}</span>
</div>
<select v-model="currentTheme" class="form-select">
<option v-for="theme in themeList" :key="theme.key" :value="theme.key">
{{ theme.label }}
</option>
</select>
</div>
</div>
<div class="theme-actions-grid">
<button
class="btn btn-secondary theme-action-btn"
:disabled="downloadingThemes"
@click="handleDownloadThemes"
>
<Download :size="14" />
<span>{{
downloadingThemes
? t('pages.settings.system.downloadingThemes')
: t('pages.settings.system.downloadThemes')
}}</span>
</button>
<button class="btn btn-secondary theme-action-btn" @click="handleImportThemes">
<Import :size="14" />
<span>{{ t('pages.settings.system.importThemes') }}</span>
</button>
</div>
</div>
@@ -1812,6 +1843,9 @@ const { picBedG, updatePicBeds } = usePicBed()
const showPicBedList = ref<string[]>([])
const galleryPicBedFilterList = ref<string[]>([])
const themeList = ref<{ key: string; label: string }[]>([{ key: 'default.css', label: '默认' }])
const currentTheme = ref('default.css')
const downloadingThemes = ref(false)
const currentTab = useStorage<'system' | 'sync' | 'upload' | 'advanced' | 'update'>('settings-current-tab', 'system')
// Tab configuration
@@ -1883,6 +1917,7 @@ const formOfSetting = ref<ISettingForm>({
mainWindowWidth: 1200,
mainWindowHeight: 800,
enableSecondUploader: false,
theme: 'default.css',
})
const proxy = ref('')
@@ -1956,6 +1991,12 @@ const addWatch = () => {
handleShortUrlServerChange(newVal)
}
})
watch(currentTheme, newVal => {
if (newVal) {
handleThemeChange(newVal)
}
})
}
const addProxyWatch = () => {
@@ -2095,12 +2136,69 @@ onBeforeMount(() => {
initData()
})
async function loadThemes() {
try {
const themes = await window.electron.triggerRPC<{ key: string; label: string }[]>(
IRPCActionType.THEME_RESOLVE_THEMES,
)
if (themes && themes.length > 0) {
themeList.value = themes
}
} catch (error) {
console.error('Failed to load themes:', error)
}
}
async function handleDownloadThemes() {
try {
downloadingThemes.value = true
await window.electron.triggerRPC(IRPCActionType.THEME_FETCH_THEMES)
message.success(t('pages.settings.system.downloadThemesSuccess'))
await loadThemes()
} catch (error) {
console.error('Failed to download themes:', error)
message.error(t('pages.settings.system.downloadThemesFailed'))
} finally {
downloadingThemes.value = false
}
}
async function handleImportThemes() {
try {
const result = await window.electron.triggerRPC<string[]>(IRPCActionType.MANAGE_OPEN_FILE_SELECT_DIALOG, {
title: t('pages.settings.system.importThemes'),
filters: [{ name: 'CSS Files', extensions: ['css'] }],
properties: ['openFile', 'multiSelections'],
})
if (result && result.length > 0) {
await window.electron.triggerRPC(IRPCActionType.THEME_IMPORT_THEMES, result)
message.success(t('pages.settings.system.importThemesSuccess'))
await loadThemes()
}
} catch (error) {
console.error('Failed to import themes:', error)
message.error(t('pages.settings.system.importThemesFailed'))
}
}
async function handleThemeChange(theme: string) {
try {
await window.electron.triggerRPC(IRPCActionType.THEME_APPLY_THEME, theme)
saveConfig({ [configPaths.settings.theme]: theme })
} catch (error) {
console.error('Failed to apply theme:', error)
message.error(t('pages.settings.system.applyThemeFailed'))
}
}
async function initData() {
const config = (await getConfig<IConfig>()) || ({} as IConfig)
const settings = config.settings || {}
const picBed = config.picBed
showPicBedList.value = picBedG.value.filter(item => item.visible).map(item => item.name)
galleryPicBedFilterList.value = settings.galleryPicBedFilter || []
currentTheme.value = settings.theme || 'default.css'
await loadThemes()
formKeys.forEach(key => {
;(formOfSetting.value as any)[key] = settings[key] ?? formOfSetting.value[key]
})

View File

@@ -339,12 +339,4 @@ export default {
.input-error {
animation: shake 0.3s ease-in-out;
}
/* Dark mode adjustments */
:root.dark .rename-card,
:root.auto.dark .rename-card {
box-shadow:
0 20px 25px -5px rgb(0 0 0 / 30%),
0 10px 10px -5px rgb(0 0 0 / 20%);
}
</style>

View File

@@ -134,11 +134,11 @@
</div>
<div class="quick-actions">
<button class="quick-action-button" @click="uploadClipboardFiles">
<ClipboardIcon :size="20" />
<ClipboardIcon class="action-icon" :size="18" />
<span>{{ t('pages.upload.clipboardPicture') }}</span>
</button>
<button class="quick-action-button" @click="uploadURLFiles">
<LinkIcon :size="20" />
<LinkIcon class="action-icon" :size="18" />
<span>{{ t('pages.upload.urlUpload') }}</span>
</button>
<button
@@ -146,7 +146,7 @@
:class="{ 'has-badge': taskQueueStatus.tasks.length > 0 }"
@click="openTaskDialog"
>
<ListTodoIcon :size="20" />
<ListTodoIcon class="action-icon" :size="18" />
<span>{{ t('pages.upload.taskUpload') }}</span>
<span v-if="taskQueueStatus.tasks.length > 0" class="task-count-badge">
{{ taskQueueStatus.tasks.length }}

View File

@@ -41,7 +41,7 @@ html, body {
overflow: hidden;
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-xl);
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow: var(--shadow-sm);
transition: var(--transition-medium);
}
@@ -717,7 +717,7 @@ input:checked + .switch-slider::before {
width: 32px;
height: 32px;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
cursor: pointer;
}
@@ -1303,7 +1303,7 @@ input:checked + .switch-slider::before {
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-lg);
margin: 0;
background: var(--color-surface);
background: var(--color-background-secondary);
cursor: pointer;
width: 100%;
height: calc(100% - 8px);

View File

@@ -22,7 +22,7 @@
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1rem;
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
}
@@ -55,7 +55,7 @@
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 0.5rem;
background: var(--color-background-primary);
background: var(--color-background-secondary);
box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
}
@@ -83,7 +83,7 @@
.tab-button.active {
color: white;
background: #409eff;
background: var(--color-accent);
box-shadow: 0 2px 4px rgb(64 158 255 / 30%);
}
@@ -146,7 +146,7 @@
width: 100%;
font-size: 0.875rem;
color: var(--color-text-primary);
background: var(--color-background-primary);
background: var(--color-surface);
transition: all 0.2s ease;
box-sizing: border-box;
}
@@ -154,9 +154,8 @@
.form-input:focus,
.form-textarea:focus,
.form-select:focus {
border-color: var(--color-blue-common);
border-color: var(--color-accent);
outline: none;
box-shadow: 0 0 0 2px var(--el-color-primary-light-9, rgb(64 158 255 / 20%));
}
.form-textarea {
@@ -252,7 +251,7 @@
}
.switch-input:checked + .switch-slider {
background: #409eff;
background: var(--color-accent);
}
.switch-input:checked + .switch-slider::before {
@@ -361,7 +360,7 @@
.btn-primary {
color: white;
background: #409eff;
background: var(--color-accent);
}
.btn-primary:hover:not(:disabled) {
@@ -371,7 +370,7 @@
.btn-secondary {
border: 1px solid var(--color-border);
color: var(--color-text-primary);
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.btn-secondary:hover:not(:disabled) {
@@ -600,81 +599,6 @@ small {
}
}
/* Dark mode adjustments */
:root.dark .piclist-settings,
:root.auto.dark .piclist-settings {
background: var(--color-background-secondary);
}
:root.dark .settings-header,
:root.dark .tab-navigation,
:root.dark .settings-section,
:root.auto.dark .settings-header,
:root.auto.dark .tab-navigation,
:root.auto.dark .settings-section {
border-color: var(--color-border);
background: var(--color-background-secondary);
}
:root.dark .form-input,
:root.dark .form-textarea,
:root.dark .form-select,
:root.auto.dark .form-input,
:root.auto.dark .form-textarea,
:root.auto.dark .form-select {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-background-tertiary);
}
:root.dark .switch-slider::before,
:root.auto.dark .switch-slider::before {
background: var(--color-surface);
}
:root.dark .btn-secondary,
:root.auto.dark .btn-secondary {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-background-tertiary);
}
:root.dark .btn-secondary:hover,
:root.auto.dark .btn-secondary:hover {
background: var(--color-background-secondary);
}
:root.dark .switch-label,
:root.auto.dark .switch-label {
border-color: var(--color-border);
background: var(--color-background-tertiary);
}
:root.dark .switch-label:hover,
:root.auto.dark .switch-label:hover {
background: var(--color-background-secondary);
}
:root.dark .radio-option,
:root.dark .checkbox-option,
:root.auto.dark .radio-option,
:root.auto.dark .checkbox-option {
border-color: var(--color-border);
background: var(--color-background-tertiary);
}
:root.dark .radio-option:hover,
:root.dark .checkbox-option:hover,
:root.auto.dark .radio-option:hover,
:root.auto.dark .checkbox-option:hover {
background: var(--color-background-secondary);
}
:root.dark .dialog,
:root.auto.dark .dialog {
background: var(--color-background-tertiary);
}
/* Placeholder Help Styles */
.placeholder-help {
overflow-y: auto;
@@ -770,36 +694,6 @@ small {
background: var(--color-text-secondary);
}
/* Dark theme adjustments */
:root.dark .placeholder-help,
:root.auto.dark .placeholder-help {
border-color: var(--color-border);
background: var(--color-background-secondary);
box-shadow: 0 2px 8px rgb(0 0 0 / 20%);
}
:root.dark .category-title,
:root.auto.dark .category-title {
border-bottom-color: var(--color-border);
background: linear-gradient(135deg, var(--color-background-tertiary) 0%, var(--color-background-secondary) 100%);
}
:root.dark .placeholder-category,
:root.auto.dark .placeholder-category {
border-bottom-color: var(--color-border);
}
:root.dark .placeholder-item:hover,
:root.auto.dark .placeholder-item:hover {
background: rgb(var(--color-accent-rgb), 0.12);
}
:root.dark .placeholder-item code,
:root.auto.dark .placeholder-item code {
border-color: rgb(255 255 255 / 15%);
background: var(--color-blue-common);
}
/* Update info and Release Notes Styles */
.update-info {
margin-bottom: 1.5rem;
@@ -943,7 +837,7 @@ small {
display: flex;
align-items: center;
font-size: 0.75rem;
color: var(--color-text-tertiary);
color: var(--color-text-secondary);
gap: 0.375rem;
}
@@ -1184,7 +1078,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 0.5rem 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -1260,7 +1154,7 @@ small {
border: 1px dashed var(--color-border);
border-radius: 12px;
padding: 1.5rem 1rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 0.75rem;
@@ -1305,8 +1199,8 @@ small {
border-radius: 10px;
width: 34px;
height: 34px;
color: white;
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
color: var(--color-surface);
background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-hover) 100%);
box-shadow: 0 4px 12px rgb(64 158 255 / 25%);
flex-shrink: 0;
}
@@ -1418,50 +1312,6 @@ small {
margin-top: 0.5rem;
}
/* Dark Mode Adjustments for Sync Panel */
:root.dark .sync-overview-card,
:root.auto.dark .sync-overview-card {
background: linear-gradient(135deg, var(--color-background-secondary) 0%, var(--color-background-tertiary) 100%);
box-shadow: 0 4px 16px rgb(0 0 0 / 20%);
}
:root.dark .sync-action-card,
:root.auto.dark .sync-action-card {
border-color: var(--color-border);
background: var(--color-background-secondary);
}
:root.dark .sync-action-card:hover,
:root.auto.dark .sync-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .file-action-btn,
:root.auto.dark .file-action-btn {
background: var(--color-background-secondary);
}
:root.dark .file-action-btn:hover,
:root.auto.dark .file-action-btn:hover {
background: rgb(64 158 255 / 12%);
}
:root.dark .sync-type-btn,
:root.auto.dark .sync-type-btn {
border-color: var(--color-border);
background: var(--color-background-secondary);
}
:root.dark .sync-type-btn:hover,
:root.auto.dark .sync-type-btn:hover {
background: rgb(64 158 255 / 15%);
}
:root.dark .sync-type-btn.active,
:root.auto.dark .sync-type-btn.active {
background: rgb(64 158 255 / 20%);
}
/* Responsive Adjustments */
@media (width <= 768px) {
.sync-overview-card {
@@ -1497,7 +1347,7 @@ small {
border-radius: 12px;
width: 44px;
height: 44px;
color: white;
color: var(--color-surface);
flex-shrink: 0;
}
@@ -1539,7 +1389,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -1609,7 +1459,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
}
@@ -1674,7 +1524,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.encryption-key-header {
@@ -1777,7 +1627,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 0.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.update-preferences-section .switch-label {
@@ -1801,7 +1651,7 @@ small {
align-items: center;
border-bottom: 1px solid var(--color-border);
padding: 1rem 1.5rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.release-notes-title {
@@ -1894,64 +1744,6 @@ small {
background: var(--color-background-tertiary);
}
/* Dark Mode for Advanced & Update */
:root.dark .advanced-action-card,
:root.auto.dark .advanced-action-card {
border-color: var(--color-border);
background: var(--color-background-secondary);
}
:root.dark .advanced-action-card:hover,
:root.auto.dark .advanced-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .server-config-card,
:root.auto.dark .server-config-card {
background: var(--color-background-secondary);
}
:root.dark .server-config-card:hover,
:root.auto.dark .server-config-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .encryption-key-section,
:root.auto.dark .encryption-key-section {
background: var(--color-background-secondary);
}
:root.dark .update-status-card,
:root.auto.dark .update-status-card {
background: linear-gradient(135deg, var(--color-background-secondary) 0%, var(--color-background-tertiary) 100%);
box-shadow: 0 4px 16px rgb(0 0 0 / 20%);
}
:root.dark .release-notes-card.enhanced,
:root.auto.dark .release-notes-card.enhanced {
background: var(--color-background-secondary);
}
:root.dark .release-notes-card.enhanced .release-notes-header,
:root.auto.dark .release-notes-card.enhanced .release-notes-header {
background: var(--color-background-tertiary);
}
:root.dark .release-notes-card.enhanced .release-notes-content,
:root.auto.dark .release-notes-card.enhanced .release-notes-content {
background: var(--color-background-secondary);
}
:root.dark .release-notes-card.enhanced .release-notes-footer,
:root.auto.dark .release-notes-card.enhanced .release-notes-footer {
background: var(--color-background-tertiary);
}
:root.dark .update-preference-card,
:root.auto.dark .update-preference-card {
background: var(--color-background-secondary);
}
/* Responsive for Advanced & Update */
@media (width <= 768px) {
.advanced-action-grid {
@@ -1975,17 +1767,10 @@ small {
/* ==================== System Settings Panel ==================== */
/* Section Icon Wrapper - Additional Colors */
.section-icon-wrapper.window,
.section-icon-wrapper.startup,
.section-icon-wrapper.language {
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
}
.section-icon-wrapper.window {
background: linear-gradient(135deg, #909399 0%, #c0c4cc 100%);
}
.section-icon-wrapper.startup {
background: linear-gradient(135deg, #e6a23c 0%, #f5c55c 100%);
background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-hover) 100%);
}
/* System Option Grid */
@@ -1999,7 +1784,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.system-option-header {
@@ -2024,7 +1809,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -2088,7 +1873,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 10px;
padding: 0.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.system-toggle-card .switch-label {
@@ -2117,6 +1902,39 @@ small {
color: var(--color-accent);
}
/* Theme Actions Grid */
.theme-actions-grid {
display: flex;
gap: 0.5rem;
margin-top: 0.75rem;
}
.theme-action-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.375rem;
padding: 0.5rem 0.75rem;
font-size: 0.8125rem;
font-weight: 500;
transition: all 0.25s ease;
}
.theme-action-btn svg {
width: 14px;
height: 14px;
}
.theme-action-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.theme-action-btn:not(:disabled):hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgb(64 158 255 / 15%);
}
/* Startup Options Grid */
.startup-options-grid {
display: grid;
@@ -2128,7 +1946,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 0.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.startup-toggle-card .switch-label {
@@ -2144,7 +1962,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -2235,7 +2053,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 0.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.upload-feature-card .switch-label {
@@ -2267,7 +2085,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 0.75rem;
@@ -2275,7 +2093,6 @@ small {
.upload-action-card:hover {
border-color: var(--color-accent);
background: var(--color-background-secondary);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgb(64 158 255 / 15%);
}
@@ -2334,7 +2151,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -2394,7 +2211,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 10px;
padding: 0.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
}
.upload-toggle-card .switch-label {
@@ -2416,7 +2233,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 1.25rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.25s ease;
cursor: pointer;
gap: 1rem;
@@ -2510,7 +2327,7 @@ small {
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 0.625rem 0.875rem;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
transition: all 0.2s ease;
cursor: pointer;
gap: 0.5rem;
@@ -2791,122 +2608,6 @@ small {
color: var(--color-accent);
}
/* Dark Mode Adjustments */
:root.dark .system-option-card,
:root.auto.dark .system-option-card {
background: var(--color-background-secondary);
}
:root.dark .window-size-card,
:root.auto.dark .window-size-card {
background: var(--color-background-secondary);
}
:root.dark .window-size-card:hover,
:root.auto.dark .window-size-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .system-toggle-card,
:root.auto.dark .system-toggle-card {
background: var(--color-background-secondary);
}
:root.dark .startup-toggle-card,
:root.auto.dark .startup-toggle-card {
background: var(--color-background-secondary);
}
:root.dark .shortcut-action-card,
:root.auto.dark .shortcut-action-card {
background: var(--color-background-secondary);
}
:root.dark .shortcut-action-card:hover,
:root.auto.dark .shortcut-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .upload-feature-card,
:root.auto.dark .upload-feature-card {
background: var(--color-background-secondary);
}
:root.dark .upload-action-card,
:root.auto.dark .upload-action-card {
background: var(--color-background-secondary);
}
:root.dark .upload-action-card:hover,
:root.auto.dark .upload-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .processing-action-card,
:root.auto.dark .processing-action-card {
background: var(--color-background-secondary);
}
:root.dark .processing-action-card:hover,
:root.auto.dark .processing-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .upload-toggle-card,
:root.auto.dark .upload-toggle-card {
background: var(--color-background-secondary);
}
:root.dark .url-format-action-card,
:root.auto.dark .url-format-action-card {
background: var(--color-background-secondary);
}
:root.dark .url-format-action-card:hover,
:root.auto.dark .url-format-action-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .short-url-config,
:root.auto.dark .short-url-config {
background: var(--color-background-secondary);
}
:root.dark .picbed-checkbox-card,
:root.auto.dark .picbed-checkbox-card {
background: var(--color-background-secondary);
}
:root.dark .picbed-checkbox-card:hover,
:root.auto.dark .picbed-checkbox-card:hover {
background: var(--color-background-tertiary);
}
:root.dark .enhanced-dialog,
:root.auto.dark .enhanced-dialog {
background: var(--color-background-secondary);
}
:root.dark .placeholder-info-card,
:root.auto.dark .placeholder-info-card {
background: var(--color-background-tertiary);
}
:root.dark .proxy-config-card,
:root.auto.dark .proxy-config-card {
background: var(--color-background-tertiary);
}
:root.dark .version-card,
:root.auto.dark .version-card {
background: var(--color-background-tertiary);
}
:root.dark .rename-toggle-card,
:root.auto.dark .rename-toggle-card {
background: var(--color-background-tertiary);
}
/* ============================
Log Dialog Styles
============================ */
@@ -3087,31 +2788,6 @@ small {
color: var(--color-accent);
}
/* Dark mode for new dialog components */
:root.dark .log-file-card,
:root.auto.dark .log-file-card {
background: var(--color-background-tertiary);
}
:root.dark .log-file-card:hover,
:root.auto.dark .log-file-card:hover {
background: var(--color-background-secondary);
}
:root.dark .server-notice-card,
:root.auto.dark .server-notice-card {
background: var(--color-background-tertiary);
}
:root.dark .server-toggle-card,
:root.auto.dark .server-toggle-card {
background: var(--color-background-tertiary);
}
:root.dark .server-config-section,
:root.auto.dark .server-config-section {
background: var(--color-background-tertiary);
}
/* Responsive Adjustments */
@media (width <= 768px) {
@@ -3174,12 +2850,11 @@ small {
.notes-body {
overflow-y: auto;
border-radius: 12px;
padding: 1.25rem;
max-height: 195px;
font-size: 0.9375rem;
line-height: 1.5;
background: var(--color-background-tertiary);
background: var(--color-background-secondary);
color: var(--color-text-secondary);
}

View File

@@ -21,7 +21,7 @@ html, body {
overflow: hidden;
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-xl);
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow: var(--shadow-sm);
transition: var(--transition-medium);
}
@@ -86,7 +86,7 @@ html, body {
font-family: inherit;
font-weight: 500;
color: white;
background: var(--color-blue-common);
background: var(--color-accent);
transition: var(--transition-fast);
gap: 0.5rem;
cursor: pointer;
@@ -101,7 +101,7 @@ html, body {
.action-button.secondary {
border: 1px solid var(--color-border);
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.action-button.secondary:hover {
@@ -148,12 +148,13 @@ html, body {
font-size: 0.875rem;
font-family: inherit;
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: var(--transition-fast);
}
.search-input:focus {
border-color: var(--color-accent);
background: var(--color-background-tertiary);
outline: none;
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
}
@@ -369,8 +370,7 @@ html, body {
}
.plugin-logo {
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-md);
border-radius: var(--radius-lg);
width: 48px;
height: 48px;
object-fit: cover;
@@ -407,7 +407,7 @@ html, body {
font-size: 0.75rem;
font-weight: 400;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-tertiary);
}
.plugin-author {
@@ -434,7 +434,7 @@ html, body {
min-height: 2.6rem;
font-size: 0.875rem;
text-overflow: ellipsis;
color: var(--color-text-secondary);
color: var(--color-text-primary);
line-height: 1.5;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
@@ -489,8 +489,8 @@ html, body {
}
.settings-button {
color: white;
background: var(--color-blue-common);
color: var(--color-text-primary);
background: var(--color-background-secondary);
}
.settings-button:hover:not(:disabled) {
@@ -501,7 +501,7 @@ html, body {
.disabled-button {
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.disabled-button:hover:not(:disabled) {
@@ -660,7 +660,7 @@ html, body {
.btn:disabled {
cursor: not-allowed;
opacity: 0.6;
opacity: 0.8;
}
.btn:hover:not(:disabled) {
@@ -755,48 +755,6 @@ html, body {
}
}
/* Dark mode adjustments */
:root.dark .plugin-container,
:root.auto.dark .plugin-container {
background: var(--color-background-secondary);
}
:root.dark .plugin-card,
:root.auto.dark .plugin-card {
border-color: var(--color-border-secondary);
background: var(--color-surface-elevated);
}
:root.dark .search-input,
:root.auto.dark .search-input {
border-color: var(--color-border);
color: var(--color-text-primary);
background: var(--color-surface-elevated);
}
:root.dark .search-input:focus,
:root.auto.dark .search-input:focus {
border-color: var(--color-accent);
}
:root.dark .modal-container,
:root.auto.dark .modal-container {
border-color: var(--color-border);
background: var(--color-surface);
}
:root.dark .btn-secondary,
:root.auto.dark .btn-secondary {
border-color: var(--color-border);
background: var(--color-surface-elevated);
}
:root.dark .btn-secondary:hover,
:root.auto.dark .btn-secondary:hover {
border-color: var(--color-accent);
background: var(--color-surface);
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
* {

View File

@@ -380,7 +380,7 @@ html, body {
border: 2px dashed var(--color-border);
border-radius: var(--radius-xl);
padding: 3rem 2rem;
background: var(--color-background-primary);
background: var(--color-background-secondary);
transition: var(--transition-medium);
cursor: pointer;
}
@@ -409,7 +409,7 @@ html, body {
width: 80px;
height: 80px;
color: white;
background: var(--color-accent-hover);
background: var(--color-accent);
transition: var(--transition-medium);
}
@@ -522,15 +522,19 @@ html, body {
.quick-action-button:hover {
border-color: var(--color-accent-hover);
background: var(--color-surface-elevated);
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
.quick-action-button .action-icon {
flex-shrink: 0;
color: var(--color-accent);
}
.quick-action-button span {
font-size: 0.8rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text-primary);
color: var(--color-text-secondary);
}
.quick-action-button.has-badge {
@@ -631,7 +635,7 @@ html, body {
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
font-weight: 500;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-surface);
transition: var(--transition-fast);
cursor: pointer;
}
@@ -653,7 +657,7 @@ html, body {
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-md);
width: 100%;
background: var(--color-surface-elevated);
background: var(--color-surface);
}
.toggle-button {
@@ -721,7 +725,7 @@ html, body {
max-width: 90vw;
height: 85vh;
max-height: 85vh;
background: var(--color-surface);
background: var(--color-background-tertiary);
box-shadow: var(--shadow-xl);
}
@@ -731,7 +735,7 @@ html, body {
align-items: center;
border-bottom: 1px solid var(--color-border-secondary);
padding: 1rem 1.25rem;
background: var(--color-surface-elevated);
background: var(--color-background-tertiary);
}
.modal-title {
@@ -896,28 +900,6 @@ html, body {
}
}
/* Dark mode adjustments */
:root.dark .upload-zone,
:root.auto.dark .upload-zone {
background: linear-gradient(135deg, var(--color-background-secondary) 0%, var(--color-background-tertiary) 100%);
}
:root.dark .upload-zone:hover,
:root.dark .upload-zone.drag-active,
:root.auto.dark .upload-zone:hover,
:root.auto.dark .upload-zone.drag-active {
background: linear-gradient(135deg, var(--color-surface) 0%, var(--color-light-blue) 100%);
}
:root.dark .picbed-badge.is-active,
:root.auto.dark .picbed-badge.is-active,
:root.dark .picbed-badge:hover
{
border-color: var(--color-accent-hover);
border-width: 0.1rem;
font-weight: 600;
}
/* Animation for upload icon */
@keyframes float {
0%, 100% {
@@ -1633,11 +1615,7 @@ html, body {
gap: 1rem;
flex-wrap: wrap;
padding: 1rem 1.25rem;
background: linear-gradient(
180deg,
var(--color-surface-elevated) 0%,
var(--color-surface) 100%
);
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
backdrop-filter: blur(10px);
}
@@ -1797,6 +1775,7 @@ html, body {
padding: 1rem 1.25rem 1.25rem;
background: var(--color-surface);
border-bottom: 1px solid var(--color-background-primary);
scrollbar-color: var(--color-border-secondary) var(--color-surface);
}
.settings-grid {
@@ -1920,7 +1899,7 @@ html, body {
flex-direction: column;
gap: 1rem;
padding: 1.25rem;
background: var(--color-background-secondary);
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
}
@@ -1929,7 +1908,7 @@ html, body {
align-items: center;
gap: 0.625rem;
padding: 0.625rem 1rem;
border: 1px solid var(--color-border);
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-lg);
background: var(--color-background-secondary);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
@@ -1970,7 +1949,7 @@ html, body {
padding: 0.5rem 1rem;
font-size: 0.8125rem;
font-weight: 500;
border: 1px solid var(--color-border);
border: 1px solid var(--color-border-secondary);
border-radius: var(--radius-md);
background: var(--color-background-secondary);
color: var(--color-text-secondary);
@@ -1988,7 +1967,7 @@ html, body {
}
.filter-tab.active {
background: linear-gradient(135deg, var(--color-accent) 0%, rgb(0 100 220) 100%);
background: var(--color-accent);
border-color: transparent;
color: var(--color-background-tertiary);
box-shadow: 0 2px 8px rgb(0 122 255 / 30%);

View File

@@ -175,7 +175,7 @@
border-radius: 16px;
padding: 1.25rem;
min-height: 180px;
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow:
0 2px 8px rgb(0 0 0 / 4%),
0 1px 2px rgb(0 0 0 / 6%);
@@ -326,7 +326,7 @@
width: 30px;
height: 30px;
color: var(--color-text-secondary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
transition: all 0.2s ease;
cursor: pointer;
}
@@ -392,7 +392,7 @@
.status-badge.inactive {
color: var(--color-text-tertiary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.config-card:hover .status-badge.inactive {
@@ -407,7 +407,7 @@
justify-content: center;
align-items: center;
border: 2px dashed var(--color-border);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
}
.config-card-add:hover {
@@ -433,7 +433,7 @@
width: 56px;
height: 56px;
color: var(--color-text-tertiary);
background: var(--color-surface);
background: var(--color-background-secondary);
transition: all 0.3s ease;
}

View File

@@ -6,22 +6,6 @@
background: var(--color-background);
}
/* Ambient Background Effect */
.ambient-bg {
position: fixed;
top: -50%;
left: -50%;
z-index: 0;
width: 200%;
height: 200%;
background:
radial-gradient(circle at 30% 20%, rgb(var(--accent-rgb) / 8%) 0%, transparent 50%),
radial-gradient(circle at 70% 80%, rgb(16 185 129 / 6%) 0%, transparent 50%),
radial-gradient(circle at 50% 50%, rgb(59 130 246 / 4%) 0%, transparent 40%);
animation: ambient-drift 25s ease-in-out infinite;
pointer-events: none;
}
@keyframes ambient-drift {
0%,
100% {
@@ -161,7 +145,7 @@
.btn-secondary {
color: var(--color-text-primary);
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
box-shadow:
0 2px 8px rgb(0 0 0 / 8%),
inset 0 1px 0 rgb(255 255 255 / 5%);
@@ -245,7 +229,7 @@
overflow: hidden;
border: 1px solid var(--color-border-secondary);
border-radius: 20px;
background: var(--color-surface);
background: var(--color-background-secondary);
box-shadow:
0 4px 24px rgb(0 0 0 / 6%),
0 1px 2px rgb(0 0 0 / 4%);
@@ -269,7 +253,7 @@
align-items: center;
border-bottom: 1px solid var(--color-border-secondary);
padding: 1.25rem 1.5rem;
background: var(--color-surface-elevated);
background: var(--color-background-secondary);
gap: 0.75rem;
}

View File

@@ -1,8 +1,5 @@
<template>
<div class="picbeds-page">
<!-- Ambient Background -->
<div class="ambient-bg" />
<div class="page-container">
<header class="page-header">
<div class="header-content">

View File

@@ -81,6 +81,7 @@ export interface IConfigStruct {
autoImport: boolean
autoImportPicBed: string[]
galleryPicBedFilter: string[]
theme: string
}
needReload: boolean
picgoPlugins: IPicGoPlugins
@@ -173,6 +174,7 @@ export const configPaths = {
galleryPicBedFilter: 'settings.galleryPicBedFilter',
enableSecondUploader: 'settings.enableSecondUploader',
secondPicBedMode: 'settings.secondPicBedMode',
theme: 'settings.theme',
},
needReload: 'needReload',
picgoPlugins: 'picgoPlugins',

View File

@@ -21,6 +21,10 @@ export const IRPCActionType = {
OPEN_FILE: 'OPEN_FILE',
HIDE_DOCK: 'HIDE_DOCK',
SET_CURRENT_LANGUAGE: 'SET_CURRENT_LANGUAGE',
THEME_RESOLVE_THEMES: 'THEME_RESOLVE_THEMES',
THEME_FETCH_THEMES: 'THEME_FETCH_THEMES',
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
OPEN_WINDOW: 'OPEN_WINDOW',
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
CLOSE_WINDOW: 'CLOSE_WINDOW',

View File

@@ -40,6 +40,7 @@ interface ISettingForm {
mainWindowWidth: number
mainWindowHeight: number
enableSecondUploader: boolean
theme: string
}
interface IToolboxItem {

View File

@@ -3420,6 +3420,13 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@types/adm-zip@^0.5.7":
version "0.5.7"
resolved "https://registry.yarnpkg.com/@types/adm-zip/-/adm-zip-0.5.7.tgz#eec10b6f717d3948beb64aca0abebc4b344ac7e9"
integrity sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==
dependencies:
"@types/node" "*"
"@types/ali-oss@^6.23.0":
version "6.23.0"
resolved "https://registry.yarnpkg.com/@types/ali-oss/-/ali-oss-6.23.0.tgz#c7668d1b8a3a648144866b1b331c4e3b0f437001"
@@ -4230,6 +4237,11 @@ address@^1.2.2:
resolved "https://registry.npmjs.org/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e"
integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==
adm-zip@^0.5.16:
version "0.5.16"
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909"
integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==
aes-decrypter@4.0.1, aes-decrypter@^4.0.1:
version "4.0.1"
resolved "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.1.tgz#c1a81d0bde0e96fed0674488d2a31a6d7ab9b7a7"