mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-30 20:50:52 +08:00
✨ Feature(custom): rewrite setting page, WIP
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
:key="pageReloadCount"
|
||||
>
|
||||
<router-view />
|
||||
<UIServiceProvider />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,11 +12,12 @@
|
||||
import type { IConfig } from 'piclist'
|
||||
import { onBeforeMount, onMounted } from 'vue'
|
||||
|
||||
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
|
||||
import { useStore } from '@/hooks/useStore'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { pageReloadCount } from '@/utils/global'
|
||||
|
||||
import { useAppStore } from './hooks/appStore'
|
||||
import { useAppStore } from './hooks/useAppStore'
|
||||
|
||||
const store = useStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getRawData } from '@/utils/common'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
export default class ALLApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
|
||||
@@ -110,7 +110,7 @@ import { reactive, ref, toRefs, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { IPicGoPluginConfig, IStringKeyMap } from '#/types/types'
|
||||
import type { IPicGoPluginConfig, IStringKeyMap } from '#/types/types'
|
||||
|
||||
interface IProps {
|
||||
config: any[]
|
||||
|
||||
@@ -83,7 +83,7 @@ import { cloneDeep, union } from 'lodash-es'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { IPicGoPluginConfig, IStringKeyMap } from '#/types/types'
|
||||
import type { IPicGoPluginConfig, IStringKeyMap } from '#/types/types'
|
||||
|
||||
interface IProps {
|
||||
config: any[]
|
||||
|
||||
@@ -24,7 +24,7 @@ import { Loading } from '@element-plus/icons-vue'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
const preSignedUrl = ref('')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ElIcon, ElImage } from 'element-plus'
|
||||
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
|
||||
@@ -511,8 +511,8 @@ import type { IBuildInCompressOptions, IBuildInWaterMarkOptions } from 'piclist'
|
||||
import { computed, onBeforeMount, reactive, ref, toRaw } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const { t } = useI18n()
|
||||
const imageProcessDialogVisible = defineModel<boolean>()
|
||||
|
||||
@@ -25,7 +25,7 @@ import { computed, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||
import { formatEndpoint } from '#/utils/common'
|
||||
import { formatEndpoint } from '@/utils/common'
|
||||
|
||||
const base64Url = ref('')
|
||||
const success = ref(false)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { computed, defineComponent, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||
import { formatEndpoint } from '#/utils/common'
|
||||
import { formatEndpoint } from '@/utils/common'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
|
||||
@@ -32,8 +32,8 @@ import type { IpcRendererEvent } from 'electron'
|
||||
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
|
||||
|
||||
import $bus from '@/utils/bus'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
import { IShowInputBoxOption } from '#/types/types'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '@/utils/constant'
|
||||
import type { IShowInputBoxOption } from '#/types/types'
|
||||
|
||||
const inputBoxValue = ref('')
|
||||
const showInputBoxVisible = ref(false)
|
||||
|
||||
@@ -218,14 +218,14 @@ import { pick } from 'lodash-es'
|
||||
import { BadgeInfoIcon, CheckIcon, ChevronDownIcon, CopyIcon, DatabaseIcon, FolderIcon, PieChartIcon, PlugIcon, Settings, UploadIcon } from 'lucide-vue-next'
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import pkg from 'root/package.json'
|
||||
import { SHOW_MAIN_PAGE_QRCODE } from 'root/src/universal/events/constants'
|
||||
import { computed, nextTick, onBeforeMount, reactive, Ref, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import * as config from '@/router/config'
|
||||
import { SHOW_MAIN_PAGE_QRCODE } from '@/utils/constant'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
import ThemeSwitcher from './ui/ThemeSwitcher.vue'
|
||||
const version = ref(pkg.version)
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IToolboxItemCheckStatus } from '#/types/enum'
|
||||
|
||||
interface IProps {
|
||||
status: IToolboxItemCheckStatus
|
||||
status: string
|
||||
value: any
|
||||
handlerText: string
|
||||
handler: (value: any) => void | Promise<void>
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
import { CircleCloseFilled, Loading, SuccessFilled } from '@element-plus/icons-vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { IToolboxItemCheckStatus } from '#/types/enum'
|
||||
import { IToolboxItemCheckStatus } from '@/utils/enum'
|
||||
|
||||
interface IProps {
|
||||
status: IToolboxItemCheckStatus
|
||||
status: string
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
342
src/renderer/components/ui/ConfirmMessageBox.vue
Normal file
342
src/renderer/components/ui/ConfirmMessageBox.vue
Normal file
@@ -0,0 +1,342 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="messagebox-overlay"
|
||||
@click="onCancel"
|
||||
>
|
||||
<div
|
||||
class="messagebox-container"
|
||||
@click.stop
|
||||
>
|
||||
<div class="messagebox-header">
|
||||
<h3 class="messagebox-title">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<button
|
||||
v-if="showClose"
|
||||
class="messagebox-close"
|
||||
@click="onCancel"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
<div class="messagebox-content">
|
||||
<div
|
||||
v-if="type"
|
||||
class="messagebox-icon"
|
||||
>
|
||||
<component
|
||||
:is="iconComponent"
|
||||
:size="48"
|
||||
/>
|
||||
</div>
|
||||
<div class="messagebox-message">
|
||||
<p>{{ message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="center"
|
||||
class="messagebox-actions center"
|
||||
>
|
||||
<button
|
||||
class="messagebox-btn cancel-btn"
|
||||
@click="onCancel"
|
||||
>
|
||||
{{ cancelButtonText }}
|
||||
</button>
|
||||
<button
|
||||
class="messagebox-btn confirm-btn"
|
||||
:class="confirmButtonClass"
|
||||
@click="onConfirm"
|
||||
>
|
||||
{{ confirmButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="messagebox-actions"
|
||||
>
|
||||
<button
|
||||
class="messagebox-btn confirm-btn"
|
||||
:class="confirmButtonClass"
|
||||
@click="onConfirm"
|
||||
>
|
||||
{{ confirmButtonText }}
|
||||
</button>
|
||||
<button
|
||||
class="messagebox-btn cancel-btn"
|
||||
@click="onCancel"
|
||||
>
|
||||
{{ cancelButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { AlertTriangle, CheckCircle, Info, XCircle } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
|
||||
interface Props {
|
||||
isOpen: boolean
|
||||
title?: string
|
||||
message: string
|
||||
type?: 'info' | 'success' | 'warning' | 'error'
|
||||
confirmButtonText?: string
|
||||
cancelButtonText?: string
|
||||
showClose?: boolean
|
||||
center?: boolean
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'confirm'): void
|
||||
(e: 'cancel'): void
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: 'Confirm',
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
showClose: true,
|
||||
center: false,
|
||||
type: undefined
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
const iconComponent = computed(() => {
|
||||
switch (props.type) {
|
||||
case 'warning':
|
||||
return AlertTriangle
|
||||
case 'info':
|
||||
return Info
|
||||
case 'success':
|
||||
return CheckCircle
|
||||
case 'error':
|
||||
return XCircle
|
||||
default:
|
||||
return Info
|
||||
}
|
||||
})
|
||||
|
||||
const confirmButtonClass = computed(() => {
|
||||
switch (props.type) {
|
||||
case 'warning':
|
||||
case 'error':
|
||||
return 'danger'
|
||||
case 'success':
|
||||
return 'success'
|
||||
default:
|
||||
return 'primary'
|
||||
}
|
||||
})
|
||||
|
||||
const onConfirm = () => {
|
||||
emit('confirm')
|
||||
}
|
||||
|
||||
const onCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ConfirmMessageBox'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.messagebox-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.messagebox-container {
|
||||
background: white;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
max-width: 32rem;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:root.dark .messagebox-container,
|
||||
:root.auto.dark .messagebox-container {
|
||||
background: rgb(31 41 55);
|
||||
border: 1px solid rgb(55 65 81);
|
||||
}
|
||||
|
||||
.messagebox-header {
|
||||
padding: 1.5rem 1.5rem 0 1.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.messagebox-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: rgb(17 24 39);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:root.dark .messagebox-title,
|
||||
:root.auto.dark .messagebox-title {
|
||||
color: rgb(243 244 246);
|
||||
}
|
||||
|
||||
.messagebox-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: rgb(107 114 128);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.messagebox-close:hover {
|
||||
background: rgb(243 244 246);
|
||||
color: rgb(17 24 39);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: rgb(55 65 81);
|
||||
color: rgb(243 244 246);
|
||||
}
|
||||
|
||||
.messagebox-content {
|
||||
padding: 1rem 1.5rem;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.messagebox-icon {
|
||||
flex-shrink: 0;
|
||||
color: rgb(107 114 128);
|
||||
}
|
||||
|
||||
.messagebox-icon svg[data-lucide="alert-triangle"] {
|
||||
color: rgb(245 158 11);
|
||||
}
|
||||
|
||||
.messagebox-icon svg[data-lucide="info"] {
|
||||
color: rgb(59 130 246);
|
||||
}
|
||||
|
||||
.messagebox-icon svg[data-lucide="check-circle"] {
|
||||
color: rgb(34 197 94);
|
||||
}
|
||||
|
||||
.messagebox-icon svg[data-lucide="x-circle"] {
|
||||
color: rgb(239 68 68);
|
||||
}
|
||||
|
||||
.messagebox-message {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.messagebox-message p {
|
||||
color: rgb(107 114 128);
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:root.dark .messagebox-message p,
|
||||
:root.auto.dark .messagebox-message p {
|
||||
color: rgb(156 163 175);
|
||||
}
|
||||
|
||||
.messagebox-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
padding: 0 1.5rem 1.5rem 1.5rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.messagebox-actions.center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.messagebox-btn {
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
min-width: 4rem;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: rgb(243 244 246);
|
||||
color: rgb(75 85 99);
|
||||
border: 1px solid rgb(209 213 219);
|
||||
}
|
||||
|
||||
.cancel-btn:hover {
|
||||
background: rgb(229 231 235);
|
||||
}
|
||||
|
||||
:root.dark .cancel-btn,
|
||||
:root.auto.dark .cancel-btn {
|
||||
background: rgb(55 65 81);
|
||||
color: rgb(209 213 219);
|
||||
border-color: rgb(75 85 99);
|
||||
}
|
||||
|
||||
:root.dark .cancel-btn:hover,
|
||||
:root.auto.dark .cancel-btn:hover {
|
||||
background: rgb(75 85 99);
|
||||
}
|
||||
|
||||
.confirm-btn.primary {
|
||||
background: rgb(59 130 246);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.confirm-btn.primary:hover {
|
||||
background: rgb(37 99 235);
|
||||
}
|
||||
|
||||
.confirm-btn.danger {
|
||||
background: rgb(239 68 68);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.confirm-btn.danger:hover {
|
||||
background: rgb(220 38 38);
|
||||
}
|
||||
|
||||
.confirm-btn.success {
|
||||
background: rgb(34 197 94);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.confirm-btn.success:hover {
|
||||
background: rgb(22 163 74);
|
||||
}
|
||||
</style>
|
||||
260
src/renderer/components/ui/MessageToast.vue
Normal file
260
src/renderer/components/ui/MessageToast.vue
Normal file
@@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div class="message-container">
|
||||
<TransitionGroup
|
||||
name="message"
|
||||
tag="div"
|
||||
>
|
||||
<div
|
||||
v-for="message in messages"
|
||||
:key="message.id"
|
||||
class="message-toast"
|
||||
:class="getMessageClass(message.type)"
|
||||
>
|
||||
<div class="message-icon">
|
||||
<component
|
||||
:is="getIconComponent(message.type)"
|
||||
:size="20"
|
||||
/>
|
||||
</div>
|
||||
<div class="message-content">
|
||||
{{ message.message }}
|
||||
</div>
|
||||
<button
|
||||
v-if="message.showClose"
|
||||
class="message-close"
|
||||
@click="removeMessage(message.id)"
|
||||
>
|
||||
<X :size="16" />
|
||||
</button>
|
||||
</div>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { AlertTriangle, CheckCircle, Info, X, XCircle } from 'lucide-vue-next'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
export interface MessageOptions {
|
||||
message: string
|
||||
type?: 'success' | 'warning' | 'info' | 'error'
|
||||
duration?: number
|
||||
showClose?: boolean
|
||||
}
|
||||
|
||||
interface MessageItem extends MessageOptions {
|
||||
id: string
|
||||
timer?: ReturnType<typeof setTimeout>
|
||||
}
|
||||
|
||||
const messages = reactive<MessageItem[]>([])
|
||||
|
||||
const getIconComponent = (type: MessageOptions['type']) => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return CheckCircle
|
||||
case 'warning':
|
||||
return AlertTriangle
|
||||
case 'error':
|
||||
return XCircle
|
||||
default:
|
||||
return Info
|
||||
}
|
||||
}
|
||||
|
||||
const getMessageClass = (type: MessageOptions['type']) => {
|
||||
return `message-${type || 'info'}`
|
||||
}
|
||||
|
||||
const removeMessage = (id: string) => {
|
||||
const index = messages.findIndex(msg => msg.id === id)
|
||||
if (index > -1) {
|
||||
const message = messages[index]
|
||||
if (message.timer) {
|
||||
clearTimeout(message.timer)
|
||||
}
|
||||
messages.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
const addMessage = (options: MessageOptions) => {
|
||||
const id = `message-${Date.now()}-${Math.random()}`
|
||||
const duration = options.duration ?? 3000
|
||||
const showClose = options.showClose ?? true
|
||||
|
||||
const message: MessageItem = {
|
||||
id,
|
||||
...options,
|
||||
showClose
|
||||
}
|
||||
|
||||
if (duration > 0) {
|
||||
message.timer = setTimeout(() => {
|
||||
removeMessage(id)
|
||||
}, duration)
|
||||
}
|
||||
|
||||
messages.push(message)
|
||||
return id
|
||||
}
|
||||
|
||||
// Expose methods for external use
|
||||
const success = (message: string, options?: Partial<MessageOptions>) => {
|
||||
return addMessage({ message, type: 'success', ...options })
|
||||
}
|
||||
|
||||
const error = (message: string, options?: Partial<MessageOptions>) => {
|
||||
return addMessage({ message, type: 'error', ...options })
|
||||
}
|
||||
|
||||
const warning = (message: string, options?: Partial<MessageOptions>) => {
|
||||
return addMessage({ message, type: 'warning', ...options })
|
||||
}
|
||||
|
||||
const info = (message: string, options?: Partial<MessageOptions>) => {
|
||||
return addMessage({ message, type: 'info', ...options })
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
addMessage,
|
||||
removeMessage
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'MessageToast'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.message-container {
|
||||
position: fixed;
|
||||
top: 34px;
|
||||
right: 20px;
|
||||
z-index: 3000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.message-toast {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
max-width: 24rem;
|
||||
pointer-events: all;
|
||||
background: white;
|
||||
border: 1px solid rgb(229 231 235);
|
||||
}
|
||||
|
||||
:root.dark .message-toast,
|
||||
:root.auto.dark .message-toast {
|
||||
background: rgb(31 41 55);
|
||||
border-color: rgb(55 65 81);
|
||||
}
|
||||
|
||||
.message-info {
|
||||
border-left: 4px solid rgb(59 130 246);
|
||||
}
|
||||
|
||||
.message-info .message-icon {
|
||||
color: rgb(59 130 246);
|
||||
}
|
||||
|
||||
.message-success {
|
||||
border-left: 4px solid rgb(34 197 94);
|
||||
}
|
||||
|
||||
.message-success .message-icon {
|
||||
color: rgb(34 197 94);
|
||||
}
|
||||
|
||||
.message-warning {
|
||||
border-left: 4px solid rgb(245 158 11);
|
||||
}
|
||||
|
||||
.message-warning .message-icon {
|
||||
color: rgb(245 158 11);
|
||||
}
|
||||
|
||||
.message-error {
|
||||
border-left: 4px solid rgb(239 68 68);
|
||||
}
|
||||
|
||||
.message-error .message-icon {
|
||||
color: rgb(239 68 68);
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
flex: 1;
|
||||
color: rgb(75 85 99);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
:root.dark .message-content,
|
||||
:root.auto.dark .message-content {
|
||||
color: rgb(209 213 219);
|
||||
}
|
||||
|
||||
.message-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: rgb(107 114 128);
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.message-close:hover {
|
||||
background: rgb(243 244 246);
|
||||
color: rgb(75 85 99);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: rgb(55 65 81);
|
||||
color: rgb(209 213 219);
|
||||
}
|
||||
|
||||
/* Transition animations */
|
||||
.message-enter-active,
|
||||
.message-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.message-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.message-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.message-move {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@ import { Monitor, Moon, Sun } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useAppStore } from '@/hooks/appStore'
|
||||
import { useAppStore } from '@/hooks/useAppStore'
|
||||
|
||||
const { t } = useI18n()
|
||||
const appStore = useAppStore()
|
||||
|
||||
@@ -78,7 +78,7 @@ import type { IpcRendererEvent } from 'electron'
|
||||
import { MinusIcon, PinIcon, ShrinkIcon, XIcon } from 'lucide-vue-next'
|
||||
import { onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
||||
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
const isShowprogress = ref(false)
|
||||
const progress = ref(0)
|
||||
|
||||
101
src/renderer/components/ui/UIServiceProvider.vue
Normal file
101
src/renderer/components/ui/UIServiceProvider.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- MessageToast component -->
|
||||
<MessageToast ref="messageRef" />
|
||||
|
||||
<!-- ConfirmMessageBox component -->
|
||||
<ConfirmMessageBox
|
||||
:is-open="confirmVisible"
|
||||
:title="confirmOptions.title"
|
||||
:message="confirmOptions.message"
|
||||
:type="confirmOptions.type"
|
||||
:confirm-button-text="confirmOptions.confirmButtonText"
|
||||
:cancel-button-text="confirmOptions.cancelButtonText"
|
||||
:show-close="confirmOptions.showClose"
|
||||
:center="confirmOptions.center"
|
||||
@confirm="handleConfirm"
|
||||
@cancel="handleCancel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import useConfirm, { type ConfirmOptions } from '@/hooks/useConfirm'
|
||||
import useMessage from '@/hooks/useMessage'
|
||||
|
||||
import ConfirmMessageBox from './ConfirmMessageBox.vue'
|
||||
import MessageToast from './MessageToast.vue'
|
||||
|
||||
const messageRef = ref<InstanceType<typeof MessageToast> | null>(null)
|
||||
const confirmVisible = ref(false)
|
||||
const confirmOptions = reactive<ConfirmOptions>({
|
||||
message: '',
|
||||
title: 'Confirm',
|
||||
type: 'info',
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
showClose: true,
|
||||
center: false
|
||||
})
|
||||
|
||||
let confirmResolve: ((value: boolean) => void) | null = null
|
||||
|
||||
const handleConfirm = () => {
|
||||
confirmVisible.value = false
|
||||
if (confirmResolve) {
|
||||
confirmResolve(true)
|
||||
confirmResolve = null
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
confirmVisible.value = false
|
||||
if (confirmResolve) {
|
||||
confirmResolve(false)
|
||||
confirmResolve = null
|
||||
}
|
||||
}
|
||||
|
||||
const showConfirm = (options: ConfirmOptions): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
Object.assign(confirmOptions, {
|
||||
title: 'Confirm',
|
||||
type: 'info',
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
showClose: true,
|
||||
center: false,
|
||||
...options
|
||||
})
|
||||
confirmResolve = resolve
|
||||
confirmVisible.value = true
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Initialize message service
|
||||
const { setMessageService } = useMessage()
|
||||
if (messageRef.value) {
|
||||
setMessageService({
|
||||
success: messageRef.value.success,
|
||||
error: messageRef.value.error,
|
||||
warning: messageRef.value.warning,
|
||||
info: messageRef.value.info
|
||||
})
|
||||
}
|
||||
|
||||
// Initialize confirm service
|
||||
const { setConfirmService } = useConfirm()
|
||||
setConfirmService({
|
||||
confirm: showConfirm
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'UIServiceProvider'
|
||||
}
|
||||
</script>
|
||||
0
src/renderer/composables/useConfirm.ts
Normal file
0
src/renderer/composables/useConfirm.ts
Normal file
0
src/renderer/composables/useMessage.ts
Normal file
0
src/renderer/composables/useMessage.ts
Normal file
@@ -1,6 +1,7 @@
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
export function useATagClick () {
|
||||
const handleATagClick = (e: MouseEvent) => {
|
||||
if (e.target instanceof HTMLAnchorElement) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
const settings = ref<IStringKeyMap>({
|
||||
38
src/renderer/hooks/useConfirm.ts
Normal file
38
src/renderer/hooks/useConfirm.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
export interface ConfirmOptions {
|
||||
title?: string
|
||||
message: string
|
||||
type?: 'info' | 'success' | 'warning' | 'error'
|
||||
confirmButtonText?: string
|
||||
cancelButtonText?: string
|
||||
showClose?: boolean
|
||||
center?: boolean
|
||||
}
|
||||
|
||||
interface ConfirmService {
|
||||
confirm: (options: ConfirmOptions) => Promise<boolean>
|
||||
}
|
||||
|
||||
const confirmServiceRef = ref<ConfirmService | null>(null)
|
||||
|
||||
export function useConfirm () {
|
||||
const setConfirmService = (service: ConfirmService) => {
|
||||
confirmServiceRef.value = service
|
||||
}
|
||||
|
||||
const confirm = (options: ConfirmOptions): Promise<boolean> => {
|
||||
if (confirmServiceRef.value) {
|
||||
return confirmServiceRef.value.confirm(options)
|
||||
}
|
||||
console.warn('Confirm service not initialized')
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
|
||||
return {
|
||||
setConfirmService,
|
||||
confirm
|
||||
}
|
||||
}
|
||||
|
||||
export default useConfirm
|
||||
60
src/renderer/hooks/useMessage.ts
Normal file
60
src/renderer/hooks/useMessage.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import type { MessageOptions } from '@/components/ui/MessageToast.vue'
|
||||
|
||||
interface MessageService {
|
||||
success: (message: string, options?: Partial<MessageOptions>) => string
|
||||
error: (message: string, options?: Partial<MessageOptions>) => string
|
||||
warning: (message: string, options?: Partial<MessageOptions>) => string
|
||||
info: (message: string, options?: Partial<MessageOptions>) => string
|
||||
}
|
||||
|
||||
const messageServiceRef = ref<MessageService | null>(null)
|
||||
|
||||
export function useMessage () {
|
||||
const setMessageService = (service: MessageService) => {
|
||||
messageServiceRef.value = service
|
||||
}
|
||||
|
||||
const success = (message: string, options?: Partial<MessageOptions>) => {
|
||||
if (messageServiceRef.value) {
|
||||
return messageServiceRef.value.success(message, options)
|
||||
}
|
||||
console.warn('Message service not initialized')
|
||||
return ''
|
||||
}
|
||||
|
||||
const error = (message: string, options?: Partial<MessageOptions>) => {
|
||||
if (messageServiceRef.value) {
|
||||
return messageServiceRef.value.error(message, options)
|
||||
}
|
||||
console.warn('Message service not initialized')
|
||||
return ''
|
||||
}
|
||||
|
||||
const warning = (message: string, options?: Partial<MessageOptions>) => {
|
||||
if (messageServiceRef.value) {
|
||||
return messageServiceRef.value.warning(message, options)
|
||||
}
|
||||
console.warn('Message service not initialized')
|
||||
return ''
|
||||
}
|
||||
|
||||
const info = (message: string, options?: Partial<MessageOptions>) => {
|
||||
if (messageServiceRef.value) {
|
||||
return messageServiceRef.value.info(message, options)
|
||||
}
|
||||
console.warn('Message service not initialized')
|
||||
return ''
|
||||
}
|
||||
|
||||
return {
|
||||
setMessageService,
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
info
|
||||
}
|
||||
}
|
||||
|
||||
export default useMessage
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
export function setCurrentLanguage (lang: string) {
|
||||
window.electron.sendRPC(IRPCActionType.SET_CURRENT_LANGUAGE, lang)
|
||||
|
||||
@@ -128,6 +128,50 @@
|
||||
"isResizeByPercentHint": "Higher priority",
|
||||
"resizePercent": "Resize Percentage (Enter 50 for 50%)"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"description": "Configure the PicList application",
|
||||
"docs": "Documentation",
|
||||
"clickToSet": "Click to set",
|
||||
"system": {
|
||||
"title": "General",
|
||||
"languageAndAppearance": "Language and Appearance",
|
||||
"chooseLanguage": "Choose Language",
|
||||
"startMode": "Startup Mode",
|
||||
"quietMode": "Quiet Mode",
|
||||
"miniMode": "Mini Window",
|
||||
"mainMode": "Main Window",
|
||||
"noTrayMode": "Hide Tray",
|
||||
"windowBehavior": "Window Behavior",
|
||||
"isHideDock": "Hide Dock Icon",
|
||||
"mainWindowSize": "Set Main Window Size (Requires Restart)",
|
||||
"autoCloseMiniWindow": "Close Mini Window when Opening Main Window",
|
||||
"autoCloseMainWindow": "Close Main Window when Opening Mini Window",
|
||||
"miniWindowOnTop": "Mini Window Always on Top",
|
||||
"isCustomMiniIcon": "Custom Mini Window Icon",
|
||||
"customMiniIconPath": "Custom Mini Window Icon Path",
|
||||
"startupAndShortcuts": "Startup and Shortcuts",
|
||||
"autoLaunch": "Auto Launch",
|
||||
"setShortCuts": "Set Shortcuts"
|
||||
},
|
||||
"sync": {
|
||||
"title": "Configuration/Sync",
|
||||
"syncConfiguration": "Sync Configuration",
|
||||
"syncEndpointConfig": "Sync Endpoint Configuration",
|
||||
"upDownloadSettings": "Upload/Download Settings",
|
||||
"migrateFromPicGo": "Migrate from PicGo",
|
||||
"fileManagement": "File Management"
|
||||
},
|
||||
"upload": {
|
||||
"title": "Upload"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "Advanced"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OPEN_MAIN_WINDOW": "Open Main Window",
|
||||
@@ -145,15 +189,8 @@
|
||||
"TOOLBOX_RE_SCAN": "Re scanning",
|
||||
"TOOLBOX_START_FIX": "Start fixing",
|
||||
"TOOLBOX_SUCCESS_TIPS": "Congratulations, no problems were found",
|
||||
"MANUAL_PAGE_OPEN_TIP": "Please select the way to open the manual",
|
||||
"MANUAL_PAGE_OPEN_TIP_TITLE": "Tips",
|
||||
"MANUAL_PAGE_OPEN_BY_BROWSER": "Browser",
|
||||
"MANUAL_PAGE_OPEN_BY_BUILD_IN": "Built-in Window",
|
||||
"MANUAL_PAGE_OPEN_SETTING_TIP": "Select the way to open the manual",
|
||||
"UPLOAD_VIEW_HINT": "Click to open picbeds settings",
|
||||
"REFRESH": "Refresh",
|
||||
"MANUAL": "Manual",
|
||||
"PICLIST_SETTINGS": "Settings",
|
||||
"PLUGIN_SETTINGS": "Plugins",
|
||||
"CHOOSE_PICBED": "Choose Picbed",
|
||||
"COPY_PICBED_CONFIG": "Copy Picbed Config",
|
||||
@@ -191,11 +228,6 @@
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_CONTENT": "Migrate from PicGo will overwrite your current settings and gallery, do you want to continue?",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_SUCCESS": "Import succeed, please restart PicList",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_FAILED": "Import failed",
|
||||
"SETTINGS_START_MODE": "Default Start Mode",
|
||||
"SETTINGS_START_MODE_MINI": "Mini Window",
|
||||
"SETTINGS_START_MODE_MAIN": "Main Window",
|
||||
"SETTINGS_START_MODE_NO_TRAY": "No Tray",
|
||||
"SETTINGS_START_MODE_QUIET": "Quiet Mode",
|
||||
"SETTINGS_CLICK_TO_OPEN": "Click to Open",
|
||||
"SETTINGS_SET_LOG_FILE": "Set Log File",
|
||||
"SETTINGS_CLICK_TO_SET": "Click to Set",
|
||||
@@ -354,11 +386,6 @@
|
||||
"SETTINGS_SYNC_MANAGE_CONFIG": "Manage configuration",
|
||||
"SETTINGS_AUTO_IMPORT": "Auto import config in manage page",
|
||||
"SETTINGS_AUTO_IMPORT_SELECT_PICBED": "Select picbed",
|
||||
"SETTINGS_TAB_SYSTEM": "System",
|
||||
"SETTINGS_TAB_SYNC_CONFIG": "Configuration",
|
||||
"SETTINGS_TAB_UPLOAD": "Upload",
|
||||
"SETTINGS_TAB_ADVANCED": "Advanced",
|
||||
"SETTINGS_TAB_UPDATE": "Update",
|
||||
"BUILTIN_CLIPBOARD_TIPS": "Use builtin clipboard function to upload instead of using scripts",
|
||||
"SHORTCUT_NAME": "Shortcut Name",
|
||||
"SHORTCUT_BIND": "Shortcut Binding",
|
||||
|
||||
@@ -128,6 +128,55 @@
|
||||
"isResizeByPercentHint": "优先级更高",
|
||||
"resizePercent": "调整比例 (输入 50 表示 50%)"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "设置",
|
||||
"description": "配置 PicList 应用程序",
|
||||
"docs": "文档",
|
||||
"clickToSet": "点击设置",
|
||||
"clickToOpen": "点击打开",
|
||||
"system": {
|
||||
"title": "通用",
|
||||
"languageAndAppearance": "语言和外观",
|
||||
"chooseLanguage": "选择语言",
|
||||
"startMode": "启动模式",
|
||||
"quietMode": "静默模式",
|
||||
"miniMode": "迷你窗口",
|
||||
"mainMode": "主窗口",
|
||||
"noTrayMode": "隐藏托盘",
|
||||
"windowBehavior": "窗口行为",
|
||||
"isHideDock": "是否隐藏 Dock 图标",
|
||||
"mainWindowSize": "设置主窗口大小(需重启)",
|
||||
"autoCloseMiniWindow": "打开主窗口时关闭迷你窗口",
|
||||
"autoCloseMainWindow": "打开迷你窗口时关闭主窗口",
|
||||
"miniWindowOnTop": "迷你窗口置顶",
|
||||
"isCustomMiniIcon": "是否自定义迷你窗口图标",
|
||||
"customMiniIconPath": "自定义迷你窗口图标路径",
|
||||
"startupAndShortcuts": "启动和快捷键",
|
||||
"autoLaunch": "开机自启",
|
||||
"setShortCuts": "设置快捷键"
|
||||
},
|
||||
"sync": {
|
||||
"title": "配置/同步",
|
||||
"syncConfiguration": "同步配置",
|
||||
"syncEndpointConfig": "同步方案配置",
|
||||
"upDownloadSettings": "上传下载配置文件",
|
||||
"migrateFromPicGo": "从PicGo迁移",
|
||||
"fileManagement": "文件管理",
|
||||
"openConfigFile": "打开配置文件",
|
||||
"openConfigFileDir": "打开配置文件目录",
|
||||
"autoImportInManage": "管理页面自动导入配置"
|
||||
},
|
||||
"upload": {
|
||||
"title": "上传",
|
||||
"uploadBehavior": "上传行为"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "高级"
|
||||
},
|
||||
"update": {
|
||||
"title": "更新"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OPEN_MAIN_WINDOW": "打开主窗口",
|
||||
@@ -145,15 +194,8 @@
|
||||
"TOOLBOX_RE_SCAN": "重新扫描",
|
||||
"TOOLBOX_START_FIX": "开始修复",
|
||||
"TOOLBOX_SUCCESS_TIPS": "恭喜你,没有检查出问题",
|
||||
"MANUAL_PAGE_OPEN_TIP": "请选择打开方式",
|
||||
"MANUAL_PAGE_OPEN_TIP_TITLE": "Tips",
|
||||
"MANUAL_PAGE_OPEN_BY_BROWSER": "浏览器",
|
||||
"MANUAL_PAGE_OPEN_BY_BUILD_IN": "内置窗口",
|
||||
"MANUAL_PAGE_OPEN_SETTING_TIP": "选择手册打开方式",
|
||||
"UPLOAD_VIEW_HINT": "点击打开图床设置",
|
||||
"REFRESH": "刷新",
|
||||
"MANUAL": "手册",
|
||||
"PICLIST_SETTINGS": "设置",
|
||||
"PLUGIN_SETTINGS": "插件",
|
||||
"CHOOSE_PICBED": "选择图床",
|
||||
"COPY_PICBED_CONFIG": "复制图床配置",
|
||||
@@ -191,11 +233,6 @@
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_CONTENT": "即将导入PicGo的配置文件和相册, 这将覆盖当前的配置文件和相册, 是否继续?",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_SUCCESS": "导入成功, 请重启PicList生效",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_FAILED": "导入失败",
|
||||
"SETTINGS_START_MODE": "启动模式",
|
||||
"SETTINGS_START_MODE_MINI": "mini窗口",
|
||||
"SETTINGS_START_MODE_MAIN": "主窗口",
|
||||
"SETTINGS_START_MODE_NO_TRAY": "隐藏托盘",
|
||||
"SETTINGS_START_MODE_QUIET": "静默启动",
|
||||
"SETTINGS_CLICK_TO_OPEN": "点击打开",
|
||||
"SETTINGS_SET_LOG_FILE": "设置日志文件",
|
||||
"SETTINGS_CLICK_TO_SET": "点击设置",
|
||||
@@ -355,11 +392,6 @@
|
||||
"SETTINGS_SYNC_MANAGE_CONFIG": "管理配置",
|
||||
"SETTINGS_AUTO_IMPORT": "管理页面自动导入配置",
|
||||
"SETTINGS_AUTO_IMPORT_SELECT_PICBED": "选择需要开启自动导入的图床",
|
||||
"SETTINGS_TAB_SYSTEM": "系统设置",
|
||||
"SETTINGS_TAB_SYNC_CONFIG": "同步与配置",
|
||||
"SETTINGS_TAB_UPLOAD": "上传设置",
|
||||
"SETTINGS_TAB_ADVANCED": "高级设置",
|
||||
"SETTINGS_TAB_UPDATE": "更新",
|
||||
"SHORTCUT_NAME": "快捷键名称",
|
||||
"SHORTCUT_BIND": "快捷键绑定",
|
||||
"SHORTCUT_STATUS": "状态",
|
||||
|
||||
@@ -128,6 +128,50 @@
|
||||
"isResizeByPercentHint": "優先級更高",
|
||||
"resizePercent": "調整比例 (輸入 50 表示 50%)"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "設定",
|
||||
"description": "配置 PicList 應用程序",
|
||||
"docs": "文檔",
|
||||
"clickToSet": "點擊設置",
|
||||
"system": {
|
||||
"title": "通用",
|
||||
"languageAndAppearance": "語言和外觀",
|
||||
"chooseLanguage": "選擇語言",
|
||||
"startMode": "啟動模式",
|
||||
"quietMode": "靜默模式",
|
||||
"miniMode": "迷你窗口",
|
||||
"mainMode": "主窗口",
|
||||
"noTrayMode": "隱藏托盤",
|
||||
"windowBehavior": "窗口行為",
|
||||
"isHideDock": "是否隱藏 Dock 圖標",
|
||||
"mainWindowSize": "設置主窗口大小(需重啟)",
|
||||
"autoCloseMiniWindow": "打開主窗口時關閉迷你窗口",
|
||||
"autoCloseMainWindow": "打開迷你窗口時關閉主窗口",
|
||||
"miniWindowOnTop": "迷你窗口置頂",
|
||||
"isCustomMiniIcon": "是否自定義迷你窗口圖標",
|
||||
"customMiniIconPath": "自定義迷你窗口圖標路徑",
|
||||
"startupAndShortcuts": "啟動和快捷鍵",
|
||||
"autoLaunch": "開機自啟",
|
||||
"setShortCuts": "設置快捷鍵"
|
||||
},
|
||||
"sync": {
|
||||
"title": "配置/同步",
|
||||
"syncConfiguration": "同步配置",
|
||||
"syncEndpointConfig": "同步方案配置",
|
||||
"upDownloadSettings": "上傳下載配置文件",
|
||||
"migrateFromPicGo": "從PicGo遷移",
|
||||
"fileManagement": "文件管理"
|
||||
},
|
||||
"upload": {
|
||||
"title": "上傳"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "高級"
|
||||
},
|
||||
"update": {
|
||||
"title": "更新"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OPEN_MAIN_WINDOW": "打開主視窗",
|
||||
@@ -145,15 +189,8 @@
|
||||
"TOOLBOX_RE_SCAN": "重新掃描",
|
||||
"TOOLBOX_START_FIX": "開始修復",
|
||||
"TOOLBOX_SUCCESS_TIPS": "恭喜你,沒有檢查出問題",
|
||||
"MANUAL_PAGE_OPEN_TIP": "請選擇打開方式",
|
||||
"MANUAL_PAGE_OPEN_TIP_TITLE": "Tips",
|
||||
"MANUAL_PAGE_OPEN_BY_BROWSER": "瀏覽器",
|
||||
"MANUAL_PAGE_OPEN_BY_BUILD_IN": "內置窗口",
|
||||
"MANUAL_PAGE_OPEN_SETTING_TIP": "選擇打開手冊方式",
|
||||
"UPLOAD_VIEW_HINT": "點擊打開圖床設定",
|
||||
"REFRESH": "刷新",
|
||||
"MANUAL": "手冊",
|
||||
"PICLIST_SETTINGS": "設定",
|
||||
"PLUGIN_SETTINGS": "插件",
|
||||
"CHOOSE_PICBED": "選擇圖床",
|
||||
"COPY_PICBED_CONFIG": "複製圖床設定",
|
||||
@@ -191,11 +228,6 @@
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_CONTENT": "即將導入PicGo的設定文件和相冊, 這將會覆蓋當前的設定, 是否繼續?",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_SUCCESS": "導入成功, 請重啟應用",
|
||||
"SETTINGS_MIGRATE_FROM_PICGO_FAILED": "導入失敗",
|
||||
"SETTINGS_START_MODE": "啟動模式",
|
||||
"SETTINGS_START_MODE_MINI": "mini視窗",
|
||||
"SETTINGS_START_MODE_MAIN": "主視窗",
|
||||
"SETTINGS_START_MODE_QUIET": "靜默啟動",
|
||||
"SETTINGS_START_MODE_NO_TRAY": "隐藏托盘",
|
||||
"SETTINGS_CLICK_TO_OPEN": "點擊打開",
|
||||
"SETTINGS_SET_LOG_FILE": "設定記錄檔案",
|
||||
"SETTINGS_CLICK_TO_SET": "點擊設定",
|
||||
@@ -355,11 +387,6 @@
|
||||
"SETTINGS_SYNC_MANAGE_CONFIG": "管理配置",
|
||||
"SETTINGS_AUTO_IMPORT": "管理頁面自動導入配置",
|
||||
"SETTINGS_AUTO_IMPORT_SELECT_PICBED": "選擇需要開啟自動導入的圖床",
|
||||
"SETTINGS_TAB_SYSTEM": "系統設置",
|
||||
"SETTINGS_TAB_SYNC_CONFIG": "同步與配置",
|
||||
"SETTINGS_TAB_UPLOAD": "上傳設置",
|
||||
"SETTINGS_TAB_ADVANCED": "高級設置",
|
||||
"SETTINGS_TAB_UPDATE": "更新",
|
||||
"SHORTCUT_NAME": "快捷鍵名稱",
|
||||
"SHORTCUT_BIND": "快捷鍵綁定",
|
||||
"SHORTCUT_STATUS": "狀態",
|
||||
|
||||
@@ -22,7 +22,7 @@ import router from '@/router'
|
||||
import { store } from '@/store'
|
||||
import db from '@/utils/db'
|
||||
|
||||
type MessageSchema = typeof en
|
||||
type MessageSchema = typeof zhCN
|
||||
|
||||
window.electron.setVisualZoomLevelLimits(1, 1)
|
||||
|
||||
@@ -33,7 +33,7 @@ app.config.globalProperties.triggerRPC = window.electron.triggerRPC
|
||||
app.config.globalProperties.sendRPC = window.electron.sendRPC
|
||||
app.config.globalProperties.sendToMain = window.electron.sendToMain
|
||||
|
||||
const i18n = createI18n<MessageSchema, 'en' | 'zh-CN' | 'zh-TW'>({
|
||||
const i18n = createI18n<[MessageSchema], 'en' | 'zh-CN' | 'zh-TW'>({
|
||||
legacy: false,
|
||||
locale: localStorage.getItem('currentLanguage') || 'zh-CN',
|
||||
fallbackLocale: 'zh-CN',
|
||||
|
||||
@@ -1589,11 +1589,11 @@ import {
|
||||
import { getConfig, saveConfig } from '@/manage/utils/dataSender'
|
||||
import { textFileExt } from '@/manage/utils/textfile'
|
||||
import { videoExt } from '@/manage/utils/videofile'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IDownloadTask, IUploadTask } from '#/types/manage'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { trimPath } from '#/utils/common'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '#/utils/static'
|
||||
import { trimPath } from '@/utils/common'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/utils/static'
|
||||
import type { IDownloadTask, IUploadTask } from '#/types/manage'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
/*
|
||||
|
||||
@@ -273,10 +273,10 @@ import { useManageStore } from '@/manage/store/manageStore'
|
||||
import { formObjToTableData } from '@/manage/utils/common'
|
||||
import { supportedPicBedList } from '@/manage/utils/constants'
|
||||
import { getConfig, removeConfig, saveConfig } from '@/manage/utils/dataSender'
|
||||
import { formatEndpoint, isNeedToShorten, safeSliceF } from '@/utils/common'
|
||||
import { getConfig as getPicBedsConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IStringKeyMap, IUploaderConfigListItem } from '#/types/types'
|
||||
import { formatEndpoint, isNeedToShorten, safeSliceF } from '#/utils/common'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IStringKeyMap, IUploaderConfigListItem } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const manageStore = useManageStore()
|
||||
|
||||
@@ -279,7 +279,6 @@ import {
|
||||
Tools
|
||||
} from '@element-plus/icons-vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
import { computed, onBeforeMount, reactive, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
@@ -287,7 +286,8 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { useManageStore } from '@/manage/store/manageStore'
|
||||
import { supportedPicBedList } from '@/manage/utils/constants'
|
||||
import { newBucketConfig } from '@/manage/utils/newBucketConfig'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const manageStore = useManageStore() as any
|
||||
|
||||
@@ -225,7 +225,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { Folder, InfoFilled } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
import { onBeforeMount, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
@@ -233,7 +232,8 @@ import DynamicSwitch from '@/manage/components/DynamicSwitch.vue'
|
||||
import { fileCacheDbInstance } from '@/manage/store/bucketFileDb'
|
||||
import { customRenameFormatTable, formatFileSize } from '@/manage/utils/common'
|
||||
import { getConfig, saveConfig } from '@/manage/utils/dataSender'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const form = ref<IStringKeyMap>({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Dexie, { Table } from 'dexie'
|
||||
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
/*
|
||||
* create a database for bucket file cache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
import { getConfig } from '@/manage/utils/dataSender'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
export const useManageStore = defineStore('manageConfig', {
|
||||
state: () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
const AliyunAreaCodeName: IStringKeyMap = {
|
||||
'oss-cn-hangzhou': '华东1(杭州)',
|
||||
|
||||
@@ -2,8 +2,19 @@ import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { getConfig } from '@/manage/utils/dataSender'
|
||||
import { availableIconList } from '@/manage/utils/icon'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { handleUrlEncode, isNeedToShorten, safeSliceF } from '#/utils/common'
|
||||
import { isNeedToShorten, safeSliceF } from '@/utils/common'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
export const isUrlEncode = (url: string): boolean => {
|
||||
url = url || ''
|
||||
try {
|
||||
return url !== decodeURI(url)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const handleUrlEncode = (url: string): string => (isUrlEncode(url) ? url : encodeURI(url))
|
||||
|
||||
export function randomStringGenerator (length: number): string {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createI18n } from 'vue-i18n'
|
||||
import en from '@/i18n/locales/en.json'
|
||||
import zhCN from '@/i18n/locales/zh-CN.json'
|
||||
import zhTW from '@/i18n/locales/zh-TW.json'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
type MessageSchema = typeof en
|
||||
|
||||
const i18n = createI18n<MessageSchema, 'en' | 'zh-CN' | 'zh-TW'>({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IObj } from '#/types/types'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IObj } from '#/types/types'
|
||||
|
||||
export function saveConfig (config: IObj | string, value?: any) {
|
||||
const configObj = typeof config === 'string' ? { [config]: value } : config
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
const AUTH_KEY_VALUE_RE = /(\w+)=["']?([^'"]{1,10000})["']?/
|
||||
let NC = 0
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createI18n } from 'vue-i18n'
|
||||
import en from '@/i18n/locales/en.json'
|
||||
import zhCN from '@/i18n/locales/zh-CN.json'
|
||||
import zhTW from '@/i18n/locales/zh-TW.json'
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
import { AliyunAreaCodeName, QiniuAreaCodeName, TencentAreaCodeName } from './bucketConfigCons'
|
||||
type MessageSchema = typeof en
|
||||
|
||||
@@ -475,13 +475,13 @@ import { onBeforeRouteUpdate } from 'vue-router'
|
||||
|
||||
import ALLApi from '@/apis/allApi'
|
||||
import { customRenameFormatTable, customStrMatch, customStrReplace } from '@/manage/utils/common'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import $$db from '@/utils/db'
|
||||
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
||||
import { picBedGlobal } from '@/utils/global'
|
||||
import { IPasteStyle, IRPCActionType } from '#/types/enum'
|
||||
import { ICheckBoxValueType, IGalleryItem, ImgInfo, IObj, IObjT } from '#/types/types'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { picBedsCanbeDeleted } from '#/utils/static'
|
||||
import { picBedsCanbeDeleted } from '@/utils/static'
|
||||
import type { ICheckBoxValueType, IGalleryItem, ImgInfo, IObj, IObjT } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
type IResult<T> = T & {
|
||||
|
||||
@@ -36,16 +36,16 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { IpcRendererEvent } from 'electron'
|
||||
import { ElMessage as $message } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { IConfig } from 'piclist'
|
||||
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { isUrl } from '@/utils/common'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import { osGlobal } from '@/utils/global'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IFileWithPath } from '#/types/types'
|
||||
import { isUrl } from '#/utils/common'
|
||||
import type { IFileWithPath } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const logoPath = ref('')
|
||||
@@ -117,7 +117,7 @@ function onDrop (e: DragEvent) {
|
||||
if (isUrl(str)) {
|
||||
window.electron.sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [{ path: str }])
|
||||
} else {
|
||||
$message.error(t('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
ElMessage.error(t('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
|
||||
}
|
||||
])
|
||||
} else {
|
||||
$message.error(t('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
ElMessage.error(t('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -239,18 +239,18 @@ import { computed, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref, toR
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ConfigForm from '@/components/ConfigFormForPlugin.vue'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { osGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
import { handleStreamlinePluginName } from '@/utils/common'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import {
|
||||
PICGO_CONFIG_PLUGIN,
|
||||
PICGO_HANDLE_PLUGIN_DONE,
|
||||
PICGO_HANDLE_PLUGIN_ING,
|
||||
PICGO_TOGGLE_PLUGIN
|
||||
} from '#/events/constants'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { INPMSearchResultObject, IPicGoPlugin } from '#/types/types'
|
||||
import { handleStreamlinePluginName } from '#/utils/common'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
} from '@/utils/constant'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import { osGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
import type { INPMSearchResultObject, IPicGoPlugin } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const $confirm = ElMessageBox.confirm
|
||||
|
||||
@@ -56,7 +56,7 @@ import type { IpcRendererEvent } from 'electron'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
|
||||
|
||||
import { GET_RENAME_FILE_NAME, RENAME_FILE_NAME } from '#/events/constants'
|
||||
import { GET_RENAME_FILE_NAME, RENAME_FILE_NAME } from '@/utils/constant'
|
||||
|
||||
const id = ref<string | null>(null)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
@@ -116,11 +116,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
|
||||
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import keyBinding from '@/utils/key-binding'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IShortKeyConfig, IShortKeyConfigs } from '#/types/types'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import type { IShortKeyConfig, IShortKeyConfigs } from '#/types/types'
|
||||
|
||||
const list = ref<IShortKeyConfig[]>([])
|
||||
const keyBindingVisible = ref(false)
|
||||
|
||||
@@ -100,14 +100,14 @@ import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ToolboxHandler from '@/components/ToolboxHandler.vue'
|
||||
import ToolboxStatusIcon from '@/components/ToolboxStatusIcon.vue'
|
||||
import { IRPCActionType, IToolboxItemCheckStatus, IToolboxItemType } from '#/types/enum'
|
||||
import { IToolboxCheckRes } from '#/types/rpc'
|
||||
import { IToolboxMap } from '#/types/view'
|
||||
import { IRPCActionType, IToolboxItemCheckStatus, IToolboxItemType } from '@/utils/enum'
|
||||
import type { IToolboxCheckRes } from '#/types/rpc'
|
||||
import type { IToolboxMap } from '#/types/view'
|
||||
|
||||
const { t } = useI18n()
|
||||
const $confirm = ElMessageBox.confirm
|
||||
const defaultLogo = ref('/roundLogo.png')
|
||||
const activeTypes = ref<IToolboxItemType[]>([])
|
||||
const activeTypes = ref<string[]>([])
|
||||
const fixList = reactive<IToolboxMap>({
|
||||
[IToolboxItemType.IS_CONFIG_FILE_BROKEN]: {
|
||||
title: t('TOOLBOX_CHECK_CONFIG_FILE_BROKEN'),
|
||||
@@ -139,7 +139,7 @@ const fixList = reactive<IToolboxMap>({
|
||||
const progress = computed(() => {
|
||||
const total = Object.keys(fixList).length
|
||||
const done = Object.keys(fixList).filter(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
const status = fixList[key].status
|
||||
return status !== IToolboxItemCheckStatus.INIT && status !== IToolboxItemCheckStatus.LOADING
|
||||
}).length
|
||||
return (done / total) * 100
|
||||
@@ -147,22 +147,22 @@ const progress = computed(() => {
|
||||
|
||||
const isAllSuccess = computed(() => {
|
||||
return Object.keys(fixList).every(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
const status = fixList[key].status
|
||||
return status === IToolboxItemCheckStatus.SUCCESS
|
||||
})
|
||||
})
|
||||
|
||||
const isLoading = computed(() => {
|
||||
return Object.keys(fixList).some(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
const status = fixList[key].status
|
||||
return status === IToolboxItemCheckStatus.LOADING
|
||||
})
|
||||
})
|
||||
|
||||
const canFixLength = computed(() => {
|
||||
return Object.keys(fixList).filter(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
|
||||
const status = fixList[key].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key].hasNoFixMethod
|
||||
}).length
|
||||
})
|
||||
|
||||
@@ -182,9 +182,9 @@ window.electron.ipcRendererOn(IRPCActionType.TOOLBOX_CHECK_RES, toolboxCheckResH
|
||||
const handleCheck = () => {
|
||||
activeTypes.value = []
|
||||
Object.keys(fixList).forEach(key => {
|
||||
fixList[key as IToolboxItemType].status = IToolboxItemCheckStatus.LOADING
|
||||
fixList[key as IToolboxItemType].msg = ''
|
||||
fixList[key as IToolboxItemType].value = ''
|
||||
fixList[key].status = IToolboxItemCheckStatus.LOADING
|
||||
fixList[key].msg = ''
|
||||
fixList[key].value = ''
|
||||
})
|
||||
window.electron.sendRPC(IRPCActionType.TOOLBOX_CHECK)
|
||||
}
|
||||
@@ -193,11 +193,11 @@ const handleFix = async () => {
|
||||
const fixRes = await Promise.all(
|
||||
Object.keys(fixList)
|
||||
.filter(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
|
||||
const status = fixList[key].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key].hasNoFixMethod
|
||||
})
|
||||
.map(async key => {
|
||||
return window.electron.triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key as IToolboxItemType)
|
||||
return window.electron.triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key)
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ import type { IpcRendererEvent } from 'electron'
|
||||
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { handleUrlEncode } from '@/utils/common'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import $$db from '@/utils/db'
|
||||
import { IPasteStyle, IRPCActionType, IWindowList } from '#/types/enum'
|
||||
import { ImgInfo } from '#/types/types'
|
||||
import { handleUrlEncode } from '#/utils/common'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { IPasteStyle, IRPCActionType, IWindowList } from '@/utils/enum'
|
||||
import type { ImgInfo } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -117,7 +117,7 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
}
|
||||
|
||||
async function copyTheLink (item: ImgInfo) {
|
||||
const pasteStyle = (await getConfig<IPasteStyle>(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
|
||||
const pasteStyle = (await getConfig<string>(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
|
||||
const customLink = await getConfig<string>(configPaths.settings.customLink)
|
||||
const txt = await pasteTemplate(pasteStyle, item, customLink)
|
||||
window.electron.clipboard.writeText(txt)
|
||||
@@ -127,7 +127,7 @@ async function copyTheLink (item: ImgInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) {
|
||||
async function pasteTemplate (style: string, item: ImgInfo, customLink: string | undefined) {
|
||||
let url = item.url || item.imgUrl
|
||||
if (item.type === 'aws-s3' || item.type === 'aws-s3-plist') {
|
||||
url = item.imgUrl || item.url || ''
|
||||
@@ -141,7 +141,7 @@ async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: str
|
||||
}
|
||||
notification.body = url
|
||||
const _customLink = customLink || ''
|
||||
const tpl = {
|
||||
const tpl: Record<string, string> = {
|
||||
markdown: ``,
|
||||
HTML: `<img src="${url}"/>`,
|
||||
URL: url,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="provider-section">
|
||||
<button
|
||||
class="provider-button"
|
||||
:title="$t('pages.upload.uploadViewHint')"
|
||||
:title="t('pages.upload.uploadViewHint')"
|
||||
@click="handlePicBedNameClick(picBedName, picBedConfigName)"
|
||||
>
|
||||
<div class="provider-info">
|
||||
@@ -25,14 +25,14 @@
|
||||
@click="handleImageProcess"
|
||||
>
|
||||
<Settings :size="16" />
|
||||
<span>{{ $t('pages.upload.imageProcessName') }}</span>
|
||||
<span>{{ t('pages.upload.imageProcessName') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="action-button"
|
||||
@click="handleChangePicBed"
|
||||
>
|
||||
<DatabaseIcon :size="16" />
|
||||
<span>{{ $t('pages.upload.changePicBed') }}</span>
|
||||
<span>{{ t('pages.upload.changePicBed') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,13 +54,13 @@
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
<h3 class="upload-title">
|
||||
{{ $t('pages.upload.dragFileToHere') }}
|
||||
{{ t('pages.upload.dragFileToHere') }}
|
||||
</h3>
|
||||
<p class="upload-subtitle">
|
||||
{{ $t('pages.upload.clickToUpload') }}
|
||||
{{ t('pages.upload.clickToUpload') }}
|
||||
</p>
|
||||
<div class="upload-formats">
|
||||
<span class="format-label">{{ $t('pages.upload.uploadHint') }}</span>
|
||||
<span class="format-label">{{ t('pages.upload.uploadHint') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,7 +88,7 @@
|
||||
/>
|
||||
</div>
|
||||
<span class="progress-text">
|
||||
{{ showError ? $t('pages.upload.uploadFailed') : `${progress}%` }}
|
||||
{{ showError ? t('pages.upload.uploadFailed') : `${progress}%` }}
|
||||
</span>
|
||||
</div>
|
||||
</transition>
|
||||
@@ -98,7 +98,7 @@
|
||||
<div class="upload-card actions-card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">
|
||||
{{ $t('pages.upload.quickUpload') }}
|
||||
{{ t('pages.upload.quickUpload') }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="quick-actions">
|
||||
@@ -107,14 +107,14 @@
|
||||
@click="uploadClipboardFiles"
|
||||
>
|
||||
<ClipboardIcon :size="20" />
|
||||
<span>{{ $t('pages.upload.clipboardPicture') }}</span>
|
||||
<span>{{ t('pages.upload.clipboardPicture') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="quick-action-button"
|
||||
@click="uploadURLFiles"
|
||||
>
|
||||
<LinkIcon :size="20" />
|
||||
<span>{{ $t('pages.upload.urlUpload') }}</span>
|
||||
<span>{{ t('pages.upload.urlUpload') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,13 +123,13 @@
|
||||
<div class="upload-card settings-card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">
|
||||
{{ $t('pages.upload.linkFormat') }}
|
||||
{{ t('pages.upload.linkFormat') }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="settings-content">
|
||||
<!-- Format Options -->
|
||||
<div class="setting-group">
|
||||
<label class="setting-label">{{ $t('pages.upload.outputFormat') }}</label>
|
||||
<label class="setting-label">{{ t('pages.upload.outputFormat') }}</label>
|
||||
<div class="format-buttons">
|
||||
<button
|
||||
v-for="(format, key) in pasteFormatList"
|
||||
@@ -146,21 +146,21 @@
|
||||
|
||||
<!-- URL Length Options -->
|
||||
<div class="setting-group">
|
||||
<label class="setting-label">{{ $t('pages.upload.urlType.title') }}</label>
|
||||
<label class="setting-label">{{ t('pages.upload.urlType.title') }}</label>
|
||||
<div class="url-toggle">
|
||||
<button
|
||||
class="toggle-button"
|
||||
:class="{ active: !useShortUrl }"
|
||||
@click="updateUrlType(false)"
|
||||
>
|
||||
<span>{{ $t('pages.upload.urlType.normal') }}</span>
|
||||
<span>{{ t('pages.upload.urlType.normal') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="toggle-button"
|
||||
:class="{ active: useShortUrl }"
|
||||
@click="updateUrlType(true)"
|
||||
>
|
||||
<span>{{ $t('pages.upload.urlType.short') }}</span>
|
||||
<span>{{ t('pages.upload.urlType.short') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -180,7 +180,7 @@
|
||||
>
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">
|
||||
{{ $t('pages.imageProcess.title') }}
|
||||
{{ t('pages.imageProcess.title') }}
|
||||
</h3>
|
||||
<button
|
||||
class="modal-close"
|
||||
@@ -209,18 +209,18 @@ import { useRouter } from 'vue-router'
|
||||
import ImageProcessSetting from '@/components/ImageProcessSetting.vue'
|
||||
import { PICBEDS_PAGE } from '@/router/config'
|
||||
import $bus from '@/utils/bus'
|
||||
import { isUrl } from '@/utils/common'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '@/utils/constant'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { useDragEventListeners } from '@/utils/drag'
|
||||
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
||||
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
import { IPasteStyle, IRPCActionType } from '#/types/enum'
|
||||
import { IFileWithPath, IUploaderConfigItem } from '#/types/types'
|
||||
import { isUrl } from '#/utils/common'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import type { IFileWithPath, IUploaderConfigItem } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
useDragEventListeners()
|
||||
const $router = useRouter()
|
||||
const { t } = useI18n()
|
||||
|
||||
const imageProcessDialogVisible = ref(false)
|
||||
const useShortUrl = ref(false)
|
||||
@@ -233,7 +233,7 @@ const picBedName = ref('')
|
||||
const picBedConfigName = ref('')
|
||||
const fileInput = ref<HTMLInputElement>()
|
||||
|
||||
const pasteFormatList = ref({
|
||||
const pasteFormatList = ref<Record<string, string>>({
|
||||
[IPasteStyle.MARKDOWN]: '',
|
||||
[IPasteStyle.HTML]: '<img src="url"/>',
|
||||
[IPasteStyle.URL]: 'http://test.com/test.png',
|
||||
@@ -440,687 +440,4 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Global scrolling behavior */
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.upload-container {
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.25rem;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Card Base */
|
||||
.upload-card {
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
border-radius: var(--radius-xl);
|
||||
overflow: hidden;
|
||||
transition: var(--transition-medium);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.upload-card:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
/* Compact cards styling */
|
||||
.actions-card,
|
||||
.settings-card {
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
.actions-card .card-header,
|
||||
.settings-card .card-header {
|
||||
padding: 0.875rem 1.25rem;
|
||||
}
|
||||
|
||||
/* Header Card */
|
||||
.header-card .card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.provider-section {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.provider-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
width: auto;
|
||||
min-width: 200px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.provider-button:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.provider-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.provider-name {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.provider-config {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.provider-arrow {
|
||||
color: var(--color-text-secondary);
|
||||
transition: var(--transition-fast);
|
||||
}
|
||||
|
||||
.provider-button:hover .provider-arrow {
|
||||
color: var(--color-accent);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.625rem 1rem;
|
||||
background: var(--color-accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
background: var(--color-accent-hover);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.action-button.secondary {
|
||||
background: var(--color-surface-elevated);
|
||||
color: var(--color-text-primary);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.action-button.secondary:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* Main Upload Card */
|
||||
.main-card {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
position: relative;
|
||||
padding: 3rem 2rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-medium);
|
||||
border: 2px dashed var(--color-border);
|
||||
border-radius: var(--radius-xl);
|
||||
background: linear-gradient(135deg, var(--color-surface) 0%, var(--color-background-secondary) 100%);
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.upload-zone:hover,
|
||||
.upload-zone.drag-active {
|
||||
border-color: var(--color-accent);
|
||||
background: linear-gradient(135deg, var(--color-surface-elevated) 0%, rgba(0, 122, 255, 0.05) 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--color-accent) 0%, rgba(0, 122, 255, 0.8) 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
transition: var(--transition-medium);
|
||||
}
|
||||
|
||||
.upload-zone:hover .upload-icon,
|
||||
.upload-zone.drag-active .upload-icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.upload-subtitle {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.upload-formats {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.format-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
}
|
||||
|
||||
/* Progress */
|
||||
.progress-container {
|
||||
margin: 1rem 1.5rem;
|
||||
padding: 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border-radius: var(--radius-lg);
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 6px;
|
||||
background: var(--color-border-secondary);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, var(--color-accent) 0%, var(--color-primary) 100%);
|
||||
border-radius: 3px;
|
||||
transition: width var(--transition-medium);
|
||||
}
|
||||
|
||||
.progress-fill.progress-error {
|
||||
background: var(--color-danger);
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Quick Actions Card */
|
||||
.card-header {
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
padding: 1rem 1.5rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.quick-action-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.875rem 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-medium);
|
||||
font-family: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.quick-action-button:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.quick-action-button span {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* Settings Card */
|
||||
.settings-content {
|
||||
padding: 1.25rem 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.settings-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.upload-container {
|
||||
padding: 1.5rem 2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.format-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.format-button {
|
||||
padding: 0.4rem 0.75rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.format-button:hover {
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.format-button.active {
|
||||
background: var(--color-accent);
|
||||
border-color: var(--color-accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.url-toggle {
|
||||
display: flex;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
flex: 1;
|
||||
padding: 0.625rem 0.875rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.toggle-button:hover {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.toggle-button.active {
|
||||
background: var(--color-accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.toggle-button:first-child.active {
|
||||
border-top-left-radius: calc(var(--radius-md) - 1px);
|
||||
border-bottom-left-radius: calc(var(--radius-md) - 1px);
|
||||
}
|
||||
|
||||
.toggle-button:last-child.active {
|
||||
border-top-right-radius: calc(var(--radius-md) - 1px);
|
||||
border-bottom-right-radius: calc(var(--radius-md) - 1px);
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
background: var(--color-surface);
|
||||
border-radius: var(--radius-2xl);
|
||||
border: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-xl);
|
||||
max-width: 90vw;
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1.5rem 2rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-danger);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 0.2rem;
|
||||
overflow-y: auto;
|
||||
max-height: calc(90vh - 120px);
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.modal-content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Transitions */
|
||||
.progress-enter-active,
|
||||
.progress-leave-active {
|
||||
transition: all var(--transition-medium);
|
||||
}
|
||||
|
||||
.progress-enter-from,
|
||||
.progress-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.modal-enter-active,
|
||||
.modal-leave-active {
|
||||
transition: all var(--transition-medium);
|
||||
}
|
||||
|
||||
.modal-enter-from,
|
||||
.modal-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.upload-container {
|
||||
padding: 0.75rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.header-card .card-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.provider-section {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
order: 2;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
padding: 2rem 1rem;
|
||||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 0.875rem 1rem;
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
grid-template-columns: 1fr !important;
|
||||
padding: 1rem 1.25rem;
|
||||
}
|
||||
|
||||
.format-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.upload-container {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
margin: 0.5rem;
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.quick-action-button {
|
||||
padding: 0.75rem 0.875rem;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.provider-button {
|
||||
min-width: unset;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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%, rgba(0, 122, 255, 0.1) 100%);
|
||||
}
|
||||
|
||||
/* Animation for upload icon */
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
.upload-zone.drag-active .upload-icon {
|
||||
animation: float 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Focus styles for keyboard navigation */
|
||||
.provider-button:focus-visible,
|
||||
.action-button:focus-visible,
|
||||
.quick-action-button:focus-visible,
|
||||
.format-button:focus-visible,
|
||||
.toggle-button:focus-visible,
|
||||
.modal-close:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.upload-zone:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 4px;
|
||||
}
|
||||
</style>
|
||||
<style scoped src="./css/UploadPage.css"></style>
|
||||
|
||||
@@ -99,10 +99,10 @@ import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import { useStore } from '@/hooks/useStore'
|
||||
import { PICBEDS_PAGE, UPLOADER_CONFIG_PAGE } from '@/router/config'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { saveConfig } from '@/utils/dataSender'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IStringKeyMap, IUploaderConfigItem } from '#/types/types'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IStringKeyMap, IUploaderConfigItem } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
|
||||
676
src/renderer/pages/css/PicgoSetting.css
Normal file
676
src/renderer/pages/css/PicgoSetting.css
Normal file
@@ -0,0 +1,676 @@
|
||||
.piclist-settings {
|
||||
padding: 1.5rem;
|
||||
min-height: 100vh;
|
||||
background: var(--color-background-secondary);
|
||||
color: var(--color-text-primary);
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.piclist-settings::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.settings-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--color-surface);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.settings-header h1 {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.settings-header p {
|
||||
margin: 0;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
/* Tab Navigation */
|
||||
.tab-navigation {
|
||||
display: flex;
|
||||
background: var(--color-background-primary);
|
||||
border-radius: 12px;
|
||||
padding: 0.25rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
color: var(--color-text-primary);
|
||||
background: var(--color-background-primary);
|
||||
}
|
||||
|
||||
.tab-button.active {
|
||||
background: #409eff;
|
||||
color: white;
|
||||
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Settings Content */
|
||||
.settings-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
background: var(--color-background-primary);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
box-shadow: 0 2px 8px var(--color-border);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.settings-section h2 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.settings-section p {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Form Elements */
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group > label:not(.switch-label):not(.radio-option) {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-textarea,
|
||||
.form-select {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 8px;
|
||||
background: var(--color-background-primary);
|
||||
color: var(--color-text-primary);
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.2s ease;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-textarea:focus,
|
||||
.form-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-blue-common);
|
||||
box-shadow: 0 0 0 2px var(--el-color-primary-light-9, rgba(64, 158, 255, 0.2));
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
resize: vertical;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
.form-range {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background: #e4e7ed;
|
||||
outline: none;
|
||||
margin-bottom: 0.5rem;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.form-range::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-range::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #409eff;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.range-value {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Grid Layout */
|
||||
.form-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
/* Switch Component */
|
||||
.switch-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
cursor: pointer;
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
border-radius: 8px;
|
||||
background: var(--color-background-tertiary);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.switch-label:hover {
|
||||
background: var(--color-background-secondary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
.switch-input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.switch-slider {
|
||||
position: relative;
|
||||
width: 44px;
|
||||
height: 24px;
|
||||
background: var(--color-border);
|
||||
border-radius: 12px;
|
||||
transition: background-color 0.3s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.switch-slider::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.switch-input:checked + .switch-slider {
|
||||
background: #409eff;
|
||||
}
|
||||
|
||||
.switch-input:checked + .switch-slider::before {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.switch-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.switch-title {
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.switch-description {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
/* Radio Group */
|
||||
.radio-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.radio-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
cursor: pointer;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
border-radius: 8px;
|
||||
background: var(--color-background-tertiary);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.radio-option:hover {
|
||||
background: var(--color-background-secondary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
.radio-input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.radio-indicator {
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.radio-input:checked + .radio-indicator {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.radio-input:checked + .radio-indicator::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #409eff;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.radio-label {
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn:hover:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #409eff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: #66b1ff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--color-background-tertiary);
|
||||
color: var(--color-text-primary);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background: var(--color-background-secondary);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: #f56c6c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger:hover:not(:disabled) {
|
||||
background: #f78989;
|
||||
}
|
||||
|
||||
/* Checkbox Group */
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.checkbox-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
border-radius: 6px;
|
||||
background: var(--color-background-tertiary);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.checkbox-option:hover {
|
||||
background: var(--color-background-secondary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
.checkbox-input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.checkbox-indicator {
|
||||
position: relative;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.checkbox-input:checked + .checkbox-indicator {
|
||||
background: #409eff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.checkbox-input:checked + .checkbox-indicator::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* Input Groups */
|
||||
.input-group {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.input-group .form-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.input-addon-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 8px;
|
||||
background: var(--color-background-tertiary);
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.input-addon-btn:hover {
|
||||
background: var(--color-background-secondary);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* Dialog Overlay */
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
background: var(--color-surface);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.dialog-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-secondary);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.dialog-close:hover {
|
||||
background: var(--color-background-secondary);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.dialog-content {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.button-group .btn {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Notice Text */
|
||||
.notice-text {
|
||||
background: rgba(64, 158, 255, 0.1);
|
||||
color: #409eff;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Small text */
|
||||
small {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.piclist-settings {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.tab-navigation {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.form-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
width: 95%;
|
||||
margin: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode adjustments */
|
||||
:root.dark .piclist-settings,
|
||||
:root.auto.dark .piclist-settings {
|
||||
background: var(--color-background-primary);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: var(--color-background-tertiary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: var(--color-background-tertiary);
|
||||
border-color: var(--color-border);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
:root.dark .switch-slider::before,
|
||||
:root.auto.dark .switch-slider::before {
|
||||
background: var(--color-surface);
|
||||
}
|
||||
|
||||
:root.dark .btn-secondary,
|
||||
:root.auto.dark .btn-secondary {
|
||||
background: var(--color-background-tertiary);
|
||||
border-color: var(--color-border);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: var(--color-background-tertiary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
: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 {
|
||||
background: var(--color-background-tertiary);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
: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);
|
||||
}
|
||||
682
src/renderer/pages/css/UploadPage.css
Normal file
682
src/renderer/pages/css/UploadPage.css
Normal file
@@ -0,0 +1,682 @@
|
||||
/* Global scrolling behavior */
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.upload-container {
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.25rem;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Card Base */
|
||||
.upload-card {
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
border-radius: var(--radius-xl);
|
||||
overflow: hidden;
|
||||
transition: var(--transition-medium);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.upload-card:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
/* Compact cards styling */
|
||||
.actions-card,
|
||||
.settings-card {
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
.actions-card .card-header,
|
||||
.settings-card .card-header {
|
||||
padding: 0.875rem 1.25rem;
|
||||
}
|
||||
|
||||
/* Header Card */
|
||||
.header-card .card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.provider-section {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.provider-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
width: auto;
|
||||
min-width: 200px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.provider-button:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.provider-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.provider-name {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.provider-config {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.provider-arrow {
|
||||
color: var(--color-text-secondary);
|
||||
transition: var(--transition-fast);
|
||||
}
|
||||
|
||||
.provider-button:hover .provider-arrow {
|
||||
color: var(--color-accent);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.625rem 1rem;
|
||||
background: var(--color-accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
background: var(--color-accent-hover);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.action-button.secondary {
|
||||
background: var(--color-surface-elevated);
|
||||
color: var(--color-text-primary);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.action-button.secondary:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* Main Upload Card */
|
||||
.main-card {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
position: relative;
|
||||
padding: 3rem 2rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-medium);
|
||||
border: 2px dashed var(--color-border);
|
||||
border-radius: var(--radius-xl);
|
||||
background: linear-gradient(135deg, var(--color-surface) 0%, var(--color-background-secondary) 100%);
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.upload-zone:hover,
|
||||
.upload-zone.drag-active {
|
||||
border-color: var(--color-accent);
|
||||
background: linear-gradient(135deg, var(--color-surface-elevated) 0%, rgba(0, 122, 255, 0.05) 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--color-accent) 0%, rgba(0, 122, 255, 0.8) 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
transition: var(--transition-medium);
|
||||
}
|
||||
|
||||
.upload-zone:hover .upload-icon,
|
||||
.upload-zone.drag-active .upload-icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.upload-subtitle {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.upload-formats {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.format-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
}
|
||||
|
||||
/* Progress */
|
||||
.progress-container {
|
||||
margin: 1rem 1.5rem;
|
||||
padding: 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border-radius: var(--radius-lg);
|
||||
border: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 6px;
|
||||
background: var(--color-border-secondary);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, var(--color-accent) 0%, var(--color-primary) 100%);
|
||||
border-radius: 3px;
|
||||
transition: width var(--transition-medium);
|
||||
}
|
||||
|
||||
.progress-fill.progress-error {
|
||||
background: var(--color-danger);
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Quick Actions Card */
|
||||
.card-header {
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
padding: 1rem 1.5rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.quick-action-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.875rem 1rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-medium);
|
||||
font-family: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.quick-action-button:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-accent);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.quick-action-button span {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* Settings Card */
|
||||
.settings-content {
|
||||
padding: 1.25rem 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.settings-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.upload-container {
|
||||
padding: 1.5rem 2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.format-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.format-button {
|
||||
padding: 0.4rem 0.75rem;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.format-button:hover {
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.format-button.active {
|
||||
background: var(--color-accent);
|
||||
border-color: var(--color-accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.url-toggle {
|
||||
display: flex;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
flex: 1;
|
||||
padding: 0.625rem 0.875rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.toggle-button:hover {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.toggle-button.active {
|
||||
background: var(--color-accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.toggle-button:first-child.active {
|
||||
border-top-left-radius: calc(var(--radius-md) - 1px);
|
||||
border-bottom-left-radius: calc(var(--radius-md) - 1px);
|
||||
}
|
||||
|
||||
.toggle-button:last-child.active {
|
||||
border-top-right-radius: calc(var(--radius-md) - 1px);
|
||||
border-bottom-right-radius: calc(var(--radius-md) - 1px);
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
background: var(--color-surface);
|
||||
border-radius: var(--radius-2xl);
|
||||
border: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-xl);
|
||||
max-width: 90vw;
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1.5rem 2rem;
|
||||
border-bottom: 1px solid var(--color-border-secondary);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: var(--color-surface-elevated);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: var(--transition-fast);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-danger);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 0.2rem;
|
||||
overflow-y: auto;
|
||||
max-height: calc(90vh - 120px);
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.modal-content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Transitions */
|
||||
.progress-enter-active,
|
||||
.progress-leave-active {
|
||||
transition: all var(--transition-medium);
|
||||
}
|
||||
|
||||
.progress-enter-from,
|
||||
.progress-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.modal-enter-active,
|
||||
.modal-leave-active {
|
||||
transition: all var(--transition-medium);
|
||||
}
|
||||
|
||||
.modal-enter-from,
|
||||
.modal-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.upload-container {
|
||||
padding: 0.75rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.header-card .card-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.provider-section {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
order: 2;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
padding: 2rem 1rem;
|
||||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 0.875rem 1rem;
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
grid-template-columns: 1fr !important;
|
||||
padding: 1rem 1.25rem;
|
||||
}
|
||||
|
||||
.format-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.upload-container {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.upload-zone {
|
||||
margin: 0.5rem;
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.quick-action-button {
|
||||
padding: 0.75rem 0.875rem;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.provider-button {
|
||||
min-width: unset;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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%, rgba(0, 122, 255, 0.1) 100%);
|
||||
}
|
||||
|
||||
/* Animation for upload icon */
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
.upload-zone.drag-active .upload-icon {
|
||||
animation: float 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Focus styles for keyboard navigation */
|
||||
.provider-button:focus-visible,
|
||||
.action-button:focus-visible,
|
||||
.quick-action-button:focus-visible,
|
||||
.format-button:focus-visible,
|
||||
.toggle-button:focus-visible,
|
||||
.modal-close:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.upload-zone:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 4px;
|
||||
}
|
||||
@@ -99,11 +99,11 @@ import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import ConfigForm from '@/components/ConfigForm.vue'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig } from '@/utils/dataSender'
|
||||
import { II18nLanguage, IRPCActionType } from '#/types/enum'
|
||||
import { IPicGoPluginConfig, IStringKeyMap, IUploaderConfigItem, IUploaderConfigListItem } from '#/types/types'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { picBedManualUrlList } from '#/utils/static'
|
||||
import { II18nLanguage, IRPCActionType } from '@/utils/enum'
|
||||
import { picBedManualUrlList } from '@/utils/static'
|
||||
import type { IPicGoPluginConfig, IStringKeyMap, IUploaderConfigItem, IUploaderConfigListItem } from '#/types/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const type = ref('')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { App, InjectionKey, reactive, readonly, UnwrapRef } from 'vue'
|
||||
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { saveConfig } from '@/utils/dataSender'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export interface IState {
|
||||
defaultPicBed: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mitt from 'mitt'
|
||||
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '@/utils/constant'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
type IEvent = {
|
||||
|
||||
@@ -16,3 +16,52 @@ export const getRawData = (args: any): any => {
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
export const isUrl = (url: string): boolean => {
|
||||
try {
|
||||
return Boolean(new URL(url))
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const isUrlEncode = (url: string): boolean => {
|
||||
url = url || ''
|
||||
try {
|
||||
return url !== decodeURI(url)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const handleUrlEncode = (url: string): string => (isUrlEncode(url) ? url : encodeURI(url))
|
||||
|
||||
export const handleStreamlinePluginName = (name: string) => name.replace(/(@[^/]+\/)?picgo-plugin-/, '')
|
||||
export const enforceNumber = (num: number | string) => (isNaN(+num) ? 0 : +num)
|
||||
|
||||
export function isNeedToShorten (alias: string, cutOff = 20) {
|
||||
return [...alias].reduce((len, char) => len + (char.charCodeAt(0) > 255 ? 2 : 1), 0) > cutOff
|
||||
}
|
||||
|
||||
export function safeSliceF (str: string, total: number) {
|
||||
let result = ''
|
||||
let totalLen = 0
|
||||
for (const s of str) {
|
||||
if (totalLen >= total) {
|
||||
break
|
||||
}
|
||||
result += s
|
||||
totalLen += s.charCodeAt(0) > 255 ? 2 : 1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string => {
|
||||
const hasProtocol = /^https?:\/\//.test(endpoint)
|
||||
if (!hasProtocol) {
|
||||
return `${sslEnabled ? 'https' : 'http'}://${endpoint}`
|
||||
}
|
||||
return sslEnabled ? endpoint.replace(/^http:\/\//, 'https://') : endpoint.replace(/^https:\/\//, 'http://')
|
||||
}
|
||||
|
||||
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
||||
|
||||
188
src/renderer/utils/configPaths.ts
Normal file
188
src/renderer/utils/configPaths.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
import type { IBuildInCompressOptions, IBuildInWaterMarkOptions } from 'piclist'
|
||||
|
||||
import type { IAliYunConfig, IAwsS3PListUserConfig, IGitHubConfig, IImgurConfig, ILocalConfig, ILskyConfig, IPicBedType, IQiniuConfig, IServerConfig, ISftpPlistConfig, IShortKeyConfig, ISMMSConfig, ISyncConfig, ITcYunConfig, IUploaderConfig, IUpYunConfig, IWebdavPlistConfig } from '#/types/types'
|
||||
|
||||
export type manualPageOpenType = 'window' | 'browser'
|
||||
|
||||
interface IPicGoPlugins {
|
||||
[key: `picgo-plugin-${string}`]: boolean
|
||||
}
|
||||
|
||||
export interface IConfigStruct {
|
||||
picBed: {
|
||||
uploader: string
|
||||
current?: string
|
||||
smms?: ISMMSConfig
|
||||
qiniu?: IQiniuConfig
|
||||
upyun?: IUpYunConfig
|
||||
tcyun?: ITcYunConfig
|
||||
github?: IGitHubConfig
|
||||
aliyun?: IAliYunConfig
|
||||
imgur?: IImgurConfig
|
||||
webdavplist?: IWebdavPlistConfig
|
||||
local?: ILocalConfig
|
||||
sftpplist?: ISftpPlistConfig
|
||||
lskyplist?: ILskyConfig
|
||||
'aws-s3-plist': IAwsS3PListUserConfig
|
||||
proxy?: string
|
||||
transformer?: string
|
||||
list: IPicBedType[]
|
||||
[others: string]: any
|
||||
}
|
||||
settings: {
|
||||
shortKey: {
|
||||
[key: string]: IShortKeyConfig
|
||||
}
|
||||
logLevel: string[]
|
||||
logPath: string
|
||||
logFileSizeLimit: number
|
||||
isAutoListenClipboard: boolean
|
||||
isListeningClipboard: boolean
|
||||
showUpdateTip: boolean
|
||||
miniWindowPosition: [number, number]
|
||||
miniWindowOntop: boolean
|
||||
mainWindowWidth: number
|
||||
mainWindowHeight: number
|
||||
isHideDock: boolean
|
||||
autoCloseMiniWindow: boolean
|
||||
autoCloseMainWindow: boolean
|
||||
isCustomMiniIcon: boolean
|
||||
customMiniIcon: string
|
||||
startMode: string
|
||||
autoRename: boolean
|
||||
deleteCloudFile: boolean
|
||||
server: IServerConfig
|
||||
serverKey: string
|
||||
pasteStyle: string
|
||||
aesPassword: string
|
||||
rename: boolean
|
||||
sync: ISyncConfig
|
||||
tempDirPath: string
|
||||
language: string
|
||||
customLink: string
|
||||
manualPageOpen: manualPageOpenType
|
||||
encodeOutputURL: boolean
|
||||
useShortUrl: boolean
|
||||
shortUrlServer: string
|
||||
c1nToken: string
|
||||
cfWorkerHost: string
|
||||
yourlsDomain: string
|
||||
yourlsSignature: string
|
||||
sinkDomain: string
|
||||
sinkToken: string
|
||||
isSilentNotice: boolean
|
||||
proxy: string
|
||||
registry: string
|
||||
autoCopy: boolean
|
||||
enableWebServer: boolean
|
||||
webServerHost: string
|
||||
webServerPort: number
|
||||
webServerPath: string
|
||||
deleteLocalFile: boolean
|
||||
uploadResultNotification: boolean
|
||||
uploadNotification: boolean
|
||||
useBuiltinClipboard: boolean
|
||||
autoStart: boolean
|
||||
autoImport: boolean
|
||||
autoImportPicBed: string[]
|
||||
}
|
||||
needReload: boolean
|
||||
picgoPlugins: IPicGoPlugins
|
||||
uploader: IUploaderConfig
|
||||
buildIn: {
|
||||
compress: IBuildInCompressOptions
|
||||
watermark: IBuildInWaterMarkOptions
|
||||
rename: {
|
||||
enable: boolean
|
||||
format: string
|
||||
}
|
||||
skipProcess: {
|
||||
skipProcessExtList: string
|
||||
}
|
||||
}
|
||||
debug: boolean
|
||||
PICGO_ENV: string
|
||||
}
|
||||
|
||||
export const configPaths = {
|
||||
picBed: {
|
||||
current: 'picBed.current',
|
||||
uploader: 'picBed.uploader',
|
||||
secondUploader: 'picBed.secondUploader',
|
||||
secondUploaderId: 'picBed.secondUploaderId',
|
||||
secondUploaderConfig: 'picBed.secondUploaderConfig',
|
||||
proxy: 'picBed.proxy',
|
||||
transformer: 'picBed.transformer',
|
||||
list: 'picBed.list'
|
||||
},
|
||||
settings: {
|
||||
shortKey: {
|
||||
_path: 'settings.shortKey',
|
||||
'picgo:upload': 'settings.shortKey[picgo:upload]'
|
||||
},
|
||||
logLevel: 'settings.logLevel',
|
||||
logPath: 'settings.logPath',
|
||||
logFileSizeLimit: 'settings.logFileSizeLimit',
|
||||
isAutoListenClipboard: 'settings.isAutoListenClipboard',
|
||||
isListeningClipboard: 'settings.isListeningClipboard',
|
||||
showUpdateTip: 'settings.showUpdateTip',
|
||||
miniWindowPosition: 'settings.miniWindowPosition',
|
||||
miniWindowOntop: 'settings.miniWindowOntop',
|
||||
isHideDock: 'settings.isHideDock',
|
||||
mainWindowWidth: 'settings.mainWindowWidth',
|
||||
mainWindowHeight: 'settings.mainWindowHeight',
|
||||
autoCloseMiniWindow: 'settings.autoCloseMiniWindow',
|
||||
autoCloseMainWindow: 'settings.autoCloseMainWindow',
|
||||
isCustomMiniIcon: 'settings.isCustomMiniIcon',
|
||||
customMiniIcon: 'settings.customMiniIcon',
|
||||
startMode: 'settings.startMode',
|
||||
autoRename: 'settings.autoRename',
|
||||
deleteCloudFile: 'settings.deleteCloudFile',
|
||||
server: 'settings.server',
|
||||
serverKey: 'settings.serverKey',
|
||||
pasteStyle: 'settings.pasteStyle',
|
||||
aesPassword: 'settings.aesPassword',
|
||||
rename: 'settings.rename',
|
||||
sync: 'settings.sync',
|
||||
tempDirPath: 'settings.tempDirPath',
|
||||
language: 'settings.language',
|
||||
customLink: 'settings.customLink',
|
||||
manualPageOpen: 'settings.manualPageOpen',
|
||||
encodeOutputURL: 'settings.encodeOutputURL',
|
||||
useShortUrl: 'settings.useShortUrl',
|
||||
shortUrlServer: 'settings.shortUrlServer',
|
||||
c1nToken: 'settings.c1nToken',
|
||||
cfWorkerHost: 'settings.cfWorkerHost',
|
||||
yourlsDomain: 'settings.yourlsDomain',
|
||||
yourlsSignature: 'settings.yourlsSignature',
|
||||
sinkDomain: 'settings.sinkDomain',
|
||||
sinkToken: 'settings.sinkToken',
|
||||
isSilentNotice: 'settings.isSilentNotice',
|
||||
proxy: 'settings.proxy',
|
||||
registry: 'settings.registry',
|
||||
autoCopy: 'settings.autoCopy',
|
||||
enableWebServer: 'settings.enableWebServer',
|
||||
webServerHost: 'settings.webServerHost',
|
||||
webServerPort: 'settings.webServerPort',
|
||||
webServerPath: 'settings.webServerPath',
|
||||
deleteLocalFile: 'settings.deleteLocalFile',
|
||||
uploadResultNotification: 'settings.uploadResultNotification',
|
||||
uploadNotification: 'settings.uploadNotification',
|
||||
useBuiltinClipboard: 'settings.useBuiltinClipboard',
|
||||
autoStart: 'settings.autoStart',
|
||||
autoImport: 'settings.autoImport',
|
||||
autoImportPicBed: 'settings.autoImportPicBed',
|
||||
enableSecondUploader: 'settings.enableSecondUploader'
|
||||
},
|
||||
needReload: 'needReload',
|
||||
picgoPlugins: 'picgoPlugins',
|
||||
uploader: 'uploader',
|
||||
buildIn: {
|
||||
compress: 'buildIn.compress',
|
||||
watermark: 'buildIn.watermark',
|
||||
rename: 'buildIn.rename',
|
||||
skipProcess: 'buildIn.skipProcess'
|
||||
},
|
||||
debug: 'debug',
|
||||
PICGO_ENV: 'PICGO_ENV'
|
||||
}
|
||||
14
src/renderer/utils/constant.ts
Normal file
14
src/renderer/utils/constant.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX'
|
||||
export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE'
|
||||
// picgo plugin
|
||||
export const PICGO_CONFIG_PLUGIN = 'PICGO_CONFIG_PLUGIN'
|
||||
export const PICGO_HANDLE_PLUGIN_ING = 'PICGO_HANDLE_PLUGIN_ING'
|
||||
export const PICGO_HANDLE_PLUGIN_DONE = 'PICGO_HANDLE_PLUGIN_DONE'
|
||||
export const PICGO_TOGGLE_PLUGIN = 'PICGO_TOGGLE_PLUGIN'
|
||||
// picgo uploader
|
||||
export const RENAME_FILE_NAME = 'RENAME_FILE_NAME'
|
||||
export const GET_RENAME_FILE_NAME = 'GET_RENAME_FILE_NAME'
|
||||
export const SHOW_MAIN_PAGE_QRCODE = 'SHOW_MAIN_PAGE_QRCODE'
|
||||
// rpc
|
||||
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
||||
export const RPC_ACTIONS_INVOKE = 'RPC_ACTIONS_INVOKE'
|
||||
@@ -1,9 +1,10 @@
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IObj } from '#/types/types'
|
||||
import { getRawData } from '@/utils/common'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IObj } from '#/types/types'
|
||||
|
||||
export function saveConfig (config: IObj | string, value?: any) {
|
||||
const configObject = typeof config === 'string' ? { [config]: value } : config
|
||||
window.electron.sendRPC(IRPCActionType.PICLIST_SAVE_CONFIG, configObject)
|
||||
window.electron.sendRPC(IRPCActionType.PICLIST_SAVE_CONFIG, getRawData(configObject))
|
||||
}
|
||||
|
||||
export async function getConfig<T> (key?: string): Promise<T | undefined> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IGalleryDB } from '#/types/extra-vue'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IGalleryDB } from '#/types/extra-vue'
|
||||
|
||||
interface IFilter {
|
||||
orderBy?: 'asc' | 'desc'
|
||||
@@ -23,7 +23,7 @@ interface IObject {
|
||||
}
|
||||
|
||||
export class GalleryDB implements IGalleryDB {
|
||||
async #actionHandler<T>(method: IRPCActionType, ...args: any[]): Promise<T | undefined> {
|
||||
async #actionHandler<T>(method: string, ...args: any[]): Promise<T | undefined> {
|
||||
return await window.electron.triggerRPC<T>(method, ...args)
|
||||
}
|
||||
|
||||
|
||||
163
src/renderer/utils/enum.ts
Normal file
163
src/renderer/utils/enum.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
export const IPasteStyle = {
|
||||
MARKDOWN: 'markdown',
|
||||
HTML: 'HTML',
|
||||
URL: 'URL',
|
||||
UBB: 'UBB',
|
||||
CUSTOM: 'Custom'
|
||||
}
|
||||
|
||||
export const IWindowList = {
|
||||
SETTING_WINDOW: 'SETTING_WINDOW',
|
||||
TRAY_WINDOW: 'TRAY_WINDOW',
|
||||
MINI_WINDOW: 'MINI_WINDOW',
|
||||
RENAME_WINDOW: 'RENAME_WINDOW',
|
||||
TOOLBOX_WINDOW: 'TOOLBOX_WINDOW'
|
||||
}
|
||||
|
||||
export const IRPCActionType = {
|
||||
// system rpc
|
||||
RELOAD_APP: 'RELOAD_APP',
|
||||
OPEN_URL: 'OPEN_URL',
|
||||
OPEN_FILE: 'OPEN_FILE',
|
||||
HIDE_DOCK: 'HIDE_DOCK',
|
||||
SET_CURRENT_LANGUAGE: 'SET_CURRENT_LANGUAGE',
|
||||
OPEN_WINDOW: 'OPEN_WINDOW',
|
||||
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
|
||||
CLOSE_WINDOW: 'CLOSE_WINDOW',
|
||||
MINIMIZE_WINDOW: 'MINIMIZE_WINDOW',
|
||||
SHOW_MINI_PAGE_MENU: 'SHOW_MINI_PAGE_MENU',
|
||||
SHOW_MAIN_PAGE_MENU: 'SHOW_MAIN_PAGE_MENU',
|
||||
SHOW_UPLOAD_PAGE_MENU: 'SHOW_UPLOAD_PAGE_MENU',
|
||||
SHOW_SECOND_UPLOADER_MENU: 'SHOW_SECOND_UPLOADER_MENU',
|
||||
SHOW_PLUGIN_PAGE_MENU: 'SHOW_PLUGIN_PAGE_MENU',
|
||||
SET_MINI_WINDOW_POS: 'SET_MINI_WINDOW_POS',
|
||||
MINI_WINDOW_ON_TOP: 'MINI_WINDOW_ON_TOP',
|
||||
MAIN_WINDOW_ON_TOP: 'MAIN_WINDOW_ON_TOP',
|
||||
UPDATE_MINI_WINDOW_ICON: 'UPDATE_MINI_WINDOW_ICON',
|
||||
REFRESH_SETTING_WINDOW: 'REFRESH_SETTING_WINDOW',
|
||||
// picbed RPC
|
||||
PICBED_GET_PICBED_CONFIG: 'PICBED_GET_PICBED_CONFIG',
|
||||
PICBED_GET_CONFIG_LIST: 'PICBED_GET_CONFIG_LIST',
|
||||
PICBED_DELETE_CONFIG: 'PICBED_DELETE_CONFIG',
|
||||
UPLOADER_CHANGE_CURRENT: 'UPLOADER_CHANGE_CURRENT',
|
||||
UPLOADER_SELECT: 'UPLOADER_SELECT',
|
||||
UPLOADER_UPDATE_CONFIG: 'UPLOADER_UPDATE_CONFIG',
|
||||
UPLOADER_RESET_CONFIG: 'UPLOADER_RESET_CONFIG',
|
||||
DELETE_ALL_API: 'DELETE_ALL_API',
|
||||
|
||||
// toolbox rpc
|
||||
TOOLBOX_CHECK: 'TOOLBOX_CHECK',
|
||||
TOOLBOX_CHECK_RES: 'TOOLBOX_CHECK_RES',
|
||||
TOOLBOX_CHECK_FIX: 'TOOLBOX_CHECK_FIX',
|
||||
|
||||
// main app setting rpc
|
||||
PICLIST_GET_CONFIG: 'PICLIST_GET_CONFIG',
|
||||
PICLIST_GET_CONFIG_SYNC: 'PICLIST_GET_CONFIG_SYNC',
|
||||
PICLIST_SAVE_CONFIG: 'PICLIST_SAVE_CONFIG',
|
||||
PICLIST_OPEN_FILE: 'PICLIST_OPEN_FILE',
|
||||
PICLIST_OPEN_DIRECTORY: 'PICLIST_OPEN_DIRECTORY',
|
||||
PICLIST_AUTO_START: 'PICLIST_AUTO_START',
|
||||
|
||||
// shortkey setting rpc
|
||||
SHORTKEY_UPDATE: 'SHORTKEY_UPDATE',
|
||||
SHORTKEY_BIND_OR_UNBIND: 'SHORTKEY_BIND_OR_UNBIND',
|
||||
SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE: 'SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE',
|
||||
|
||||
// configuration setting rpc
|
||||
CONFIGURE_MIGRATE_FROM_PICGO: 'CONFIGURE_MIGRATE_FROM_PICGO',
|
||||
CONFIGURE_UPLOAD_COMMON_CONFIG: 'CONFIGURE_UPLOAD_COMMON_CONFIG',
|
||||
CONFIGURE_UPLOAD_MANAGE_CONFIG: 'CONFIGURE_UPLOAD_MANAGE_CONFIG',
|
||||
CONFIGURE_UPLOAD_ALL_CONFIG: 'CONFIGURE_UPLOAD_ALL_CONFIG',
|
||||
CONFIGURE_DOWNLOAD_COMMON_CONFIG: 'CONFIGURE_DOWNLOAD_COMMON_CONFIG',
|
||||
CONFIGURE_DOWNLOAD_MANAGE_CONFIG: 'CONFIGURE_DOWNLOAD_MANAGE_CONFIG',
|
||||
CONFIGURE_DOWNLOAD_ALL_CONFIG: 'CONFIGURE_DOWNLOAD_ALL_CONFIG',
|
||||
|
||||
// advanced setting rpc
|
||||
ADVANCED_UPDATE_SERVER: 'ADVANCED_UPDATE_SERVER',
|
||||
ADVANCED_STOP_WEB_SERVER: 'ADVANCED_STOP_WEB_SERVER',
|
||||
ADVANCED_RESTART_WEB_SERVER: 'ADVANCED_RESTART_WEB_SERVER',
|
||||
|
||||
// upload and main page rpc
|
||||
MAIN_GET_PICBED: 'MAIN_GET_PICBED',
|
||||
UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE: 'UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE',
|
||||
UPLOAD_CHOOSED_FILES: 'UPLOAD_CHOOSED_FILES',
|
||||
|
||||
// gallery rpc
|
||||
GALLERY_PASTE_TEXT: 'GALLERY_PASTE_TEXT',
|
||||
GALLERY_REMOVE_FILES: 'GALLERY_REMOVE_FILES',
|
||||
GALLERY_GET_DB: 'GALLERY_GET_DB',
|
||||
GALLERY_GET_BY_ID_DB: 'GALLERY_GET_BY_ID_DB',
|
||||
GALLERY_UPDATE_BY_ID_DB: 'GALLERY_UPDATE_BY_ID_DB',
|
||||
GALLERY_REMOVE_BY_ID_DB: 'GALLERY_REMOVE_BY_ID_DB',
|
||||
GALLERY_INSERT_DB: 'GALLERY_INSERT_DB',
|
||||
GALLERY_INSERT_DB_BATCH: 'GALLERY_INSERT_DB_BATCH',
|
||||
// plugin rpc
|
||||
PLUGIN_GET_LIST: 'PLUGIN_GET_LIST',
|
||||
PLUGIN_INSTALL: 'PLUGIN_INSTALL',
|
||||
PLUGIN_IMPORT_LOCAL: 'PLUGIN_IMPORT_LOCAL',
|
||||
PLUGIN_UPDATE_ALL: 'PLUGIN_UPDATE_ALL',
|
||||
|
||||
// tray rpc
|
||||
TRAY_SET_TOOL_TIP: 'TRAY_SET_TOOL_TIP',
|
||||
TRAY_GET_SHORT_URL: 'TRAY_GET_SHORT_URL',
|
||||
TRAY_UPLOAD_CLIPBOARD_FILES: 'TRAY_UPLOAD_CLIPBOARD_FILES',
|
||||
|
||||
// manage rpc
|
||||
MANAGE_GET_CONFIG: 'MANAGE_GET_CONFIG',
|
||||
MANAGE_SAVE_CONFIG: 'MANAGE_SAVE_CONFIG',
|
||||
MANAGE_REMOVE_CONFIG: 'MANAGE_REMOVE_CONFIG',
|
||||
MANAGE_GET_BUCKET_LIST: 'MANAGE_GET_BUCKET_LIST',
|
||||
MANAGE_GET_BUCKET_LIST_BACKSTAGE: 'MANAGE_GET_BUCKET_LIST_BACKSTAGE',
|
||||
MANAGE_GET_BUCKET_LIST_RECURSIVELY: 'MANAGE_GET_BUCKET_LIST_RECURSIVELY',
|
||||
MANAGE_CREATE_BUCKET: 'MANAGE_CREATE_BUCKET',
|
||||
MANAGE_GET_BUCKET_FILE_LIST: 'MANAGE_GET_BUCKET_FILE_LIST',
|
||||
MANAGE_GET_BUCKET_DOMAIN: 'MANAGE_GET_BUCKET_DOMAIN',
|
||||
MANAGE_SET_BUCKET_ACL_POLICY: 'MANAGE_SET_BUCKET_ACL_POLICY',
|
||||
MANAGE_RENAME_BUCKET_FILE: 'MANAGE_RENAME_BUCKET_FILE',
|
||||
MANAGE_DELETE_BUCKET_FILE: 'MANAGE_DELETE_BUCKET_FILE',
|
||||
MANAGE_DELETE_BUCKET_FOLDER: 'MANAGE_DELETE_BUCKET_FOLDER',
|
||||
MANAGE_GET_PRE_SIGNED_URL: 'MANAGE_GET_PRE_SIGNED_URL',
|
||||
MANAGE_UPLOAD_BUCKET_FILE: 'MANAGE_UPLOAD_BUCKET_FILE',
|
||||
MANAGE_DOWNLOAD_BUCKET_FILE: 'MANAGE_DOWNLOAD_BUCKET_FILE',
|
||||
MANAGE_CREATE_BUCKET_FOLDER: 'MANAGE_CREATE_BUCKET_FOLDER',
|
||||
MANAGE_OPEN_FILE_SELECT_DIALOG: 'MANAGE_OPEN_FILE_SELECT_DIALOG',
|
||||
MANAGE_GET_UPLOAD_TASK_LIST: 'MANAGE_GET_UPLOAD_TASK_LIST',
|
||||
MANAGE_GET_DOWNLOAD_TASK_LIST: 'MANAGE_GET_DOWNLOAD_TASK_LIST',
|
||||
MANAGE_DELETE_UPLOADED_TASK: 'MANAGE_DELETE_UPLOADED_TASK',
|
||||
MANAGE_DELETE_ALL_UPLOADED_TASK: 'MANAGE_DELETE_ALL_UPLOADED_TASK',
|
||||
MANAGE_DELETE_DOWNLOADED_TASK: 'MANAGE_DELETE_DOWNLOADED_TASK',
|
||||
MANAGE_DELETE_ALL_DOWNLOADED_TASK: 'MANAGE_DELETE_ALL_DOWNLOADED_TASK',
|
||||
MANAGE_SELECT_DOWNLOAD_FOLDER: 'MANAGE_SELECT_DOWNLOAD_FOLDER',
|
||||
MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER: 'MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER',
|
||||
MANAGE_OPEN_DOWNLOADED_FOLDER: 'MANAGE_OPEN_DOWNLOADED_FOLDER',
|
||||
MANAGE_OPEN_LOCAL_FILE: 'MANAGE_OPEN_LOCAL_FILE',
|
||||
MANAGE_DOWNLOAD_FILE_FROM_URL: 'MANAGE_DOWNLOAD_FILE_FROM_URL',
|
||||
MANAGE_CONVERT_PATH_TO_BASE64: 'MANAGE_CONVERT_PATH_TO_BASE64'
|
||||
}
|
||||
|
||||
export const IToolboxItemType = {
|
||||
IS_CONFIG_FILE_BROKEN: 'IS_CONFIG_FILE_BROKEN',
|
||||
IS_GALLERY_FILE_BROKEN: 'IS_GALLERY_FILE_BROKEN',
|
||||
HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: 'HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD',
|
||||
HAS_PROBLEM_WITH_PROXY: 'HAS_PROBLEM_WITH_PROXY'
|
||||
}
|
||||
|
||||
export const IToolboxItemCheckStatus = {
|
||||
INIT: 'init',
|
||||
LOADING: 'loading',
|
||||
SUCCESS: 'success',
|
||||
ERROR: 'error'
|
||||
}
|
||||
|
||||
export const ISartMode = {
|
||||
QUIET: 'quiet',
|
||||
MINI: 'mini',
|
||||
MAIN: 'main',
|
||||
NO_TRAY: 'no-tray'
|
||||
}
|
||||
|
||||
export const II18nLanguage = {
|
||||
ZH_CN: 'zh-CN',
|
||||
ZH_TW: 'zh-TW',
|
||||
EN: 'en'
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IStringKeyMap } from '#/types/types'
|
||||
import { RELEASE_URL, RELEASE_URL_BACKUP } from '#/utils/static'
|
||||
import { RELEASE_URL, RELEASE_URL_BACKUP } from '@/utils/static'
|
||||
import type { IStringKeyMap } from '#/types/types'
|
||||
|
||||
export const getLatestVersion = async (): Promise<string> => {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
import { IPicBedType } from '#/types/types'
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
import type { IPicBedType } from '#/types/types'
|
||||
|
||||
console.log('global.ts loaded', window.electron.platform)
|
||||
const osGlobal = ref<string>(window.electron.platform)
|
||||
|
||||
71
src/renderer/utils/static.ts
Normal file
71
src/renderer/utils/static.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { IStringKeyMap } from 'root/src/universal/types/types'
|
||||
|
||||
export const RELEASE_URL = 'https://api.github.com/repos/Kuingsmile/PicList/releases'
|
||||
export const RELEASE_URL_BACKUP = 'https://release.piclist.cn'
|
||||
|
||||
export const cancelDownloadLoadingFileList = 'cancelDownloadLoadingFileList'
|
||||
export const refreshDownloadFileTransferList = 'refreshDownloadFileTransferList'
|
||||
|
||||
export const picBedsCanbeDeleted = [
|
||||
'aliyun',
|
||||
'alist',
|
||||
'alistplist',
|
||||
'aws-s3',
|
||||
'aws-s3-plist',
|
||||
'dogecloud',
|
||||
'github',
|
||||
'huaweicloud-uploader',
|
||||
'imgur',
|
||||
'local',
|
||||
'lskyplist',
|
||||
'piclist',
|
||||
'qiniu',
|
||||
'sftpplist',
|
||||
'smms',
|
||||
'tcyun',
|
||||
'upyun',
|
||||
'webdavplist'
|
||||
]
|
||||
|
||||
export const picBedManualUrlList: IStringKeyMap = {
|
||||
zh_cn: {
|
||||
advancedpiclist: 'https://piclist.cn/configure.html#%E9%AB%98%E7%BA%A7%E8%87%AA%E5%AE%9A%E4%B9%89',
|
||||
aliyun: 'https://piclist.cn/configure.html#%E9%98%BF%E9%87%8C%E4%BA%91oss',
|
||||
alistplist: 'https://piclist.cn/configure.html#alist',
|
||||
'aws-s3': 'https://piclist.cn/configure.html#%E5%86%85%E7%BD%AEaws-s3',
|
||||
'aws-s3-plist': 'https://piclist.cn/configure.html#%E5%86%85%E7%BD%AEaws-s3',
|
||||
github: 'https://piclist.cn/configure.html#github%E5%9B%BE%E5%BA%8A',
|
||||
githubPlus: 'https://piclist.cn/configure.html#github%E5%9B%BE%E5%BA%8A',
|
||||
imgur: 'https://piclist.cn/configure.html#imgur',
|
||||
lankong: 'https://github.com/hellodk34/picgo-plugin-lankong',
|
||||
local: 'https://piclist.cn/configure.html#%E6%9C%AC%E5%9C%B0%E5%9B%BE%E5%BA%8A',
|
||||
lskyplist: 'https://piclist.cn/configure.html#%E5%85%B0%E7%A9%BA%E5%9B%BE%E5%BA%8A',
|
||||
tcyun: 'https://piclist.cn/configure.html#%E8%85%BE%E8%AE%AF%E4%BA%91cos',
|
||||
piclist: 'https://piclist.cn/configure.html#piclist',
|
||||
qiniu: 'https://piclist.cn/configure.html#%E4%B8%83%E7%89%9B%E4%BA%91',
|
||||
sftpplist: 'https://piclist.cn/configure.html#%E5%86%85%E7%BD%AEsftp',
|
||||
smms: 'https://piclist.cn/configure.html#sm-ms',
|
||||
upyun: 'https://piclist.cn/configure.html#%E5%8F%88%E6%8B%8D%E4%BA%91',
|
||||
webdavplist: 'https://piclist.cn/configure.html#webdav'
|
||||
},
|
||||
en: {
|
||||
advancedpiclist: 'https://piclist.cn/en/configure.html#advanced',
|
||||
aliyun: 'https://piclist.cn/en/configure.html#alibaba-cloud',
|
||||
alistplist: 'https://piclist.cn/en/configure.html#alist',
|
||||
'aws-s3': 'https://piclist.cn/en/configure.html#built-in-aws-s3',
|
||||
'aws-s3-plist': 'https://piclist.cn/en/configure.html#built-in-aws-s3',
|
||||
github: 'https://piclist.cn/en/configure.html#github',
|
||||
githubPlus: 'https://piclist.cn/en/configure.html#github',
|
||||
imgur: 'https://piclist.cn/en/configure.html#imgur',
|
||||
lankong: 'https://github.com/hellodk34/picgo-plugin-lankong',
|
||||
local: 'https://piclist.cn/en/configure.html#local-image-hosting',
|
||||
lskyplist: 'https://piclist.cn/en/configure.html#lsky-pro',
|
||||
tcyun: 'https://piclist.cn/en/configure.html#tencent-cloud-cos',
|
||||
piclist: 'https://piclist.cn/en/configure.html#piclist',
|
||||
qiniu: 'https://piclist.cn/en/configure.html#qiniu-cloud',
|
||||
sftpplist: 'https://piclist.cn/en/configure.html#built-in-sftp',
|
||||
smms: 'https://piclist.cn/en/configure.html#sm-ms',
|
||||
upyun: 'https://piclist.cn/en/configure.html#upyun',
|
||||
webdavplist: 'https://piclist.cn/en/configure.html#webdav'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user