🎨 Style(custom): format with prettier

This commit is contained in:
Kuingsmile
2024-06-15 19:37:50 +08:00
parent 096f564c31
commit 5af8a6b529
157 changed files with 21365 additions and 22952 deletions

View File

@@ -1,21 +1,11 @@
<template>
<el-form-item>
<template #label>
<span style="position:absolute;left: 0;">
<span
v-for="(segment, index) in segments"
:key="index"
:style="segment.style"
>
<span style="position: absolute; left: 0">
<span v-for="(segment, index) in segments" :key="index" :style="segment.style">
{{ segment.text }}
</span>
<el-tooltip
:content="tooltip"
effect="dark"
placement="right"
:persistent="false"
teleported
>
<el-tooltip :content="tooltip" effect="dark" placement="right" :persistent="false" teleported>
<el-icon>
<InfoFilled />
</el-icon>
@@ -26,7 +16,7 @@
v-model="value"
:active-text="activeText"
:inactive-text="inactiveText"
style="--el-switch-on-color: #13ce66;--el-switch-off-color: #ff4949; position:absolute; right: 0;"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949; position: absolute; right: 0"
/>
</el-form-item>
</template>
@@ -35,12 +25,11 @@
import { InfoFilled } from '@element-plus/icons-vue'
defineProps<{
tooltip?: string,
activeText?: string,
inactiveText?: string,
segments?: { text: string, style: string }[],
tooltip?: string
activeText?: string
inactiveText?: string
segments?: { text: string; style: string }[]
}>()
const value = defineModel<boolean>()
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,5 @@
<template>
<el-empty
:description="$T('MANAGE_NO_DATA')"
/>
<el-empty :description="$T('MANAGE_NO_DATA')" />
</template>
<script lang="ts" setup>

View File

