mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-06 20:42:57 +08:00
✨ Feature(custom): imporve page loading performance and remove duplicated init call
This commit is contained in:
@@ -136,7 +136,7 @@ const buildMainPageMenu = (win: BrowserWindow) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buildSecondPicBedMenu = () => {
|
const buildSecondPicBedMenu = () => {
|
||||||
const picBeds = getPicBeds()
|
const picBeds = getPicBeds().picBeds
|
||||||
const secondUploader = picgo.getConfig(configPaths.picBed.secondUploader)
|
const secondUploader = picgo.getConfig(configPaths.picBed.secondUploader)
|
||||||
const defaultSecondUploaderId = picgo.getConfig(configPaths.picBed.secondUploaderId)
|
const defaultSecondUploaderId = picgo.getConfig(configPaths.picBed.secondUploaderId)
|
||||||
const currentPicBedName = picBeds.find(item => item.type === secondUploader)?.name
|
const currentPicBedName = picBeds.find(item => item.type === secondUploader)?.name
|
||||||
@@ -189,7 +189,7 @@ const buildSecondPicBedMenu = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buildPicBedListMenu = () => {
|
const buildPicBedListMenu = () => {
|
||||||
const picBeds = getPicBeds()
|
const picBeds = getPicBeds().picBeds
|
||||||
const currentPicBed = picgo.getConfig(configPaths.picBed.uploader)
|
const currentPicBed = picgo.getConfig(configPaths.picBed.uploader)
|
||||||
const currentPicBedName = picBeds.find(item => item.type === currentPicBed)?.name
|
const currentPicBedName = picBeds.find(item => item.type === currentPicBed)?.name
|
||||||
const picBedConfigList = picgo.getConfig<IUploaderConfig>('uploader')
|
const picBedConfigList = picgo.getConfig<IUploaderConfig>('uploader')
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import { configPaths } from '~/utils/configPaths'
|
|||||||
|
|
||||||
const getPicBeds = () => {
|
const getPicBeds = () => {
|
||||||
const picBedTypes = picgo.helper.uploader.getIdList()
|
const picBedTypes = picgo.helper.uploader.getIdList()
|
||||||
|
const defaultPicBed =
|
||||||
|
picgo.getConfig<string>(configPaths.picBed.uploader) ||
|
||||||
|
picgo.getConfig<string>(configPaths.picBed.current) ||
|
||||||
|
'smms'
|
||||||
|
const defaultConfig = picgo.getConfig<IStringKeyMap>(`picBed.${defaultPicBed}`) || {}
|
||||||
|
const defaultId = defaultConfig._id || ''
|
||||||
|
const defaultConfigName = defaultConfig._configName || ''
|
||||||
const picBedFromDB = picgo.getConfig<IPicBedType[]>(configPaths.picBed.list) || []
|
const picBedFromDB = picgo.getConfig<IPicBedType[]>(configPaths.picBed.list) || []
|
||||||
const picBeds = picBedTypes
|
const picBeds = picBedTypes
|
||||||
.map((item: string) => {
|
.map((item: string) => {
|
||||||
@@ -20,7 +27,7 @@ const getPicBeds = () => {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}) as IPicBedType[]
|
}) as IPicBedType[]
|
||||||
return picBeds
|
return { picBeds, defaultPicBed, defaultId, defaultConfigName }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getPicBeds
|
export default getPicBeds
|
||||||
|
|||||||
@@ -6,26 +6,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IConfig } from 'piclist'
|
|
||||||
import { onBeforeMount, onMounted } from 'vue'
|
import { onBeforeMount, onMounted } from 'vue'
|
||||||
|
|
||||||
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
|
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
|
||||||
import { useAppStore } from '@/hooks/useAppStore'
|
import { useAppStore } from '@/hooks/useAppStore'
|
||||||
import { useATagClick } from '@/hooks/useATagClick'
|
import { useATagClick } from '@/hooks/useATagClick'
|
||||||
import { useStore } from '@/hooks/useStore'
|
import { pageReloadCount, usePicBed } from '@/hooks/useGlobal'
|
||||||
import { getConfig } from '@/utils/dataSender'
|
|
||||||
import { pageReloadCount } from '@/utils/global'
|
|
||||||
|
|
||||||
useATagClick()
|
useATagClick()
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
const { updatePicBeds } = usePicBed()
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(() => {
|
||||||
const config = await getConfig<IConfig>()
|
updatePicBeds()
|
||||||
if (config) {
|
|
||||||
store?.setDefaultPicBed(config?.picBed?.uploader || config?.picBed?.current || 'smms')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|||||||
@@ -21,26 +21,6 @@
|
|||||||
<transition name="fade-slide" mode="out-in">
|
<transition name="fade-slide" mode="out-in">
|
||||||
<!-- General Settings Tab -->
|
<!-- General Settings Tab -->
|
||||||
<div v-if="activeTab === 'general'" key="general" class="tab-content">
|
<div v-if="activeTab === 'general'" key="general" class="tab-content">
|
||||||
<div class="settings-section">
|
|
||||||
<div class="section-header">
|
|
||||||
<div class="section-icon">
|
|
||||||
<FileText :size="20" />
|
|
||||||
</div>
|
|
||||||
<div class="section-title-group">
|
|
||||||
<h2>{{ $t('pages.imageProcess.general.skipProcessExtList') }}</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<textarea
|
|
||||||
v-model="skipProcessForm.skipProcessExtList"
|
|
||||||
class="form-textarea"
|
|
||||||
rows="3"
|
|
||||||
:placeholder="'zip,rar,7z,tar,gz'"
|
|
||||||
/>
|
|
||||||
<small>{{ $t('pages.imageProcess.general.skipProcessExtListPlaceholder') }}</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<div class="section-icon">
|
<div class="section-icon">
|
||||||
@@ -62,6 +42,7 @@
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
<PerPicbedSetting
|
<PerPicbedSetting
|
||||||
|
v-if="!configId"
|
||||||
:map-field="compressForm.isRemoveExifMap"
|
:map-field="compressForm.isRemoveExifMap"
|
||||||
:default-value="defaultCompressSetting.isRemoveExif"
|
:default-value="defaultCompressSetting.isRemoveExif"
|
||||||
field-name="isRemoveExif"
|
field-name="isRemoveExif"
|
||||||
@@ -892,6 +873,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Skip Process Tab -->
|
||||||
|
<div v-else-if="activeTab === 'skipProcess'" key="skipProcess" class="tab-content">
|
||||||
|
<div class="settings-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<div class="section-icon">
|
||||||
|
<FileText :size="20" />
|
||||||
|
</div>
|
||||||
|
<div class="section-title-group">
|
||||||
|
<h2>{{ $t('pages.imageProcess.general.skipProcessExtList') }}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea
|
||||||
|
v-model="skipProcessForm.skipProcessExtList"
|
||||||
|
class="form-textarea"
|
||||||
|
rows="3"
|
||||||
|
:placeholder="'zip,rar,7z,tar,gz'"
|
||||||
|
/>
|
||||||
|
<small>{{ $t('pages.imageProcess.general.skipProcessExtListPlaceholder') }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -933,7 +937,6 @@ import { useI18n } from 'vue-i18n'
|
|||||||
|
|
||||||
import { configPaths } from '@/utils/configPaths'
|
import { configPaths } from '@/utils/configPaths'
|
||||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||||
import { updatePicBedGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
import PerPicbedSetting from './PerPicbedSetting.vue'
|
import PerPicbedSetting from './PerPicbedSetting.vue'
|
||||||
|
|
||||||
@@ -944,6 +947,13 @@ const activeTab = ref('general')
|
|||||||
const tabRefs = useTemplateRef('tabRefs')
|
const tabRefs = useTemplateRef('tabRefs')
|
||||||
const tabIndicatorStyle = ref<Record<string, string>>({})
|
const tabIndicatorStyle = ref<Record<string, string>>({})
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
// 传递配置ID以加载特定配置
|
||||||
|
configId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { configId } = defineProps<IProps>()
|
||||||
|
|
||||||
function updateTabIndicator() {
|
function updateTabIndicator() {
|
||||||
if (!tabRefs.value || tabRefs.value.length === 0) return
|
if (!tabRefs.value || tabRefs.value.length === 0) return
|
||||||
const activeIndex = tabs.value.findIndex(tab => tab.id === activeTab.value)
|
const activeIndex = tabs.value.findIndex(tab => tab.id === activeTab.value)
|
||||||
@@ -985,6 +995,16 @@ const tabs = computed(() => [
|
|||||||
label: t('pages.imageProcess.transformSettings'),
|
label: t('pages.imageProcess.transformSettings'),
|
||||||
icon: RotateCw,
|
icon: RotateCw,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'skipProcess',
|
||||||
|
label: t('pages.imageProcess.skipProcessSettings'),
|
||||||
|
icon: FileText,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'rename',
|
||||||
|
label: t('pages.imageProcess.renameSettings'),
|
||||||
|
icon: Sliders,
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const waterMarkPositionMap = new Map([
|
const waterMarkPositionMap = new Map([
|
||||||
@@ -1193,13 +1213,10 @@ function safeSetMapValue(form: any, fieldName: string, picbedType: string, value
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(() => {
|
||||||
await updatePicBedGlobal()
|
initData().then(() => {
|
||||||
await initData()
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
isInitialized.value = true
|
isInitialized.value = true
|
||||||
}, 100)
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
>
|
>
|
||||||
<ListboxOptions class="listbox-options">
|
<ListboxOptions class="listbox-options">
|
||||||
<ListboxOption
|
<ListboxOption
|
||||||
v-for="picbed in picBedGlobal"
|
v-for="picbed in picBedG"
|
||||||
:key="picbed.type"
|
:key="picbed.type"
|
||||||
v-slot="{ active, selected }"
|
v-slot="{ active, selected }"
|
||||||
:value="picbed.type"
|
:value="picbed.type"
|
||||||
@@ -173,6 +173,7 @@ import {
|
|||||||
TransitionChild,
|
TransitionChild,
|
||||||
TransitionRoot,
|
TransitionRoot,
|
||||||
} from '@headlessui/vue'
|
} from '@headlessui/vue'
|
||||||
|
import { useStorage } from '@vueuse/core'
|
||||||
import { pick } from 'lodash-es'
|
import { pick } from 'lodash-es'
|
||||||
import {
|
import {
|
||||||
BriefcaseBusiness,
|
BriefcaseBusiness,
|
||||||
@@ -194,21 +195,23 @@ import { computed, nextTick, onBeforeMount, onBeforeUnmount, reactive, Ref, ref,
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
import useMessage from '@/hooks/useMessage'
|
import useMessage from '@/hooks/useMessage'
|
||||||
import * as config from '@/router/config'
|
import * as config from '@/router/config'
|
||||||
import { SHOW_MAIN_PAGE_QRCODE } from '@/utils/constant'
|
import { SHOW_MAIN_PAGE_QRCODE } from '@/utils/constant'
|
||||||
import { getConfig } from '@/utils/dataSender'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
import ThemeSwitcher from './ui/ThemeSwitcher.vue'
|
import ThemeSwitcher from './ui/ThemeSwitcher.vue'
|
||||||
const version = ref(pkg.version)
|
const version = ref(pkg.version)
|
||||||
const isCollapsed = ref(false)
|
const isCollapsed = useStorage('navigation-collapsed', false)
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const { picBedG } = usePicBed()
|
||||||
|
|
||||||
const routerConfig = reactive(config)
|
const routerConfig = reactive(config)
|
||||||
const qrcodeVisible = ref(false)
|
const qrcodeVisible = ref(false)
|
||||||
const choosedPicBedForQRCode: Ref<string[]> = ref([])
|
const choosedPicBedForQRCode: Ref<string[]> = ref([])
|
||||||
@@ -216,11 +219,6 @@ const picBedConfigString = ref('')
|
|||||||
|
|
||||||
let removeIpcListener: () => void = () => {}
|
let removeIpcListener: () => void = () => {}
|
||||||
|
|
||||||
// Save collapsed state to localStorage when it changes
|
|
||||||
watch(isCollapsed, newValue => {
|
|
||||||
localStorage.setItem('navigation-collapsed', JSON.stringify(newValue))
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => choosedPicBedForQRCode,
|
() => choosedPicBedForQRCode,
|
||||||
val => {
|
val => {
|
||||||
@@ -235,7 +233,7 @@ watch(
|
|||||||
{ deep: true },
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
const visiblePicBeds = computed(() => picBedGlobal.value.filter(item => item.visible))
|
const visiblePicBeds = computed(() => picBedG.value.filter(item => item.visible))
|
||||||
|
|
||||||
const qrCodeHandler = () => {
|
const qrCodeHandler = () => {
|
||||||
qrcodeVisible.value = true
|
qrcodeVisible.value = true
|
||||||
@@ -279,13 +277,6 @@ function openGithubPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
// Load collapsed state from localStorage
|
|
||||||
const savedState = localStorage.getItem('navigation-collapsed')
|
|
||||||
if (savedState !== null) {
|
|
||||||
isCollapsed.value = JSON.parse(savedState)
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePicBedGlobal()
|
|
||||||
removeIpcListener = window.electron.ipcRendererOn(SHOW_MAIN_PAGE_QRCODE, qrCodeHandler)
|
removeIpcListener = window.electron.ipcRendererOn(SHOW_MAIN_PAGE_QRCODE, qrCodeHandler)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -294,523 +285,4 @@ onBeforeUnmount(() => {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped src="./css/NavigationPage.css"></style>
|
||||||
.navigation {
|
|
||||||
display: flex;
|
|
||||||
overflow: hidden;
|
|
||||||
border-right: 1px solid rgb(229 231 235);
|
|
||||||
width: 150px;
|
|
||||||
height: 100vh;
|
|
||||||
background: var(--color-background-secondary);
|
|
||||||
transition: width 0.3s ease;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation.collapsed {
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .navigation,
|
|
||||||
:root.auto.dark .navigation {
|
|
||||||
border-right-color: var(--color-background-secondary);
|
|
||||||
background: var(--color-background-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-bar {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid var(--color-border);
|
|
||||||
padding: 1.25rem 1rem;
|
|
||||||
background: var(--color-background-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation.collapsed .title-bar {
|
|
||||||
padding: 1rem 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 8px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 4px;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: transparent;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-button:hover {
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation.collapsed .collapse-button {
|
|
||||||
position: static;
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .title-bar,
|
|
||||||
:root.auto.dark .title-bar {
|
|
||||||
border-bottom-color: var(--color-border);
|
|
||||||
background: var(--color-background-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-text {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
letter-spacing: -0.025em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-text:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--color-blue-common);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-version {
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 3px 8px;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-section {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid var(--color-border);
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .theme-section,
|
|
||||||
:root.auto.dark .theme-section {
|
|
||||||
border-bottom-color: var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu {
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 1rem 0;
|
|
||||||
min-height: 0;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-item {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
color: rgb(75 85 99);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
gap: 0.75rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation.collapsed .nav-item {
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0.75rem 0.5rem;
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation.collapsed .nav-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .nav-item,
|
|
||||||
:root.auto.dark .nav-item {
|
|
||||||
color: rgb(209 213 219);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-item:hover {
|
|
||||||
color: rgb(17 24 39);
|
|
||||||
background: rgb(243 244 246);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .nav-item:hover,
|
|
||||||
:root.auto.dark .nav-item:hover {
|
|
||||||
color: rgb(243 244 246);
|
|
||||||
background: rgb(55 65 81);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-item.router-link-active {
|
|
||||||
border-right: 3px solid rgb(99 102 241);
|
|
||||||
color: rgb(99 102 241);
|
|
||||||
background: rgb(239 246 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .nav-item.router-link-active,
|
|
||||||
:root.auto.dark .nav-item.router-link-active {
|
|
||||||
border-right-color: rgb(129 140 248);
|
|
||||||
color: rgb(129 140 248);
|
|
||||||
background: rgb(30 58 138 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-icon-container {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-footer {
|
|
||||||
border-top: 1px solid var(--color-border);
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-button {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 4px;
|
|
||||||
left: 4px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 8px;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
background: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-button:hover {
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-submenu {
|
|
||||||
position: relative;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-trigger {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border: none;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
color: rgb(75 85 99);
|
|
||||||
background: transparent;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
gap: 0.75rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .submenu-trigger,
|
|
||||||
:root.auto.dark .submenu-trigger {
|
|
||||||
color: rgb(209 213 219);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-trigger:hover {
|
|
||||||
color: rgb(17 24 39);
|
|
||||||
background: rgb(243 244 246);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .submenu-trigger:hover,
|
|
||||||
:root.auto.dark .submenu-trigger:hover {
|
|
||||||
color: rgb(243 244 246);
|
|
||||||
background: rgb(55 65 81);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-trigger .nav-icon-container {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-trigger span {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-arrow {
|
|
||||||
position: absolute;
|
|
||||||
right: 1rem;
|
|
||||||
transition: transform 0.2s ease;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rotate-180 {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-panel {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 2px;
|
|
||||||
padding-left: 2.75rem;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
font-size: 0.8125rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu-item:hover {
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsed-picbed {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsed-picbed:hover {
|
|
||||||
color: rgb(17 24 39);
|
|
||||||
background: rgb(243 244 246);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .collapsed-picbed:hover,
|
|
||||||
:root.auto.dark .collapsed-picbed:hover {
|
|
||||||
color: rgb(243 244 246);
|
|
||||||
background: rgb(55 65 81);
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-dialog {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 50;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
overflow-y: auto;
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-container {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 50;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 16px;
|
|
||||||
min-height: 100vh;
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-panel {
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: 16px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
background: var(--color-background-primary);
|
|
||||||
box-shadow: var(--shadow-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-title {
|
|
||||||
margin: 0;
|
|
||||||
padding: 20px 24px 0;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-content {
|
|
||||||
padding: 20px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-button {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 12px 16px;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface);
|
|
||||||
transition: var(--transition);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-button:hover {
|
|
||||||
border-color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected-count {
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-arrow {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-options {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 10;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin-top: 4px;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
max-height: 300px;
|
|
||||||
background: var(--color-background-primary);
|
|
||||||
box-shadow: var(--shadow-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-option {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
transition: var(--transition);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-option.active {
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listbox-option.selected {
|
|
||||||
color: white;
|
|
||||||
background: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 12px;
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 10px 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: white;
|
|
||||||
background: var(--color-accent);
|
|
||||||
transition: var(--transition);
|
|
||||||
gap: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-button:hover {
|
|
||||||
background: var(--color-accent-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-code {
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
box-shadow: var(--shadow-sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
padding: 0 24px 20px;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel-button {
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: 10px 20px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
transition: var(--transition);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel-button:hover {
|
|
||||||
background: var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Design */
|
|
||||||
@media (width <= 768px) {
|
|
||||||
.navigation {
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scrollbar Styling */
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 0;
|
|
||||||
background: var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -112,9 +112,10 @@ import { Settings } from 'lucide-vue-next'
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import { picBedGlobal } from '@/utils/global'
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const { picBedG } = usePicBed()
|
||||||
|
|
||||||
interface SelectOption {
|
interface SelectOption {
|
||||||
value: string | number
|
value: string | number
|
||||||
@@ -166,7 +167,7 @@ const emit = defineEmits<{
|
|||||||
const showSettings = ref(false)
|
const showSettings = ref(false)
|
||||||
|
|
||||||
const availablePicbeds = computed(() => {
|
const availablePicbeds = computed(() => {
|
||||||
return picBedGlobal.value.map(picbed => ({
|
return picBedG.value.map(picbed => ({
|
||||||
type: picbed.type,
|
type: picbed.type,
|
||||||
name: picbed.name,
|
name: picbed.name,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<template>
|
<template>
|
||||||
<div id="config-form" :class="[{ white: props.colorMode === 'white' }]">
|
<div id="config-form" :class="[{ white: colorMode === 'white' }]">
|
||||||
<form class="config-form" @submit.prevent>
|
<form class="config-form" @submit.prevent>
|
||||||
<!-- Config Name Field -->
|
<!-- Config Name Field -->
|
||||||
<div class="form-group required">
|
<div class="form-group required">
|
||||||
@@ -125,14 +125,14 @@
|
|||||||
import { cloneDeep, union } from 'lodash-es'
|
import { cloneDeep, union } from 'lodash-es'
|
||||||
import { ChevronDownIcon, Info } from 'lucide-vue-next'
|
import { ChevronDownIcon, Info } from 'lucide-vue-next'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import { reactive, ref, toRefs, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
import { getConfig } from '@/utils/dataSender'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
config: any[]
|
config: IPicGoPluginConfig[]
|
||||||
type: 'uploader' | 'transformer' | 'plugin'
|
type: 'uploader' | 'transformer' | 'plugin'
|
||||||
id: string
|
id: string
|
||||||
colorMode?: 'white' | 'dark'
|
colorMode?: 'white' | 'dark'
|
||||||
@@ -140,11 +140,14 @@ interface IProps {
|
|||||||
showTooltips?: boolean
|
showTooltips?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<IProps>(), {
|
const {
|
||||||
colorMode: undefined,
|
config: configProp,
|
||||||
mode: 'picbed',
|
type,
|
||||||
showTooltips: true,
|
id,
|
||||||
})
|
colorMode = undefined,
|
||||||
|
mode = 'picbed',
|
||||||
|
showTooltips = true,
|
||||||
|
} = defineProps<IProps>()
|
||||||
|
|
||||||
const $route = useRoute()
|
const $route = useRoute()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -156,9 +159,9 @@ const visibleTooltips = reactive<Record<string, boolean>>({})
|
|||||||
|
|
||||||
// Watch for config changes
|
// Watch for config changes
|
||||||
watch(
|
watch(
|
||||||
toRefs(props.config),
|
() => configProp,
|
||||||
(val: IPicGoPluginConfig[]) => {
|
newVal => {
|
||||||
handleConfig(val)
|
handleConfig(newVal)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
@@ -191,10 +194,7 @@ function validateForm(): boolean {
|
|||||||
errors[config.name] = error
|
errors[config.name] = error
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
for (const key in validationErrors) delete validationErrors[key]
|
||||||
Object.keys(validationErrors).forEach(key => {
|
|
||||||
delete validationErrors[key]
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.assign(validationErrors, errors)
|
Object.assign(validationErrors, errors)
|
||||||
|
|
||||||
@@ -256,15 +256,15 @@ function transformMarkdownToHTML(markdown: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getConfigType() {
|
function getConfigType() {
|
||||||
switch (props.type) {
|
switch (type) {
|
||||||
case 'plugin': {
|
case 'plugin': {
|
||||||
return props.id
|
return id
|
||||||
}
|
}
|
||||||
case 'uploader': {
|
case 'uploader': {
|
||||||
return `picBed.${props.id}`
|
return `picBed.${id}`
|
||||||
}
|
}
|
||||||
case 'transformer': {
|
case 'transformer': {
|
||||||
return `transformer.${props.id}`
|
return `transformer.${id}`
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 'unknown'
|
return 'unknown'
|
||||||
@@ -273,14 +273,14 @@ function getConfigType() {
|
|||||||
|
|
||||||
async function handleConfig(val: IPicGoPluginConfig[]) {
|
async function handleConfig(val: IPicGoPluginConfig[]) {
|
||||||
const config = await getCurConfigFormData()
|
const config = await getCurConfigFormData()
|
||||||
const configId = props.mode === 'picbed' ? $route.params.configId : null
|
const configId = mode === 'picbed' ? $route.params.configId : null
|
||||||
|
|
||||||
Object.assign(ruleForm, config)
|
Object.assign(ruleForm, config)
|
||||||
|
|
||||||
if (val.length > 0) {
|
if (val.length > 0) {
|
||||||
configList.value = cloneDeep(val).map(item => {
|
configList.value = cloneDeep(val).map(item => {
|
||||||
// For plugin mode, don't check configId
|
// For plugin mode, don't check configId
|
||||||
if (props.mode === 'plugin' || !configId) {
|
if (mode === 'plugin' || !configId) {
|
||||||
let defaultValue = item.default !== undefined ? item.default : item.type === 'checkbox' ? [] : null
|
let defaultValue = item.default !== undefined ? item.default : item.type === 'checkbox' ? [] : null
|
||||||
|
|
||||||
if (item.type === 'checkbox') {
|
if (item.type === 'checkbox') {
|
||||||
@@ -314,11 +314,11 @@ async function handleConfig(val: IPicGoPluginConfig[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getCurConfigFormData() {
|
async function getCurConfigFormData() {
|
||||||
if (props.mode === 'plugin') {
|
if (mode === 'plugin') {
|
||||||
return (await getConfig<IStringKeyMap>(`${props.id}`)) || {}
|
return (await getConfig<IStringKeyMap>(`${id}`)) || {}
|
||||||
} else {
|
} else {
|
||||||
const configId = $route.params.configId
|
const configId = $route.params.configId
|
||||||
const curTypeConfigList = (await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`)) || []
|
const curTypeConfigList = (await getConfig<IStringKeyMap[]>(`uploader.${id}.configList`)) || []
|
||||||
return curTypeConfigList.find(i => i._id === configId) || {}
|
return curTypeConfigList.find(i => i._id === configId) || {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,386 +339,4 @@ defineExpose({
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped src="./css/UnifiedConfigForm.css"></style>
|
||||||
#config-form {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Form Groups */
|
|
||||||
.form-group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group.required .form-label::after {
|
|
||||||
content: ' *';
|
|
||||||
color: var(--color-error, #ef4444);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
line-height: 1.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tooltip Styles */
|
|
||||||
.tooltip-wrapper {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-icon {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
padding: 2px;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-icon:hover {
|
|
||||||
color: var(--color-accent);
|
|
||||||
background: rgb(0 122 255 / 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-content {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
padding: 0.75rem;
|
|
||||||
min-width: 200px;
|
|
||||||
max-width: 300px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
box-shadow: var(--shadow-lg);
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input Styles */
|
|
||||||
.form-input {
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-family: inherit;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-input:focus {
|
|
||||||
border-color: var(--color-accent);
|
|
||||||
outline: none;
|
|
||||||
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-input::placeholder {
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-input.error {
|
|
||||||
border-color: var(--color-error, #ef4444);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-input.error:focus {
|
|
||||||
box-shadow: 0 0 0 2px rgb(239 68 68 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select Styles */
|
|
||||||
.select-wrapper {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select {
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
padding: 0.75rem 2.5rem 0.75rem 1rem;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-family: inherit;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
appearance: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select:focus {
|
|
||||||
border-color: var(--color-accent);
|
|
||||||
outline: none;
|
|
||||||
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select.error {
|
|
||||||
border-color: var(--color-error, #ef4444);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select.error:focus {
|
|
||||||
box-shadow: 0 0 0 2px rgb(239 68 68 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-arrow {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 1rem;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-wrapper:hover .select-arrow,
|
|
||||||
.form-select:focus + .select-arrow {
|
|
||||||
color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checkbox Group Styles */
|
|
||||||
.checkbox-group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.75rem;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-label:hover {
|
|
||||||
color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-input {
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-custom {
|
|
||||||
position: relative;
|
|
||||||
border: 2px solid var(--color-border);
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
width: 1.25rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-custom::after {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 3px;
|
|
||||||
border: solid white;
|
|
||||||
border-width: 0 2px 2px 0;
|
|
||||||
width: 6px;
|
|
||||||
height: 10px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
content: '';
|
|
||||||
transform: rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-input:checked + .checkbox-custom {
|
|
||||||
border-color: var(--color-accent);
|
|
||||||
background: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-input:checked + .checkbox-custom::after {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-input:focus + .checkbox-custom {
|
|
||||||
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-text {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch Styles */
|
|
||||||
.switch-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: var(--color-text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-input {
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-slider {
|
|
||||||
position: relative;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
width: 3rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
background: var(--color-border);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 2px;
|
|
||||||
left: 2px;
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 1.25rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
background: white;
|
|
||||||
box-shadow: var(--shadow-sm);
|
|
||||||
transition: var(--transition-fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-input:checked + .switch-slider {
|
|
||||||
background: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-input:checked + .switch-slider .switch-button {
|
|
||||||
transform: translateX(1.5rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-input:focus + .switch-slider {
|
|
||||||
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-text {
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-input:checked ~ .switch-text {
|
|
||||||
color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error Message */
|
|
||||||
.error-message {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--color-error, #ef4444);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* White theme adjustments */
|
|
||||||
.white .form-input,
|
|
||||||
.white .form-select {
|
|
||||||
border-color: #dddddd;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.white .form-input:focus,
|
|
||||||
.white .form-select:focus {
|
|
||||||
border-color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.white .checkbox-custom {
|
|
||||||
border-color: #dddddd;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.white .switch-slider {
|
|
||||||
background: #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.white .tooltip-content {
|
|
||||||
border-color: #dddddd;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Design */
|
|
||||||
@media (width <= 768px) {
|
|
||||||
.config-form {
|
|
||||||
gap: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-input,
|
|
||||||
.form-select {
|
|
||||||
padding: 0.625rem 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select {
|
|
||||||
padding-right: 2.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-content {
|
|
||||||
min-width: 150px;
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark mode adjustments */
|
|
||||||
:root.dark .form-input,
|
|
||||||
:root.auto.dark .form-input,
|
|
||||||
:root.dark .form-select,
|
|
||||||
:root.auto.dark .form-select {
|
|
||||||
border-color: var(--color-border);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .checkbox-custom,
|
|
||||||
:root.auto.dark .checkbox-custom {
|
|
||||||
border-color: var(--color-border);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .switch-slider,
|
|
||||||
:root.auto.dark .switch-slider {
|
|
||||||
background: var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root.dark .tooltip-content,
|
|
||||||
:root.auto.dark .tooltip-content {
|
|
||||||
border-color: var(--color-border);
|
|
||||||
background: var(--color-surface-elevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Focus styles for accessibility */
|
|
||||||
.form-input:focus-visible,
|
|
||||||
.form-select:focus-visible,
|
|
||||||
.checkbox-input:focus-visible + .checkbox-custom,
|
|
||||||
.switch-input:focus-visible + .switch-slider,
|
|
||||||
.info-icon:focus-visible {
|
|
||||||
outline: 2px solid var(--color-accent);
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
518
src/renderer/components/css/NavigationPage.css
Normal file
518
src/renderer/components/css/NavigationPage.css
Normal file
@@ -0,0 +1,518 @@
|
|||||||
|
.navigation {
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
border-right: 1px solid rgb(229 231 235);
|
||||||
|
width: 150px;
|
||||||
|
height: 100vh;
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation.collapsed {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .navigation,
|
||||||
|
:root.auto.dark .navigation {
|
||||||
|
border-right-color: var(--color-background-secondary);
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
padding: 1.25rem 1rem;
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation.collapsed .title-bar {
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: transparent;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-button:hover {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation.collapsed .collapse-button {
|
||||||
|
position: static;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .title-bar,
|
||||||
|
:root.auto.dark .title-bar {
|
||||||
|
border-bottom-color: var(--color-border);
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-text:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--color-blue-common);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-version {
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .theme-section,
|
||||||
|
:root.auto.dark .theme-section {
|
||||||
|
border-bottom-color: var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu {
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 1rem 0;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgb(75 85 99);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
gap: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation.collapsed .nav-item {
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.75rem 0.5rem;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation.collapsed .nav-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .nav-item,
|
||||||
|
:root.auto.dark .nav-item {
|
||||||
|
color: rgb(209 213 219);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item:hover {
|
||||||
|
color: rgb(17 24 39);
|
||||||
|
background: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .nav-item:hover,
|
||||||
|
:root.auto.dark .nav-item:hover {
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
background: rgb(55 65 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.router-link-active {
|
||||||
|
border-right: 3px solid rgb(99 102 241);
|
||||||
|
color: rgb(99 102 241);
|
||||||
|
background: rgb(239 246 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .nav-item.router-link-active,
|
||||||
|
:root.auto.dark .nav-item.router-link-active {
|
||||||
|
border-right-color: rgb(129 140 248);
|
||||||
|
color: rgb(129 140 248);
|
||||||
|
background: rgb(30 58 138 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon-container {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
border-top: 1px solid var(--color-border);
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-button {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 4px;
|
||||||
|
left: 4px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-button:hover {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-submenu {
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-trigger {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: none;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgb(75 85 99);
|
||||||
|
background: transparent;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
gap: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .submenu-trigger,
|
||||||
|
:root.auto.dark .submenu-trigger {
|
||||||
|
color: rgb(209 213 219);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-trigger:hover {
|
||||||
|
color: rgb(17 24 39);
|
||||||
|
background: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .submenu-trigger:hover,
|
||||||
|
:root.auto.dark .submenu-trigger:hover {
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
background: rgb(55 65 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-trigger .nav-icon-container {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-trigger span {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-180 {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-panel {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 2px;
|
||||||
|
padding-left: 2.75rem;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-item:hover {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsed-picbed {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsed-picbed:hover {
|
||||||
|
color: rgb(17 24 39);
|
||||||
|
background: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .collapsed-picbed:hover,
|
||||||
|
:root.auto.dark .collapsed-picbed:hover {
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
background: rgb(55 65 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-dialog {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow-y: auto;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-container {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
min-height: 100vh;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-panel {
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 16px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
background: var(--color-background-primary);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px 24px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
padding: 20px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: 12px 16px;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface);
|
||||||
|
transition: var(--transition);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-button:hover {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-count {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-arrow {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-options {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 4px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
max-height: 300px;
|
||||||
|
background: var(--color-background-primary);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-option {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
transition: var(--transition);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-option.active {
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listbox-option.selected {
|
||||||
|
color: white;
|
||||||
|
background: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: white;
|
||||||
|
background: var(--color-accent);
|
||||||
|
transition: var(--transition);
|
||||||
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button:hover {
|
||||||
|
background: var(--color-accent-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-code {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 0 24px 20px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-button {
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
transition: var(--transition);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-button:hover {
|
||||||
|
background: var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (width <= 768px) {
|
||||||
|
.navigation {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar Styling */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 0;
|
||||||
|
background: var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--color-text-secondary);
|
||||||
|
}
|
||||||
381
src/renderer/components/css/UnifiedConfigForm.css
Normal file
381
src/renderer/components/css/UnifiedConfigForm.css
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
#config-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form Groups */
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group.required .form-label::after {
|
||||||
|
content: ' *';
|
||||||
|
color: var(--color-error, #ef4444);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip Styles */
|
||||||
|
.tooltip-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-icon {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 2px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-icon:hover {
|
||||||
|
color: var(--color-accent);
|
||||||
|
background: rgb(0 122 255 / 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-content {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 0.75rem;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input Styles */
|
||||||
|
.form-input {
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-family: inherit;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input:focus {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input::placeholder {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input.error {
|
||||||
|
border-color: var(--color-error, #ef4444);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input.error:focus {
|
||||||
|
box-shadow: 0 0 0 2px rgb(239 68 68 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select Styles */
|
||||||
|
.select-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select {
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 0.75rem 2.5rem 0.75rem 1rem;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-family: inherit;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select:focus {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select.error {
|
||||||
|
border-color: var(--color-error, #ef4444);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select.error:focus {
|
||||||
|
box-shadow: 0 0 0 2px rgb(239 68 68 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-arrow {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 1rem;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-wrapper:hover .select-arrow,
|
||||||
|
.form-select:focus + .select-arrow {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox Group Styles */
|
||||||
|
.checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label:hover {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-custom {
|
||||||
|
position: relative;
|
||||||
|
border: 2px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-custom::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 3px;
|
||||||
|
border: solid white;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
width: 6px;
|
||||||
|
height: 10px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
content: '';
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-input:checked + .checkbox-custom {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
background: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-input:checked + .checkbox-custom::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-input:focus + .checkbox-custom {
|
||||||
|
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch Styles */
|
||||||
|
.switch-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-slider {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
width: 3rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
background: var(--color-border);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
left: 2px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
background: white;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input:checked + .switch-slider {
|
||||||
|
background: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input:checked + .switch-slider .switch-button {
|
||||||
|
transform: translateX(1.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input:focus + .switch-slider {
|
||||||
|
box-shadow: 0 0 0 2px rgb(0 122 255 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-text {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input:checked ~ .switch-text {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error Message */
|
||||||
|
.error-message {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--color-error, #ef4444);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* White theme adjustments */
|
||||||
|
.white .form-input,
|
||||||
|
.white .form-select {
|
||||||
|
border-color: #dddddd;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white .form-input:focus,
|
||||||
|
.white .form-select:focus {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.white .checkbox-custom {
|
||||||
|
border-color: #dddddd;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white .switch-slider {
|
||||||
|
background: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white .tooltip-content {
|
||||||
|
border-color: #dddddd;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (width <= 768px) {
|
||||||
|
.config-form {
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input,
|
||||||
|
.form-select {
|
||||||
|
padding: 0.625rem 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select {
|
||||||
|
padding-right: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-content {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode adjustments */
|
||||||
|
:root.dark .form-input,
|
||||||
|
:root.auto.dark .form-input,
|
||||||
|
:root.dark .form-select,
|
||||||
|
:root.auto.dark .form-select {
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .checkbox-custom,
|
||||||
|
:root.auto.dark .checkbox-custom {
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .switch-slider,
|
||||||
|
:root.auto.dark .switch-slider {
|
||||||
|
background: var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .tooltip-content,
|
||||||
|
:root.auto.dark .tooltip-content {
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background: var(--color-surface-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus styles for accessibility */
|
||||||
|
.form-input:focus-visible,
|
||||||
|
.form-select:focus-visible,
|
||||||
|
.checkbox-input:focus-visible + .checkbox-custom,
|
||||||
|
.switch-input:focus-visible + .switch-slider,
|
||||||
|
.info-icon:focus-visible {
|
||||||
|
outline: 2px solid var(--color-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
@@ -43,8 +43,8 @@
|
|||||||
import { MinusIcon, PinIcon, ShrinkIcon, XIcon } from 'lucide-vue-next'
|
import { MinusIcon, PinIcon, ShrinkIcon, XIcon } from 'lucide-vue-next'
|
||||||
import { computed, onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
import { computed, onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
||||||
|
|
||||||
|
import { osGlobal } from '@/hooks/useGlobal'
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
import { osGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
const isShowprogress = ref(false)
|
const isShowprogress = ref(false)
|
||||||
const progress = ref(0)
|
const progress = ref(0)
|
||||||
|
|||||||
44
src/renderer/hooks/useGlobal.ts
Normal file
44
src/renderer/hooks/useGlobal.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { readonly, ref } from 'vue'
|
||||||
|
|
||||||
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
|
|
||||||
|
const osGlobal = ref<string>(window.electron.platform)
|
||||||
|
const pageReloadCount = ref(0)
|
||||||
|
|
||||||
|
interface getPicBedType {
|
||||||
|
picBeds: IPicBedType[]
|
||||||
|
defaultPicBed: string
|
||||||
|
defaultConfigName: string
|
||||||
|
defaultId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const _picBeds = ref<IPicBedType[]>([])
|
||||||
|
const _defaultPicBed = ref<string>('')
|
||||||
|
const _defaultConfigName = ref<string>('')
|
||||||
|
const _defaultPicBedId = ref<string>('')
|
||||||
|
|
||||||
|
export function usePicBed() {
|
||||||
|
const updatePicBeds = async () => {
|
||||||
|
console.log('Updating pic beds in global hook...')
|
||||||
|
const result = await window.electron.triggerRPC<getPicBedType>(IRPCActionType.MAIN_GET_PICBED)
|
||||||
|
if (result) {
|
||||||
|
_picBeds.value = result.picBeds
|
||||||
|
_defaultPicBed.value = result.defaultPicBed
|
||||||
|
_defaultConfigName.value = result.defaultConfigName
|
||||||
|
_defaultPicBedId.value = result.defaultId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
picBedG: readonly(_picBeds),
|
||||||
|
defaultPicBedG: readonly(_defaultPicBed),
|
||||||
|
defaultConfigNameG: readonly(_defaultConfigName),
|
||||||
|
defaultIdG: readonly(_defaultPicBedId),
|
||||||
|
updatePicBeds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePageReloadCount() {
|
||||||
|
pageReloadCount.value++
|
||||||
|
}
|
||||||
|
|
||||||
|
export { osGlobal, pageReloadCount, updatePageReloadCount }
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { inject } from 'vue'
|
|
||||||
|
|
||||||
import { storeKey } from '@/store'
|
|
||||||
|
|
||||||
export const useStore = () => {
|
|
||||||
return inject(storeKey) ?? null
|
|
||||||
}
|
|
||||||
@@ -107,6 +107,8 @@
|
|||||||
"description": "Configure settings for each PicBed individually",
|
"description": "Configure settings for each PicBed individually",
|
||||||
"title": "Per-PicBed Settings"
|
"title": "Per-PicBed Settings"
|
||||||
},
|
},
|
||||||
|
"renameSettings": "Rename",
|
||||||
|
"skipProcessSettings": "Skip Process",
|
||||||
"title": "Image Processing Settings",
|
"title": "Image Processing Settings",
|
||||||
"transform": {
|
"transform": {
|
||||||
"description": "Adjust image size, rotation, flipping, etc.",
|
"description": "Adjust image size, rotation, flipping, etc.",
|
||||||
|
|||||||
@@ -107,6 +107,8 @@
|
|||||||
"description": "为每个图床单独配置设置",
|
"description": "为每个图床单独配置设置",
|
||||||
"title": "图床独立设置"
|
"title": "图床独立设置"
|
||||||
},
|
},
|
||||||
|
"renameSettings": "重命名",
|
||||||
|
"skipProcessSettings": "文件跳过",
|
||||||
"title": "图片处理设置",
|
"title": "图片处理设置",
|
||||||
"transform": {
|
"transform": {
|
||||||
"description": "调整图片大小、旋转、翻转等",
|
"description": "调整图片大小、旋转、翻转等",
|
||||||
|
|||||||
@@ -107,6 +107,8 @@
|
|||||||
"description": "為每個圖床單獨配置設置",
|
"description": "為每個圖床單獨配置設置",
|
||||||
"title": "圖床獨立設置"
|
"title": "圖床獨立設置"
|
||||||
},
|
},
|
||||||
|
"renameSettings": "重命名",
|
||||||
|
"skipProcessSettings": "文件跳過",
|
||||||
"title": "圖片處理設置",
|
"title": "圖片處理設置",
|
||||||
"transform": {
|
"transform": {
|
||||||
"description": "調整圖片大小、旋轉、翻轉等",
|
"description": "調整圖片大小、旋轉、翻轉等",
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
<ChevronDownIcon :size="16" />
|
<ChevronDownIcon :size="16" />
|
||||||
</button>
|
</button>
|
||||||
<div v-show="picBedDropdownOpen" class="multiselect-dropdown">
|
<div v-show="picBedDropdownOpen" class="multiselect-dropdown">
|
||||||
<label v-for="item in picBedGlobal" :key="item.type" class="multiselect-option">
|
<label v-for="item in picBedG" :key="item.type" class="multiselect-option">
|
||||||
<input v-model="choosedPicBed" type="checkbox" :value="item.type" />
|
<input v-model="choosedPicBed" type="checkbox" :value="item.type" />
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</label>
|
</label>
|
||||||
@@ -514,6 +514,7 @@ import { onBeforeRouteUpdate } from 'vue-router'
|
|||||||
import ALLApi from '@/apis/allApi'
|
import ALLApi from '@/apis/allApi'
|
||||||
import VirtualScroller from '@/components/VirtualScroller.vue'
|
import VirtualScroller from '@/components/VirtualScroller.vue'
|
||||||
import useConfirm from '@/hooks/useConfirm'
|
import useConfirm from '@/hooks/useConfirm'
|
||||||
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
import useMessage from '@/hooks/useMessage'
|
import useMessage from '@/hooks/useMessage'
|
||||||
import { customStrMatch, customStrReplace } from '@/manage/utils/common'
|
import { customStrMatch, customStrReplace } from '@/manage/utils/common'
|
||||||
import { getRawData } from '@/utils/common'
|
import { getRawData } from '@/utils/common'
|
||||||
@@ -521,12 +522,12 @@ import { configPaths } from '@/utils/configPaths'
|
|||||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||||
import $$db from '@/utils/db'
|
import $$db from '@/utils/db'
|
||||||
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
||||||
import { picBedGlobal } from '@/utils/global'
|
|
||||||
import { picBedsCanbeDeleted } from '@/utils/static'
|
import { picBedsCanbeDeleted } from '@/utils/static'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
const { confirm } = useConfirm()
|
const { confirm } = useConfirm()
|
||||||
|
const { picBedG } = usePicBed()
|
||||||
|
|
||||||
type IResult<T> = T & {
|
type IResult<T> = T & {
|
||||||
id: string
|
id: string
|
||||||
|
|||||||
@@ -30,10 +30,10 @@
|
|||||||
import type { IConfig } from 'piclist'
|
import type { IConfig } from 'piclist'
|
||||||
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
|
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
|
||||||
|
|
||||||
|
import { osGlobal } from '@/hooks/useGlobal'
|
||||||
import { isUrl } from '@/utils/common'
|
import { isUrl } from '@/utils/common'
|
||||||
import { getConfig } from '@/utils/dataSender'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
import { osGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
const logoPath = ref('')
|
const logoPath = ref('')
|
||||||
const dragover = ref(false)
|
const dragover = ref(false)
|
||||||
|
|||||||
@@ -348,7 +348,7 @@
|
|||||||
<span>{{ t('pages.settings.upload.autoImportPicBed') }}</span>
|
<span>{{ t('pages.settings.upload.autoImportPicBed') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox-group compact">
|
<div class="checkbox-group compact">
|
||||||
<label v-for="item in picBedGlobal" :key="item.type" class="checkbox-option">
|
<label v-for="item in picBedG" :key="item.type" class="checkbox-option">
|
||||||
<input
|
<input
|
||||||
v-model="formOfSetting.autoImportPicBed"
|
v-model="formOfSetting.autoImportPicBed"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -676,7 +676,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="picbed-checkbox-grid">
|
<div class="picbed-checkbox-grid">
|
||||||
<label v-for="item in picBedGlobal" :key="item.name" class="picbed-checkbox-card">
|
<label v-for="item in picBedG" :key="item.name" class="picbed-checkbox-card">
|
||||||
<input v-model="showPicBedList" type="checkbox" :value="item.name" class="checkbox-input" />
|
<input v-model="showPicBedList" type="checkbox" :value="item.name" class="checkbox-input" />
|
||||||
<span class="checkbox-indicator" />
|
<span class="checkbox-indicator" />
|
||||||
<span class="checkbox-label">{{ item.name }}</span>
|
<span class="checkbox-label">{{ item.name }}</span>
|
||||||
@@ -696,7 +696,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="picbed-checkbox-grid">
|
<div class="picbed-checkbox-grid">
|
||||||
<label v-for="item in picBedGlobal" :key="`gallery-${item.name}`" class="picbed-checkbox-card">
|
<label v-for="item in picBedG" :key="`gallery-${item.name}`" class="picbed-checkbox-card">
|
||||||
<input v-model="galleryPicBedFilterList" type="checkbox" :value="item.type" class="checkbox-input" />
|
<input v-model="galleryPicBedFilterList" type="checkbox" :value="item.type" class="checkbox-input" />
|
||||||
<span class="checkbox-indicator" />
|
<span class="checkbox-indicator" />
|
||||||
<span class="checkbox-label">{{ item.name }}</span>
|
<span class="checkbox-label">{{ item.name }}</span>
|
||||||
@@ -1747,7 +1747,7 @@
|
|||||||
<button class="dialog-close" @click="imageProcessDialogVisible = false">X</button>
|
<button class="dialog-close" @click="imageProcessDialogVisible = false">X</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<ImageProcessSetting v-model="imageProcessDialogVisible" />
|
<ImageProcessSetting :config-id="''" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1784,6 +1784,7 @@ import { useRouter } from 'vue-router'
|
|||||||
|
|
||||||
import ImageProcessSetting from '@/components/ImageProcessSetting.vue'
|
import ImageProcessSetting from '@/components/ImageProcessSetting.vue'
|
||||||
import useConfirm from '@/hooks/useConfirm'
|
import useConfirm from '@/hooks/useConfirm'
|
||||||
|
import { osGlobal, usePicBed } from '@/hooks/useGlobal'
|
||||||
import useMessage from '@/hooks/useMessage'
|
import useMessage from '@/hooks/useMessage'
|
||||||
import { setCurrentLanguage } from '@/i18n'
|
import { setCurrentLanguage } from '@/i18n'
|
||||||
import { SHORTKEY_PAGE } from '@/router/config'
|
import { SHORTKEY_PAGE } from '@/router/config'
|
||||||
@@ -1792,12 +1793,13 @@ import { configPaths } from '@/utils/configPaths'
|
|||||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||||
import { II18nLanguage, IRPCActionType, ISartMode } from '@/utils/enum'
|
import { II18nLanguage, IRPCActionType, ISartMode } from '@/utils/enum'
|
||||||
import { getLatestVersion } from '@/utils/getLatestVersion'
|
import { getLatestVersion } from '@/utils/getLatestVersion'
|
||||||
import { osGlobal, picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
const $router = useRouter()
|
const $router = useRouter()
|
||||||
const { confirm } = useConfirm()
|
const { confirm } = useConfirm()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const { picBedG, updatePicBeds } = usePicBed()
|
||||||
|
|
||||||
const activeName = ref<'system' | 'sync' | 'upload' | 'advanced' | 'update'>('system')
|
const activeName = ref<'system' | 'sync' | 'upload' | 'advanced' | 'update'>('system')
|
||||||
const showPicBedList = ref<string[]>([])
|
const showPicBedList = ref<string[]>([])
|
||||||
const galleryPicBedFilterList = ref<string[]>([])
|
const galleryPicBedFilterList = ref<string[]>([])
|
||||||
@@ -2073,7 +2075,7 @@ async function initData() {
|
|||||||
const config = (await getConfig<IConfig>()) || ({} as IConfig)
|
const config = (await getConfig<IConfig>()) || ({} as IConfig)
|
||||||
const settings = config.settings || {}
|
const settings = config.settings || {}
|
||||||
const picBed = config.picBed
|
const picBed = config.picBed
|
||||||
showPicBedList.value = picBedGlobal.value.filter(item => item.visible).map(item => item.name)
|
showPicBedList.value = picBedG.value.filter(item => item.visible).map(item => item.name)
|
||||||
galleryPicBedFilterList.value = settings.galleryPicBedFilter || []
|
galleryPicBedFilterList.value = settings.galleryPicBedFilter || []
|
||||||
formKeys.forEach(key => {
|
formKeys.forEach(key => {
|
||||||
;(formOfSetting.value as any)[key] = settings[key] ?? formOfSetting.value[key]
|
;(formOfSetting.value as any)[key] = settings[key] ?? formOfSetting.value[key]
|
||||||
@@ -2225,9 +2227,9 @@ watch(galleryPicBedFilterList, val => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function handleShowPicBedListChange(val: ICheckBoxValueType[]) {
|
function handleShowPicBedListChange(val: ICheckBoxValueType[]) {
|
||||||
const list = picBedGlobal.value.map(item => ({ ...item, visible: val.includes(item.name) }))
|
const list = picBedG.value.map(item => ({ ...item, visible: val.includes(item.name) }))
|
||||||
saveConfig({ [configPaths.picBed.list]: list })
|
saveConfig({ [configPaths.picBed.list]: list })
|
||||||
updatePicBedGlobal()
|
updatePicBeds()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGalleryPicBedFilterChange(val: ICheckBoxValueType[]) {
|
function handleGalleryPicBedFilterChange(val: ICheckBoxValueType[]) {
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ import { computed, onBeforeMount, onBeforeUnmount, reactive, ref, toRaw, useTemp
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import ConfigForm from '@/components/UnifiedConfigForm.vue'
|
import ConfigForm from '@/components/UnifiedConfigForm.vue'
|
||||||
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
import { getRawData, handleStreamlinePluginName } from '@/utils/common'
|
import { getRawData, handleStreamlinePluginName } from '@/utils/common'
|
||||||
import { configPaths } from '@/utils/configPaths'
|
import { configPaths } from '@/utils/configPaths'
|
||||||
import {
|
import {
|
||||||
@@ -235,9 +236,9 @@ import {
|
|||||||
} from '@/utils/constant'
|
} from '@/utils/constant'
|
||||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
import { updatePicBedGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const { updatePicBeds } = usePicBed()
|
||||||
const searchText = ref('')
|
const searchText = ref('')
|
||||||
const pluginList = ref<IPicGoPlugin[]>([])
|
const pluginList = ref<IPicGoPlugin[]>([])
|
||||||
const config = ref<any[]>([])
|
const config = ref<any[]>([])
|
||||||
@@ -332,7 +333,7 @@ const updateSuccessHandler = (plugin: string) => {
|
|||||||
item.ing = false
|
item.ing = false
|
||||||
item.hasInstall = true
|
item.hasInstall = true
|
||||||
}
|
}
|
||||||
updatePicBedGlobal()
|
updatePicBeds()
|
||||||
})
|
})
|
||||||
handleReload()
|
handleReload()
|
||||||
getPluginList()
|
getPluginList()
|
||||||
@@ -349,7 +350,7 @@ const uninstallSuccessHandler = (plugin: string) => {
|
|||||||
if (item.config.uploader.name) {
|
if (item.config.uploader.name) {
|
||||||
handleRestoreState('uploader', item.config.uploader.name)
|
handleRestoreState('uploader', item.config.uploader.name)
|
||||||
}
|
}
|
||||||
updatePicBedGlobal()
|
updatePicBeds()
|
||||||
}
|
}
|
||||||
return item.fullName !== plugin
|
return item.fullName !== plugin
|
||||||
})
|
})
|
||||||
@@ -379,7 +380,7 @@ const picgoTogglePluginHandler = (fullName: string, enabled: boolean) => {
|
|||||||
const plugin = pluginList.value.find(item => item.fullName === fullName)
|
const plugin = pluginList.value.find(item => item.fullName === fullName)
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
plugin.enabled = enabled
|
plugin.enabled = enabled
|
||||||
updatePicBedGlobal()
|
updatePicBeds()
|
||||||
needReload.value = true
|
needReload.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
<button
|
<button
|
||||||
class="provider-button"
|
class="provider-button"
|
||||||
:title="t('pages.upload.uploadViewHint')"
|
:title="t('pages.upload.uploadViewHint')"
|
||||||
@click="handlePicBedNameClick(picBedName, picBedConfigName)"
|
@click="handlePicBedNameClick(picBedName)"
|
||||||
>
|
>
|
||||||
<div class="provider-info">
|
<div class="provider-info">
|
||||||
<span class="provider-name">{{ picBedName }}</span>
|
<span class="provider-name">{{ picBedName }}</span>
|
||||||
<span class="provider-config">{{ picBedConfigName || 'Default' }}</span>
|
<span class="provider-config">{{ defaultConfigNameG || 'Default' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<EditIcon :size="16" class="provider-arrow" />
|
<EditIcon :size="16" class="provider-arrow" />
|
||||||
</button>
|
</button>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<ImageProcessSetting v-model="imageProcessDialogVisible" />
|
<ImageProcessSetting :config-id="PicBedId" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,11 +162,12 @@ import {
|
|||||||
UploadCloudIcon,
|
UploadCloudIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from 'lucide-vue-next'
|
} from 'lucide-vue-next'
|
||||||
import { onBeforeMount, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'
|
import { computed, onBeforeMount, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
import ImageProcessSetting from '@/components/ImageProcessSetting.vue'
|
import ImageProcessSetting from '@/components/ImageProcessSetting.vue'
|
||||||
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
import useMessage from '@/hooks/useMessage'
|
import useMessage from '@/hooks/useMessage'
|
||||||
import { PICBEDS_PAGE } from '@/router/config'
|
import { PICBEDS_PAGE } from '@/router/config'
|
||||||
import $bus from '@/utils/bus'
|
import $bus from '@/utils/bus'
|
||||||
@@ -176,12 +177,12 @@ import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '@/utils/constant'
|
|||||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||||
import { useDragEventListeners } from '@/utils/drag'
|
import { useDragEventListeners } from '@/utils/drag'
|
||||||
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
import { IPasteStyle, IRPCActionType } from '@/utils/enum'
|
||||||
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
|
||||||
|
|
||||||
useDragEventListeners()
|
useDragEventListeners()
|
||||||
const $router = useRouter()
|
const $router = useRouter()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const { picBedG, defaultPicBedG, defaultConfigNameG, defaultIdG, updatePicBeds } = usePicBed()
|
||||||
|
|
||||||
const imageProcessDialogVisible = ref(false)
|
const imageProcessDialogVisible = ref(false)
|
||||||
const useShortUrl = ref(false)
|
const useShortUrl = ref(false)
|
||||||
@@ -189,11 +190,18 @@ const dragover = ref(false)
|
|||||||
const progress = ref(0)
|
const progress = ref(0)
|
||||||
const showProgress = ref(false)
|
const showProgress = ref(false)
|
||||||
const showError = ref(false)
|
const showError = ref(false)
|
||||||
const pasteStyle = ref('')
|
const pasteStyle = ref(IPasteStyle.MARKDOWN)
|
||||||
const picBedName = ref('')
|
const PicBedId = ref('')
|
||||||
const picBedConfigName = ref('')
|
|
||||||
const fileInput = useTemplateRef('fileInput')
|
const fileInput = useTemplateRef('fileInput')
|
||||||
|
|
||||||
|
const picBedName = computed(() => {
|
||||||
|
if (!picBedG.value || picBedG.value.length === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const target = picBedG.value.find(item => item.type === defaultPicBedG.value)
|
||||||
|
return target ? target.name : defaultPicBedG.value
|
||||||
|
})
|
||||||
|
|
||||||
const pasteFormatList = ref<Record<string, string>>({
|
const pasteFormatList = ref<Record<string, string>>({
|
||||||
[IPasteStyle.MARKDOWN]: '',
|
[IPasteStyle.MARKDOWN]: '',
|
||||||
[IPasteStyle.HTML]: '<img src="url"/>',
|
[IPasteStyle.HTML]: '<img src="url"/>',
|
||||||
@@ -202,9 +210,9 @@ const pasteFormatList = ref<Record<string, string>>({
|
|||||||
[IPasteStyle.CUSTOM]: '',
|
[IPasteStyle.CUSTOM]: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(picBedGlobal, () => {
|
function syncPicBedHandler(): void {
|
||||||
getDefaultPicBed()
|
updatePicBeds()
|
||||||
})
|
}
|
||||||
|
|
||||||
let removeUploadProgressListenerCallback: () => void = () => {}
|
let removeUploadProgressListenerCallback: () => void = () => {}
|
||||||
let removeSyncPicBedListenerCallback: () => void = () => {}
|
let removeSyncPicBedListenerCallback: () => void = () => {}
|
||||||
@@ -219,10 +227,6 @@ function uploadProgressHandler(p: number): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncPicBedHandler(): void {
|
|
||||||
getDefaultPicBed()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleImageProcess = () => {
|
const handleImageProcess = () => {
|
||||||
imageProcessDialogVisible.value = true
|
imageProcessDialogVisible.value = true
|
||||||
}
|
}
|
||||||
@@ -241,21 +245,13 @@ function onProgressChange(val: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handlePicBedNameClick(_picBedName: string, picBedConfigName: string | undefined) {
|
async function handlePicBedNameClick(_picBedName: string) {
|
||||||
const formatedpicBedConfigName = picBedConfigName || 'Default'
|
const currentPicBedConfig = ((await getConfig<any[]>(`uploader.${defaultPicBedG.value}`)) as any) || {}
|
||||||
const currentPicBed = await getConfig<string>(configPaths.picBed.current)
|
|
||||||
const currentPicBedConfig = ((await getConfig<any[]>(`uploader.${currentPicBed}`)) as any) || {}
|
|
||||||
const configList = await window.electron.triggerRPC<IUploaderConfigItem>(
|
|
||||||
IRPCActionType.PICBED_GET_CONFIG_LIST,
|
|
||||||
currentPicBed,
|
|
||||||
)
|
|
||||||
const currentConfigList = configList?.configList ?? []
|
|
||||||
const config = currentConfigList.find((item: any) => item._configName === formatedpicBedConfigName)
|
|
||||||
$router.push({
|
$router.push({
|
||||||
name: PICBEDS_PAGE,
|
name: PICBEDS_PAGE,
|
||||||
params: {
|
params: {
|
||||||
type: currentPicBed,
|
type: defaultPicBedG.value,
|
||||||
configId: config?._id || '',
|
configId: defaultIdG.value,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
defaultConfigId: currentPicBedConfig.defaultId || '',
|
defaultConfigId: currentPicBedConfig.defaultId || '',
|
||||||
@@ -400,16 +396,6 @@ function handleInputBoxValue(val: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDefaultPicBed() {
|
|
||||||
const currentPicBed = await getConfig<string>(configPaths.picBed.current)
|
|
||||||
picBedGlobal.value.forEach(item => {
|
|
||||||
if (item.type === currentPicBed) {
|
|
||||||
picBedName.value = item.name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
picBedConfigName.value = (await getConfig<string>(`picBed.${currentPicBed}._configName`)) || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleChangePicBed() {
|
async function handleChangePicBed() {
|
||||||
window.electron.sendRPC(IRPCActionType.SHOW_UPLOAD_PAGE_MENU)
|
window.electron.sendRPC(IRPCActionType.SHOW_UPLOAD_PAGE_MENU)
|
||||||
}
|
}
|
||||||
@@ -421,13 +407,11 @@ onBeforeUnmount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
updatePicBedGlobal()
|
|
||||||
getUseShortUrl()
|
|
||||||
getPasteStyle()
|
|
||||||
getDefaultPicBed()
|
|
||||||
removeUploadProgressListenerCallback = window.electron.ipcRendererOn('uploadProgress', uploadProgressHandler)
|
removeUploadProgressListenerCallback = window.electron.ipcRendererOn('uploadProgress', uploadProgressHandler)
|
||||||
removeSyncPicBedListenerCallback = window.electron.ipcRendererOn('syncPicBed', syncPicBedHandler)
|
removeSyncPicBedListenerCallback = window.electron.ipcRendererOn('syncPicBed', syncPicBedHandler)
|
||||||
$bus.on(SHOW_INPUT_BOX_RESPONSE, handleInputBoxValue)
|
$bus.on(SHOW_INPUT_BOX_RESPONSE, handleInputBoxValue)
|
||||||
|
getUseShortUrl()
|
||||||
|
getPasteStyle()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<button
|
<button class="btn btn-primary btn-glow" :disabled="defaultPicBedG === type" @click="setDefaultPicBed(type)">
|
||||||
class="btn btn-primary btn-glow"
|
|
||||||
:disabled="store?.state.defaultPicBed === type"
|
|
||||||
@click="setDefaultPicBed(type)"
|
|
||||||
>
|
|
||||||
<Star :size="16" />
|
<Star :size="16" />
|
||||||
<span>{{ t('pages.uploaderConfig.setAsDefault') }}</span>
|
<span>{{ t('pages.uploaderConfig.setAsDefault') }}</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -130,8 +126,8 @@ import { useI18n } from 'vue-i18n'
|
|||||||
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
import useConfirm from '@/hooks/useConfirm'
|
import useConfirm from '@/hooks/useConfirm'
|
||||||
|
import { usePicBed } from '@/hooks/useGlobal'
|
||||||
import useMessage from '@/hooks/useMessage'
|
import useMessage from '@/hooks/useMessage'
|
||||||
import { useStore } from '@/hooks/useStore'
|
|
||||||
import { PICBEDS_PAGE, UPLOADER_CONFIG_PAGE } from '@/router/config'
|
import { PICBEDS_PAGE, UPLOADER_CONFIG_PAGE } from '@/router/config'
|
||||||
import $bus from '@/utils/bus'
|
import $bus from '@/utils/bus'
|
||||||
import { configPaths } from '@/utils/configPaths'
|
import { configPaths } from '@/utils/configPaths'
|
||||||
@@ -144,15 +140,15 @@ const message = useMessage()
|
|||||||
const { confirm } = useConfirm()
|
const { confirm } = useConfirm()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const { defaultPicBedG } = usePicBed()
|
||||||
|
|
||||||
const type = ref('')
|
const type = ref('')
|
||||||
const curConfigList = ref<IStringKeyMap[]>([])
|
const curConfigList = ref<IStringKeyMap[]>([])
|
||||||
const defaultConfigId = ref('')
|
const defaultConfigId = ref('')
|
||||||
const store = useStore()
|
|
||||||
|
|
||||||
async function selectItem(id: string) {
|
async function selectItem(id: string) {
|
||||||
await window.electron.triggerRPC<void>(IRPCActionType.UPLOADER_SELECT, type.value, id)
|
await window.electron.triggerRPC<void>(IRPCActionType.UPLOADER_SELECT, type.value, id)
|
||||||
if (store?.state.defaultPicBed === type.value) {
|
if (defaultPicBedG.value === type.value) {
|
||||||
window.electron.sendRPC(
|
window.electron.sendRPC(
|
||||||
IRPCActionType.TRAY_SET_TOOL_TIP,
|
IRPCActionType.TRAY_SET_TOOL_TIP,
|
||||||
`${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`,
|
`${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`,
|
||||||
@@ -276,7 +272,6 @@ function setDefaultPicBed(type: string) {
|
|||||||
[configPaths.picBed.uploader]: type,
|
[configPaths.picBed.uploader]: type,
|
||||||
})
|
})
|
||||||
|
|
||||||
store?.setDefaultPicBed(type)
|
|
||||||
const currentConfigName = curConfigList.value.find(item => item._id === defaultConfigId.value)?._configName
|
const currentConfigName = curConfigList.value.find(item => item._id === defaultConfigId.value)?._configName
|
||||||
window.electron.sendRPC(IRPCActionType.TRAY_SET_TOOL_TIP, `${type} ${currentConfigName || ''}`)
|
window.electron.sendRPC(IRPCActionType.TRAY_SET_TOOL_TIP, `${type} ${currentConfigName || ''}`)
|
||||||
message.success(t('pages.uploaderConfig.setSuccess'))
|
message.success(t('pages.uploaderConfig.setSuccess'))
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
|
||||||
|
|
||||||
const osGlobal = ref<string>(window.electron.platform)
|
|
||||||
|
|
||||||
const picBedGlobal = ref<IPicBedType[]>([])
|
|
||||||
const pageReloadCount = ref(0)
|
|
||||||
|
|
||||||
async function updatePicBedGlobal() {
|
|
||||||
picBedGlobal.value = (await window.electron.triggerRPC<IPicBedType[]>(IRPCActionType.MAIN_GET_PICBED))!
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updatePageReloadCount() {
|
|
||||||
pageReloadCount.value++
|
|
||||||
}
|
|
||||||
|
|
||||||
export { osGlobal, pageReloadCount, picBedGlobal, updatePageReloadCount, updatePicBedGlobal }
|
|
||||||
Reference in New Issue
Block a user