mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-06 20:42:57 +08:00
🐛 Fix(custom): fix an issue settings will be saved multi times in process setting page
This commit is contained in:
@@ -65,6 +65,7 @@ TIPS_CUSTOM_CONFIG_FILE_PATH_ERROR: 自定义文件解析出错,请检查路
|
||||
TIPS_FIND_NEW_VERSION: 发现新版本${v},更新了很多功能,是否后台下载最新的版本?
|
||||
UPDATE_DOWNLOADED: 更新已下载
|
||||
TIPS_UPDATE_DOWNLOADED: 更新已下载,将在下次启动时安装,是否现在重启?
|
||||
UPDATE: 更新
|
||||
QUIT: 退出
|
||||
OPERATION_SUCCEED: "操作成功"
|
||||
OPERATION_FAILED: "操作失败"
|
||||
OPERATION_FAILED: "操作失败"
|
||||
|
||||
@@ -65,6 +65,7 @@ TIPS_CUSTOM_CONFIG_FILE_PATH_ERROR: 自訂設定檔案解析出錯,請檢查
|
||||
TIPS_FIND_NEW_VERSION: 發現新版本${v},更新了很多功能,是否後台下載最新的版本?
|
||||
UPDATE_DOWNLOADED: 更新已下載
|
||||
TIPS_UPDATE_DOWNLOADED: 更新已下載,将在下次啟動時安裝,是否立即重啟?
|
||||
UPDATE: 更新
|
||||
QUIT: 退出
|
||||
OPERATION_SUCCEED: "操作成功"
|
||||
OPERATION_FAILED: "操作失敗"
|
||||
OPERATION_FAILED: "操作失敗"
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<div class="range-value">{{ compressForm.quality }}%</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.qualityMap"
|
||||
:default-value="defaultCompressSetting.quality"
|
||||
field-name="quality"
|
||||
@@ -105,6 +106,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isConvertMap"
|
||||
:default-value="defaultCompressSetting.isConvert"
|
||||
field-name="isConvert"
|
||||
@@ -127,6 +129,7 @@
|
||||
</select>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.convertFormatMap"
|
||||
:default-value="defaultCompressSetting.convertFormat"
|
||||
field-name="convertFormat"
|
||||
@@ -149,13 +152,14 @@
|
||||
<div class="form-group">
|
||||
<label>{{ $t('pages.imageProcess.general.specificFormatConversion') }}</label>
|
||||
<textarea
|
||||
v-model="formatConvertObj"
|
||||
v-model="formatConvertObjStr"
|
||||
class="form-textarea"
|
||||
rows="3"
|
||||
placeholder='{"jpg": "png", "png": "jpg"}'
|
||||
/>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.formatConvertObjMap"
|
||||
:default-value="defaultCompressSetting.formatConvertObj"
|
||||
field-name="formatConvertObj"
|
||||
@@ -201,6 +205,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.isAddWatermarkMap"
|
||||
:default-value="defaultWaterMarkSetting.isAddWatermark"
|
||||
field-name="isAddWatermark"
|
||||
@@ -236,6 +241,7 @@
|
||||
</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkTypeMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkType"
|
||||
field-name="watermarkType"
|
||||
@@ -269,6 +275,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.isFullScreenWatermarkMap"
|
||||
:default-value="defaultWaterMarkSetting.isFullScreenWatermark"
|
||||
field-name="isFullScreenWatermark"
|
||||
@@ -299,6 +306,7 @@
|
||||
<div class="range-value">{{ waterMarkForm.watermarkDegree }}°</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkDegreeMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkDegree"
|
||||
field-name="watermarkDegree"
|
||||
@@ -334,6 +342,7 @@
|
||||
<div class="range-value">{{ Math.round((waterMarkForm.watermarkScaleRatio || 0) * 100) }}%</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkScaleRatioMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkScaleRatio"
|
||||
field-name="watermarkScaleRatio"
|
||||
@@ -369,6 +378,7 @@
|
||||
|
||||
<!-- Per-picbed settings for watermarkText -->
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkTextMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkText"
|
||||
field-name="watermarkText"
|
||||
@@ -398,6 +408,7 @@
|
||||
/>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkFontPathMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkFontPath"
|
||||
field-name="watermarkFontPath"
|
||||
@@ -430,6 +441,7 @@
|
||||
</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkColorMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkColor"
|
||||
field-name="watermarkColor"
|
||||
@@ -460,6 +472,7 @@
|
||||
/>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkImagePathMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkImagePath"
|
||||
field-name="watermarkImagePath"
|
||||
@@ -494,6 +507,7 @@
|
||||
</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkImageOpacityMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkImageOpacity"
|
||||
field-name="watermarkImageOpacity"
|
||||
@@ -530,8 +544,8 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Per-picbed settings for watermarkPosition -->
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="waterMarkForm.watermarkPositionMap"
|
||||
:default-value="defaultWaterMarkSetting.watermarkPosition"
|
||||
field-name="watermarkPosition"
|
||||
@@ -583,6 +597,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isFlipMap"
|
||||
:default-value="defaultCompressSetting.isFlip"
|
||||
field-name="isFlip"
|
||||
@@ -605,6 +620,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isFlopMap"
|
||||
:default-value="defaultCompressSetting.isFlop"
|
||||
field-name="isFlop"
|
||||
@@ -640,6 +656,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isRotateMap"
|
||||
:default-value="defaultCompressSetting.isRotate"
|
||||
field-name="isRotate"
|
||||
@@ -658,6 +675,7 @@
|
||||
<div class="range-value">{{ compressForm.rotateDegree }}°</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.rotateDegreeMap"
|
||||
:default-value="defaultCompressSetting.rotateDegree"
|
||||
field-name="rotateDegree"
|
||||
@@ -702,6 +720,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isReSizeMap"
|
||||
:default-value="defaultCompressSetting.isReSize"
|
||||
field-name="isReSize"
|
||||
@@ -721,6 +740,7 @@
|
||||
<input v-model.number="compressForm.reSizeWidth" type="number" min="0" class="form-input" />
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.reSizeWidthMap"
|
||||
:default-value="defaultCompressSetting.reSizeWidth"
|
||||
field-name="reSizeWidth"
|
||||
@@ -746,6 +766,7 @@
|
||||
<input v-model.number="compressForm.reSizeHeight" type="number" min="0" class="form-input" />
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.reSizeHeightMap"
|
||||
:default-value="defaultCompressSetting.reSizeHeight"
|
||||
field-name="reSizeHeight"
|
||||
@@ -785,6 +806,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.skipReSizeOfSmallImgMap"
|
||||
:default-value="defaultCompressSetting.skipReSizeOfSmallImg"
|
||||
field-name="skipReSizeOfSmallImg"
|
||||
@@ -826,6 +848,7 @@
|
||||
</label>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.isReSizeByPercentMap"
|
||||
:default-value="defaultCompressSetting.isReSizeByPercent"
|
||||
field-name="isReSizeByPercent"
|
||||
@@ -850,6 +873,7 @@
|
||||
<div class="range-value">{{ compressForm.reSizePercent }}%</div>
|
||||
|
||||
<PerPicbedSetting
|
||||
v-if="!configId"
|
||||
:map-field="compressForm.reSizePercentMap"
|
||||
:default-value="defaultCompressSetting.reSizePercent"
|
||||
field-name="reSizePercent"
|
||||
@@ -921,25 +945,13 @@ import type {
|
||||
IBuildInSkipProcessOptions,
|
||||
IBuildInWaterMarkOptions,
|
||||
} from 'piclist'
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onBeforeMount,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRaw,
|
||||
useTemplateRef,
|
||||
watch,
|
||||
} from 'vue'
|
||||
import { computed, nextTick, onBeforeMount, onBeforeUnmount, onMounted, ref, toRaw, useTemplateRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import PerPicbedSetting from '@/components/PerPicbedSetting.vue'
|
||||
import { configPaths } from '@/utils/configPaths'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
|
||||
import PerPicbedSetting from './PerPicbedSetting.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const activeTab = ref('general')
|
||||
|
||||
@@ -966,19 +978,6 @@ function updateTabIndicator() {
|
||||
}
|
||||
}
|
||||
|
||||
watch(activeTab, () => {
|
||||
nextTick(updateTabIndicator)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(updateTabIndicator)
|
||||
window.addEventListener('resize', updateTabIndicator)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', updateTabIndicator)
|
||||
})
|
||||
|
||||
const tabs = computed(() => [
|
||||
{
|
||||
id: 'general',
|
||||
@@ -1058,21 +1057,6 @@ const defaultWaterMarkSetting = {
|
||||
watermarkImageOpacity: 255,
|
||||
}
|
||||
|
||||
const waterMarkForm = reactive<IBuildInWaterMarkOptions>({
|
||||
isAddWatermarkMap: {},
|
||||
watermarkTypeMap: {},
|
||||
isFullScreenWatermarkMap: {},
|
||||
watermarkDegreeMap: {},
|
||||
watermarkTextMap: {},
|
||||
watermarkFontPathMap: {},
|
||||
watermarkScaleRatioMap: {},
|
||||
watermarkColorMap: {},
|
||||
watermarkImagePathMap: {},
|
||||
watermarkPositionMap: {},
|
||||
watermarkImageOpacityMap: {},
|
||||
...defaultWaterMarkSetting,
|
||||
})
|
||||
|
||||
const defaultCompressSetting = {
|
||||
quality: 100,
|
||||
isConvert: false,
|
||||
@@ -1091,7 +1075,23 @@ const defaultCompressSetting = {
|
||||
formatConvertObj: {},
|
||||
}
|
||||
|
||||
const compressForm = reactive<IBuildInCompressOptions>({
|
||||
const waterMarkForm = ref<IBuildInWaterMarkOptions>({
|
||||
isAddWatermarkMap: {},
|
||||
watermarkTypeMap: {},
|
||||
isFullScreenWatermarkMap: {},
|
||||
watermarkDegreeMap: {},
|
||||
watermarkTextMap: {},
|
||||
watermarkFontPathMap: {},
|
||||
watermarkScaleRatioMap: {},
|
||||
watermarkColorMap: {},
|
||||
watermarkImagePathMap: {},
|
||||
watermarkPositionMap: {},
|
||||
watermarkImageOpacityMap: {},
|
||||
...defaultWaterMarkSetting,
|
||||
})
|
||||
|
||||
/* Only used if configId is not provided */
|
||||
const compressForm = ref<IBuildInCompressOptions>({
|
||||
qualityMap: {},
|
||||
isConvertMap: {},
|
||||
convertFormatMap: {},
|
||||
@@ -1109,95 +1109,105 @@ const compressForm = reactive<IBuildInCompressOptions>({
|
||||
formatConvertObjMap: {},
|
||||
...defaultCompressSetting,
|
||||
})
|
||||
const formatConvertObj = ref('{}')
|
||||
/* Only used if configId is not provided */
|
||||
const formatConvertObjStr = ref('{}')
|
||||
|
||||
const skipProcessForm = reactive({
|
||||
/* Only used if configId is not provided */
|
||||
const skipProcessForm = ref<IBuildInSkipProcessOptions>({
|
||||
skipProcessExtList: 'zip,rar,7z,tar,gz,tar.gz,tar.bz2,tar.xz',
|
||||
})
|
||||
|
||||
const waterMarkFormKeys = Object.keys(waterMarkForm) as (keyof typeof waterMarkForm)[]
|
||||
const compressFormKeys = Object.keys(compressForm) as (keyof typeof compressForm)[]
|
||||
const skipProcessFormKeys = Object.keys(skipProcessForm) as (keyof typeof skipProcessForm)[]
|
||||
|
||||
const isInitialized = ref(false)
|
||||
let saveTimeout: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
function handleSaveConfig() {
|
||||
let iformatConvertObj = {}
|
||||
try {
|
||||
iformatConvertObj = JSON.parse(formatConvertObj.value)
|
||||
} catch (_error) {}
|
||||
const formatConvertObjEntries = Object.entries(iformatConvertObj)
|
||||
const formatConvertObjEntriesFilter = formatConvertObjEntries.filter((item: any) => {
|
||||
return imageExtList.includes(item[0]) && availableFormat.includes(item[1])
|
||||
})
|
||||
const formatConvertObjFilter = Object.fromEntries(formatConvertObjEntriesFilter)
|
||||
formatConvertObj.value = JSON.stringify(formatConvertObjFilter)
|
||||
compressForm.formatConvertObj = formatConvertObjFilter
|
||||
|
||||
const processedFormatConvertObjMap: Record<string, any> = {}
|
||||
Object.entries(compressForm.formatConvertObjMap || {}).forEach(([picbedType, jsonString]) => {
|
||||
try {
|
||||
const parsedObj = JSON.parse(jsonString as string)
|
||||
const objEntries = Object.entries(parsedObj)
|
||||
const filteredEntries = objEntries.filter((item: any) => {
|
||||
return imageExtList.includes(item[0]) && availableFormat.includes(item[1])
|
||||
})
|
||||
const filteredObj = Object.fromEntries(filteredEntries)
|
||||
if (Object.keys(filteredObj).length > 0) {
|
||||
processedFormatConvertObjMap[picbedType] = filteredObj
|
||||
}
|
||||
} catch (_error) {
|
||||
// Skip invalid JSON strings
|
||||
}
|
||||
})
|
||||
compressForm.formatConvertObjMap = processedFormatConvertObjMap
|
||||
|
||||
saveConfig(configPaths.buildIn.compress, toRaw(compressForm))
|
||||
saveConfig(configPaths.buildIn.watermark, toRaw(waterMarkForm))
|
||||
saveConfig(configPaths.buildIn.skipProcess, toRaw(skipProcessForm))
|
||||
function saveSkipProcessConfig() {
|
||||
saveConfig(configPaths.buildIn.skipProcess, toRaw(skipProcessForm.value))
|
||||
}
|
||||
|
||||
function debouncedSave() {
|
||||
if (!isInitialized.value) return
|
||||
function saveCompressConfig() {
|
||||
const cleanFullMap: Record<string, any> = {}
|
||||
Object.entries(compressForm.value.formatConvertObjMap || {}).forEach(([picbedType, jsonString]) => {
|
||||
try {
|
||||
const parsedObj = JSON.parse(jsonString as string)
|
||||
const cleanedObj = cleanFormatConvertObj(parsedObj)
|
||||
|
||||
if (saveTimeout) {
|
||||
clearTimeout(saveTimeout)
|
||||
if (Object.keys(cleanedObj).length > 0) {
|
||||
cleanFullMap[picbedType] = cleanedObj
|
||||
}
|
||||
} catch (_error) {}
|
||||
})
|
||||
if (JSON.stringify(cleanFullMap) !== JSON.stringify(compressForm.value.formatConvertObjMap)) {
|
||||
compressForm.value.formatConvertObjMap = cleanFullMap
|
||||
}
|
||||
|
||||
saveTimeout = setTimeout(() => {
|
||||
handleSaveConfig()
|
||||
}, 200)
|
||||
saveConfig(configPaths.buildIn.compress, toRaw(compressForm.value))
|
||||
}
|
||||
|
||||
function saveWaterMarkConfig() {
|
||||
saveConfig(configPaths.buildIn.watermark, toRaw(waterMarkForm.value))
|
||||
}
|
||||
|
||||
const singleConfigSettings = ref<IBuildInListItem>({} as IBuildInListItem)
|
||||
|
||||
function cleanFormatConvertObj(obj: any) {
|
||||
const cleanedObj: Record<string, any> = {}
|
||||
Object.entries(obj).forEach(([key, value]) => {
|
||||
if (imageExtList.includes(key) && typeof value === 'string' && availableFormat.includes(value)) {
|
||||
cleanedObj[key] = value
|
||||
}
|
||||
})
|
||||
return cleanedObj
|
||||
}
|
||||
|
||||
async function initData() {
|
||||
const compress = await getConfig<IBuildInCompressOptions>(configPaths.buildIn.compress)
|
||||
const watermark = await getConfig<IBuildInWaterMarkOptions>(configPaths.buildIn.watermark)
|
||||
const skipProcess = await getConfig<IBuildInSkipProcessOptions>(configPaths.buildIn.skipProcess)
|
||||
if (compress) {
|
||||
compressFormKeys.forEach(key => {
|
||||
compressForm[key] = compress[key] ?? compressForm[key]
|
||||
})
|
||||
try {
|
||||
if (typeof compress.formatConvertObj === 'object') {
|
||||
formatConvertObj.value = JSON.stringify(compress.formatConvertObj)
|
||||
} else {
|
||||
formatConvertObj.value = compress.formatConvertObj ?? '{}'
|
||||
}
|
||||
} catch (_error) {
|
||||
formatConvertObj.value = '{}'
|
||||
//single config settings
|
||||
if (configId) {
|
||||
const buildInList = await getConfig<Undefinable<IBuildInListItem[]>>(configPaths.buildIn.list)
|
||||
if (!buildInList) {
|
||||
console.error('Failed to load built-in config list.')
|
||||
}
|
||||
const targetConfig = buildInList?.find(item => item.id === configId)
|
||||
if (targetConfig) {
|
||||
singleConfigSettings.value = targetConfig
|
||||
}
|
||||
}
|
||||
if (watermark) {
|
||||
waterMarkFormKeys.forEach(key => {
|
||||
waterMarkForm[key] = watermark[key] ?? waterMarkForm[key]
|
||||
|
||||
// global settings
|
||||
const compress = (await getConfig<IBuildInCompressOptions>(configPaths.buildIn.compress)) || {}
|
||||
const watermark = (await getConfig<IBuildInWaterMarkOptions>(configPaths.buildIn.watermark)) || {}
|
||||
const skipProcess = (await getConfig<IBuildInSkipProcessOptions>(configPaths.buildIn.skipProcess)) || {}
|
||||
if (compress) {
|
||||
let cleanedObj = {}
|
||||
try {
|
||||
if (typeof compress.formatConvertObj === 'object') {
|
||||
cleanedObj = cleanFormatConvertObj(compress.formatConvertObj)
|
||||
} else if (typeof compress.formatConvertObj === 'string') {
|
||||
cleanedObj = cleanFormatConvertObj(JSON.parse(compress.formatConvertObj))
|
||||
} else {
|
||||
cleanedObj = {}
|
||||
}
|
||||
} catch (_error) {
|
||||
cleanedObj = {}
|
||||
}
|
||||
saveConfig(configPaths.buildIn.compress, {
|
||||
...compress,
|
||||
formatConvertObj: cleanedObj,
|
||||
})
|
||||
waterMarkForm.watermarkColor = watermark.watermarkColor === '' ? '#CCCCCC73' : watermark.watermarkColor
|
||||
compress.formatConvertObj = cleanedObj
|
||||
formatConvertObjStr.value = JSON.stringify(cleanedObj)
|
||||
compressForm.value = { ...compressForm.value, ...compress }
|
||||
}
|
||||
if (watermark) {
|
||||
if (watermark.watermarkColor === '') {
|
||||
watermark.watermarkColor = '#CCCCCC73'
|
||||
saveConfig(configPaths.buildIn.watermark, watermark)
|
||||
}
|
||||
waterMarkForm.value = { ...waterMarkForm.value, ...watermark }
|
||||
}
|
||||
if (skipProcess) {
|
||||
skipProcessFormKeys.forEach(key => {
|
||||
skipProcessForm[key] = skipProcess[key] ?? skipProcessForm[key]
|
||||
})
|
||||
skipProcessForm.value = {
|
||||
...skipProcessForm.value,
|
||||
...skipProcess,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,19 +1223,42 @@ function safeSetMapValue(form: any, fieldName: string, picbedType: string, value
|
||||
}
|
||||
}
|
||||
|
||||
watch(activeTab, () => {
|
||||
nextTick(updateTabIndicator)
|
||||
})
|
||||
|
||||
watch(formatConvertObjStr, () => {
|
||||
let parsedObj = {}
|
||||
try {
|
||||
parsedObj = JSON.parse(formatConvertObjStr.value)
|
||||
const cleanedObj = cleanFormatConvertObj(parsedObj)
|
||||
compressForm.value.formatConvertObj = cleanedObj
|
||||
if (JSON.stringify(cleanedObj) !== JSON.stringify(parsedObj)) {
|
||||
formatConvertObjStr.value = JSON.stringify(cleanedObj)
|
||||
}
|
||||
} catch (_error) {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
watch(skipProcessForm, () => saveSkipProcessConfig(), { deep: true })
|
||||
watch(compressForm, () => saveCompressConfig(), { deep: true })
|
||||
watch(waterMarkForm, () => saveWaterMarkConfig(), { deep: true })
|
||||
|
||||
onBeforeMount(() => {
|
||||
initData().then(() => {
|
||||
isInitialized.value = true
|
||||
})
|
||||
})
|
||||
|
||||
watch(
|
||||
() => [compressForm, waterMarkForm, skipProcessForm, formatConvertObj.value],
|
||||
() => {
|
||||
debouncedSave()
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
onMounted(() => {
|
||||
nextTick(updateTabIndicator)
|
||||
window.addEventListener('resize', updateTabIndicator)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', updateTabIndicator)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped src="./css/ImageProcessSetting.css"></style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<nav class="navigation" :class="{ collapsed: isCollapsed }">
|
||||
<div class="title-bar">
|
||||
<div v-if="!isCollapsed" class="app-title">
|
||||
<div v-show="!isCollapsed" class="app-title">
|
||||
<div class="app-text" @click="openGithubPage">
|
||||
{{ t('app.title') }}
|
||||
</div>
|
||||
@@ -12,8 +12,7 @@
|
||||
class="collapse-button"
|
||||
@click="isCollapsed = !isCollapsed"
|
||||
>
|
||||
<ChevronLeftIcon v-if="!isCollapsed" :size="20" />
|
||||
<ChevronRightIcon v-else :size="20" />
|
||||
<component :is="isCollapsed ? ChevronRightIcon : ChevronLeftIcon" :size="20" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -33,10 +32,10 @@
|
||||
<div class="nav-icon-container">
|
||||
<component :is="item.icon" :size="18" />
|
||||
</div>
|
||||
<span v-if="!isCollapsed" class="nav-label">{{ item.name }}</span>
|
||||
<span v-show="!isCollapsed" class="nav-label">{{ item.name }}</span>
|
||||
</div>
|
||||
|
||||
<Disclosure v-if="!isCollapsed" v-slot="{ open }" as="div" class="nav-submenu">
|
||||
<Disclosure v-show="!isCollapsed" v-slot="{ open }" as="div" class="nav-submenu">
|
||||
<DisclosureButton class="nav-item submenu-trigger">
|
||||
<div class="nav-icon-container">
|
||||
<DatabaseIcon :size="18" />
|
||||
@@ -55,7 +54,12 @@
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
</Disclosure>
|
||||
<div v-else class="nav-item collapsed-picbed" :title="t('navigation.picbed')" @click="isCollapsed = !isCollapsed">
|
||||
<div
|
||||
v-show="isCollapsed"
|
||||
class="nav-item collapsed-picbed"
|
||||
:title="t('navigation.picbed')"
|
||||
@click="isCollapsed = !isCollapsed"
|
||||
>
|
||||
<div class="nav-icon-container">
|
||||
<DatabaseIcon :size="18" />
|
||||
</div>
|
||||
@@ -72,7 +76,7 @@
|
||||
<div class="nav-icon-container">
|
||||
<component :is="item.icon" :size="18" />
|
||||
</div>
|
||||
<span v-if="!isCollapsed" class="nav-label">{{ item.name }}</span>
|
||||
<span v-show="!isCollapsed" class="nav-label">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-footer">
|
||||
|
||||
@@ -109,7 +109,9 @@
|
||||
},
|
||||
"renameSettings": "Rename",
|
||||
"skipProcessSettings": "Skip Process",
|
||||
"title": "Image Processing Settings",
|
||||
"subtitle-Global": "Configure settings for all PicBeds",
|
||||
"subtitle-PerPicbed": "Configure settings for current PicBed",
|
||||
"title": "",
|
||||
"transform": {
|
||||
"description": "Adjust image size, rotation, flipping, etc.",
|
||||
"isFlip": "Vertical Flip",
|
||||
@@ -952,7 +954,8 @@
|
||||
"dragFileToHere": "Drag file to here, or click to upload",
|
||||
"dragValidPictureOrUrl": "Please drag a valid picture file or URL here",
|
||||
"httpPrefixTip": "Starts with http:// or https://",
|
||||
"imageProcessName": "Image Processing",
|
||||
"imageProcessName": "Global Processing",
|
||||
"imageProcessNameSingle": "Single Processing",
|
||||
"inputUrlTip": "Please enter URL(s)",
|
||||
"inputValidUrl": "Please enter a valid URL",
|
||||
"invalidUrlsFound": "Invalid URLs found: {urls}",
|
||||
|
||||
@@ -109,7 +109,9 @@
|
||||
},
|
||||
"renameSettings": "重命名",
|
||||
"skipProcessSettings": "文件跳过",
|
||||
"title": "图片处理设置",
|
||||
"subtitle-Global": "为所有图床配置通用设置",
|
||||
"subtitle-PerPicbed": "为当前图床单独配置设置",
|
||||
"title": "",
|
||||
"transform": {
|
||||
"description": "调整图片大小、旋转、翻转等",
|
||||
"isFlip": "垂直翻转",
|
||||
@@ -947,7 +949,8 @@
|
||||
"dragFileToHere": "将文件拖到此处,或单击上传",
|
||||
"dragValidPictureOrUrl": "请拖入合法的图片文件或者图片URL地址",
|
||||
"httpPrefixTip": "http://或https://开头",
|
||||
"imageProcessName": "图片处理",
|
||||
"imageProcessName": "全局处理",
|
||||
"imageProcessNameSingle": "单图床处理",
|
||||
"inputUrlTip": "请输入URL地址",
|
||||
"inputValidUrl": "请输入合法的URL",
|
||||
"invalidUrlsFound": "发现无效的URL: {urls}",
|
||||
|
||||
@@ -109,7 +109,9 @@
|
||||
},
|
||||
"renameSettings": "重命名",
|
||||
"skipProcessSettings": "文件跳過",
|
||||
"title": "圖片處理設置",
|
||||
"subtitle-Global": "為所有圖床配置設置",
|
||||
"subtitle-PerPicbed": "為當前圖床單獨配置設置",
|
||||
"title": "",
|
||||
"transform": {
|
||||
"description": "調整圖片大小、旋轉、翻轉等",
|
||||
"isFlip": "垂直翻轉",
|
||||
@@ -947,7 +949,8 @@
|
||||
"dragFileToHere": "將文件拖到此處,或單擊上傳",
|
||||
"dragValidPictureOrUrl": "請拖入合法的圖片文件或者圖片URL地址",
|
||||
"httpPrefixTip": "以http://或https://開頭",
|
||||
"imageProcessName": "圖片處理",
|
||||
"imageProcessName": "全局處理",
|
||||
"imageProcessNameSingle": "單圖床處理",
|
||||
"inputUrlTip": "請輸入URL地址",
|
||||
"inputValidUrl": "請輸入合法的URL",
|
||||
"invalidUrlsFound": "發現無效的URL: {urls}",
|
||||
|
||||
@@ -178,12 +178,12 @@ function openContextMenu() {
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await initLogoPath()
|
||||
removeListeners = window.electron.ipcRendererOn('uploadProgress', uploadProgressHandler)
|
||||
window.electron.ipcRendererOn('updateMiniIcon', updateMiniIconHandler)
|
||||
window.addEventListener('mousedown', handleMouseDown, false)
|
||||
window.addEventListener('mousemove', handleMouseMove, false)
|
||||
window.addEventListener('mouseup', handleMouseUp, false)
|
||||
await initLogoPath()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
@@ -224,12 +224,12 @@ const updateFilesHandler = () => {
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
disableDragFile()
|
||||
await getData()
|
||||
window.electron.ipcRendererOn('dragFiles', dragFilesHandler)
|
||||
window.electron.ipcRendererOn('clipboardFiles', clipboardFilesHandler)
|
||||
window.electron.ipcRendererOn('uploadFiles', uploadFilesHandler)
|
||||
window.electron.ipcRendererOn('updateFiles', updateFilesHandler)
|
||||
disableDragFile()
|
||||
await getData()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
@@ -17,10 +17,20 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="action-button secondary" @click="handleImageProcess">
|
||||
<Settings :size="16" />
|
||||
<span>{{ t('pages.upload.imageProcessName') }}</span>
|
||||
</button>
|
||||
<div class="segmented-button-group">
|
||||
<button
|
||||
class="segmented-button"
|
||||
:title="t('pages.upload.imageProcessNameSingle')"
|
||||
@click="handleImageProcessSingle"
|
||||
>
|
||||
<Settings :size="16" />
|
||||
<span>{{ t('pages.upload.imageProcessNameSingle') }}</span>
|
||||
</button>
|
||||
<button class="segmented-button" :title="t('pages.upload.imageProcessName')" @click="handleImageProcess">
|
||||
<Settings :size="16" />
|
||||
<span>{{ t('pages.upload.imageProcessName') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<button class="action-button" @click="handleChangePicBed">
|
||||
<ArrowLeftRightIcon :size="16" />
|
||||
<span>{{ t('pages.upload.changePicBed') }}</span>
|
||||
@@ -139,6 +149,11 @@
|
||||
<h3 class="modal-title">
|
||||
{{ t('pages.imageProcess.title') }}
|
||||
</h3>
|
||||
<span class="modal-subtitle">
|
||||
{{
|
||||
PicBedId === '' ? t('pages.imageProcess.subtitle-Global') : t('pages.imageProcess.subtitle-PerPicbed')
|
||||
}}
|
||||
</span>
|
||||
<button class="modal-close" @click="imageProcessDialogVisible = false">
|
||||
<XIcon :size="20" />
|
||||
</button>
|
||||
@@ -228,6 +243,12 @@ function uploadProgressHandler(p: number): void {
|
||||
}
|
||||
|
||||
const handleImageProcess = () => {
|
||||
PicBedId.value = ''
|
||||
imageProcessDialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleImageProcessSingle = () => {
|
||||
PicBedId.value = defaultIdG.value
|
||||
imageProcessDialogVisible.value = true
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -95,6 +95,7 @@ export interface IConfigStruct {
|
||||
skipProcess: {
|
||||
skipProcessExtList: string
|
||||
}
|
||||
list: IBuildInListItem[]
|
||||
}
|
||||
debug: boolean
|
||||
PICGO_ENV: string
|
||||
@@ -176,10 +177,12 @@ export const configPaths = {
|
||||
picgoPlugins: 'picgoPlugins',
|
||||
uploader: 'uploader',
|
||||
buildIn: {
|
||||
_name: 'buildIn',
|
||||
compress: 'buildIn.compress',
|
||||
watermark: 'buildIn.watermark',
|
||||
rename: 'buildIn.rename',
|
||||
skipProcess: 'buildIn.skipProcess',
|
||||
list: 'buildIn.list',
|
||||
},
|
||||
debug: 'debug',
|
||||
PICGO_ENV: 'PICGO_ENV',
|
||||
|
||||
Reference in New Issue
Block a user