@@ -4,7 +4,7 @@
v-model="activeName"
type="border-card"
stretch
style="height: calc(100vh - 50px);width: 100%;overflow-x: hidden;"
style="height: calc(100vh - 50px); width: 100%; overflow-x: hidden"
tab-position="left"
lazy
@tab-change="getExistingConfig(activeName)"
@@ -12,7 +12,7 @@
<el-tab-pane
name="login"
:label="$T('MANAGE_LOGIN_PAGE_PANE_NAME')"
style="width: 100%;overflow-y: scroll;height: calc(100vh - 50px);"
style="width: 100%; overflow-y: scroll; height: calc(100vh - 50px)"
lazy
>
<el-alert
@@ -25,53 +25,31 @@
element-loading-svg-view-box="0, 0, 150, 150"
/>
<el-row>
<el-col
v-for="item in sortedAllConfigAliasMap"
:key="item"
:xs="24"
:sm="12"
:md="8"
:lg="6"
:xl="4"
>
<el-card
class="box-card"
style="margin: 10px 0;"
shadow="hover"
>
<el-popover
placement="top"
:width="300"
trigger="click"
:persistent="false"
teleported
>
<el-col v-for="item in sortedAllConfigAliasMap" :key="item" :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
<el-card class="box-card" style="margin: 10px 0" shadow="hover">
<el-popover placement="top" :width="300" trigger="click" :persistent="false" teleported>
<el-table
:data="formObjToTableData(item.config)"
style="width: 100%"
size="small"
:header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
>
<el-table-column
prop="key"
:label="$T('MANAGE_LOGIN_PAGE_PANE_KEY_NAME')"
width="100"
/>
<el-table-column
prop="value"
:label="$T('MANAGE_LOGIN_PAGE_PANE_KEY_VALUE')"
/>
<el-table-column prop="key" :label="$T('MANAGE_LOGIN_PAGE_PANE_KEY_NAME')" width="100" />
<el-table-column prop="value" :label="$T('MANAGE_LOGIN_PAGE_PANE_KEY_VALUE')" />
</el-table>
<template #reference>
<el-button
style="width: 100%; text-align: center;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;"
style="
width: 100%;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
"
>
<template #icon>
<img
:src="require(`./assets/${item.picBedName}.webp`)"
style="width: 25px; height: 25px;"
>
<img :src="require(`./assets/${item.picBedName}.webp`)" style="width: 25px; height: 25px" />
</template>
<el-tooltip
effect="light"
@@ -86,23 +64,13 @@
</el-button>
</template>
</el-popover>
<br>
<br>
<br />
<br />
<el-button-group>
<el-button
type="primary"
:icon="Pointer"
plain
@click="handleConfigClick(item)"
>
<el-button type="primary" :icon="Pointer" plain @click="handleConfigClick(item)">
{{ $T('MANAGE_LOGIN_PAGE_PANE_ENTER') }}
</el-button>
<el-button
type="warning"
:icon="Delete"
plain
@click="handleConfigRemove(item.alias)"
>
<el-button type="warning" :icon="Delete" plain @click="handleConfigRemove(item.alias)">
{{ $T('MANAGE_LOGIN_PAGE_PANE_DELETE') }}
</el-button>
</el-button-group>
@@ -117,24 +85,13 @@
:name="item.icon"
class="tab-pane"
lazy
style="width: 100%;overflow-y: scroll;height: calc(100vh - 50px);"
style="width: 100%; overflow-y: scroll; height: calc(100vh - 50px)"
>
<el-alert
:title="item.explain"
type="info"
show-icon
center
:closable="false"
/>
<el-alert
center
:closable="false"
>
<el-alert :title="item.explain" type="info" show-icon center :closable="false" />
<el-alert center :closable="false">
<div>
{{ item.referenceText }} <a
style="color:blue;cursor:pointer"
@click="handleReferenceClick(item.refLink)"
>{{ item.refLink }}</a>
{{ item.referenceText }}
<a style="color: blue; cursor: pointer" @click="handleReferenceClick(item.refLink)">{{ item.refLink }}</a>
</div>
</el-alert>
<el-form
@@ -160,9 +117,7 @@
:persistent="false"
teleported
>
<el-icon
color="#409EFF"
>
<el-icon color="#409EFF">
<InfoFilled />
</el-icon>
</el-tooltip>
@@ -176,7 +131,7 @@
<el-switch
v-else-if="supportedPicBedList[item.icon].configOptions[option].type === 'boolean'"
v-model="configResult[item.icon + '.' + option]"
style="--el-switch-on-color: #13ce66;--el-switch-off-color: #ff4949;"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
/>
<el-input
v-else-if="supportedPicBedList[item.icon].configOptions[option].type === 'number'"
@@ -199,7 +154,7 @@
</el-select>
</el-form-item>
</el-form>
<div style="margin: 0 auto;position: relative;left: 10%;right: 50%;">
<div style="margin: 0 auto; position: relative; left: 10%; right: 50%">
<el-dropdown
split-button
type="success"
@@ -210,46 +165,25 @@
>
{{ $T('MANAGE_LOGIN_PAGE_PANE_IMPORT') }}
<template #dropdown>
<el-dropdown-item
v-for="i in currentAliasList"
:key="i"
@click="handleConfigImport(i)"
>
<el-dropdown-item v-for="i in currentAliasList" :key="i" @click="handleConfigImport(i)">
{{ i }}
</el-dropdown-item>
</template>
</el-dropdown>
<el-button
type="primary"
style="margin-left: 10vw"
:icon="Edit"
plain
@click="handleConfigChange(item.icon)"
>
<el-button type="primary" style="margin-left: 10vw" :icon="Edit" plain @click="handleConfigChange(item.icon)">
{{ $T('MANAGE_LOGIN_PAGE_PANE_SAVE') }}
</el-button>
<el-button
type="danger"
style="margin-left: 10vw"
:icon="Delete"
plain
@click="handleConfigReset(item.icon)"
>
<el-button type="danger" style="margin-left: 10vw" :icon="Delete" plain @click="handleConfigReset(item.icon)">
{{ $T('MANAGE_LOGIN_PAGE_PANE_RESET') }}
</el-button>
</div>
<br>
<el-alert
:title="$T('MANAGE_LOGIN_PAGE_PANE_TABLE_TITLE')"
type="success"
center
:closable="false"
/>
<br />
<el-alert :title="$T('MANAGE_LOGIN_PAGE_PANE_TABLE_TITLE')" type="success" center :closable="false" />
<el-table
:data="dataForTable"
style="width: 100%;margin-top: 10px"
:header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}"
style="width: 100%; margin-top: 10px"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
@cell-click="handleCellClick"
>
<el-table-column
@@ -288,7 +222,7 @@ const router = useRouter()
const activeName = ref('login')
const configResult:IStringKeyMap = reactive({})
const configResult: IStringKeyMap = reactive({})
const existingConfiguration = reactive({} as IStringKeyMap)
const dataForTable = reactive([] as any[])
const allConfigAliasMap = reactive({} as IStringKeyMap)
@@ -303,9 +237,9 @@ const sortedAllConfigAliasMap = computed(() => {
const importedNewConfig: IStringKeyMap = {}
function ruleMap (options: IStringKeyMap) {
const rule:any = {}
Object.keys(options).forEach((key) => {
function ruleMap(options: IStringKeyMap) {
const rule: any = {}
Object.keys(options).forEach(key => {
const item = options[key].options
item.forEach((option: string) => {
const configOptions = options[key].configOptions[option]
@@ -321,13 +255,13 @@ function ruleMap (options: IStringKeyMap) {
return rule
}
function getDataForTable () {
function getDataForTable() {
for (const key in existingConfiguration) {
dataForTable.push({ ...existingConfiguration[key] as IStringKeyMap })
dataForTable.push({ ...(existingConfiguration[key] as IStringKeyMap) })
}
}
async function getExistingConfig (name:string) {
async function getExistingConfig(name: string) {
if (name === 'login') {
getAllConfigAliasArray()
return
@@ -353,20 +287,22 @@ async function getExistingConfig (name:string) {
handleConfigImport(currentAliasList[0])
}
function getAliasList () {
function getAliasList() {
return Object.values(existingConfiguration).map(item => item.alias)
}
async function handleConfigChange (name: string) {
async function handleConfigChange(name: string) {
const aliasList = getAliasList()
const allKeys = Object.keys(supportedPicBedList[name].configOptions)
const resultMap:IStringKeyMap = {}
const resultMap: IStringKeyMap = {}
const reg = /^[\p{Unified_Ideograph}_a-zA-Z0-9-]+$/u
for (const key of allKeys) {
const resultKey = name + '.' + key
if (supportedPicBedList[name].configOptions[key].required) {
if (supportedPicBedList[name].configOptions[key].type !== 'boolean' && !configResult[resultKey]) {
ElMessage.error(`${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_MESSAGE_A')} ${supportedPicBedList[name].configOptions[key].description}`)
ElMessage.error(
`${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_MESSAGE_A')} ${supportedPicBedList[name].configOptions[key].description}`
)
return
}
}
@@ -374,11 +310,15 @@ async function handleConfigChange (name: string) {
ElMessage.error($T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_ALIAS_MESSAGE'))
return
}
if (key === 'itemsPerPage' && configResult[resultKey] !== undefined && (configResult[resultKey] < 20 || configResult[resultKey] > 1000)) {
if (
key === 'itemsPerPage' &&
configResult[resultKey] !== undefined &&
(configResult[resultKey] < 20 || configResult[resultKey] > 1000)
) {
ElMessage.error($T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_ITEMS_PER_PAGE_MESSAGE'))
return
}
if ((key === 'customUrl') && configResult[resultKey] !== undefined && configResult[resultKey] !== '') {
if (key === 'customUrl' && configResult[resultKey] !== undefined && configResult[resultKey] !== '') {
if (name !== 'upyun') {
if (!/^https?:\/\//.test(configResult[resultKey])) {
ElMessage.error($T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_CUSTOM_URL_MESSAGE'))
@@ -414,7 +354,12 @@ async function handleConfigChange (name: string) {
[bucketName[i]]: {
baseDir: baseDir && baseDir[i] ? baseDir[i] : '/',
area: area && area[i] ? area[i] : '',
customUrl: customUrl && customUrl[i] ? /^https?:\/\//.test(customUrl[i]) ? customUrl[i] : 'http://' + customUrl[i] : '',
customUrl:
customUrl && customUrl[i]
? /^https?:\/\//.test(customUrl[i])
? customUrl[i]
: 'http://' + customUrl[i]
: '',
operator: operator && operator[i] ? operator[i] : '',
password: password && password[i] ? password[i] : ''
}
@@ -431,33 +376,29 @@ async function handleConfigChange (name: string) {
dataForTable.length = 0
getDataForTable()
if (aliasList.includes(resultMap.alias)) {
ElNotification(
{
title: $T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_NAME'),
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE')}${resultMap.alias}`,
type: 'warning',
duration: 500,
customClass: 'notification',
offset: 100
}
)
ElNotification({
title: $T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_NAME'),
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE')}${resultMap.alias}`,
type: 'warning',
duration: 500,
customClass: 'notification',
offset: 100
})
} else {
ElNotification(
{
title: $T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_NAME'),
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_B')}${resultMap.alias}`,
type: 'success',
duration: 2000,
customClass: 'notification',
offset: 100
}
)
ElNotification({
title: $T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_NAME'),
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_B')}${resultMap.alias}`,
type: 'success',
duration: 2000,
customClass: 'notification',
offset: 100
})
}
}
const handleConfigReset = (name: string) => {
const keys = Object.keys(configResult).filter((key) => key.startsWith(name))
keys.forEach((key) => {
const keys = Object.keys(configResult).filter(key => key.startsWith(name))
keys.forEach(key => {
const optionKey = key.split('.')[1]
const configOption = supportedPicBedList[name]?.configOptions?.[optionKey]
@@ -468,11 +409,15 @@ const handleConfigReset = (name: string) => {
}
const handleConfigRemove = (name: string) => {
ElMessageBox.confirm($T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_TITLE'), $T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_TIP'), {
confirmButtonText: $T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_CONFIRM'),
cancelButtonText: $T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_CANCEL'),
type: 'warning'
}).then(async () => {
ElMessageBox.confirm(
$T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_TITLE'),
$T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_TIP'),
{
confirmButtonText: $T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_CONFIRM'),
cancelButtonText: $T('MANAGE_LOGIN_PAGE_PANE_DELETE_CONFIG_CANCEL'),
type: 'warning'
}
).then(async () => {
const commonNoticeConfig = {
title: $T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_NAME'),
duration: 2000,
@@ -481,25 +426,21 @@ const handleConfigRemove = (name: string) => {
}
try {
removeConfig('picBed', name)
ElNotification(
{
...commonNoticeConfig,
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_C')}${name}`,
type: 'success',
position: 'bottom-right'
}
)
ElNotification({
...commonNoticeConfig,
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_C')}${name}`,
type: 'success',
position: 'bottom-right'
})
manageStore.refreshConfig()
getAllConfigAliasArray()
} catch (error) {
ElNotification(
{
...commonNoticeConfig,
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_D')}${name}${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_E')}`,
type: 'error',
position: 'bottom-right'
}
)
ElNotification({
...commonNoticeConfig,
message: `${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_D')}${name}${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_NOTICE_MESSAGE_E')}`,
type: 'error',
position: 'bottom-right'
})
}
})
}
@@ -519,7 +460,7 @@ const getAllConfigAliasArray = async () => {
})
}
const handleCellClick = (row:any, column:any) => {
const handleCellClick = (row: any, column: any) => {
navigator.clipboard.writeText(row[column.property])
ElMessage.success(`${$T('MANAGE_LOGIN_PAGE_PANE_CONFIG_CHANGE_COPY_SUCCESS')}${row[column.property]}`)
}
@@ -542,7 +483,7 @@ const handleConfigClick = async (item: any) => {
})
}
function handleConfigImport (alias: string) {
function handleConfigImport(alias: string) {
const selectedConfig = existingConfiguration[alias]
if (!selectedConfig) return
@@ -553,20 +494,36 @@ function handleConfigImport (alias: string) {
})
}
async function getCurrentConfigList () {
async function getCurrentConfigList() {
await manageStore.refreshConfig()
const configList = await getPicBedsConfig<any>('uploader') ?? {}
const pbList = ['aliyun', 'aws-s3', 'aws-s3-plist', 'github', 'imgur', 'local', 'qiniu', 'sftpplist', 'smms', 'tcyun', 'upyun', 'webdavplist']
const configList = (await getPicBedsConfig<any>('uploader')) ?? {}
const pbList = [
'aliyun',
'aws-s3',
'aws-s3-plist',
'github',
'imgur',
'local',
'qiniu',
'sftpplist',
'smms',
'tcyun',
'upyun',
'webdavplist'
]
const filteredConfigList = pbList.flatMap((pb) => {
const filteredConfigList = pbList.flatMap(pb => {
const config = configList[pb]
return config?.configList?.length ? config.configList.map((item: any) => ({ ...item, type: pb })) : []
})
const autoImport = await getPicBedsConfig<boolean>('settings.autoImport') || false
const autoImport = (await getPicBedsConfig<boolean>('settings.autoImport')) || false
if (autoImport) {
const autoImportPicBed = initArray(await getPicBedsConfig<string | string[]>('settings.autoImportPicBed') || '', [])
await Promise.all(filteredConfigList.flatMap((config) => transUpToManage(config, config.type, autoImportPicBed)))
const autoImportPicBed = initArray(
(await getPicBedsConfig<string | string[]>('settings.autoImportPicBed')) || '',
[]
)
await Promise.all(filteredConfigList.flatMap(config => transUpToManage(config, config.type, autoImportPicBed)))
if (Object.keys(importedNewConfig).length > 0) {
const oldConfig = await getConfig<any>('picBed')
const newConfig = { ...oldConfig, ...importedNewConfig }
@@ -578,25 +535,27 @@ async function getCurrentConfigList () {
await getAllConfigAliasArray()
}
function isImported (alias: string) {
return Object.values(allConfigAliasMap).some((item) => item.alias === alias)
function isImported(alias: string) {
return Object.values(allConfigAliasMap).some(item => item.alias === alias)
}
function initArray (arrayT: string | string[], defaultValue: string[]) {
function initArray(arrayT: string | string[], defaultValue: string[]) {
if (!Array.isArray(arrayT)) {
arrayT = arrayT ? [arrayT] : defaultValue
}
return arrayT
}
async function transUpToManage (config: IUploaderConfigListItem, picBedName: string, autoImportPicBed: string[]) {
const alias = `${picBedName === 'webdavplist'
? 'webdav'
: picBedName === 'sftpplist'
? 'sftp'
: picBedName === 'aws-s3' || picBedName === 'aws-s3-plist'
? 's3plist'
: picBedName}-${config._configName ?? 'Default'}-imp`
async function transUpToManage(config: IUploaderConfigListItem, picBedName: string, autoImportPicBed: string[]) {
const alias = `${
picBedName === 'webdavplist'
? 'webdav'
: picBedName === 'sftpplist'
? 'sftp'
: picBedName === 'aws-s3' || picBedName === 'aws-s3-plist'
? 's3plist'
: picBedName
}-${config._configName ?? 'Default'}-imp`
if (!autoImportPicBed.includes(picBedName) || isImported(alias)) return
const commonConfig = {
alias,
@@ -622,13 +581,15 @@ async function transUpToManage (config: IUploaderConfigListItem, picBedName: str
baseDir: '/',
itemsPerPage: 50,
isAutoCustomUrl: !config.customUrl,
transformedConfig: JSON.stringify(config.customUrl
? {
[config.bucket]: {
customUrl: config.customUrl
}
}
: {})
transformedConfig: JSON.stringify(
config.customUrl
? {
[config.bucket]: {
customUrl: config.customUrl
}
}
: {}
)
})
break
case 'qiniu':
@@ -654,13 +615,15 @@ async function transUpToManage (config: IUploaderConfigListItem, picBedName: str
baseDir: '/',
appId: config.appId,
isAutoCustomUrl: !config.customUrl,
transformedConfig: JSON.stringify(config.customUrl
? {
[config.bucket]: {
customUrl: config.customUrl
}
}
: {}),
transformedConfig: JSON.stringify(
config.customUrl
? {
[config.bucket]: {
customUrl: config.customUrl
}
}
: {}
),
itemsPerPage: 50
})
break
@@ -795,10 +758,10 @@ async function transUpToManage (config: IUploaderConfigListItem, picBedName: str
transformedConfig: JSON.stringify(
config.urlPrefix
? {
[config.bucketName]: {
customUrl: config.urlPrefix
[config.bucketName]: {
customUrl: config.urlPrefix
}
}
}
: {}
)
})
@@ -822,10 +785,9 @@ async function transUpToManage (config: IUploaderConfigListItem, picBedName: str
onMounted(() => {
getCurrentConfigList()
})
</script>
<style lang='stylus'>
<style lang="stylus">
.layout
background-color #fff
position absolute

View File

@@ -2,25 +2,16 @@
<div class="layout">
<div class="layout__menu">
<div class="layout__menu__button">
<span
class="layout__menu__button__item"
@click="openPicBedUrl"
>
<span class="layout__menu__button__item" @click="openPicBedUrl">
<img
:src="require(`./assets/${currentPagePicBedConfig.picBedName}.webp`)"
class="layout__menu__button__item__icon"
>
/>
{{ supportedPicBedList[currentPagePicBedConfig.picBedName].name }}
</span>
</div>
<el-divider
content-position="left"
class="layout__menu__button__divider"
border-style="none"
>
<span
style="font-size: 14px;color: #909399;"
>
<el-divider content-position="left" class="layout__menu__button__divider" border-style="none">
<span style="font-size: 14px; color: #909399">
{{ menuTitleMap[currentPicBedName] }}
<el-tooltip
v-if="showNewIconList.includes(currentPicBedName)"
@@ -34,7 +25,7 @@
<el-icon
class="layout__menu__button__divider__icon"
color="red"
style="top: 2px;"
style="top: 2px"
@click="openNewBucketDrawer()"
>
<CirclePlus />
@@ -47,24 +38,22 @@
v-loading="isLoadingBucketList"
class="layout__menu__list"
:default-active="getCurrentActiveBucket"
style="width: 120px;"
style="width: 120px"
active-text-color="#409EFF"
@select="handleSelectMenu"
>
<el-menu-item
v-for="item of bucketNameList"
:key="item"
:index="item"
>
<el-menu-item v-for="item of bucketNameList" :key="item" :index="item">
<span
class="layout__menu__list__item"
:style="{ color: item === currentSelectedBucket ? '#409EFF' : '#606266'}"
:style="{
color: item === currentSelectedBucket ? '#409EFF' : '#606266'
}"
>
<el-icon
v-if="currentSelectedBucket === item && currentPicBedName !== 'github'"
class="layout__menu__list__item__icon"
color="#409EFF"
style="top: 2px;"
style="top: 2px"
>
<FolderOpened />
</el-icon>
@@ -72,63 +61,42 @@
v-else-if="currentPicBedName !== 'github'"
class="layout__menu__list__item__icon"
color="#606266"
style="top: 2px;"
style="top: 2px"
>
<Folder />
</el-icon>
{{ currentPicBedName === 'tcyun' ? item.slice(0, item.length - 11)
: currentPicBedName === 'github'? item.length > 10 ? `${item.slice(0, 5)}..${item.slice(-5)}` : item
: item }}
{{
currentPicBedName === 'tcyun'
? item.slice(0, item.length - 11)
: currentPicBedName === 'github'
? item.length > 10
? `${item.slice(0, 5)}..${item.slice(-5)}`
: item
: item
}}
</span>
</el-menu-item>
</el-menu>
<el-menu
class="layout__menu__setting"
style="width: 120px;"
>
<el-menu-item
index="changePicBed"
style="height: 40px;"
@click="switchPicBed('main')"
>
<span
class="layout__menu__setting__item"
>
<el-icon
class="layout__menu__setting__item__icon"
>
<el-menu class="layout__menu__setting" style="width: 120px">
<el-menu-item index="changePicBed" style="height: 40px" @click="switchPicBed('main')">
<span class="layout__menu__setting__item">
<el-icon class="layout__menu__setting__item__icon">
<HomeFilled />
</el-icon>
{{ $T('MANAGE_MAIN_PAGE_BACK_TO_HOME') }}
</span>
</el-menu-item>
<el-menu-item
index="changePicBed"
style="height: 40px;"
@click="changePicBed"
>
<span
class="layout__menu__setting__item"
>
<el-icon
class="layout__menu__setting__item__icon"
>
<el-menu-item index="changePicBed" style="height: 40px" @click="changePicBed">
<span class="layout__menu__setting__item">
<el-icon class="layout__menu__setting__item__icon">
<Switch />
</el-icon>
{{ $T('MANAGE_MAIN_PAGE_SWITCH_PICBED') }}
</span>
</el-menu-item>
<el-menu-item
index="bucketPageSetting"
style="height: 40px;"
@click="openBucketPageSetting"
>
<span
class="layout__menu__setting__item"
>
<el-icon
class="layout__menu__setting__item__icon"
>
<el-menu-item index="bucketPageSetting" style="height: 40px" @click="openBucketPageSetting">
<span class="layout__menu__setting__item">
<el-icon class="layout__menu__setting__item__icon">
<Tools />
</el-icon>
{{ $T('MANAGE_MAIN_PAGE_SETTING') }}
@@ -136,70 +104,39 @@
</el-menu-item>
</el-menu>
</div>
<div
class="layout__content"
style="height: 100%;background-color: transparent;flex: 1;width: 0;"
>
<div class="layout__content" style="height: 100%; background-color: transparent; flex: 1; width: 0">
<router-view />
</div>
<el-dialog
v-model="picBedSwitchDialogVisible"
top="30vh"
append-to-body
>
<el-dialog v-model="picBedSwitchDialogVisible" top="30vh" append-to-body>
<div
class="choice-cos"
style="display: flex;flex-direction: row;flex-wrap: wrap;justify-content: space-around;"
style="display: flex; flex-direction: row; flex-wrap: wrap; justify-content: space-around"
>
<el-card
shadow="hover"
>
<div
style="text-align: center;display: flex;flex-direction: column;"
@click="switchPicBed('main')"
>
<el-icon
color="red"
size="25px"
style="margin: 0 auto;"
>
<el-card shadow="hover">
<div style="text-align: center; display: flex; flex-direction: column" @click="switchPicBed('main')">
<el-icon color="red" size="25px" style="margin: 0 auto">
<ChromeFilled />
</el-icon>
<span
style="font-size: 13px;margin-top: 5px;color: red;"
>
<span style="font-size: 13px; margin-top: 5px; color: red">
{{ $T('MANAGE_MAIN_PAGE_BACK_TO_HOME') }}
</span>
</div>
</el-card>
<el-card
v-for="item in allPicBedConfigure"
:key="item"
shadow="hover"
>
<div
style="text-align: center;display: flex;flex-direction: column;"
@click="switchPicBed(item.alias)"
>
<el-card v-for="item in allPicBedConfigure" :key="item" shadow="hover">
<div style="text-align: center; display: flex; flex-direction: column" @click="switchPicBed(item.alias)">
<el-image
:src="require(`./assets/${item.picBedName}.webp`)"
class="layout__addNewBucket__icon"
style="width: 25px;height: 25px;margin: 0 auto;"
style="width: 25px; height: 25px; margin: 0 auto"
/>
<span
style="font-size: 13px;margin-top: 5px;color: cornflowerblue;"
>
<span style="font-size: 13px; margin-top: 5px; color: cornflowerblue">
{{ item.alias }}
</span>
</div>
</el-card>
</div>
</el-dialog>
<el-drawer
v-model="nweBucketDrawerVisible"
class="layout__addNewBucket"
append-to-body
>
<el-drawer v-model="nweBucketDrawerVisible" class="layout__addNewBucket" append-to-body>
<el-form
label-position="top"
require-asterisk-position="right"
@@ -208,18 +145,14 @@
:model="newBucketConfigResult"
:rules="rules"
>
<div
style="position: relative;height: 10vh;width: 100%;"
>
<div style="position: relative; height: 10vh; width: 100%">
<el-image
:src="require(`./assets/${currentPicBedName}.webp`)"
class="layout__addNewBucket__icon"
style="position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);"
style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)"
/>
</div>
<el-divider
border-style="none"
/>
<el-divider border-style="none" />
<el-form-item
v-for="option in newBucketConfig[currentPicBedName].options"
:key="option"
@@ -227,13 +160,19 @@
:label="newBucketConfig[currentPicBedName].configOptions[option].description"
>
<el-input
v-if="newBucketConfig[currentPicBedName].configOptions[option].component === 'input' && currentPicBedName !== 'tcyun'"
v-model.trim="newBucketConfigResult[currentPicBedName+'.'+option]"
v-if="
newBucketConfig[currentPicBedName].configOptions[option].component === 'input' &&
currentPicBedName !== 'tcyun'
"
v-model.trim="newBucketConfigResult[currentPicBedName + '.' + option]"
:placeholder="newBucketConfig[currentPicBedName].configOptions[option].placeholder"
/>
<el-input
v-if="currentPicBedName === 'tcyun' && newBucketConfig[currentPicBedName].configOptions[option].component === 'input'"
v-model.trim="newBucketConfigResult[currentPicBedName+'.'+option]"
v-if="
currentPicBedName === 'tcyun' &&
newBucketConfig[currentPicBedName].configOptions[option].component === 'input'
"
v-model.trim="newBucketConfigResult[currentPicBedName + '.' + option]"
:placeholder="newBucketConfig[currentPicBedName].configOptions[option].placeholder"
>
<template #append>
@@ -242,7 +181,7 @@
</el-input>
<el-select
v-if="newBucketConfig[currentPicBedName].configOptions[option].component === 'select'"
v-model="newBucketConfigResult[currentPicBedName+'.'+option]"
v-model="newBucketConfigResult[currentPicBedName + '.' + option]"
size="large"
:persistent="false"
teleported
@@ -256,18 +195,16 @@
</el-select>
<el-switch
v-if="newBucketConfig[currentPicBedName].configOptions[option].component === 'switch'"
v-model="newBucketConfigResult[currentPicBedName+'.'+option]"
v-model="newBucketConfigResult[currentPicBedName + '.' + option]"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
<div
style="position: relative;height: 10vh;width: 100%;z-index: 1;"
>
<div style="position: relative; height: 10vh; width: 100%; z-index: 1">
<el-button
:icon="SuccessFilled"
type="primary"
style="position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);"
style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)"
@click="createNewBucket(currentPicBedName)"
>
{{ $T('MANAGE_MAIN_PAGE_SUBMIT') }}
@@ -281,7 +218,16 @@
<script lang="ts" setup>
import { shell } from 'electron'
import { ElNotification } from 'element-plus'
import { CirclePlus, SuccessFilled, Folder, Switch, Tools, ChromeFilled, HomeFilled, FolderOpened } from '@element-plus/icons-vue'
import {
CirclePlus,
SuccessFilled,
Folder,
Switch,
Tools,
ChromeFilled,
HomeFilled,
FolderOpened
} from '@element-plus/icons-vue'
import path from 'path'
import { ref, reactive, computed, onBeforeMount, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
@@ -312,7 +258,7 @@ const isLoadingBucketList = ref(false)
const nweBucketDrawerVisible = ref(false)
const picBedSwitchDialogVisible = ref(false)
watch(route, async (newRoute) => {
watch(route, async newRoute => {
if (newRoute.fullPath.split('?')[0] === '/main-page/manage-main-page') {
currentAlias.value = newRoute.query.alias as string
currentPicBedName.value = newRoute.query.picBedName as string
@@ -322,9 +268,9 @@ watch(route, async (newRoute) => {
}
})
const getCurrentActiveBucket = computed(() => bucketNameList.value.length === 0 ? '' : bucketNameList.value[0])
const getCurrentActiveBucket = computed(() => (bucketNameList.value.length === 0 ? '' : bucketNameList.value[0]))
const urlMap : IStringKeyMap = {
const urlMap: IStringKeyMap = {
aliyun: 'https://oss.console.aliyun.com',
github: 'https://github.com',
imgur: 'https://imgur.com',
@@ -344,7 +290,7 @@ const bucketT = $T('MANAGE_MAIN_PAGE_BUCKET')
const galleryT = $T('MANAGE_MAIN_PAGE_GALLERY')
const repositoryT = $T('MANAGE_MAIN_PAGE_REPOSITORY')
const menuTitleMap:IStringKeyMap = {
const menuTitleMap: IStringKeyMap = {
aliyun: bucketT,
qiniu: bucketT,
tcyun: bucketT,
@@ -362,7 +308,7 @@ const rules = ruleMap(newBucketConfig)
const openPicBedUrl = () => shell.openExternal(urlMap[currentPagePicBedConfig.picBedName])
function ruleMap (options: IStringKeyMap) {
function ruleMap(options: IStringKeyMap) {
return Object.keys(options).reduce((result, key) => {
options[key].options.forEach((option: string) => {
const keyName = `${key}.${option}`
@@ -378,20 +324,23 @@ function ruleMap (options: IStringKeyMap) {
}, {} as IStringKeyMap)
}
function openNewBucketDrawer () {
function openNewBucketDrawer() {
nweBucketDrawerVisible.value = true
}
function createNewBucket (picBedName: string) {
function createNewBucket(picBedName: string) {
const configOptions = newBucketConfig[picBedName].configOptions
const resultMap: IStringKeyMap = Object.keys(configOptions).reduce((result, key) => {
const resultKey = `${picBedName}.${key}`
const defaultValue = configOptions[key].default
const resultValue = newBucketConfigResult[resultKey]
result[key] = resultValue === '' && defaultValue !== undefined
? defaultValue
: resultValue === undefined ? defaultValue ?? '' : resultValue
result[key] =
resultValue === '' && defaultValue !== undefined
? defaultValue
: resultValue === undefined
? defaultValue ?? ''
: resultValue
return result
}, {} as IStringKeyMap)
@@ -420,7 +369,7 @@ function createNewBucket (picBedName: string) {
})
}
async function getBucketList () {
async function getBucketList() {
bucketList.value = {}
bucketNameList.value = []
isLoadingBucketList.value = true
@@ -436,12 +385,17 @@ async function getBucketList () {
}
}
function transPathToUnix (filePath: string | undefined) {
function transPathToUnix(filePath: string | undefined) {
if (!filePath) return ''
return process.platform === 'win32' ? filePath.split(path.sep).join(path.posix.sep).replace(/^\/+|\/+$/g, '') : filePath.replace(/^\/+|\/+$/g, '')
return process.platform === 'win32'
? filePath
.split(path.sep)
.join(path.posix.sep)
.replace(/^\/+|\/+$/g, '')
: filePath.replace(/^\/+|\/+$/g, '')
}
function handleSelectMenu (bucketName: string) {
function handleSelectMenu(bucketName: string) {
const currentPicBedConfig = manageStore.config.picBed[currentAlias.value]
const transformedConfig = JSON.parse(currentPicBedConfig.transformedConfig ?? '{}')
@@ -474,14 +428,16 @@ function handleSelectMenu (bucketName: string) {
})
}
function switchPicBed (picBedAlias:string) {
function switchPicBed(picBedAlias: string) {
if (picBedAlias === 'main') {
router.push({
path: '/main-page/manage-login-page'
})
return
}
if (route.fullPath.startsWith('/main-page/manage-main-page/manage-bucket-page') || route.fullPath.startsWith('/main-page/manage-main-page/manage-setting-page')
if (
route.fullPath.startsWith('/main-page/manage-main-page/manage-bucket-page') ||
route.fullPath.startsWith('/main-page/manage-main-page/manage-setting-page')
) {
picBedSwitchDialogVisible.value = false
router.push({
@@ -503,11 +459,11 @@ function switchPicBed (picBedAlias:string) {
}
}
function changePicBed () {
function changePicBed() {
picBedSwitchDialogVisible.value = true
}
function openBucketPageSetting () {
function openBucketPageSetting() {
router.push({
path: '/main-page/manage-main-page/manage-setting-page'
})

View File

@@ -1,42 +1,19 @@
<template>
<div id="manage-setting">
<el-row
class="view-title"
align="middle"
justify="center"
style="font-size: 20px;color: black;"
>
<el-row class="view-title" align="middle" justify="center" style="font-size: 20px; color: black">
{{ $T('MANAGE_SETTING_TITLE') }}
</el-row>
<el-row
class="setting-list"
>
<el-col
:span="20"
:offset="2"
>
<el-row
style="width: 100%;"
>
<el-form
label-position="left"
label-width="50%"
size="default"
style="position: relative;width: 100%;"
>
<el-row class="setting-list">
<el-col :span="20" :offset="2">
<el-row style="width: 100%">
<el-form label-position="left" label-width="50%" size="default" style="position: relative; width: 100%">
<el-form-item>
<template #label>
<span
style="position:absolute;left: 0;"
>
<span style="position: absolute; left: 0">
<span>{{ $T('MANAGE_SETTING_CLEAR_CACHE_TITLE') }} </span>
<span
style="color: #ff4949;"
>{{ formatFileSize(dbSize) === ''? 0 : formatFileSize(dbSize) }} </span>
<span style="color: #ff4949">{{ formatFileSize(dbSize) === '' ? 0 : formatFileSize(dbSize) }} </span>
<span> &nbsp;{{ $T('MANAGE_SETTING_CLEAR_CACHE_FREE_TITLE') }} </span>
<span
style="color: #ff4949;"
>{{ dbSizeAvailableRate }} %</span>
<span style="color: #ff4949">{{ dbSizeAvailableRate }} %</span>
<el-tooltip
effect="dark"
:content="$T('MANAGE_SETTING_CLEAR_CACHE_TIPS')"
@@ -60,11 +37,7 @@
@confirm="handleClearDb"
>
<template #reference>
<el-button
type="primary"
plain
style="position:absolute;right: 0;"
>
<el-button type="primary" plain style="position: absolute; right: 0">
{{ $T('MANAGE_SETTING_CLEAR_CACHE_BUTTON') }}
</el-button>
</template>
@@ -82,7 +55,7 @@
/>
<el-link
v-if="form.customRename"
style="margin-top: 10px;margin-bottom: 10px;color: #409eff;"
style="margin-top: 10px; margin-bottom: 10px; color: #409eff"
:underline="false"
>
{{ $T('MANAGE_SETTING_CUSTOM_PATTERN_TITLE') }}
@@ -91,25 +64,25 @@
v-if="form.customRename"
v-model="form.customRenameFormat"
:placeholder="$T('MANAGE_SETTING_CUSTOM_PATTERN_TIPS')"
style="width: 100%;"
style="width: 100%"
/>
<el-table
v-if="form.customRename"
:data="customRenameFormatTable"
style="width: 100%;margin-top: 10px;margin-left: 10%;"
:header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}"
style="width: 100%; margin-top: 10px; margin-left: 10%"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
@cell-click="handleCellClick"
>
<el-table-column
v-for="(prop) in ['placeholder', 'description', 'placeholderB', 'descriptionB']"
v-for="prop in ['placeholder', 'description', 'placeholderB', 'descriptionB']"
:key="prop"
:prop="prop"
:label="$T('MANAGE_SETTING_CUSTOM_PATTERN_TABLE_TITLE' as any)"
width="150"
/>
</el-table>
<br v-if="form.customRename">
<br v-if="form.customRename" />
<DynamicSwitch
v-for="item in switchFieldsSpecialList"
:key="item.configName"
@@ -120,9 +93,7 @@
/>
<el-form-item>
<template #label>
<span
style="position:absolute;left: 0;"
>
<span style="position: absolute; left: 0">
{{ $T('MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_TITLE') }}
<el-tooltip
effect="dark"
@@ -139,7 +110,7 @@
</template>
<el-input-number
v-model="form.maxDownloadFileCount"
style="position:absolute;right: 0;"
style="position: absolute; right: 0"
:placeholder="$T('MANAGE_SETTING_MAX_DOWNLOAD_FILE_SIZE_INPUT_TIPS')"
:min="1"
:max="9999"
@@ -148,9 +119,7 @@
</el-form-item>
<el-form-item>
<template #label>
<span
style="position:absolute;left: 0;"
>
<span style="position: absolute; left: 0">
{{ $T('MANAGE_SETTING_PRESIGNED_URL_EXPIRE_TITLE') }}
<el-tooltip
effect="dark"
@@ -167,33 +136,24 @@
</template>
<el-input-number
v-model="form.PreSignedExpire"
style="position:absolute;right: 0;"
style="position: absolute; right: 0"
:placeholder="$T('MANAGE_SETTING_PRESIGNED_URL_EXPIRE_TIPS')"
:min="1"
:step="1"
/>
</el-form-item>
<el-link
style="margin-top: 10px;margin-bottom: 10px;color: #409eff;"
:underline="false"
>
<el-link style="margin-top: 10px; margin-bottom: 10px; color: #409eff" :underline="false">
{{ $T('MANAGE_SETTING_CHOOSE_COPY_FORMAT_TITLE') }}
</el-link>
<br>
<el-radio-group
v-model="form.pasteFormat"
>
<el-radio
v-for="item in pasteFormatList"
:key="item"
:value="item"
>
<br />
<el-radio-group v-model="form.pasteFormat">
<el-radio v-for="item in pasteFormatList" :key="item" :value="item">
{{ $T(`MANAGE_SETTING_CHOOSE_COPY_FORMAT_${item.toUpperCase().replace(/-/g, '_')}` as any) }}
</el-radio>
</el-radio-group>
<el-link
v-if="form.pasteFormat === 'custom'"
style="margin-top: 10px;margin-bottom: 10px;color: #409eff;"
style="margin-top: 10px; margin-bottom: 10px; color: #409eff"
:underline="false"
>
{{ $T('MANAGE_SETTING_CUSTOM_COPY_FORMAT_TITLE') }}
@@ -202,13 +162,10 @@
v-if="form.pasteFormat === 'custom'"
v-model="form.customPasteFormat"
:placeholder="$T('MANAGE_SETTING_CUSTOM_COPY_FORMAT_TIPS')"
style="width: 100%;"
style="width: 100%"
/>
<div>
<el-link
style="margin-top: 10px;margin-bottom: 10px;color: #409eff;"
:underline="false"
>
<el-link style="margin-top: 10px; margin-bottom: 10px; color: #409eff" :underline="false">
{{ $T('MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_TITLE') }}
</el-link>
</div>
@@ -216,13 +173,10 @@
v-model="form.downloadDir"
disabled
:placeholder="$T('MANAGE_SETTING_CHOOSE_DOWNLOAD_FOLDER_TIPS')"
style="width: 100%;margin-top: 10px;"
style="width: 100%; margin-top: 10px"
>
<template #append>
<el-button
type="primary"
@click="handleDownloadDirClick"
>
<el-button type="primary" @click="handleDownloadDirClick">
<el-icon>
<Folder />
</el-icon>
@@ -231,9 +185,7 @@
</template>
</el-input>
</el-form>
<el-divider
border-style="none"
/>
<el-divider border-style="none" />
</el-row>
</el-col>
</el-row>
@@ -284,97 +236,128 @@ const dbSizeAvailableRate = ref('0')
const pasteFormatList = ['markdown', 'markdown-with-link', 'rawurl', 'html', 'bbcode', 'custom']
settingsKeys.forEach(key => {
watch(() => form.value[key], (newValue) => saveConfig({ [`settings.${key}`]: newValue }))
watch(
() => form.value[key],
newValue => saveConfig({ [`settings.${key}`]: newValue })
)
})
const switchFieldsList = ['isAutoRefresh', 'isShowThumbnail', 'isShowList', 'isForceCustomUrlHttps', 'isEncodeUrl', 'isUploadKeepDirStructure', 'isIgnoreCase', 'timestampRename', 'randomStringRename', 'customRename']
const switchFieldsList = [
'isAutoRefresh',
'isShowThumbnail',
'isShowList',
'isForceCustomUrlHttps',
'isEncodeUrl',
'isUploadKeepDirStructure',
'isIgnoreCase',
'timestampRename',
'randomStringRename',
'customRename'
]
const switchFieldsNoTipsList = ['isShowThumbnail', 'isShowList']
const switchFieldsHasActiveTextList = ['isShowList']
const switchFieldsConfigList = switchFieldsList.map((item) => ({
const switchFieldsConfigList = switchFieldsList.map(item => ({
configName: item,
segments: [{
text: $T(`MANAGE_SETTING_${item.toUpperCase()}_TITLE` as any),
style: 'color: black;'
}],
segments: [
{
text: $T(`MANAGE_SETTING_${item.toUpperCase()}_TITLE` as any),
style: 'color: black;'
}
],
tooltip: switchFieldsNoTipsList.includes(item) ? undefined : $T(`MANAGE_SETTING_${item.toUpperCase()}_TIPS` as any),
activeText: switchFieldsHasActiveTextList.includes(item) ? $T(`MANAGE_SETTING_${item.toUpperCase()}_ON` as any) : undefined,
inactiveText: switchFieldsHasActiveTextList.includes(item) ? $T(`MANAGE_SETTING_${item.toUpperCase()}_OFF` as any) : undefined
activeText: switchFieldsHasActiveTextList.includes(item)
? $T(`MANAGE_SETTING_${item.toUpperCase()}_ON` as any)
: undefined,
inactiveText: switchFieldsHasActiveTextList.includes(item)
? $T(`MANAGE_SETTING_${item.toUpperCase()}_OFF` as any)
: undefined
}))
const switchFieldsSpecialList = [{
configName: 'isDownloadFileKeepDirStructure',
segments: [{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A'),
style: 'color: black;'
}, {
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B'),
style: 'color: orange;'
}, {
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C'),
style: 'color: black;'
}],
tooltip: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS')
}, {
configName: 'isDownloadFolderKeepDirStructure',
segments: [{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A'),
style: 'color: black;'
const switchFieldsSpecialList = [
{
configName: 'isDownloadFileKeepDirStructure',
segments: [
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A'),
style: 'color: black;'
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_B'),
style: 'color: orange;'
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C'),
style: 'color: black;'
}
],
tooltip: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS')
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D'),
style: 'color: coral;'
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C'),
style: 'color: black;'
}],
tooltip: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS')
}]
configName: 'isDownloadFolderKeepDirStructure',
segments: [
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_A'),
style: 'color: black;'
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFOLDERKEEPDIRSTRUCTURE_TITLE_D'),
style: 'color: coral;'
},
{
text: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TITLE_C'),
style: 'color: black;'
}
],
tooltip: $T('MANAGE_SETTING_ISDOWNLOADFILEKEEPDIRSTRUCTURE_TIPS')
}
]
async function initData () {
const config = await getConfig() as IStringKeyMap
async function initData() {
const config = (await getConfig()) as IStringKeyMap
settingsKeys.forEach(key => {
form.value[key] = config.settings[key] ?? form.value[key]
})
}
async function handleDownloadDirClick () {
async function handleDownloadDirClick() {
const result = await invokeToMain(selectDownloadFolder)
if (result) {
form.value.downloadDir = result
}
}
const handleCellClick = (row:any, column:any) => {
const handleCellClick = (row: any, column: any) => {
navigator.clipboard.writeText(row[column.property])
ElMessage.success(`${$T('MANAGE_SETTING_COPY_MESSAGE')}${row[column.property]}`)
}
function handleClearDb () {
fileCacheDbInstance.delete().then(() => {
getIndexDbSize()
ElMessage.success($T('MANAGE_SETTING_CLEAR_CACHE_SUCCESS'))
}).catch(() => {
ElMessage.error($T('MANAGE_SETTING_CLEAR_CACHE_FAILED'))
})
function handleClearDb() {
fileCacheDbInstance
.delete()
.then(() => {
getIndexDbSize()
ElMessage.success($T('MANAGE_SETTING_CLEAR_CACHE_SUCCESS'))
})
.catch(() => {
ElMessage.error($T('MANAGE_SETTING_CLEAR_CACHE_FAILED'))
})
}
async function getIndexDbSize () {
async function getIndexDbSize() {
const size = (await navigator.storage.estimate()).usage ?? 0
const quota = (await navigator.storage.estimate()).quota ?? 0
dbSize.value = size
dbSizeAvailableRate.value = (100 - size / quota * 100).toFixed(2)
dbSizeAvailableRate.value = (100 - (size / quota) * 100).toFixed(2)
}
onBeforeMount(() => {
initData()
getIndexDbSize()
})
</script>
<style lang='stylus'>
<style lang="stylus">
#manage-setting
height 100%
overflow-y auto

View File

@@ -1,14 +1,14 @@
import Dexie, { Table } from 'dexie'
/*
* create a database for bucket file cache
*database name: bucketFileDb
*structure:
* - table: picBedName
* - key: alias-bucketName-prefix
* - value: from fullList
* - primaryKey: key
*/
* create a database for bucket file cache
*database name: bucketFileDb
*structure:
* - table: picBedName
* - key: alias-bucketName-prefix
* - value: from fullList
* - primaryKey: key
*/
export interface IFileCache {
key: string
@@ -31,9 +31,21 @@ export class FileCacheDb extends Dexie {
upyun: Table<IFileCache, string>
webdavplist: Table<IFileCache, string>
constructor () {
constructor() {
super('bucketFileDb')
const tableNames = ['aliyun', 'github', 'imgur', 'local', 'qiniu', 's3plist', 'sftp', 'smms', 'tcyun', 'upyun', 'webdavplist']
const tableNames = [
'aliyun',
'github',
'imgur',
'local',
'qiniu',
's3plist',
'sftp',
'smms',
'tcyun',
'upyun',
'webdavplist'
]
const tableNamesMap = tableNames.reduce((acc, cur) => {
acc[cur] = '&key, value'

View File

@@ -9,8 +9,8 @@ export const useManageStore = defineStore('manageConfig', {
}
},
actions: {
async refreshConfig () {
this.config = await getConfig() ?? {}
async refreshConfig() {
this.config = (await getConfig()) ?? {}
}
},
persist: true
@@ -25,23 +25,23 @@ export const useFileTransferStore = defineStore('fileTransfer', {
}
},
actions: {
refreshFileTransferList (newData: IStringKeyMap) {
refreshFileTransferList(newData: IStringKeyMap) {
this.fileTransferList = newData.fullList ?? []
this.success = newData.success
this.finished = newData.finished
},
resetFileTransferList () {
resetFileTransferList() {
this.fileTransferList = []
this.success = false
this.finished = false
},
getFileTransferList () {
getFileTransferList() {
return this.fileTransferList
},
isFinished () {
isFinished() {
return this.finished
},
isSuccess () {
isSuccess() {
return this.success
}
}
@@ -56,23 +56,23 @@ export const useDownloadFileTransferStore = defineStore('downloadFileTransfer',
}
},
actions: {
refreshDownloadFileTransferList (newData: IStringKeyMap) {
refreshDownloadFileTransferList(newData: IStringKeyMap) {
this.downloadFileTransferList = newData.fullList ?? []
this.success = newData.success
this.finished = newData.finished
},
resetDownloadFileTransferList () {
resetDownloadFileTransferList() {
this.downloadFileTransferList = []
this.success = false
this.finished = false
},
getDownloadFileTransferList () {
getDownloadFileTransferList() {
return this.downloadFileTransferList
},
isFinished () {
isFinished() {
return this.finished
},
isSuccess () {
isSuccess() {
return this.success
}
}

View File

@@ -7,32 +7,34 @@ import { getConfig } from '@/manage/utils/dataSender'
import { handleUrlEncode, safeSliceF, isNeedToShorten } from '#/utils/common'
export function randomStringGenerator (length: number): string {
export function randomStringGenerator(length: number): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
return Array.from({ length }).map(() => chars.charAt(Math.floor(Math.random() * chars.length))).join('')
return Array.from({ length })
.map(() => chars.charAt(Math.floor(Math.random() * chars.length)))
.join('')
}
export function renameFileNameWithTimestamp (oldName: string): string {
export function renameFileNameWithTimestamp(oldName: string): string {
return `${Math.floor(Date.now() / 1000)}${randomStringGenerator(5)}${path.extname(oldName)}`
}
export function renameFileNameWithRandomString (oldName: string, length: number = 5): string {
export function renameFileNameWithRandomString(oldName: string, length: number = 5): string {
return `${randomStringGenerator(length)}${path.extname(oldName)}`
}
function renameFormatHelper (num: number): string {
function renameFormatHelper(num: number): string {
return num.toString().length === 1 ? `0${num}` : num.toString()
}
function getMd5 (input: crypto.BinaryLike): string {
function getMd5(input: crypto.BinaryLike): string {
return crypto.createHash('md5').update(input).digest('hex')
}
export function renameFileNameWithCustomString (oldName: string, customFormat: string, affixFileName?: string): string {
export function renameFileNameWithCustomString(oldName: string, customFormat: string, affixFileName?: string): string {
const date = new Date()
const year = date.getFullYear().toString()
const fileBaseName = path.basename(oldName, path.extname(oldName))
const conversionMap : {[key: string]: () => string} = {
const conversionMap: { [key: string]: () => string } = {
'{Y}': () => year,
'{y}': () => year.slice(2),
'{m}': () => renameFormatHelper(date.getMonth() + 1),
@@ -43,17 +45,24 @@ export function renameFileNameWithCustomString (oldName: string, customFormat: s
'{ms}': () => date.getMilliseconds().toString().padStart(3, '0'),
'{md5}': () => getMd5(fileBaseName),
'{md5-16}': () => getMd5(fileBaseName).slice(0, 16),
'{filename}': () => affixFileName ? path.basename(affixFileName, path.extname(affixFileName)) : path.basename(oldName, path.extname(oldName)),
'{filename}': () =>
affixFileName
? path.basename(affixFileName, path.extname(affixFileName))
: path.basename(oldName, path.extname(oldName)),
'{uuid}': () => uuidv4().replace(/-/g, ''),
'{timestamp}': () => date.getTime().toString()
}
if (customFormat === undefined || (!Object.keys(conversionMap).some(item => customFormat.includes(item)) && !customFormat.includes('{str-'))) {
if (
customFormat === undefined ||
(!Object.keys(conversionMap).some(item => customFormat.includes(item)) && !customFormat.includes('{str-'))
) {
return oldName
}
const ext = path.extname(oldName)
let newName = Object.keys(conversionMap).reduce((acc, cur) => {
return acc.replace(new RegExp(cur, 'g'), conversionMap[cur]())
}, customFormat) + ext
let newName =
Object.keys(conversionMap).reduce((acc, cur) => {
return acc.replace(new RegExp(cur, 'g'), conversionMap[cur]())
}, customFormat) + ext
const strRegex = /{str-(\d+)}/gi
newName = newName.replace(strRegex, (_, group1) => {
const length = parseInt(group1, 10)
@@ -62,7 +71,10 @@ export function renameFileNameWithCustomString (oldName: string, customFormat: s
return newName
}
export function renameFile ({ timestampRename, randomStringRename, customRename, customRenameFormat }: IStringKeyMap, oldName = ''): string {
export function renameFile(
{ timestampRename, randomStringRename, customRename, customRenameFormat }: IStringKeyMap,
oldName = ''
): string {
switch (true) {
case timestampRename:
return renameFileNameWithTimestamp(oldName)
@@ -75,8 +87,8 @@ export function renameFile ({ timestampRename, randomStringRename, customRename,
}
}
export async function formatLink (url: string, fileName: string, type: string, format?: string) : Promise<string> {
const encodedUrl = await getConfig('settings.isEncodeUrl') ? handleUrlEncode(url) : url
export async function formatLink(url: string, fileName: string, type: string, format?: string): Promise<string> {
const encodedUrl = (await getConfig('settings.isEncodeUrl')) ? handleUrlEncode(url) : url
switch (type) {
case 'markdown':
return `![${fileName}](${encodedUrl})`
@@ -98,35 +110,38 @@ export async function formatLink (url: string, fileName: string, type: string, f
}
}
export function getFileIconPath (fileName: string) {
export function getFileIconPath(fileName: string) {
const ext = path.extname(fileName).slice(1).toLowerCase()
return availableIconList.includes(ext) ? `${ext}.webp` : 'unknown.webp'
}
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
export function formatFileSize (size: number) {
export function formatFileSize(size: number) {
if (size === 0) return ''
const index = Math.floor(Math.log2(size) / 10)
return `${(size / Math.pow(2, index * 10)).toFixed(2)} ${units[index]}`
}
export function formatFileName (fileName: string, length: number = 20) {
export function formatFileName(fileName: string, length: number = 20) {
let ext = path.extname(fileName)
ext = ext.length > 5 ? ext.slice(ext.length - 5) : ext
const name = path.basename(fileName, ext)
return isNeedToShorten(fileName, length) ? `${safeSliceF(name, length - 3 - ext.length)}...${ext}` : fileName
}
export function formObjToTableData (obj: any) {
export function formObjToTableData(obj: any) {
const exclude = [undefined, null, '', 'transformedConfig']
return Object.keys(obj).filter(key => !exclude.includes(obj[key])).map(key => ({
key,
value: typeof obj[key] === 'object' ? JSON.stringify(obj[key]) : obj[key]
})).sort((a, b) => a.key.localeCompare(b.key))
return Object.keys(obj)
.filter(key => !exclude.includes(obj[key]))
.map(key => ({
key,
value: typeof obj[key] === 'object' ? JSON.stringify(obj[key]) : obj[key]
}))
.sort((a, b) => a.key.localeCompare(b.key))
}
export function isValidUrl (str: string) {
export function isValidUrl(str: string) {
try {
return !!new URL(str)
} catch (e) {
@@ -145,7 +160,7 @@ export const svg = `
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
`
export function customStrMatch (str: string, pattern: string) : boolean {
export function customStrMatch(str: string, pattern: string): boolean {
if (!str || !pattern) return false
try {
const reg = new RegExp(pattern, 'ug')
@@ -156,7 +171,7 @@ export function customStrMatch (str: string, pattern: string) : boolean {
}
}
export function customStrReplace (str: string, pattern: string, replacement: string) : string {
export function customStrReplace(str: string, pattern: string, replacement: string): string {
if (!str || !pattern) return str
replacement = replacement || ''
let result = str

View File

@@ -334,7 +334,16 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_ALIYUN_EXPLAIN'),
options: ['alias', 'accessKeyId', 'accessKeySecret', 'bucketName', 'baseDir', 'isAutoCustomUrl', 'paging', 'itemsPerPage'],
options: [
'alias',
'accessKeyId',
'accessKeySecret',
'bucketName',
'baseDir',
'isAutoCustomUrl',
'paging',
'itemsPerPage'
],
refLink: 'https://piclist.cn/manage.html#%E9%98%BF%E9%87%8C%E4%BA%91oss',
referenceText: $T('MANAGE_CONSTANT_ALIYUN_REFER_TEXT')
},
@@ -412,7 +421,17 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_TENCENT_EXPLAIN'),
options: ['alias', 'secretId', 'secretKey', 'appId', 'bucketName', 'baseDir', 'isAutoCustomUrl', 'paging', 'itemsPerPage'],
options: [
'alias',
'secretId',
'secretKey',
'appId',
'bucketName',
'baseDir',
'isAutoCustomUrl',
'paging',
'itemsPerPage'
],
refLink: 'https://piclist.cn/manage.html#%E8%85%BE%E8%AE%AF%E4%BA%91',
referenceText: $T('MANAGE_CONSTANT_TENCENT_REFER_TEXT')
},
@@ -525,7 +544,18 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_UPYUN_EXPLAIN'),
options: ['alias', 'bucketName', 'operator', 'password', 'baseDir', 'customUrl', 'paging', 'itemsPerPage', 'antiLeechToken', 'expireTime'],
options: [
'alias',
'bucketName',
'operator',
'password',
'baseDir',
'customUrl',
'paging',
'itemsPerPage',
'antiLeechToken',
'expireTime'
],
refLink: 'https://piclist.cn/manage.html#%E5%8F%88%E6%8B%8D%E4%BA%91',
referenceText: $T('MANAGE_CONSTANT_UPYUN_REFER_TEXT')
},
@@ -680,7 +710,21 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_S3_EXPLAIN'),
options: ['alias', 'accessKeyId', 'secretAccessKey', 'endpoint', 'sslEnabled', 's3ForcePathStyle', 'proxy', 'aclForUpload', 'bucketName', 'baseDir', 'dogeCloudSupport', 'paging', 'itemsPerPage'],
options: [
'alias',
'accessKeyId',
'secretAccessKey',
'endpoint',
'sslEnabled',
's3ForcePathStyle',
'proxy',
'aclForUpload',
'bucketName',
'baseDir',
'dogeCloudSupport',
'paging',
'itemsPerPage'
],
refLink: 'https://piclist.cn/manage.html#s3',
referenceText: $T('MANAGE_CONSTANT_S3_REFER_TEXT')
},
@@ -792,7 +836,19 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_WEBDAV_EXPLAIN'),
options: ['alias', 'endpoint', 'username', 'password', 'bucketName', 'baseDir', 'customUrl', 'webPath', 'proxy', 'sslEnabled', 'authType'],
options: [
'alias',
'endpoint',
'username',
'password',
'bucketName',
'baseDir',
'customUrl',
'webPath',
'proxy',
'sslEnabled',
'authType'
],
refLink: 'https://piclist.cn/manage.html#webdav',
referenceText: $T('MANAGE_CONSTANT_WEBDAV_REFER_TEXT')
},
@@ -1003,7 +1059,21 @@ export const supportedPicBedList: IStringKeyMap = {
}
},
explain: $T('MANAGE_CONSTANT_SFTP_EXPLAIN'),
options: ['alias', 'host', 'port', 'username', 'password', 'privateKey', 'passphrase', 'fileMode', 'dirMode', 'baseDir', 'customUrl', 'bucketName', 'webPath'],
options: [
'alias',
'host',
'port',
'username',
'password',
'privateKey',
'passphrase',
'fileMode',
'dirMode',
'baseDir',
'customUrl',
'bucketName',
'webPath'
],
refLink: 'https://piclist.cn/manage.html#sftp',
referenceText: $T('MANAGE_CONSTANT_SFTP_REFER_TEXT')
}

View File

@@ -2,17 +2,21 @@ import { ipcRenderer } from 'electron'
import { getRawData } from '@/utils/common'
import { PICLIST_MANAGE_GET_CONFIG, PICLIST_MANAGE_SAVE_CONFIG, PICLIST_MANAGE_REMOVE_CONFIG } from '~/manage/events/constants'
import {
PICLIST_MANAGE_GET_CONFIG,
PICLIST_MANAGE_SAVE_CONFIG,
PICLIST_MANAGE_REMOVE_CONFIG
} from '~/manage/events/constants'
export function saveConfig (config: IObj | string, value?: any) {
export function saveConfig(config: IObj | string, value?: any) {
const configObj = typeof config === 'string' ? { [config]: value } : getRawData(config)
ipcRenderer.send(PICLIST_MANAGE_SAVE_CONFIG, configObj)
}
export async function getConfig<T> (key?: string): Promise<T | undefined> {
export async function getConfig<T>(key?: string): Promise<T | undefined> {
return await ipcRenderer.invoke(PICLIST_MANAGE_GET_CONFIG, key)
}
export function removeConfig (key: string, propName: string) {
export function removeConfig(key: string, propName: string) {
ipcRenderer.send(PICLIST_MANAGE_REMOVE_CONFIG, key, propName)
}

View File

@@ -5,11 +5,17 @@ const AUTH_KEY_VALUE_RE = /(\w+)=["']?([^'"]{1,10000})["']?/
let NC = 0
const NC_PAD = '00000000'
function md5 (text: crypto.BinaryLike) {
function md5(text: crypto.BinaryLike) {
return crypto.createHash('md5').update(text).digest('hex')
}
export function digestAuthHeader (method: string, uri: string, wwwAuthenticate: string, username: string, password: string) {
export function digestAuthHeader(
method: string,
uri: string,
wwwAuthenticate: string,
username: string,
password: string
) {
const parts = wwwAuthenticate.split(',')
const opts = {} as IStringKeyMap
for (let i = 0; i < parts.length; i++) {
@@ -61,11 +67,9 @@ export function digestAuthHeader (method: string, uri: string, wwwAuthenticate:
return authstring
}
export async function getAuthHeader (method: string, host: string, uri: string, username: string, password: string) {
export async function getAuthHeader(method: string, host: string, uri: string, username: string, password: string) {
try {
await axios.get(
`${host}${uri}`
)
await axios.get(`${host}${uri}`)
} catch (error: any) {
if (error.response.status === 401 && error.response.headers['www-authenticate']) {
return digestAuthHeader(method, uri, error.response.headers['www-authenticate'], username, password)

View File

@@ -1,7 +1,7 @@
import { AliyunAreaCodeName, QiniuAreaCodeName, TencentAreaCodeName } from '~/manage/utils/constants'
import { T as $T } from '@/i18n'
export const newBucketConfig:IStringKeyMap = {
export const newBucketConfig: IStringKeyMap = {
tcyun: {
name: $T('MANAGE_NEW_BUCKET_TCYUN_NAME'),
icon: 'tcyun',