mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-06-01 07:29:44 +08:00
🎨 Style(custom): format with prettier
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
id="app"
|
||||
:key="pageReloadCount"
|
||||
>
|
||||
<div id="app" :key="pageReloadCount">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
@@ -25,7 +22,6 @@ onBeforeMount(async () => {
|
||||
store?.setDefaultPicBed(config?.picBed?.uploader || config?.picBed?.current || 'smms')
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -35,18 +31,18 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
body,
|
||||
html
|
||||
padding 0
|
||||
margin 0
|
||||
height 100%
|
||||
font-family "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif
|
||||
#app
|
||||
height 100%
|
||||
user-select none
|
||||
overflow hidden
|
||||
.el-button-group
|
||||
width 100%
|
||||
.el-button
|
||||
width 50%
|
||||
body,
|
||||
html
|
||||
padding 0
|
||||
margin 0
|
||||
height 100%
|
||||
font-family "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif
|
||||
#app
|
||||
height 100%
|
||||
user-select none
|
||||
overflow hidden
|
||||
.el-button-group
|
||||
width 100%
|
||||
.el-button
|
||||
width 50%
|
||||
</style>
|
||||
|
||||
@@ -14,7 +14,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class AlistApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
const { version, url, uploadPath, token } = config
|
||||
|
||||
@@ -8,13 +8,11 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class AliyunApi {
|
||||
static #getKey (fileName: string, path?: string): string {
|
||||
return path && path !== '/'
|
||||
? `${path.replace(/^\/+|\/+$/, '')}/${fileName}`
|
||||
: fileName
|
||||
static #getKey(fileName: string, path?: string): string {
|
||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${fileName}` : fileName
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
const client = new OSS({ ...config, region: config.area })
|
||||
|
||||
@@ -36,7 +36,7 @@ const apiMap: IStringKeyMap = {
|
||||
}
|
||||
|
||||
export default class ALLApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const api = apiMap[configMap.type]
|
||||
return api ? await api.delete(configMap) : false
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import { deleteFailedLog } from '#/utils/deleteLog'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
export default class AwsS3Api {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return ipcRenderer
|
||||
? await triggerRPC(IRPCActionType.GALLERY_DELETE_AWS_S3_FILE, getRawData(configMap)) || false
|
||||
? (await triggerRPC(IRPCActionType.GALLERY_DELETE_AWS_S3_FILE, getRawData(configMap))) || false
|
||||
: await removeFileFromS3InMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
deleteFailedLog(configMap.fileName, 'AWS S3', error)
|
||||
|
||||
@@ -7,10 +7,10 @@ import { deleteFailedLog } from '#/utils/deleteLog'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
export default class AwsS3Api {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return ipcRenderer
|
||||
? await triggerRPC(IRPCActionType.GALLERY_DELETE_DOGE_FILE, getRawData(configMap)) || false
|
||||
? (await triggerRPC(IRPCActionType.GALLERY_DELETE_DOGE_FILE, getRawData(configMap))) || false
|
||||
: await removeFileFromDogeInMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
deleteFailedLog(configMap.fileName, 'DogeCloud', error)
|
||||
|
||||
@@ -9,21 +9,23 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class GithubApi {
|
||||
static #createOctokit (token: string) {
|
||||
static #createOctokit(token: string) {
|
||||
return new Octokit({
|
||||
auth: token
|
||||
})
|
||||
}
|
||||
|
||||
static #createKey (path: string | undefined, fileName: string): string {
|
||||
static #createKey(path: string | undefined, fileName: string): string {
|
||||
const formatedFileName = fileName.replace(/%2F/g, '/')
|
||||
return path && path !== '/'
|
||||
? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}`
|
||||
: formatedFileName
|
||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}` : formatedFileName
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, hash, config: { repo, token, branch, path } } = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
hash,
|
||||
config: { repo, token, branch, path }
|
||||
} = configMap
|
||||
const [owner, repoName] = repo.split('/')
|
||||
const octokit = GithubApi.#createOctokit(token)
|
||||
const key = GithubApi.#createKey(path, fileName)
|
||||
|
||||
@@ -7,10 +7,10 @@ import { deleteFailedLog } from '#/utils/deleteLog'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
export default class HuaweicloudApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return ipcRenderer
|
||||
? await triggerRPC(IRPCActionType.GALLERY_DELETE_HUAWEI_OSS_FILE, getRawData(configMap)) || false
|
||||
? (await triggerRPC(IRPCActionType.GALLERY_DELETE_HUAWEI_OSS_FILE, getRawData(configMap))) || false
|
||||
: await removeFileFromHuaweiInMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
deleteFailedLog(configMap.fileName, 'HuaweiCloud', error)
|
||||
|
||||
@@ -10,11 +10,8 @@ interface IConfigMap {
|
||||
export default class ImgurApi {
|
||||
static #baseUrl = 'https://api.imgur.com/3'
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
config: { clientId = '', username = '', accessToken = '' } = {},
|
||||
hash = ''
|
||||
} = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { config: { clientId = '', username = '', accessToken = '' } = {}, hash = '' } = configMap
|
||||
let Authorization: string, apiUrl: string
|
||||
|
||||
if (username && accessToken) {
|
||||
|
||||
@@ -7,7 +7,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class LocalApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { hash } = configMap
|
||||
if (!hash) {
|
||||
deleteLog(hash, 'Local', false, 'Local.delete: invalid params')
|
||||
|
||||
@@ -4,7 +4,7 @@ import https from 'https'
|
||||
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||
|
||||
export default class LskyplistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { hash, config } = configMap
|
||||
if (!hash || !config || !config.token) {
|
||||
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params')
|
||||
@@ -26,12 +26,11 @@ export default class LskyplistApi {
|
||||
rejectUnauthorized: false
|
||||
})
|
||||
try {
|
||||
const response: AxiosResponse = await axios.delete(
|
||||
`${host}/api/v1/images/${hash}`, {
|
||||
headers: v2Headers,
|
||||
timeout: 30000,
|
||||
httpsAgent: requestAgent
|
||||
})
|
||||
const response: AxiosResponse = await axios.delete(`${host}/api/v1/images/${hash}`, {
|
||||
headers: v2Headers,
|
||||
timeout: 30000,
|
||||
httpsAgent: requestAgent
|
||||
})
|
||||
if (response.status === 200 && response.data.status === true) {
|
||||
deleteLog(hash, 'Lskyplist')
|
||||
return true
|
||||
|
||||
@@ -3,7 +3,7 @@ import axios, { AxiosResponse } from 'axios'
|
||||
import { deleteFailedLog, deleteLog } from '#/utils/deleteLog'
|
||||
|
||||
export default class PiclistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { config, fullResult } = configMap
|
||||
const { host, port } = config
|
||||
if (!host) {
|
||||
@@ -14,12 +14,9 @@ export default class PiclistApi {
|
||||
const url = `http://${host || '127.0.0.1'}:${port || 36677}/delete`
|
||||
|
||||
try {
|
||||
const response: AxiosResponse = await axios.post(
|
||||
url,
|
||||
{
|
||||
list: [fullResult]
|
||||
}
|
||||
)
|
||||
const response: AxiosResponse = await axios.post(url, {
|
||||
list: [fullResult]
|
||||
})
|
||||
if (response.status === 200 && response.data?.success) {
|
||||
deleteLog(fullResult, 'Piclist')
|
||||
return true
|
||||
|
||||
@@ -8,15 +8,18 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class QiniuApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config: { accessKey, secretKey, bucket, path } } = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { accessKey, secretKey, bucket, path }
|
||||
} = configMap
|
||||
const mac = new Qiniu.auth.digest.Mac(accessKey, secretKey)
|
||||
const qiniuConfig = new Qiniu.conf.Config()
|
||||
try {
|
||||
const bucketManager = new Qiniu.rs.BucketManager(mac, qiniuConfig)
|
||||
const formattedPath = path?.replace(/^\/+|\/+$/, '') || ''
|
||||
const key = path === '/' || !path ? fileName : `${formattedPath}/${fileName}`
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
const res = (await new Promise((resolve, reject) => {
|
||||
bucketManager.delete(bucket, key, (err, respBody, respInfo) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
@@ -27,7 +30,7 @@ export default class QiniuApi {
|
||||
})
|
||||
}
|
||||
})
|
||||
}) as any
|
||||
})) as any
|
||||
if (res?.respInfo?.statusCode === 200) {
|
||||
deleteLog(fileName, 'Qiniu')
|
||||
return true
|
||||
|
||||
@@ -7,12 +7,11 @@ import { deleteFailedLog } from '#/utils/deleteLog'
|
||||
import { IRPCActionType } from '#/types/enum'
|
||||
|
||||
export default class SftpPlistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
return ipcRenderer
|
||||
? await triggerRPC(IRPCActionType.GALLERY_DELETE_SFTP_FILE, getRawData(config),
|
||||
fileName) || false
|
||||
? (await triggerRPC(IRPCActionType.GALLERY_DELETE_SFTP_FILE, getRawData(config), fileName)) || false
|
||||
: await removeFileFromSFTPInMain(getRawData(config), fileName)
|
||||
} catch (error: any) {
|
||||
deleteFailedLog(fileName, 'SFTP', error)
|
||||
|
||||
@@ -10,7 +10,7 @@ interface IConfigMap {
|
||||
export default class SmmsApi {
|
||||
static readonly #baseUrl = 'https://smms.app/api/v2'
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { hash, config } = configMap
|
||||
if (!hash || !config || !config.token) {
|
||||
deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params')
|
||||
@@ -20,17 +20,16 @@ export default class SmmsApi {
|
||||
const { token } = config
|
||||
|
||||
try {
|
||||
const response: AxiosResponse = await axios.get(
|
||||
`${SmmsApi.#baseUrl}/delete/${hash}`, {
|
||||
headers: {
|
||||
Authorization: token
|
||||
},
|
||||
params: {
|
||||
hash,
|
||||
format: 'json'
|
||||
},
|
||||
timeout: 30000
|
||||
})
|
||||
const response: AxiosResponse = await axios.get(`${SmmsApi.#baseUrl}/delete/${hash}`, {
|
||||
headers: {
|
||||
Authorization: token
|
||||
},
|
||||
params: {
|
||||
hash,
|
||||
format: 'json'
|
||||
},
|
||||
timeout: 30000
|
||||
})
|
||||
if (response.status === 200) {
|
||||
deleteLog(hash, 'Smms')
|
||||
return true
|
||||
|
||||
@@ -8,15 +8,18 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class TcyunApi {
|
||||
static #createCOS (SecretId: string, SecretKey: string): COS {
|
||||
static #createCOS(SecretId: string, SecretKey: string): COS {
|
||||
return new COS({
|
||||
SecretId,
|
||||
SecretKey
|
||||
})
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config: { secretId, secretKey, bucket, area, path } } = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { secretId, secretKey, bucket, area, path }
|
||||
} = configMap
|
||||
try {
|
||||
const cos = TcyunApi.#createCOS(secretId, secretKey)
|
||||
let key
|
||||
|
||||
@@ -8,8 +8,11 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class UpyunApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config: { bucket, operator, password, path } } = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { bucket, operator, password, path }
|
||||
} = configMap
|
||||
try {
|
||||
const service = new Upyun.Service(bucket, operator, password)
|
||||
const client = new Upyun.Client(service)
|
||||
|
||||
@@ -9,8 +9,11 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class WebdavApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config: { host, username, password, path, sslEnabled, authType } } = configMap
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { host, username, password, path, sslEnabled, authType }
|
||||
} = configMap
|
||||
const endpoint = formatEndpoint(host, sslEnabled)
|
||||
const options: WebDAVClientOptions = {
|
||||
username,
|
||||
@@ -19,10 +22,7 @@ export default class WebdavApi {
|
||||
if (authType === 'digest') {
|
||||
options.authType = AuthType.Digest
|
||||
}
|
||||
const ctx = createClient(
|
||||
endpoint,
|
||||
options
|
||||
)
|
||||
const ctx = createClient(endpoint, options)
|
||||
let key
|
||||
if (path === '/' || !path) {
|
||||
key = fileName
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
<template>
|
||||
<div
|
||||
id="config-form"
|
||||
:class="props.colorMode === 'white' ? 'white' : ''"
|
||||
>
|
||||
<el-form
|
||||
ref="$form"
|
||||
label-position="left"
|
||||
label-width="50%"
|
||||
:model="ruleForm"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('UPLOADER_CONFIG_NAME')"
|
||||
required
|
||||
prop="_configName"
|
||||
>
|
||||
<el-input
|
||||
v-model="ruleForm._configName"
|
||||
type="input"
|
||||
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
|
||||
/>
|
||||
<div id="config-form" :class="props.colorMode === 'white' ? 'white' : ''">
|
||||
<el-form ref="$form" label-position="left" label-width="50%" :model="ruleForm" size="small">
|
||||
<el-form-item :label="$T('UPLOADER_CONFIG_NAME')" required prop="_configName">
|
||||
<el-input v-model="ruleForm._configName" type="input" :placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')" />
|
||||
</el-form-item>
|
||||
<!-- dynamic config -->
|
||||
<el-form-item
|
||||
@@ -32,18 +15,9 @@
|
||||
<el-row align="middle">
|
||||
{{ item.alias || item.name }}
|
||||
<template v-if="item.tips">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
placement="right"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-tooltip class="item" effect="dark" placement="right" :persistent="false" teleported>
|
||||
<template #content>
|
||||
<span
|
||||
class="config-form-common-tips"
|
||||
v-html="transformMarkdownToHTML(item.tips)"
|
||||
/>
|
||||
<span class="config-form-common-tips" v-html="transformMarkdownToHTML(item.tips)" />
|
||||
</template>
|
||||
<el-icon class="ml-[4px] cursor-pointer hover:text-blue">
|
||||
<InfoFilled />
|
||||
@@ -124,19 +98,23 @@ const $form = ref<FormInstance>()
|
||||
const configList = ref<IPicGoPluginConfig[]>([])
|
||||
const ruleForm = reactive<IStringKeyMap>({})
|
||||
|
||||
watch(toRefs(props.config), (val: IPicGoPluginConfig[]) => {
|
||||
handleConfigChange(val)
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
watch(
|
||||
toRefs(props.config),
|
||||
(val: IPicGoPluginConfig[]) => {
|
||||
handleConfigChange(val)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
function handleConfigChange (val: any) {
|
||||
function handleConfigChange(val: any) {
|
||||
handleConfig(val)
|
||||
}
|
||||
|
||||
async function validate (): Promise<IStringKeyMap | false> {
|
||||
return new Promise((resolve) => {
|
||||
async function validate(): Promise<IStringKeyMap | false> {
|
||||
return new Promise(resolve => {
|
||||
$form.value?.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
resolve(ruleForm)
|
||||
@@ -147,7 +125,7 @@ async function validate (): Promise<IStringKeyMap | false> {
|
||||
})
|
||||
}
|
||||
|
||||
function transformMarkdownToHTML (markdown: string) {
|
||||
function transformMarkdownToHTML(markdown: string) {
|
||||
try {
|
||||
return marked.parse(markdown)
|
||||
} catch (e) {
|
||||
@@ -155,7 +133,7 @@ function transformMarkdownToHTML (markdown: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function getConfigType () {
|
||||
function getConfigType() {
|
||||
switch (props.type) {
|
||||
case 'plugin': {
|
||||
return props.id
|
||||
@@ -171,22 +149,21 @@ function getConfigType () {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleConfig (val: IPicGoPluginConfig[]) {
|
||||
async function handleConfig(val: IPicGoPluginConfig[]) {
|
||||
const config = await getCurConfigFormData()
|
||||
const configId = $route.params.configId
|
||||
Object.assign(ruleForm, config)
|
||||
if (val.length > 0) {
|
||||
configList.value = cloneDeep(val).map((item) => {
|
||||
configList.value = cloneDeep(val).map(item => {
|
||||
if (!configId) return item
|
||||
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') {
|
||||
const defaults = item.choices?.filter((i: any) => {
|
||||
return i.checked
|
||||
}).map((i: any) => i.value) || []
|
||||
const defaults =
|
||||
item.choices
|
||||
?.filter((i: any) => {
|
||||
return i.checked
|
||||
})
|
||||
.map((i: any) => i.value) || []
|
||||
defaultValue = union(defaultValue, defaults)
|
||||
}
|
||||
if (config && config[item.name] !== undefined) {
|
||||
@@ -198,13 +175,13 @@ async function handleConfig (val: IPicGoPluginConfig[]) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getCurConfigFormData () {
|
||||
async function getCurConfigFormData() {
|
||||
const configId = $route.params.configId
|
||||
const curTypeConfigList = await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`) || []
|
||||
const curTypeConfigList = (await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`)) || []
|
||||
return curTypeConfigList.find(i => i._id === configId) || {}
|
||||
}
|
||||
|
||||
function updateRuleForm (key: string, value: any) {
|
||||
function updateRuleForm(key: string, value: any) {
|
||||
try {
|
||||
ruleForm[key] = value
|
||||
} catch (e) {
|
||||
@@ -218,7 +195,7 @@ defineExpose({
|
||||
getConfigType
|
||||
})
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
.config-form-common-tips
|
||||
a
|
||||
color #409EFF
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
<template>
|
||||
<div
|
||||
id="config-form"
|
||||
:class="props.colorMode === 'white' ? 'white' : ''"
|
||||
>
|
||||
<el-form
|
||||
ref="$form"
|
||||
label-position="left"
|
||||
label-width="50%"
|
||||
:model="ruleForm"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('UPLOADER_CONFIG_NAME')"
|
||||
required
|
||||
prop="_configName"
|
||||
>
|
||||
<el-input
|
||||
v-model="ruleForm._configName"
|
||||
type="input"
|
||||
:placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')"
|
||||
/>
|
||||
<div id="config-form" :class="props.colorMode === 'white' ? 'white' : ''">
|
||||
<el-form ref="$form" label-position="left" label-width="50%" :model="ruleForm" size="small">
|
||||
<el-form-item :label="$T('UPLOADER_CONFIG_NAME')" required prop="_configName">
|
||||
<el-input v-model="ruleForm._configName" type="input" :placeholder="$T('UPLOADER_CONFIG_PLACEHOLDER')" />
|
||||
</el-form-item>
|
||||
<!-- dynamic config -->
|
||||
<el-form-item
|
||||
@@ -98,19 +81,23 @@ const $form = ref<FormInstance>()
|
||||
const configList = ref<IPicGoPluginConfig[]>([])
|
||||
const ruleForm = reactive<IStringKeyMap>({})
|
||||
|
||||
watch(() => props.config, (val: IPicGoPluginConfig[]) => {
|
||||
handleConfigChange(val)
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
watch(
|
||||
() => props.config,
|
||||
(val: IPicGoPluginConfig[]) => {
|
||||
handleConfigChange(val)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
function handleConfigChange (val: any) {
|
||||
function handleConfigChange(val: any) {
|
||||
handleConfig(val)
|
||||
}
|
||||
|
||||
async function validate (): Promise<IStringKeyMap | false> {
|
||||
return new Promise((resolve) => {
|
||||
async function validate(): Promise<IStringKeyMap | false> {
|
||||
return new Promise(resolve => {
|
||||
$form.value?.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
resolve(ruleForm)
|
||||
@@ -121,7 +108,7 @@ async function validate (): Promise<IStringKeyMap | false> {
|
||||
})
|
||||
}
|
||||
|
||||
function getConfigType () {
|
||||
function getConfigType() {
|
||||
switch (props.type) {
|
||||
case 'plugin': {
|
||||
return props.id
|
||||
@@ -137,20 +124,19 @@ function getConfigType () {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleConfig (val: IPicGoPluginConfig[]) {
|
||||
async function handleConfig(val: IPicGoPluginConfig[]) {
|
||||
const config = await getCurConfigFormData()
|
||||
Object.assign(ruleForm, config)
|
||||
if (val.length > 0) {
|
||||
configList.value = cloneDeep(val).map((item) => {
|
||||
let defaultValue = item.default !== undefined
|
||||
? item.default
|
||||
: item.type === 'checkbox'
|
||||
? []
|
||||
: null
|
||||
configList.value = cloneDeep(val).map(item => {
|
||||
let defaultValue = item.default !== undefined ? item.default : item.type === 'checkbox' ? [] : null
|
||||
if (item.type === 'checkbox') {
|
||||
const defaults = item.choices?.filter((i: any) => {
|
||||
return i.checked
|
||||
}).map((i: any) => i.value) || []
|
||||
const defaults =
|
||||
item.choices
|
||||
?.filter((i: any) => {
|
||||
return i.checked
|
||||
})
|
||||
.map((i: any) => i.value) || []
|
||||
defaultValue = union(defaultValue, defaults)
|
||||
}
|
||||
if (config && config[item.name] !== undefined) {
|
||||
@@ -162,11 +148,11 @@ async function handleConfig (val: IPicGoPluginConfig[]) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getCurConfigFormData () {
|
||||
return await getConfig<IStringKeyMap>(`${props.id}`) || {}
|
||||
async function getCurConfigFormData() {
|
||||
return (await getConfig<IStringKeyMap>(`${props.id}`)) || {}
|
||||
}
|
||||
|
||||
function updateRuleForm (key: string, value: any) {
|
||||
function updateRuleForm(key: string, value: any) {
|
||||
try {
|
||||
ruleForm[key] = value
|
||||
} catch (e) {
|
||||
@@ -180,7 +166,7 @@ defineExpose({
|
||||
getConfigType
|
||||
})
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
#config-form
|
||||
.el-form
|
||||
label
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<el-image
|
||||
:src="isShowThumbnail && item.isImage ?
|
||||
base64Image
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
||||
:src="
|
||||
isShowThumbnail && item.isImage
|
||||
? base64Image
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(item.fileName ?? '')}`)
|
||||
"
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
style="height: 100px; width: 100%; margin: 0 auto"
|
||||
>
|
||||
<template #placeholder>
|
||||
<el-icon>
|
||||
@@ -15,7 +17,7 @@
|
||||
<el-image
|
||||
:src="require(`../manage/pages/assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
style="height: 100px; width: 100%; margin: 0 auto"
|
||||
/>
|
||||
</template>
|
||||
</el-image>
|
||||
|
||||
@@ -6,18 +6,10 @@
|
||||
size="default"
|
||||
:model="waterMarkForm"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISADDWM')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="waterMarkForm.isAddWatermark"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISADDWM')">
|
||||
<el-switch v-model="waterMarkForm.isAddWatermark" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE')"
|
||||
>
|
||||
<el-form-item v-show="waterMarkForm.isAddWatermark" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE')">
|
||||
<el-radio-group v-model="waterMarkForm.watermarkType">
|
||||
<el-radio value="text">
|
||||
{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_TEXT') }}
|
||||
@@ -27,23 +19,11 @@
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFULLSCREEN_WM')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="waterMarkForm.isFullScreenWatermark"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item v-show="waterMarkForm.isAddWatermark" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFULLSCREEN_WM')">
|
||||
<el-switch v-model="waterMarkForm.isFullScreenWatermark" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMDEGREE')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="waterMarkForm.watermarkDegree"
|
||||
:step="1"
|
||||
/>
|
||||
<el-form-item v-show="waterMarkForm.isAddWatermark" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMDEGREE')">
|
||||
<el-input-number v-model="waterMarkForm.watermarkDegree" :step="1" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark && waterMarkForm.watermarkType === 'text'"
|
||||
@@ -57,25 +37,14 @@
|
||||
>
|
||||
<el-input v-model="waterMarkForm.watermarkFontPath" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMRATIO')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="waterMarkForm.watermarkScaleRatio"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
/>
|
||||
<el-form-item v-show="waterMarkForm.isAddWatermark" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMRATIO')">
|
||||
<el-input-number v-model="waterMarkForm.watermarkScaleRatio" :min="0" :max="1" :step="0.01" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark && waterMarkForm.watermarkType === 'text'"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMCOLOR')"
|
||||
>
|
||||
<el-color-picker
|
||||
v-model="waterMarkForm.watermarkColor"
|
||||
show-alpha
|
||||
/>
|
||||
<el-color-picker v-model="waterMarkForm.watermarkColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark && waterMarkForm.watermarkType === 'image'"
|
||||
@@ -83,175 +52,76 @@
|
||||
>
|
||||
<el-input v-model="waterMarkForm.watermarkImagePath" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="waterMarkForm.isAddWatermark"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMPOSITION')"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="waterMarkForm.watermarkPosition"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item in waterMarkPositionMap"
|
||||
:key="item[0]"
|
||||
:value="item[0]"
|
||||
>
|
||||
<el-form-item v-show="waterMarkForm.isAddWatermark" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_WMPOSITION')">
|
||||
<el-radio-group v-model="waterMarkForm.watermarkPosition">
|
||||
<el-radio v-for="item in waterMarkPositionMap" :key="item[0]" :value="item[0]">
|
||||
{{ item[1] }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISREMOVEEXIF')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isRemoveExif"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISREMOVEEXIF')">
|
||||
<el-switch v-model="compressForm.isRemoveExif" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_QUALITY')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="compressForm.quality"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="1"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_QUALITY')">
|
||||
<el-input-number v-model="compressForm.quality" :min="0" :max="100" :step="1" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isConvert"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT')">
|
||||
<el-switch v-model="compressForm.isConvert" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isConvert"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT')"
|
||||
>
|
||||
<el-select
|
||||
v-model="compressForm.convertFormat"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-option
|
||||
v-for="item in availableFormat"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
<el-form-item v-show="compressForm.isConvert" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT')">
|
||||
<el-select v-model="compressForm.convertFormat" :persistent="false" teleported>
|
||||
<el-option v-for="item in availableFormat" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isConvert"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT_SPECIFIC')"
|
||||
>
|
||||
<el-form-item v-show="compressForm.isConvert" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT_SPECIFIC')">
|
||||
<el-input
|
||||
v-model="formatConvertObj"
|
||||
placeholder="{"jpg": "png", "png": "jpg"}"
|
||||
placeholder='{"jpg": "png", "png": "jpg"}'
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isFlip"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP')">
|
||||
<el-switch v-model="compressForm.isFlip" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isFlop"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP')">
|
||||
<el-switch v-model="compressForm.isFlop" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isReSize"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE')">
|
||||
<el-switch v-model="compressForm.isReSize" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isReSize"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEWIDTH')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="compressForm.reSizeWidth"
|
||||
:min="0"
|
||||
/>
|
||||
<el-form-item v-show="compressForm.isReSize" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEWIDTH')">
|
||||
<el-input-number v-model="compressForm.reSizeWidth" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isReSize"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEHEIGHT')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="compressForm.reSizeHeight"
|
||||
:min="0"
|
||||
/>
|
||||
<el-form-item v-show="compressForm.isReSize" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEHEIGHT')">
|
||||
<el-input-number v-model="compressForm.reSizeHeight" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isReSize && compressForm.reSizeHeight! > 0 && compressForm.reSizeWidth === 0"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_SKIPRESIZEOfSMALLIMG_HEIGHT')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.skipReSizeOfSmallImg"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-switch v-model="compressForm.skipReSizeOfSmallImg" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isReSize && compressForm.reSizeWidth! > 0 && compressForm.reSizeHeight === 0"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_SKIPRESIZEOfSMALLIMG_WIDTH')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.skipReSizeOfSmallImg"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-switch v-model="compressForm.skipReSizeOfSmallImg" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZEBYPERCENT')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isReSizeByPercent"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZEBYPERCENT')">
|
||||
<el-switch v-model="compressForm.isReSizeByPercent" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isReSizeByPercent"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEPERCENT')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="compressForm.reSizePercent"
|
||||
:min="0"
|
||||
/>
|
||||
<el-form-item v-show="compressForm.isReSizeByPercent" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_RESIZEPERCENT')">
|
||||
<el-input-number v-model="compressForm.reSizePercent" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISROTATE')"
|
||||
>
|
||||
<el-switch
|
||||
v-model="compressForm.isRotate"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
<el-form-item :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ISROTATE')">
|
||||
<el-switch v-model="compressForm.isRotate" :style="switchStyle" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="compressForm.isRotate"
|
||||
:label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ROTATEDEGREE')"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="compressForm.rotateDegree"
|
||||
:step="1"
|
||||
/>
|
||||
<el-form-item v-show="compressForm.isRotate" :label="$T('UPLOAD_PAGE_IMAGE_PROCESS_ROTATEDEGREE')">
|
||||
<el-input-number v-model="compressForm.rotateDegree" :step="1" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSaveConfig"
|
||||
>
|
||||
<el-button type="primary" @click="handleSaveConfig">
|
||||
{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_CONFIRM') }}
|
||||
</el-button>
|
||||
<el-button @click="closeDialog">
|
||||
@@ -283,7 +153,29 @@ const waterMarkPositionMap = new Map([
|
||||
['centre', $T('UPLOAD_PAGE_IMAGE_PROCESS_POSITION_CENTER')]
|
||||
])
|
||||
const imageExtList = ['jpg', 'jpeg', 'png', 'webp', 'bmp', 'tiff', 'tif', 'svg', 'ico', 'avif', 'heif', 'heic']
|
||||
const availableFormat = ['avif', 'dz', 'fits', 'gif', 'heif', 'input', 'jpeg', 'jpg', 'jp2', 'jxl', 'magick', 'openslide', 'pdf', 'png', 'ppm', 'raw', 'svg', 'tiff', 'tif', 'v', 'webp']
|
||||
const availableFormat = [
|
||||
'avif',
|
||||
'dz',
|
||||
'fits',
|
||||
'gif',
|
||||
'heif',
|
||||
'input',
|
||||
'jpeg',
|
||||
'jpg',
|
||||
'jp2',
|
||||
'jxl',
|
||||
'magick',
|
||||
'openslide',
|
||||
'pdf',
|
||||
'png',
|
||||
'ppm',
|
||||
'raw',
|
||||
'svg',
|
||||
'tiff',
|
||||
'tif',
|
||||
'v',
|
||||
'webp'
|
||||
]
|
||||
|
||||
const waterMarkForm = reactive<IBuildInWaterMarkOptions>({
|
||||
isAddWatermark: false,
|
||||
@@ -320,12 +212,11 @@ const compressFormKeys = Object.keys(compressForm) as (keyof typeof compressForm
|
||||
|
||||
const switchStyle = '--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949;'
|
||||
|
||||
function handleSaveConfig () {
|
||||
function handleSaveConfig() {
|
||||
let iformatConvertObj = {}
|
||||
try {
|
||||
iformatConvertObj = JSON.parse(formatConvertObj.value)
|
||||
} catch (error) {
|
||||
}
|
||||
} catch (error) {}
|
||||
const formatConvertObjEntries = Object.entries(iformatConvertObj)
|
||||
const formatConvertObjEntriesFilter = formatConvertObjEntries.filter((item: any) => {
|
||||
return imageExtList.includes(item[0]) && availableFormat.includes(item[1])
|
||||
@@ -338,11 +229,11 @@ function handleSaveConfig () {
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
async function initData () {
|
||||
async function initData() {
|
||||
const compress = await getConfig<any>(configPaths.buildIn.compress)
|
||||
const watermark = await getConfig<any>(configPaths.buildIn.watermark)
|
||||
if (compress) {
|
||||
compressFormKeys.forEach((key) => {
|
||||
compressFormKeys.forEach(key => {
|
||||
compressForm[key] = compress[key] ?? compressForm[key]
|
||||
})
|
||||
try {
|
||||
@@ -356,14 +247,14 @@ async function initData () {
|
||||
}
|
||||
}
|
||||
if (watermark) {
|
||||
waterMarkFormKeys.forEach((key) => {
|
||||
waterMarkFormKeys.forEach(key => {
|
||||
waterMarkForm[key] = watermark[key] ?? waterMarkForm[key]
|
||||
})
|
||||
waterMarkForm.watermarkColor = watermark.watermarkColor === '' ? '#CCCCCC73' : watermark.watermarkColor
|
||||
}
|
||||
}
|
||||
|
||||
function closeDialog () {
|
||||
function closeDialog() {
|
||||
imageProcessDialogVisible.value = false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
<template>
|
||||
<el-image
|
||||
:src="imageSource"
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
>
|
||||
<el-image :src="imageSource" fit="contain" style="height: 100px; width: 100%; margin: 0 auto">
|
||||
<template #placeholder>
|
||||
<el-icon>
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template #error>
|
||||
<el-image
|
||||
:src="iconPath"
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
/>
|
||||
<el-image :src="iconPath" fit="contain" style="height: 100px; width: 100%; margin: 0 auto" />
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
@@ -43,14 +35,14 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const imageSource = computed(() => {
|
||||
return (props.isShowThumbnail && props.item.isImage && success.value)
|
||||
return props.isShowThumbnail && props.item.isImage && success.value
|
||||
? base64Url.value
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
})
|
||||
|
||||
const iconPath = computed(() => require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`))
|
||||
|
||||
async function getWebdavHeader (key: string) {
|
||||
async function getWebdavHeader(key: string) {
|
||||
let headers = {} as any
|
||||
if (props.config.authType === 'digest') {
|
||||
const authHeader = await getAuthHeader(
|
||||
@@ -91,5 +83,4 @@ const fetchImage = async () => {
|
||||
watch(() => [props.url, props.item], fetchImage, { deep: true })
|
||||
|
||||
onMounted(fetchImage)
|
||||
|
||||
</script>
|
||||
|
||||
@@ -27,18 +27,20 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
|
||||
setup (props) {
|
||||
setup(props) {
|
||||
const base64Url = ref('')
|
||||
const success = ref(false)
|
||||
|
||||
const imageSource = computed(() => {
|
||||
return (props.isShowThumbnail && props.item.isImage && success.value)
|
||||
return props.isShowThumbnail && props.item.isImage && success.value
|
||||
? base64Url.value
|
||||
: require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
})
|
||||
const iconPath = computed(() => require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`))
|
||||
const iconPath = computed(() =>
|
||||
require(`../manage/pages/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||
)
|
||||
|
||||
async function getWebdavHeader (key: string) {
|
||||
async function getWebdavHeader(key: string) {
|
||||
let headers = {} as any
|
||||
if (props.config.authType === 'digest') {
|
||||
const authHeader = await getAuthHeader(
|
||||
@@ -79,24 +81,14 @@ export default defineComponent({
|
||||
onMounted(fetchImage)
|
||||
|
||||
return () => (
|
||||
<ElImage
|
||||
src={imageSource.value}
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
>
|
||||
<ElImage src={imageSource.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;'>
|
||||
{{
|
||||
placeholder: () => (
|
||||
<ElIcon>
|
||||
<Loading />
|
||||
</ElIcon>
|
||||
),
|
||||
error: () => (
|
||||
<ElImage
|
||||
src={iconPath.value}
|
||||
fit="contain"
|
||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
||||
/>
|
||||
)
|
||||
error: () => <ElImage src={iconPath.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;' />
|
||||
}}
|
||||
</ElImage>
|
||||
)
|
||||
|
||||
@@ -5,22 +5,12 @@
|
||||
:modal-append-to-body="false"
|
||||
append-to-body
|
||||
>
|
||||
<el-input
|
||||
v-model="inputBoxValue"
|
||||
:placeholder="inputBoxOptions.placeholder"
|
||||
/>
|
||||
<el-input v-model="inputBoxValue" :placeholder="inputBoxOptions.placeholder" />
|
||||
<template #footer>
|
||||
<el-button
|
||||
round
|
||||
@click="handleInputBoxCancel"
|
||||
>
|
||||
<el-button round @click="handleInputBoxCancel">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
@click="handleInputBoxConfirm"
|
||||
>
|
||||
<el-button type="primary" round @click="handleInputBoxConfirm">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -35,10 +25,7 @@ import { T as $T } from '@/i18n/index'
|
||||
import $bus from '@/utils/bus'
|
||||
import { sendToMain } from '@/utils/common'
|
||||
|
||||
import {
|
||||
SHOW_INPUT_BOX,
|
||||
SHOW_INPUT_BOX_RESPONSE
|
||||
} from '#/events/constants'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
|
||||
const inputBoxValue = ref('')
|
||||
const showInputBoxVisible = ref(false)
|
||||
@@ -52,25 +39,25 @@ onBeforeMount(() => {
|
||||
$bus.on(SHOW_INPUT_BOX, initInputBoxValue)
|
||||
})
|
||||
|
||||
function ipcEventHandler (_: IpcRendererEvent, options: IShowInputBoxOption) {
|
||||
function ipcEventHandler(_: IpcRendererEvent, options: IShowInputBoxOption) {
|
||||
initInputBoxValue(options)
|
||||
}
|
||||
|
||||
function initInputBoxValue (options: IShowInputBoxOption) {
|
||||
function initInputBoxValue(options: IShowInputBoxOption) {
|
||||
inputBoxValue.value = options.value || ''
|
||||
inputBoxOptions.title = options.title || ''
|
||||
inputBoxOptions.placeholder = options.placeholder || ''
|
||||
showInputBoxVisible.value = true
|
||||
}
|
||||
|
||||
function handleInputBoxCancel () {
|
||||
function handleInputBoxCancel() {
|
||||
// TODO: RPCServer
|
||||
showInputBoxVisible.value = false
|
||||
sendToMain(SHOW_INPUT_BOX, '')
|
||||
$bus.emit(SHOW_INPUT_BOX_RESPONSE, '')
|
||||
}
|
||||
|
||||
function handleInputBoxConfirm () {
|
||||
function handleInputBoxConfirm() {
|
||||
showInputBoxVisible.value = false
|
||||
sendToMain(SHOW_INPUT_BOX, inputBoxValue.value)
|
||||
$bus.emit(SHOW_INPUT_BOX_RESPONSE, inputBoxValue.value)
|
||||
@@ -80,12 +67,10 @@ onBeforeUnmount(() => {
|
||||
ipcRenderer.removeListener(SHOW_INPUT_BOX, ipcEventHandler)
|
||||
$bus.off(SHOW_INPUT_BOX)
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'InputBoxDialog'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
</style>
|
||||
<style lang="stylus"></style>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<div class="toolbox-handler">
|
||||
<ElButton
|
||||
type="primary"
|
||||
:link="true"
|
||||
@click="() => props.handler(value)"
|
||||
>
|
||||
<ElButton type="primary" :link="true" @click="() => props.handler(value)">
|
||||
{{ props.handlerText }}
|
||||
</ElButton>
|
||||
</div>
|
||||
@@ -21,12 +17,10 @@ interface IProps {
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ToolboxHandler'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
</style>
|
||||
<style lang="stylus"></style>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<el-icon
|
||||
:color="color"
|
||||
class="toolbox-status-icon"
|
||||
>
|
||||
<el-icon :color="color" class="toolbox-status-icon">
|
||||
<template v-if="props.status === IToolboxItemCheckStatus.SUCCESS">
|
||||
<SuccessFilled />
|
||||
</template>
|
||||
@@ -37,14 +34,13 @@ const color = computed(() => {
|
||||
return '#909399'
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ToolboxStatusIcon'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
.toolbox-status-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { onMounted, onUnmounted } from 'vue'
|
||||
import { sendRPC } from '@/utils/common'
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
|
||||
export function useATagClick () {
|
||||
export function useATagClick() {
|
||||
const handleATagClick = (e: MouseEvent) => {
|
||||
if (e.target instanceof HTMLAnchorElement) {
|
||||
if (e.target.href) {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class I18nManager {
|
||||
#i18n: I18n | null = null
|
||||
#i18nFileList: II18nItem[] = builtinI18nList
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.#getCurrentLanguage()
|
||||
this.#getLanguageList()
|
||||
ipcRenderer.on(SET_CURRENT_LANGUAGE, (_, lang: string, locales: ILocales) => {
|
||||
@@ -21,16 +21,16 @@ export class I18nManager {
|
||||
})
|
||||
}
|
||||
|
||||
#getLanguageList () {
|
||||
#getLanguageList() {
|
||||
this.#i18nFileList = sendRpcSync(IRPCActionType.GET_LANGUAGE_LIST)
|
||||
}
|
||||
|
||||
#getCurrentLanguage () {
|
||||
#getCurrentLanguage() {
|
||||
const [lang, locales] = sendRpcSync(IRPCActionType.GET_CURRENT_LANGUAGE)
|
||||
this.#setLocales(lang, locales)
|
||||
}
|
||||
|
||||
#setLocales (lang: string, locales: ILocales) {
|
||||
#setLocales(lang: string, locales: ILocales) {
|
||||
const objectAdapter = new ObjectAdapter({
|
||||
[lang]: locales
|
||||
})
|
||||
@@ -40,15 +40,15 @@ export class I18nManager {
|
||||
})
|
||||
}
|
||||
|
||||
T (key: ILocalesKey, args: IStringKeyMap = {}): string {
|
||||
T(key: ILocalesKey, args: IStringKeyMap = {}): string {
|
||||
return this.#i18n?.translate(key, args) || key
|
||||
}
|
||||
|
||||
setCurrentLanguage (lang: string) {
|
||||
setCurrentLanguage(lang: string) {
|
||||
sendRPC(IRPCActionType.SET_CURRENT_LANGUAGE, lang)
|
||||
}
|
||||
|
||||
get languageList () {
|
||||
get languageList() {
|
||||
return this.#i18nFileList
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,4 @@ const T = (key: ILocalesKey, args: IStringKeyMap = {}): string => {
|
||||
return i18nManager.T(key, args)
|
||||
}
|
||||
|
||||
export {
|
||||
i18nManager,
|
||||
T
|
||||
}
|
||||
export { i18nManager, T }
|
||||
|
||||
@@ -1,48 +1,24 @@
|
||||
<template>
|
||||
<div id="main-page">
|
||||
<div
|
||||
class="fake-title-bar"
|
||||
>
|
||||
<div class="fake-title-bar__title">
|
||||
PicList - {{ version }}
|
||||
</div>
|
||||
<div
|
||||
v-if="osGlobal !== 'darwin'"
|
||||
class="handle-bar"
|
||||
>
|
||||
<div class="fake-title-bar">
|
||||
<div class="fake-title-bar__title">PicList - {{ version }}</div>
|
||||
<div v-if="osGlobal !== 'darwin'" class="handle-bar">
|
||||
<el-icon
|
||||
class="minus"
|
||||
:color="isAlwaysOnTop ? '#409EFF' : '#fff'"
|
||||
size="20"
|
||||
style="margin-right: 10px;"
|
||||
style="margin-right: 10px"
|
||||
@click="setAlwaysOnTop"
|
||||
>
|
||||
<ArrowUpBold />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="minus"
|
||||
color="#fff"
|
||||
size="20"
|
||||
style="margin-right: 10px;"
|
||||
@click="minimizeWindow"
|
||||
>
|
||||
<el-icon class="minus" color="#fff" size="20" style="margin-right: 10px" @click="minimizeWindow">
|
||||
<SemiSelect />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="plus"
|
||||
color="orange"
|
||||
size="20"
|
||||
style="margin-right: 10px;"
|
||||
@click="openMiniWindow"
|
||||
>
|
||||
<el-icon class="plus" color="orange" size="20" style="margin-right: 10px" @click="openMiniWindow">
|
||||
<ArrowDownBold />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="close"
|
||||
color="#fff"
|
||||
size="20"
|
||||
@click="closeWindow"
|
||||
>
|
||||
<el-icon class="close" color="#fff" size="20" @click="closeWindow">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -56,19 +32,9 @@
|
||||
status="success"
|
||||
class="progress-bar"
|
||||
/>
|
||||
<el-row
|
||||
style="padding-top: 22px;"
|
||||
class="main-content"
|
||||
>
|
||||
<el-col
|
||||
class="side-bar-menu"
|
||||
>
|
||||
<el-menu
|
||||
class="picgo-sidebar"
|
||||
:default-active="defaultActive"
|
||||
:unique-opened="true"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-row style="padding-top: 22px" class="main-content">
|
||||
<el-col class="side-bar-menu">
|
||||
<el-menu class="picgo-sidebar" :default-active="defaultActive" :unique-opened="true" @select="handleSelect">
|
||||
<el-menu-item :index="routerConfig.UPLOAD_PAGE">
|
||||
<el-icon>
|
||||
<UploadFilled />
|
||||
@@ -87,21 +53,14 @@
|
||||
</el-icon>
|
||||
<span>{{ $T('GALLERY') }}</span>
|
||||
</el-menu-item>
|
||||
<el-sub-menu
|
||||
index="sub-menu"
|
||||
:show-timeout="0"
|
||||
:hide-timeout="0"
|
||||
:popper-offset="0"
|
||||
>
|
||||
<el-sub-menu index="sub-menu" :show-timeout="0" :hide-timeout="0" :popper-offset="0">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<Menu />
|
||||
</el-icon>
|
||||
<span>{{ $T('PICBEDS_SETTINGS') }}</span>
|
||||
</template>
|
||||
<template
|
||||
v-for="item in picBedGlobal"
|
||||
>
|
||||
<template v-for="item in picBedGlobal">
|
||||
<el-menu-item
|
||||
v-if="item.visible"
|
||||
:key="item.type"
|
||||
@@ -123,39 +82,22 @@
|
||||
</el-icon>
|
||||
<span>{{ $T('PLUGIN_SETTINGS') }}</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item
|
||||
:index="routerConfig.DocumentPage"
|
||||
>
|
||||
<el-menu-item :index="routerConfig.DocumentPage">
|
||||
<el-icon>
|
||||
<Link />
|
||||
</el-icon>
|
||||
<span>{{ $T('MANUAL') }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<el-icon
|
||||
class="info-window"
|
||||
@click="openMenu"
|
||||
>
|
||||
<el-icon class="info-window" @click="openMenu">
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</el-col>
|
||||
<el-col
|
||||
:span="21"
|
||||
:offset="3"
|
||||
style="height: 100%"
|
||||
class="main-wrapper"
|
||||
>
|
||||
<router-view
|
||||
v-slot="{ Component }"
|
||||
>
|
||||
<transition
|
||||
name="picgo-fade"
|
||||
mode="out-in"
|
||||
>
|
||||
<el-col :span="21" :offset="3" style="height: 100%" class="main-wrapper">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="picgo-fade" mode="out-in">
|
||||
<keep-alive :include="keepAlivePages">
|
||||
<component
|
||||
:is="Component"
|
||||
/>
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
@@ -171,27 +113,10 @@
|
||||
lock-scroll
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
label-position="left"
|
||||
label-width="70px"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('CHOOSE_PICBED')"
|
||||
>
|
||||
<el-select
|
||||
v-model="choosedPicBedForQRCode"
|
||||
multiple
|
||||
collapse-tags
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-option
|
||||
v-for="item in picBedGlobal"
|
||||
:key="item.type"
|
||||
:label="item.name"
|
||||
:value="item.type"
|
||||
/>
|
||||
<el-form label-position="left" label-width="70px" size="small">
|
||||
<el-form-item :label="$T('CHOOSE_PICBED')">
|
||||
<el-select v-model="choosedPicBedForQRCode" multiple collapse-tags :persistent="false" teleported>
|
||||
<el-option v-for="item in picBedGlobal" :key="item.type" :label="item.name" :value="item.type" />
|
||||
</el-select>
|
||||
<el-button
|
||||
v-show="choosedPicBedForQRCode.length > 0"
|
||||
@@ -205,11 +130,7 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="qrcode-container">
|
||||
<qrcode-vue
|
||||
v-show="choosedPicBedForQRCode.length > 0"
|
||||
:size="280"
|
||||
:value="picBedConfigString"
|
||||
/>
|
||||
<qrcode-vue v-show="choosedPicBedForQRCode.length > 0" :size="280" :value="picBedConfigString" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
<input-box-dialog />
|
||||
@@ -231,11 +152,7 @@ import {
|
||||
Link,
|
||||
ArrowUpBold
|
||||
} from '@element-plus/icons-vue'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent,
|
||||
clipboard
|
||||
} from 'electron'
|
||||
import { ipcRenderer, IpcRendererEvent, clipboard } from 'electron'
|
||||
import { ElMessage as $message, ElMessageBox } from 'element-plus'
|
||||
import pick from 'lodash/pick'
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
@@ -249,9 +166,7 @@ import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { sendRPC } from '@/utils/common'
|
||||
import { osGlobal, picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
|
||||
import {
|
||||
SHOW_MAIN_PAGE_QRCODE
|
||||
} from '#/events/constants'
|
||||
import { SHOW_MAIN_PAGE_QRCODE } from '#/events/constants'
|
||||
import { configPaths, manualPageOpenType } from '#/utils/configPaths'
|
||||
import { II18nLanguage, IRPCActionType } from '#/types/enum'
|
||||
|
||||
@@ -265,7 +180,10 @@ const qrcodeVisible = ref(false)
|
||||
const picBedConfigString = ref('')
|
||||
const choosedPicBedForQRCode: Ref<string[]> = ref([])
|
||||
const isAlwaysOnTop = ref(false)
|
||||
const keepAlivePages = $router.getRoutes().filter(item => item.meta.keepAlive).map(item => item.name as string)
|
||||
const keepAlivePages = $router
|
||||
.getRoutes()
|
||||
.filter(item => item.meta.keepAlive)
|
||||
.map(item => item.name as string)
|
||||
|
||||
const isShowprogress = ref(false)
|
||||
const progress = ref(0)
|
||||
@@ -275,29 +193,37 @@ onBeforeMount(() => {
|
||||
ipcRenderer.on(SHOW_MAIN_PAGE_QRCODE, () => {
|
||||
qrcodeVisible.value = true
|
||||
})
|
||||
ipcRenderer.on('updateProgress', (_event: IpcRendererEvent, data: { progress: number}) => {
|
||||
ipcRenderer.on('updateProgress', (_event: IpcRendererEvent, data: { progress: number }) => {
|
||||
isShowprogress.value = data.progress !== 100 && data.progress !== 0
|
||||
progress.value = data.progress
|
||||
})
|
||||
})
|
||||
|
||||
watch(() => choosedPicBedForQRCode, (val) => {
|
||||
if (val.value.length > 0) {
|
||||
nextTick(async () => {
|
||||
const picBedConfig = await getConfig('picBed')
|
||||
const config = pick(picBedConfig, ...choosedPicBedForQRCode.value)
|
||||
picBedConfigString.value = JSON.stringify(config)
|
||||
})
|
||||
}
|
||||
}, { deep: true })
|
||||
watch(
|
||||
() => choosedPicBedForQRCode,
|
||||
val => {
|
||||
if (val.value.length > 0) {
|
||||
nextTick(async () => {
|
||||
const picBedConfig = await getConfig('picBed')
|
||||
const config = pick(picBedConfig, ...choosedPicBedForQRCode.value)
|
||||
picBedConfigString.value = JSON.stringify(config)
|
||||
})
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const handleSelect = async (index: string) => {
|
||||
defaultActive.value = index
|
||||
if (index === routerConfig.DocumentPage) {
|
||||
const manualPageOpenSetting = await getConfig<manualPageOpenType>(configPaths.settings.manualPageOpen)
|
||||
const lang = await getConfig(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||
const lang = (await getConfig(configPaths.settings.language)) || II18nLanguage.ZH_CN
|
||||
const openManual = () => sendRPC(IRPCActionType.OPEN_MANUAL_WINDOW)
|
||||
const openExternal = () => sendRPC(IRPCActionType.OPEN_URL, lang === II18nLanguage.ZH_CN ? 'https://piclist.cn/app.html' : 'https://piclist.cn/en/app.html')
|
||||
const openExternal = () =>
|
||||
sendRPC(
|
||||
IRPCActionType.OPEN_URL,
|
||||
lang === II18nLanguage.ZH_CN ? 'https://piclist.cn/app.html' : 'https://piclist.cn/en/app.html'
|
||||
)
|
||||
|
||||
if (!manualPageOpenSetting) {
|
||||
ElMessageBox.confirm($T('MANUAL_PAGE_OPEN_TIP'), $T('MANUAL_PAGE_OPEN_TIP_TITLE'), {
|
||||
@@ -305,13 +231,15 @@ const handleSelect = async (index: string) => {
|
||||
cancelButtonText: $T('MANUAL_PAGE_OPEN_BY_BUILD_IN'),
|
||||
type: 'info',
|
||||
center: true
|
||||
}).then(() => {
|
||||
saveConfig(configPaths.settings.manualPageOpen, 'browser')
|
||||
openExternal()
|
||||
}).catch(() => {
|
||||
saveConfig(configPaths.settings.manualPageOpen, 'window')
|
||||
openManual()
|
||||
})
|
||||
.then(() => {
|
||||
saveConfig(configPaths.settings.manualPageOpen, 'browser')
|
||||
openExternal()
|
||||
})
|
||||
.catch(() => {
|
||||
saveConfig(configPaths.settings.manualPageOpen, 'window')
|
||||
openManual()
|
||||
})
|
||||
} else {
|
||||
manualPageOpenSetting === 'window' ? openManual() : openExternal()
|
||||
}
|
||||
@@ -333,33 +261,33 @@ const handleSelect = async (index: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
function minimizeWindow () {
|
||||
function minimizeWindow() {
|
||||
sendRPC(IRPCActionType.MINIMIZE_WINDOW)
|
||||
}
|
||||
|
||||
function closeWindow () {
|
||||
function closeWindow() {
|
||||
sendRPC(IRPCActionType.CLOSE_WINDOW)
|
||||
}
|
||||
|
||||
function openMenu () {
|
||||
function openMenu() {
|
||||
sendRPC(IRPCActionType.SHOW_MAIN_PAGE_MENU)
|
||||
}
|
||||
|
||||
function openMiniWindow () {
|
||||
function openMiniWindow() {
|
||||
sendRPC(IRPCActionType.OPEN_MINI_WINDOW)
|
||||
}
|
||||
|
||||
function handleCopyPicBedConfig () {
|
||||
function handleCopyPicBedConfig() {
|
||||
clipboard.writeText(picBedConfigString.value)
|
||||
$message.success($T('COPY_PICBED_CONFIG_SUCCEED'))
|
||||
}
|
||||
|
||||
function setAlwaysOnTop () {
|
||||
function setAlwaysOnTop() {
|
||||
isAlwaysOnTop.value = !isAlwaysOnTop.value
|
||||
sendRPC(IRPCActionType.MAIN_WINDOW_ON_TOP)
|
||||
}
|
||||
|
||||
onBeforeRouteUpdate(async (to) => {
|
||||
onBeforeRouteUpdate(async to => {
|
||||
if (to.params.type) {
|
||||
defaultActive.value = `${routerConfig.UPLOADER_CONFIG_PAGE}-${to.params.type}`
|
||||
} else {
|
||||
@@ -371,14 +299,13 @@ onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners(SHOW_MAIN_PAGE_QRCODE)
|
||||
ipcRenderer.removeAllListeners('updateProgress')
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'MainPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
$darwinBg = transparentify(#172426, #000, 0.7)
|
||||
.setting-list-scroll
|
||||
height 800px
|
||||
|
||||
@@ -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
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<el-empty
|
||||
:description="$T('MANAGE_NO_DATA')"
|
||||
/>
|
||||
<el-empty :description="$T('MANAGE_NO_DATA')" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
})
|
||||
|
||||
@@ -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> {{ $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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ``
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
allowpopups
|
||||
autosize="on"
|
||||
scrollbars="none"
|
||||
style="width: 100%; height: 100%;"
|
||||
style="width: 100%; height: 100%"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -20,14 +20,13 @@ import { configPaths } from '#/utils/configPaths'
|
||||
const srcUrl = ref('https://piclist.cn/app.html')
|
||||
|
||||
const updateUrl = async () => {
|
||||
const lang = await getConfig(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||
const lang = (await getConfig(configPaths.settings.language)) || II18nLanguage.ZH_CN
|
||||
srcUrl.value = lang === II18nLanguage.ZH_CN ? 'https://piclist.cn/app.html' : 'https://piclist.cn/en/app.html'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateUrl()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
id="gallery-view"
|
||||
:style="handleBarActive? 'height: 85%;': 'height: 95%;'"
|
||||
>
|
||||
<div id="gallery-view" :style="handleBarActive ? 'height: 85%;' : 'height: 95%;'">
|
||||
<div class="view-title">
|
||||
{{ $T('GALLERY') }} - {{ filterList.length }}
|
||||
<el-icon
|
||||
style="margin-left: 4px"
|
||||
class="cursor-pointer"
|
||||
@click="toggleHandleBar"
|
||||
>
|
||||
<el-icon style="margin-left: 4px" class="cursor-pointer" @click="toggleHandleBar">
|
||||
<CaretBottom v-show="!handleBarActive" />
|
||||
<CaretTop v-show="handleBarActive" />
|
||||
</el-icon>
|
||||
<span
|
||||
style="position: absolute; right: 0; top: 0; margin-right: 20px; font-size: 0.8em; color: #fff;"
|
||||
>
|
||||
<span style="position: absolute; right: 0; top: 0; margin-right: 20px; font-size: 0.8em; color: #fff">
|
||||
{{ $T('GALLERY_SYNC_DELETE') }}
|
||||
<el-switch
|
||||
v-model="deleteCloud"
|
||||
@@ -23,11 +14,7 @@
|
||||
:inactive-text="$T('SETTINGS_CLOSE')"
|
||||
@change="handleDeleteCloudFile"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:link="true"
|
||||
@click="refreshPage"
|
||||
>
|
||||
<el-button type="primary" :link="true" @click="refreshPage">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
@@ -36,10 +23,7 @@
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-icon
|
||||
size="25"
|
||||
style="cursor: pointer; margin-left: 10px;"
|
||||
>
|
||||
<el-icon size="25" style="cursor: pointer; margin-left: 10px">
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
@@ -48,14 +32,8 @@
|
||||
</div>
|
||||
<transition name="el-zoom-in-top">
|
||||
<el-row v-show="handleBarActive">
|
||||
<el-col
|
||||
:span="22"
|
||||
:offset="1"
|
||||
>
|
||||
<el-row
|
||||
class="handle-bar"
|
||||
:gutter="16"
|
||||
>
|
||||
<el-col :span="22" :offset="1">
|
||||
<el-row class="handle-bar" :gutter="16">
|
||||
<el-col :span="5">
|
||||
<el-select
|
||||
v-model="choosedPicBed"
|
||||
@@ -67,12 +45,7 @@
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-option
|
||||
v-for="item in picBedGlobal"
|
||||
:key="item.type"
|
||||
:label="item.name"
|
||||
:value="item.type"
|
||||
/>
|
||||
<el-option v-for="item in picBedGlobal" :key="item.type" :label="item.name" :value="item.type" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
@@ -88,11 +61,7 @@
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-divider
|
||||
direction="vertical"
|
||||
style="height: 100%;"
|
||||
border-style="hidden"
|
||||
/>
|
||||
<el-divider direction="vertical" style="height: 100%" border-style="hidden" />
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-select
|
||||
@@ -104,12 +73,7 @@
|
||||
teleported
|
||||
@change="handlePasteStyleChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="(value, key) in pasteStyleMap"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="value"
|
||||
/>
|
||||
<el-option v-for="(value, key) in pasteStyleMap" :key="key" :label="key" :value="value" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
@@ -122,23 +86,12 @@
|
||||
teleported
|
||||
@change="handleUseShortUrlChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="(value, key) in shortURLMap"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="value"
|
||||
/>
|
||||
<el-option v-for="(value, key) in shortURLMap" :key="key" :label="key" :value="value" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-dropdown
|
||||
teleported
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:icon="Sort"
|
||||
>
|
||||
<el-dropdown teleported>
|
||||
<el-button size="small" type="primary" :icon="Sort">
|
||||
{{ $T('MANAGE_BUCKET_SORT_TITLE') }}
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
@@ -158,57 +111,30 @@
|
||||
</el-dropdown>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row
|
||||
class="handle-bar"
|
||||
:gutter="16"
|
||||
>
|
||||
<el-row class="handle-bar" :gutter="16">
|
||||
<el-col :span="5">
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
:placeholder="$T('GALLERY_SEARCH_FILENAME')"
|
||||
size="small"
|
||||
>
|
||||
<el-input v-model="searchText" :placeholder="$T('GALLERY_SEARCH_FILENAME')" size="small">
|
||||
<template #suffix>
|
||||
<el-icon
|
||||
class="el-input__icon"
|
||||
style="cursor: pointer;"
|
||||
@click="cleanSearch"
|
||||
>
|
||||
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearch">
|
||||
<close />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-input
|
||||
v-model="searchTextURL"
|
||||
:placeholder="$T('GALLERY_SEARCH_URL')"
|
||||
size="small"
|
||||
>
|
||||
<el-input v-model="searchTextURL" :placeholder="$T('GALLERY_SEARCH_URL')" size="small">
|
||||
<template #suffix>
|
||||
<el-icon
|
||||
class="el-input__icon"
|
||||
style="cursor: pointer;"
|
||||
@click="cleanSearchUrl"
|
||||
>
|
||||
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearchUrl">
|
||||
<close />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-divider
|
||||
direction="vertical"
|
||||
style="height: 100%;"
|
||||
border-style="hidden"
|
||||
/>
|
||||
<el-divider direction="vertical" style="height: 100%" border-style="hidden" />
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<div
|
||||
class="item-base copy round"
|
||||
:class="{ active: isMultiple(choosedList) }"
|
||||
@click="multiCopy"
|
||||
>
|
||||
<div class="item-base copy round" :class="{ active: isMultiple(choosedList) }" @click="multiCopy">
|
||||
{{ $T('COPY') }}
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -216,41 +142,27 @@
|
||||
<div
|
||||
class="item-base all-pick round"
|
||||
:class="{ active: filterList.length > 0 }"
|
||||
@click="() => isShowBatchRenameDialog = true"
|
||||
@click="() => (isShowBatchRenameDialog = true)"
|
||||
>
|
||||
{{ $T('GALLERY_CHANGE_URL') }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<div
|
||||
class="item-base delete round"
|
||||
:class="{ active: isMultiple(choosedList) }"
|
||||
@click="multiRemove"
|
||||
>
|
||||
<div class="item-base delete round" :class="{ active: isMultiple(choosedList) }" @click="multiRemove">
|
||||
{{ $T('DELETE') }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<div
|
||||
class="item-base all-pick round"
|
||||
:class="{ active: filterList.length > 0 }"
|
||||
@click="toggleSelectAll"
|
||||
>
|
||||
{{ isAllSelected? $T('CANCEL'): $T('SELECT_ALL') }}
|
||||
<div class="item-base all-pick round" :class="{ active: filterList.length > 0 }" @click="toggleSelectAll">
|
||||
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</transition>
|
||||
<el-row
|
||||
class="gallery-list"
|
||||
:class="{ small: handleBarActive }"
|
||||
>
|
||||
<el-col
|
||||
:span="22"
|
||||
:offset="1"
|
||||
>
|
||||
<el-row class="gallery-list" :class="{ small: handleBarActive }">
|
||||
<el-col :span="22" :offset="1">
|
||||
<el-row :gutter="16">
|
||||
<photo-slider
|
||||
:items="filterList"
|
||||
@@ -271,43 +183,21 @@
|
||||
:xl="2"
|
||||
class="gallery-list__img"
|
||||
>
|
||||
<div
|
||||
class="gallery-list__item"
|
||||
@click="zoomImage(index)"
|
||||
>
|
||||
<img
|
||||
v-lazy="item.galleryPath || item.imgUrl"
|
||||
class="gallery-list__item-img"
|
||||
>
|
||||
<div class="gallery-list__item" @click="zoomImage(index)">
|
||||
<img v-lazy="item.galleryPath || item.imgUrl" class="gallery-list__item-img" />
|
||||
</div>
|
||||
<div
|
||||
class="gallery-list__file-name"
|
||||
:title="item.fileName"
|
||||
>
|
||||
<div class="gallery-list__file-name" :title="item.fileName">
|
||||
{{ formatFileName(item.fileName || '') }}
|
||||
</div>
|
||||
<el-row
|
||||
class="gallery-list__tool-panel"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
>
|
||||
<el-row class="gallery-list__tool-panel" justify="space-between" align="middle">
|
||||
<el-row>
|
||||
<el-icon
|
||||
class="cursor-pointer document"
|
||||
@click="copy(item)"
|
||||
>
|
||||
<el-icon class="cursor-pointer document" @click="copy(item)">
|
||||
<Document />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="cursor-pointer edit"
|
||||
@click="openDialog(item)"
|
||||
>
|
||||
<el-icon class="cursor-pointer edit" @click="openDialog(item)">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="cursor-pointer delete"
|
||||
@click="remove(item)"
|
||||
>
|
||||
<el-icon class="cursor-pointer delete" @click="remove(item)">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-row>
|
||||
@@ -332,10 +222,7 @@
|
||||
<el-button @click="dialogVisible = false">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="confirmModify"
|
||||
>
|
||||
<el-button type="primary" @click="confirmModify">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -349,10 +236,7 @@
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="margin-bottom: 10px;"
|
||||
>
|
||||
<el-link :underline="false" style="margin-bottom: 10px">
|
||||
<span>
|
||||
{{ $T('MANAGE_BUCKET_RENAME_FILE_INPUT_A') + $T('GALLERY_MATCHED') + mathcedCount + ' ' }}
|
||||
<el-tooltip
|
||||
@@ -362,9 +246,7 @@
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-icon
|
||||
color="#409EFF"
|
||||
>
|
||||
<el-icon color="#409EFF">
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
@@ -375,31 +257,16 @@
|
||||
:placeholder="$T('MANAGE_BUCKET_RENAME_FILE_INPUT_A_PLACEHOLDER')"
|
||||
clearable
|
||||
/>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="margin-bottom: 10px;margin-top: 10px;"
|
||||
>
|
||||
<el-link :underline="false" style="margin-bottom: 10px; margin-top: 10px">
|
||||
<span>
|
||||
{{ $T('MANAGE_BUCKET_RENAME_FILE_INPUT_B') }}
|
||||
<el-popover
|
||||
effect="light"
|
||||
placement="right"
|
||||
width="280"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-popover effect="light" placement="right" width="280" :persistent="false" teleported>
|
||||
<template #reference>
|
||||
<el-icon
|
||||
color="#409EFF"
|
||||
>
|
||||
<el-icon color="#409EFF">
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</template>
|
||||
<el-descriptions
|
||||
:column="1"
|
||||
style="width: 250px;"
|
||||
border
|
||||
>
|
||||
<el-descriptions :column="1" style="width: 250px" border>
|
||||
<el-descriptions-item
|
||||
v-for="(item, index) in customRenameFormatTable"
|
||||
:key="index"
|
||||
@@ -410,7 +277,7 @@
|
||||
{{ item.description }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
v-for="(item, index) in customRenameFormatTable.slice(0, customRenameFormatTable.length-1)"
|
||||
v-for="(item, index) in customRenameFormatTable.slice(0, customRenameFormatTable.length - 1)"
|
||||
:key="index"
|
||||
:label="item.placeholderB"
|
||||
align="center"
|
||||
@@ -418,40 +285,29 @@
|
||||
>
|
||||
{{ item.descriptionB }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="{auto}"
|
||||
align="center"
|
||||
label-style="width: 100px;"
|
||||
>
|
||||
<el-descriptions-item label="{auto}" align="center" label-style="width: 100px;">
|
||||
{{ $T('MANAGE_BUCKET_RENAME_FILE_TABLE_IID') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-popover>
|
||||
</span>
|
||||
</el-link>
|
||||
<el-input
|
||||
v-model="batchRenameReplace"
|
||||
placeholder="Ex. {Y}-{m}-{uuid}"
|
||||
clearable
|
||||
/>
|
||||
<div
|
||||
style="margin-top: 10px;align-items: center;display: flex;justify-content: flex-end;"
|
||||
>
|
||||
<el-input v-model="batchRenameReplace" placeholder="Ex. {Y}-{m}-{uuid}" clearable />
|
||||
<div style="margin-top: 10px; align-items: center; display: flex; justify-content: flex-end">
|
||||
<el-button
|
||||
type="danger"
|
||||
style="margin-right: 30px;"
|
||||
style="margin-right: 30px"
|
||||
plain
|
||||
:icon="Close"
|
||||
@click="() => {isShowBatchRenameDialog = false}"
|
||||
@click="
|
||||
() => {
|
||||
isShowBatchRenameDialog = false
|
||||
}
|
||||
"
|
||||
>
|
||||
{{ $T('MANAGE_BUCKET_RENAME_FILE_CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
:icon="Edit"
|
||||
@click="handleBatchRename()"
|
||||
>
|
||||
<el-button type="primary" plain :icon="Edit" @click="handleBatchRename()">
|
||||
{{ $T('MANAGE_BUCKET_RENAME_FILE_CONFIRM') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -460,12 +316,19 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
ipcRenderer,
|
||||
clipboard
|
||||
} from 'electron'
|
||||
import { ipcRenderer, clipboard } from 'electron'
|
||||
import { CheckboxValueType, ElMessageBox, ElNotification, ElMessage } from 'element-plus'
|
||||
import { InfoFilled, Close, CaretBottom, Document, Edit, Delete, CaretTop, Sort, Refresh } from '@element-plus/icons-vue'
|
||||
import {
|
||||
InfoFilled,
|
||||
Close,
|
||||
CaretBottom,
|
||||
Document,
|
||||
Edit,
|
||||
Delete,
|
||||
CaretTop,
|
||||
Sort,
|
||||
Refresh
|
||||
} from '@element-plus/icons-vue'
|
||||
import path from 'path'
|
||||
import { computed, nextTick, onActivated, onBeforeUnmount, onBeforeMount, reactive, ref, watch } from 'vue'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
@@ -538,8 +401,8 @@ onBeforeRouteUpdate((to, from) => {
|
||||
})
|
||||
|
||||
// init deleteCloud
|
||||
async function initDeleteCloud () {
|
||||
const config = await getConfig() as any
|
||||
async function initDeleteCloud() {
|
||||
const config = (await getConfig()) as any
|
||||
deleteCloud.value = config.settings.deleteCloudFile || false
|
||||
}
|
||||
|
||||
@@ -555,7 +418,7 @@ onBeforeMount(async () => {
|
||||
document.addEventListener('keyup', handleDetectShiftKey)
|
||||
})
|
||||
|
||||
function handleDetectShiftKey (event: KeyboardEvent) {
|
||||
function handleDetectShiftKey(event: KeyboardEvent) {
|
||||
if (event.key === 'Shift') {
|
||||
if (event.type === 'keydown') {
|
||||
isShiftKeyPress.value = true
|
||||
@@ -580,11 +443,11 @@ const isAllSelected = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
function formatFileName (name: string) {
|
||||
function formatFileName(name: string) {
|
||||
return path.basename(name)
|
||||
}
|
||||
|
||||
function getGallery (): IGalleryItem[] {
|
||||
function getGallery(): IGalleryItem[] {
|
||||
if (searchText.value || choosedPicBed.value.length > 0 || searchTextURL.value || dateRange.value) {
|
||||
return images.value
|
||||
.filter(item => {
|
||||
@@ -607,11 +470,12 @@ function getGallery (): IGalleryItem[] {
|
||||
isIncludesDateRange = date >= new Date(start).getTime() && date <= new Date(end).getTime() + 86400000
|
||||
}
|
||||
return isIncludesSearchText && isInChoosedPicBed && isIncludesSearchTextURL && isIncludesDateRange
|
||||
}).map(item => {
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
...item,
|
||||
src: item.imgUrl || '',
|
||||
key: (item.id || `${Date.now()}`),
|
||||
key: item.id || `${Date.now()}`,
|
||||
intro: item.fileName || ''
|
||||
}
|
||||
})
|
||||
@@ -620,22 +484,25 @@ function getGallery (): IGalleryItem[] {
|
||||
return {
|
||||
...item,
|
||||
src: item.imgUrl || '',
|
||||
key: (item.id || `${Date.now()}`),
|
||||
key: item.id || `${Date.now()}`,
|
||||
intro: item.fileName || ''
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function updateGallery () {
|
||||
async function updateGallery() {
|
||||
images.value = (await $$db.get({ orderBy: 'desc' }))!.data
|
||||
}
|
||||
|
||||
watch(() => filterList, () => {
|
||||
clearChoosedList()
|
||||
})
|
||||
watch(
|
||||
() => filterList,
|
||||
() => {
|
||||
clearChoosedList()
|
||||
}
|
||||
)
|
||||
|
||||
function handleChooseImage (val: CheckboxValueType, index: number) {
|
||||
function handleChooseImage(val: CheckboxValueType, index: number) {
|
||||
if (val === true) {
|
||||
handleBarActive.value = true
|
||||
if (lastChoosed.value !== -1 && isShiftKeyPress.value) {
|
||||
@@ -650,11 +517,11 @@ function handleChooseImage (val: CheckboxValueType, index: number) {
|
||||
}
|
||||
}
|
||||
|
||||
function refreshPage () {
|
||||
function refreshPage() {
|
||||
sendRPC(IRPCActionType.REFRESH_SETTING_WINDOW)
|
||||
}
|
||||
|
||||
function clearChoosedList () {
|
||||
function clearChoosedList() {
|
||||
isShiftKeyPress.value = false
|
||||
Object.keys(choosedList).forEach(key => {
|
||||
choosedList[key] = false
|
||||
@@ -662,29 +529,29 @@ function clearChoosedList () {
|
||||
lastChoosed.value = -1
|
||||
}
|
||||
|
||||
function zoomImage (index: number) {
|
||||
function zoomImage(index: number) {
|
||||
gallerySliderControl.index = index
|
||||
gallerySliderControl.visible = true
|
||||
changeZIndexForGallery(true)
|
||||
}
|
||||
|
||||
function changeZIndexForGallery (isOpen: boolean) {
|
||||
function changeZIndexForGallery(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||
} else {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||
}
|
||||
}
|
||||
|
||||
function handleClose () {
|
||||
function handleClose() {
|
||||
gallerySliderControl.index = 0
|
||||
gallerySliderControl.visible = false
|
||||
changeZIndexForGallery(false)
|
||||
}
|
||||
|
||||
async function copy (item: ImgInfo) {
|
||||
async function copy(item: ImgInfo) {
|
||||
item.config = JSON.parse(JSON.stringify(item.config) || '{}')
|
||||
const copyLink = await triggerRPC<string>(IRPCActionType.GALLERY_PASTE_TEXT, item)
|
||||
const obj = {
|
||||
@@ -699,61 +566,66 @@ async function copy (item: ImgInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
function remove (item: ImgInfo) {
|
||||
function remove(item: ImgInfo) {
|
||||
if (!item.id) return
|
||||
$confirm($T('TIPS_REMOVE_LINK'), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const file = await $$db.getById(item.id!)
|
||||
if (await getConfig(configPaths.settings.deleteCloudFile) && picBedsCanbeDeleted.includes(item?.type || 'placeholder')) {
|
||||
const result = await ALLApi.delete(item)
|
||||
if (result) {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
|
||||
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
|
||||
type: 'success'
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
|
||||
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
.then(async () => {
|
||||
const file = await $$db.getById(item.id!)
|
||||
if (
|
||||
(await getConfig(configPaths.settings.deleteCloudFile)) &&
|
||||
picBedsCanbeDeleted.includes(item?.type || 'placeholder')
|
||||
) {
|
||||
const result = await ALLApi.delete(item)
|
||||
if (result) {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
|
||||
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
|
||||
type: 'success'
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
|
||||
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
|
||||
type: 'error'
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
await $$db.removeById(item.id!)
|
||||
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, [file])
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
await $$db.removeById(item.id!)
|
||||
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, [file])
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
updateGallery()
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e)
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
}).catch((e) => {
|
||||
console.log(e)
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleDeleteCloudFile (val: ICheckBoxValueType) {
|
||||
function handleDeleteCloudFile(val: ICheckBoxValueType) {
|
||||
saveConfig({
|
||||
[configPaths.settings.deleteCloudFile]: val
|
||||
})
|
||||
}
|
||||
|
||||
function openDialog (item: ImgInfo) {
|
||||
function openDialog(item: ImgInfo) {
|
||||
imgInfo.id = item.id!
|
||||
imgInfo.imgUrl = item.imgUrl as string
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmModify () {
|
||||
async function confirmModify() {
|
||||
await $$db.updateById(imgInfo.id, {
|
||||
imgUrl: imgInfo.imgUrl
|
||||
})
|
||||
@@ -769,100 +641,106 @@ async function confirmModify () {
|
||||
updateGallery()
|
||||
}
|
||||
|
||||
function cleanSearch () {
|
||||
function cleanSearch() {
|
||||
searchText.value = ''
|
||||
}
|
||||
|
||||
function cleanSearchUrl () {
|
||||
function cleanSearchUrl() {
|
||||
searchTextURL.value = ''
|
||||
}
|
||||
|
||||
function isMultiple (obj: IObj) {
|
||||
function isMultiple(obj: IObj) {
|
||||
return Object.values(obj).some(item => item)
|
||||
}
|
||||
|
||||
function toggleSelectAll () {
|
||||
function toggleSelectAll() {
|
||||
const result = !isAllSelected.value
|
||||
filterList.value.forEach(item => {
|
||||
choosedList[item.id!] = result
|
||||
})
|
||||
}
|
||||
|
||||
function multiRemove () {
|
||||
function multiRemove() {
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const multiRemoveNumber = Object.values(choosedList).filter(item => item).length
|
||||
if (multiRemoveNumber) {
|
||||
$confirm($T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
||||
m: multiRemoveNumber
|
||||
}), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const files: IResult<ImgInfo>[] = []
|
||||
const imageIDList = Object.keys(choosedList)
|
||||
const isDeleteCloudFile = await getConfig(configPaths.settings.deleteCloudFile)
|
||||
if (isDeleteCloudFile) {
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const file = await $$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
if (file.type !== undefined && picBedsCanbeDeleted.includes(file.type)) {
|
||||
const result = await ALLApi.delete(file)
|
||||
if (result) {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE'),
|
||||
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
|
||||
type: 'success',
|
||||
duration: multiRemoveNumber > 5 ? 1000 : 2000
|
||||
})
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
} else {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE'),
|
||||
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
|
||||
type: 'error',
|
||||
duration: multiRemoveNumber > 5 ? 1000 : 2000
|
||||
})
|
||||
$confirm(
|
||||
$T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
||||
m: multiRemoveNumber
|
||||
}),
|
||||
$T('TIPS_NOTICE'),
|
||||
{
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
.then(async () => {
|
||||
const files: IResult<ImgInfo>[] = []
|
||||
const imageIDList = Object.keys(choosedList)
|
||||
const isDeleteCloudFile = await getConfig(configPaths.settings.deleteCloudFile)
|
||||
if (isDeleteCloudFile) {
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const file = await $$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
if (file.type !== undefined && picBedsCanbeDeleted.includes(file.type)) {
|
||||
const result = await ALLApi.delete(file)
|
||||
if (result) {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE'),
|
||||
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
|
||||
type: 'success',
|
||||
duration: multiRemoveNumber > 5 ? 1000 : 2000
|
||||
})
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
} else {
|
||||
ElNotification({
|
||||
title: $T('GALLERY_SYNC_DELETE'),
|
||||
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
|
||||
type: 'error',
|
||||
duration: multiRemoveNumber > 5 ? 1000 : 2000
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const file = await $$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
} else {
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const file = await $$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clearChoosedList()
|
||||
// TODO: check this
|
||||
// choosedList = {} // 只有删除才能将这个置空
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, files)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
clearChoosedList()
|
||||
// TODO: check this
|
||||
// choosedList = {} // 只有删除才能将这个置空
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, files)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
})
|
||||
.catch(() => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function multiCopy () {
|
||||
async function multiCopy() {
|
||||
if (Object.values(choosedList).some(item => item)) {
|
||||
const copyString: string[] = []
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
@@ -890,21 +768,21 @@ async function multiCopy () {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleHandleBar () {
|
||||
function toggleHandleBar() {
|
||||
handleBarActive.value = !handleBarActive.value
|
||||
}
|
||||
|
||||
async function handlePasteStyleChange (val: string) {
|
||||
async function handlePasteStyleChange(val: string) {
|
||||
saveConfig(configPaths.settings.pasteStyle, val)
|
||||
pasteStyle.value = val
|
||||
}
|
||||
|
||||
function handleUseShortUrlChange (value: string) {
|
||||
function handleUseShortUrlChange(value: string) {
|
||||
saveConfig(configPaths.settings.useShortUrl, value === $T('UPLOAD_SHORT_URL'))
|
||||
useShortUrl.value = value
|
||||
}
|
||||
|
||||
function sortFile (type: 'name' | 'time' | 'ext' | 'check') {
|
||||
function sortFile(type: 'name' | 'time' | 'ext' | 'check') {
|
||||
switch (type) {
|
||||
case 'name':
|
||||
fileSortNameReverse.value = !fileSortNameReverse.value
|
||||
@@ -950,7 +828,7 @@ function sortFile (type: 'name' | 'time' | 'ext' | 'check') {
|
||||
}
|
||||
}
|
||||
|
||||
function handleBatchRename () {
|
||||
function handleBatchRename() {
|
||||
isShowBatchRenameDialog.value = false
|
||||
if (batchRenameMatch.value === '') {
|
||||
ElMessage.warning($T('MANAGE_BUCKET_BATCH_RENAME_ERROR_MSG'))
|
||||
@@ -976,7 +854,9 @@ function handleBatchRename () {
|
||||
for (let i = 0; i < matchedFiles.length; i++) {
|
||||
matchedFiles[i].newUrl = matchedFiles[i].newUrl.replaceAll('{auto}', (i + 1).toString())
|
||||
}
|
||||
const duplicateFilesNum = matchedFiles.filter((item: any) => matchedFiles.filter((item2: any) => item2.newUrl === item.newUrl).length > 1).length
|
||||
const duplicateFilesNum = matchedFiles.filter(
|
||||
(item: any) => matchedFiles.filter((item2: any) => item2.newUrl === item.newUrl).length > 1
|
||||
).length
|
||||
const renamefunc = async (item: any) => {
|
||||
await $$db.updateById(item.id, {
|
||||
imgUrl: item.newUrl
|
||||
@@ -987,30 +867,38 @@ function handleBatchRename () {
|
||||
for (let i = 0; i < matchedFiles.length; i++) {
|
||||
promiseList.push(renamefunc(matchedFiles[i]))
|
||||
}
|
||||
Promise.all(promiseList).then(() => {
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
Promise.all(promiseList)
|
||||
.then(() => {
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
})
|
||||
.catch(() => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
if (duplicateFilesNum > 0) {
|
||||
ElMessageBox.confirm(`${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_A')} ${duplicateFilesNum} ${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_B')}`, $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_C'), {
|
||||
confirmButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CONFIRM'),
|
||||
cancelButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
rename()
|
||||
}).catch(() => {
|
||||
ElMessage.info($T('MANAGE_BUCKET_BATCH_RENAME_CANCEL'))
|
||||
})
|
||||
ElMessageBox.confirm(
|
||||
`${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_A')} ${duplicateFilesNum} ${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_B')}`,
|
||||
$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_C'),
|
||||
{
|
||||
confirmButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CONFIRM'),
|
||||
cancelButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CANCEL'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
rename()
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info($T('MANAGE_BUCKET_BATCH_RENAME_CANCEL'))
|
||||
})
|
||||
} else {
|
||||
rename()
|
||||
}
|
||||
@@ -1022,17 +910,18 @@ onBeforeUnmount(() => {
|
||||
|
||||
onActivated(async () => {
|
||||
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
|
||||
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl) ? $T('UPLOAD_SHORT_URL') : $T('UPLOAD_NORMAL_URL'))
|
||||
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl))
|
||||
? $T('UPLOAD_SHORT_URL')
|
||||
: $T('UPLOAD_NORMAL_URL')
|
||||
initDeleteCloud()
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'GalleryPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
.PhotoSlider
|
||||
&__BannerIcon
|
||||
&:nth-child(1)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div
|
||||
id="mini-page"
|
||||
>
|
||||
<div id="mini-page">
|
||||
<div
|
||||
id="upload-area"
|
||||
:class="{ 'is-dragover': dragover, uploading: isShowingProgress, linux: osGlobal === 'linux' }"
|
||||
:style="{ backgroundPosition: '0 ' + progress + '%'}"
|
||||
:class="{
|
||||
'is-dragover': dragover,
|
||||
uploading: isShowingProgress,
|
||||
linux: osGlobal === 'linux'
|
||||
}"
|
||||
:style="{ backgroundPosition: '0 ' + progress + '%' }"
|
||||
@drop.prevent="onDrop"
|
||||
@dragover.prevent="dragover = true"
|
||||
@dragleave.prevent="dragover = false"
|
||||
@@ -13,18 +15,10 @@
|
||||
<img
|
||||
v-if="!dragover && !isShowingProgress"
|
||||
:src="logoPath ? logoPath : require('../assets/squareLogo.png')"
|
||||
style="width: 100%; height: 100%;border-radius: 50%;"
|
||||
>
|
||||
<div
|
||||
id="upload-dragger"
|
||||
@dblclick="openUploadWindow"
|
||||
>
|
||||
<input
|
||||
id="file-uploader"
|
||||
type="file"
|
||||
multiple
|
||||
@change="onChange"
|
||||
>
|
||||
style="width: 100%; height: 100%; border-radius: 50%"
|
||||
/>
|
||||
<div id="upload-dragger" @dblclick="openUploadWindow">
|
||||
<input id="file-uploader" type="file" multiple @change="onChange" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,10 +26,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage as $message } from 'element-plus'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { IConfig } from 'piclist'
|
||||
import { onBeforeUnmount, onBeforeMount, ref, watch } from 'vue'
|
||||
|
||||
@@ -57,11 +48,12 @@ const wY = ref(-1)
|
||||
const screenX = ref(-1)
|
||||
const screenY = ref(-1)
|
||||
|
||||
async function initLogoPath () {
|
||||
async function initLogoPath() {
|
||||
const config = await getConfig<IConfig>()
|
||||
if (config) {
|
||||
if (config.settings?.isCustomMiniIcon && config.settings?.customMiniIcon) {
|
||||
logoPath.value = 'data:image/jpg;base64,' + await invokeToMain('convertPathToBase64', config.settings.customMiniIcon)
|
||||
logoPath.value =
|
||||
'data:image/jpg;base64,' + (await invokeToMain('convertPathToBase64', config.settings.customMiniIcon))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,7 +76,7 @@ onBeforeMount(async () => {
|
||||
window.addEventListener('mouseup', handleMouseUp, false)
|
||||
})
|
||||
|
||||
watch(progress, (val) => {
|
||||
watch(progress, val => {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
isShowingProgress.value = false
|
||||
@@ -95,17 +87,16 @@ watch(progress, (val) => {
|
||||
}
|
||||
})
|
||||
|
||||
function onDrop (e: DragEvent) {
|
||||
function onDrop(e: DragEvent) {
|
||||
dragover.value = false
|
||||
const items = e.dataTransfer?.items!
|
||||
const files = e.dataTransfer?.files!
|
||||
|
||||
// send files first
|
||||
if (files?.length) {
|
||||
ipcSendFiles(e.dataTransfer?.files!)
|
||||
} else {
|
||||
if (e.dataTransfer?.files?.length) {
|
||||
ipcSendFiles(e.dataTransfer.files)
|
||||
} else if (e.dataTransfer?.items) {
|
||||
const items = e.dataTransfer.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
handleURLDrag(items, e.dataTransfer!)
|
||||
handleURLDrag(items, e.dataTransfer)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
@@ -117,7 +108,7 @@ function onDrop (e: DragEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
function handleURLDrag(items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
@@ -133,20 +124,20 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
|
||||
}
|
||||
}
|
||||
|
||||
function openUploadWindow () {
|
||||
// @ts-ignore
|
||||
function openUploadWindow() {
|
||||
// @ts-expect-error file-uploader
|
||||
document.getElementById('file-uploader').click()
|
||||
}
|
||||
|
||||
function onChange (e: any) {
|
||||
function onChange(e: any) {
|
||||
ipcSendFiles(e.target.files)
|
||||
// @ts-ignore
|
||||
// @ts-expect-error file-uploader
|
||||
document.getElementById('file-uploader').value = ''
|
||||
}
|
||||
|
||||
function ipcSendFiles (files: FileList) {
|
||||
function ipcSendFiles(files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
Array.from(files).forEach(item => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
@@ -156,7 +147,7 @@ function ipcSendFiles (files: FileList) {
|
||||
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles)
|
||||
}
|
||||
|
||||
function handleMouseDown (e: MouseEvent) {
|
||||
function handleMouseDown(e: MouseEvent) {
|
||||
draggingState.value = true
|
||||
wX.value = e.pageX
|
||||
wY.value = e.pageY
|
||||
@@ -164,7 +155,7 @@ function handleMouseDown (e: MouseEvent) {
|
||||
screenY.value = e.screenY
|
||||
}
|
||||
|
||||
function handleMouseMove (e: MouseEvent) {
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (draggingState.value) {
|
||||
@@ -179,10 +170,11 @@ function handleMouseMove (e: MouseEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleMouseUp (e: MouseEvent) {
|
||||
function handleMouseUp(e: MouseEvent) {
|
||||
draggingState.value = false
|
||||
if (screenX.value === e.screenX && screenY.value === e.screenY) {
|
||||
if (e.button === 0) { // left mouse
|
||||
if (e.button === 0) {
|
||||
// left mouse
|
||||
openUploadWindow()
|
||||
} else {
|
||||
openContextMenu()
|
||||
@@ -190,7 +182,7 @@ function handleMouseUp (e: MouseEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function openContextMenu () {
|
||||
function openContextMenu() {
|
||||
sendRPC(IRPCActionType.SHOW_MINI_PAGE_MENU)
|
||||
}
|
||||
|
||||
@@ -201,47 +193,46 @@ onBeforeUnmount(() => {
|
||||
window.removeEventListener('mousemove', handleMouseMove, false)
|
||||
window.removeEventListener('mouseup', handleMouseUp, false)
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'MiniPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#mini-page
|
||||
background #409EFF
|
||||
color #FFF
|
||||
height 100vh
|
||||
width 100vw
|
||||
<style lang="stylus">
|
||||
#mini-page
|
||||
background #409EFF
|
||||
color #FFF
|
||||
height 100vh
|
||||
width 100vw
|
||||
border-radius 50%
|
||||
text-align center
|
||||
line-height 100vh
|
||||
font-size 40px
|
||||
background-size 90vh 90vw
|
||||
background-position center center
|
||||
background-repeat no-repeat
|
||||
position relative
|
||||
border 4px solid #fff
|
||||
box-sizing border-box
|
||||
cursor pointer
|
||||
&.linux
|
||||
border-radius 0
|
||||
background-size 100vh 100vw
|
||||
#upload-area
|
||||
height 100%
|
||||
width 100%
|
||||
border-radius 50%
|
||||
text-align center
|
||||
line-height 100vh
|
||||
font-size 40px
|
||||
background-size 90vh 90vw
|
||||
background-position center center
|
||||
background-repeat no-repeat
|
||||
position relative
|
||||
border 4px solid #fff
|
||||
box-sizing border-box
|
||||
cursor pointer
|
||||
transition all .2s ease-in-out
|
||||
&.linux
|
||||
border-radius 0
|
||||
background-size 100vh 100vw
|
||||
#upload-area
|
||||
&.uploading
|
||||
background: linear-gradient(to top, #409EFF 50%, #fff 51%)
|
||||
background-size 200%
|
||||
#upload-dragger
|
||||
height 100%
|
||||
width 100%
|
||||
border-radius 50%
|
||||
transition all .2s ease-in-out
|
||||
&.linux
|
||||
border-radius 0
|
||||
&.uploading
|
||||
background: linear-gradient(to top, #409EFF 50%, #fff 51%)
|
||||
background-size 200%
|
||||
#upload-dragger
|
||||
height 100%
|
||||
&.is-dragover
|
||||
background rgba(0,0,0,0.3)
|
||||
#file-uploader
|
||||
display none
|
||||
&.is-dragover
|
||||
background rgba(0,0,0,0.3)
|
||||
#file-uploader
|
||||
display none
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,72 +2,32 @@
|
||||
<div id="plugin-view">
|
||||
<div class="view-title">
|
||||
{{ $T('PLUGIN_SETTINGS') }} -
|
||||
<el-tooltip
|
||||
:content="pluginListToolTip"
|
||||
placement="right"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-icon
|
||||
class="el-icon-goods"
|
||||
@click="goAwesomeList"
|
||||
>
|
||||
<el-tooltip :content="pluginListToolTip" placement="right" :persistent="false" teleported>
|
||||
<el-icon class="el-icon-goods" @click="goAwesomeList">
|
||||
<Goods />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:content="updateAllToolTip"
|
||||
placement="left"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<el-icon
|
||||
class="el-icon-update"
|
||||
@click="handleUpdateAllPlugin"
|
||||
>
|
||||
<el-tooltip :content="updateAllToolTip" placement="left" :persistent="false" teleported>
|
||||
<el-icon class="el-icon-update" @click="handleUpdateAllPlugin">
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:content="importLocalPluginToolTip"
|
||||
placement="left"
|
||||
>
|
||||
<el-icon
|
||||
class="el-icon-download"
|
||||
:persistent="false"
|
||||
teleported
|
||||
@click="handleImportLocalPlugin"
|
||||
>
|
||||
<el-tooltip :content="importLocalPluginToolTip" placement="left">
|
||||
<el-icon class="el-icon-download" :persistent="false" teleported @click="handleImportLocalPlugin">
|
||||
<Download />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-row
|
||||
class="handle-bar"
|
||||
:class="{ 'cut-width': pluginList.length > 6 }"
|
||||
>
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
:placeholder="$T('PLUGIN_SEARCH_PLACEHOLDER')"
|
||||
size="small"
|
||||
>
|
||||
<el-row class="handle-bar" :class="{ 'cut-width': pluginList.length > 6 }">
|
||||
<el-input v-model="searchText" :placeholder="$T('PLUGIN_SEARCH_PLACEHOLDER')" size="small">
|
||||
<template #suffix>
|
||||
<el-icon
|
||||
class="el-input__icon"
|
||||
style="cursor: pointer;"
|
||||
@click="cleanSearch"
|
||||
>
|
||||
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearch">
|
||||
<close />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-row>
|
||||
<el-row
|
||||
id="pluginList"
|
||||
v-loading="loading"
|
||||
:gutter="10"
|
||||
class="plugin-list"
|
||||
>
|
||||
<el-row id="pluginList" v-loading="loading" :gutter="10" class="plugin-list">
|
||||
<el-col
|
||||
v-for="item in pluginList"
|
||||
:key="item.fullName"
|
||||
@@ -78,30 +38,11 @@
|
||||
:lg="pluginList.length === 1 ? 24 : 12"
|
||||
:xl="pluginList.length === 1 ? 24 : 12"
|
||||
>
|
||||
<div
|
||||
class="plugin-item"
|
||||
:class="{ 'darwin': osGlobal === 'darwin' }"
|
||||
>
|
||||
<div
|
||||
v-if="!item.gui"
|
||||
class="cli-only-badge"
|
||||
title="CLI only"
|
||||
>
|
||||
CLI
|
||||
</div>
|
||||
<img
|
||||
class="plugin-item__logo"
|
||||
:src="item.logo"
|
||||
:onerror="defaultLogo"
|
||||
>
|
||||
<div
|
||||
class="plugin-item__content"
|
||||
:class="{ disabled: !item.enabled }"
|
||||
>
|
||||
<div
|
||||
class="plugin-item__name"
|
||||
@click="openHomepage(item.homepage)"
|
||||
>
|
||||
<div class="plugin-item" :class="{ darwin: osGlobal === 'darwin' }">
|
||||
<div v-if="!item.gui" class="cli-only-badge" title="CLI only">CLI</div>
|
||||
<img class="plugin-item__logo" :src="item.logo" :onerror="defaultLogo" />
|
||||
<div class="plugin-item__content" :class="{ disabled: !item.enabled }">
|
||||
<div class="plugin-item__name" @click="openHomepage(item.homepage)">
|
||||
{{ item.name }} <small>{{ ' ' + item.version }}</small>
|
||||
<!-- 升级提示 -->
|
||||
<el-tag
|
||||
@@ -114,10 +55,7 @@
|
||||
new
|
||||
</el-tag>
|
||||
</div>
|
||||
<div
|
||||
class="plugin-item__desc"
|
||||
:title="item.description"
|
||||
>
|
||||
<div class="plugin-item__desc" :title="item.description">
|
||||
{{ item.description }}
|
||||
</div>
|
||||
<div class="plugin-item__info-bar">
|
||||
@@ -127,47 +65,26 @@
|
||||
<span class="plugin-item__config">
|
||||
<template v-if="searchText">
|
||||
<template v-if="!item.hasInstall">
|
||||
<span
|
||||
v-if="!item.ing"
|
||||
class="config-button install"
|
||||
@click="installPlugin(item)"
|
||||
>
|
||||
<span v-if="!item.ing" class="config-button install" @click="installPlugin(item)">
|
||||
{{ $T('PLUGIN_INSTALL') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="item.ing"
|
||||
class="config-button ing"
|
||||
>
|
||||
<span v-else-if="item.ing" class="config-button ing">
|
||||
{{ $T('PLUGIN_INSTALLING') }}
|
||||
</span>
|
||||
</template>
|
||||
<span
|
||||
v-else
|
||||
class="config-button ing"
|
||||
>
|
||||
<span v-else class="config-button ing">
|
||||
{{ $T('PLUGIN_INSTALLED') }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span
|
||||
v-if="item.ing"
|
||||
class="config-button ing"
|
||||
>
|
||||
<span v-if="item.ing" class="config-button ing">
|
||||
{{ $T('PLUGIN_DOING_SOMETHING') }}
|
||||
</span>
|
||||
<template v-else>
|
||||
<el-icon
|
||||
v-if="item.enabled"
|
||||
class="el-icon-setting"
|
||||
@click="buildContextMenu(item)"
|
||||
>
|
||||
<el-icon v-if="item.enabled" class="el-icon-setting" @click="buildContextMenu(item)">
|
||||
<Tools />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-else
|
||||
class="el-icon-remove-outline"
|
||||
@click="buildContextMenu(item)"
|
||||
>
|
||||
<el-icon v-else class="el-icon-remove-outline" @click="buildContextMenu(item)">
|
||||
<Remove />
|
||||
</el-icon>
|
||||
</template>
|
||||
@@ -178,49 +95,28 @@
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row
|
||||
v-show="needReload"
|
||||
class="reload-mask"
|
||||
:class="{ 'cut-width': pluginList.length > 6 }"
|
||||
justify="center"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
round
|
||||
@click="reloadApp"
|
||||
>
|
||||
<el-row v-show="needReload" class="reload-mask" :class="{ 'cut-width': pluginList.length > 6 }" justify="center">
|
||||
<el-button type="primary" size="small" round @click="reloadApp">
|
||||
{{ $T('TIPS_NEED_RELOAD') }}
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:modal-append-to-body="false"
|
||||
:title="$T('CONFIG_THING', {
|
||||
c: configName
|
||||
})"
|
||||
:title="
|
||||
$T('CONFIG_THING', {
|
||||
c: configName
|
||||
})
|
||||
"
|
||||
width="70%"
|
||||
append-to-body
|
||||
>
|
||||
<config-form
|
||||
:id="configName"
|
||||
ref="$configForm"
|
||||
:config="config"
|
||||
:type="currentType"
|
||||
color-mode="white"
|
||||
/>
|
||||
<config-form :id="configName" ref="$configForm" :config="config" :type="currentType" color-mode="white" />
|
||||
<template #footer>
|
||||
<el-button
|
||||
round
|
||||
@click="dialogVisible = false"
|
||||
>
|
||||
<el-button round @click="dialogVisible = false">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
@click="handleConfirmConfig"
|
||||
>
|
||||
<el-button type="primary" round @click="handleConfirmConfig">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -230,10 +126,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import axios from 'axios'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { debounce, DebouncedFunc } from 'lodash'
|
||||
import { Close, Download, Refresh, Goods, Remove, Tools } from '@element-plus/icons-vue'
|
||||
@@ -293,15 +186,15 @@ watch(npmSearchText, (val: string) => {
|
||||
|
||||
watch(dialogVisible, (val: boolean) => {
|
||||
if (val) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||
} else {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||
}
|
||||
})
|
||||
|
||||
async function getLatestVersionOfPlugIn (pluginName: string) {
|
||||
async function getLatestVersionOfPlugIn(pluginName: string) {
|
||||
try {
|
||||
const res = await axios.get(`https://registry.npmjs.com/${pluginName}`)
|
||||
latestVersionMap[pluginName] = res.data['dist-tags'].latest
|
||||
@@ -316,7 +209,7 @@ onBeforeMount(async () => {
|
||||
})
|
||||
ipcRenderer.on(PICGO_HANDLE_PLUGIN_DONE, (_: IpcRendererEvent, fullName: string) => {
|
||||
pluginList.value.forEach(item => {
|
||||
if (item.fullName === fullName || (item.name === fullName)) {
|
||||
if (item.fullName === fullName || item.name === fullName) {
|
||||
item.ing = false
|
||||
}
|
||||
})
|
||||
@@ -330,18 +223,27 @@ onBeforeMount(async () => {
|
||||
}
|
||||
loading.value = false
|
||||
})
|
||||
ipcRenderer.on('installPlugin', (_: IpcRendererEvent, { success, body }: {
|
||||
success: boolean,
|
||||
body: string
|
||||
}) => {
|
||||
loading.value = false
|
||||
pluginList.value.forEach(item => {
|
||||
if (item.fullName === body) {
|
||||
item.ing = false
|
||||
item.hasInstall = success
|
||||
ipcRenderer.on(
|
||||
'installPlugin',
|
||||
(
|
||||
_: IpcRendererEvent,
|
||||
{
|
||||
success,
|
||||
body
|
||||
}: {
|
||||
success: boolean
|
||||
body: string
|
||||
}
|
||||
})
|
||||
})
|
||||
) => {
|
||||
loading.value = false
|
||||
pluginList.value.forEach(item => {
|
||||
if (item.fullName === body) {
|
||||
item.ing = false
|
||||
item.hasInstall = success
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
ipcRenderer.on('updateSuccess', (_: IpcRendererEvent, plugin: string) => {
|
||||
loading.value = false
|
||||
pluginList.value.forEach(item => {
|
||||
@@ -357,7 +259,8 @@ onBeforeMount(async () => {
|
||||
ipcRenderer.on('uninstallSuccess', (_: IpcRendererEvent, plugin: string) => {
|
||||
loading.value = false
|
||||
pluginList.value = pluginList.value.filter(item => {
|
||||
if (item.fullName === plugin) { // restore Uploader & Transformer after uninstalling
|
||||
if (item.fullName === plugin) {
|
||||
// restore Uploader & Transformer after uninstalling
|
||||
if (item.config.transformer.name) {
|
||||
handleRestoreState('transformer', item.config.transformer.name)
|
||||
}
|
||||
@@ -370,15 +273,18 @@ onBeforeMount(async () => {
|
||||
})
|
||||
pluginNameList.value = pluginNameList.value.filter(item => item !== plugin)
|
||||
})
|
||||
ipcRenderer.on(PICGO_CONFIG_PLUGIN, (_: IpcRendererEvent, _currentType: 'plugin' | 'transformer' | 'uploader', _configName: string, _config: any) => {
|
||||
currentType.value = _currentType
|
||||
configName.value = _configName
|
||||
config.value = _config
|
||||
dialogVisible.value = true
|
||||
})
|
||||
ipcRenderer.on(
|
||||
PICGO_CONFIG_PLUGIN,
|
||||
(_: IpcRendererEvent, _currentType: 'plugin' | 'transformer' | 'uploader', _configName: string, _config: any) => {
|
||||
currentType.value = _currentType
|
||||
configName.value = _configName
|
||||
config.value = _config
|
||||
dialogVisible.value = true
|
||||
}
|
||||
)
|
||||
ipcRenderer.on(PICGO_HANDLE_PLUGIN_ING, (_: IpcRendererEvent, fullName: string) => {
|
||||
pluginList.value.forEach(item => {
|
||||
if (item.fullName === fullName || (item.name === fullName)) {
|
||||
if (item.fullName === fullName || item.name === fullName) {
|
||||
item.ing = true
|
||||
}
|
||||
})
|
||||
@@ -394,14 +300,14 @@ onBeforeMount(async () => {
|
||||
})
|
||||
getPluginList()
|
||||
getSearchResult = debounce(_getSearchResult, 50)
|
||||
needReload.value = await getConfig<boolean>(configPaths.needReload) || false
|
||||
needReload.value = (await getConfig<boolean>(configPaths.needReload)) || false
|
||||
})
|
||||
|
||||
async function buildContextMenu (plugin: IPicGoPlugin) {
|
||||
async function buildContextMenu(plugin: IPicGoPlugin) {
|
||||
sendRPC(IRPCActionType.SHOW_PLUGIN_PAGE_MENU, plugin)
|
||||
}
|
||||
|
||||
function handleResize () {
|
||||
function handleResize() {
|
||||
const myDiv = document.getElementById('pluginList') as HTMLElement
|
||||
const windowHeight = window.innerHeight
|
||||
const newHeight = windowHeight * 0.75
|
||||
@@ -412,33 +318,35 @@ onMounted(() => {
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
function getPluginList () {
|
||||
function getPluginList() {
|
||||
sendRPC(IRPCActionType.PLUGIN_GET_LIST)
|
||||
}
|
||||
|
||||
function installPlugin (item: IPicGoPlugin) {
|
||||
function installPlugin(item: IPicGoPlugin) {
|
||||
if (!item.gui) {
|
||||
$confirm($T('TIPS_PLUGIN_NOT_GUI_IMPLEMENT'), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
item.ing = true
|
||||
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
|
||||
}).catch(() => {
|
||||
console.log('Install canceled')
|
||||
})
|
||||
.then(() => {
|
||||
item.ing = true
|
||||
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('Install canceled')
|
||||
})
|
||||
} else {
|
||||
item.ing = true
|
||||
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
|
||||
}
|
||||
}
|
||||
|
||||
function reloadApp () {
|
||||
function reloadApp() {
|
||||
sendRPC(IRPCActionType.RELOAD_APP)
|
||||
}
|
||||
|
||||
async function handleReload () {
|
||||
async function handleReload() {
|
||||
saveConfig({
|
||||
needReload: true
|
||||
})
|
||||
@@ -451,12 +359,12 @@ async function handleReload () {
|
||||
}
|
||||
}
|
||||
|
||||
function cleanSearch () {
|
||||
function cleanSearch() {
|
||||
searchText.value = ''
|
||||
}
|
||||
|
||||
async function handleConfirmConfig () {
|
||||
const result = (await $configForm.value?.validate() || false)
|
||||
async function handleConfirmConfig() {
|
||||
const result = (await $configForm.value?.validate()) || false
|
||||
if (result !== false) {
|
||||
switch (currentType.value) {
|
||||
case 'plugin':
|
||||
@@ -486,11 +394,12 @@ async function handleConfirmConfig () {
|
||||
}
|
||||
}
|
||||
|
||||
function _getSearchResult (val: string) {
|
||||
axios.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
|
||||
function _getSearchResult(val: string) {
|
||||
axios
|
||||
.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
|
||||
.then((res: INPMSearchResult) => {
|
||||
pluginList.value = res.data.objects
|
||||
.filter((item:INPMSearchResultObject) => {
|
||||
.filter((item: INPMSearchResultObject) => {
|
||||
return item.package.name.includes('picgo-plugin-')
|
||||
})
|
||||
.map((item: INPMSearchResultObject) => {
|
||||
@@ -504,7 +413,7 @@ function _getSearchResult (val: string) {
|
||||
})
|
||||
}
|
||||
|
||||
function handleSearchResult (item: INPMSearchResultObject) {
|
||||
function handleSearchResult(item: INPMSearchResultObject) {
|
||||
const name = handleStreamlinePluginName(item.package.name)
|
||||
let gui = false
|
||||
if (item.package.keywords && item.package.keywords.length > 0) {
|
||||
@@ -528,7 +437,7 @@ function handleSearchResult (item: INPMSearchResultObject) {
|
||||
}
|
||||
|
||||
// restore Uploader & Transformer
|
||||
async function handleRestoreState (item: string, name: string) {
|
||||
async function handleRestoreState(item: string, name: string) {
|
||||
if (item === 'uploader') {
|
||||
const current = await getConfig(configPaths.picBed.current)
|
||||
if (current === name) {
|
||||
@@ -548,22 +457,22 @@ async function handleRestoreState (item: string, name: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function openHomepage (url: string) {
|
||||
function openHomepage(url: string) {
|
||||
if (url) {
|
||||
sendRPC(IRPCActionType.OPEN_URL, url)
|
||||
}
|
||||
}
|
||||
|
||||
function goAwesomeList () {
|
||||
function goAwesomeList() {
|
||||
sendRPC(IRPCActionType.OPEN_URL, 'https://github.com/PicGo/Awesome-PicGo')
|
||||
}
|
||||
|
||||
function handleImportLocalPlugin () {
|
||||
function handleImportLocalPlugin() {
|
||||
sendRPC(IRPCActionType.PLUGIN_IMPORT_LOCAL)
|
||||
loading.value = true
|
||||
}
|
||||
|
||||
function handleUpdateAllPlugin () {
|
||||
function handleUpdateAllPlugin() {
|
||||
sendRPC(IRPCActionType.PLUGIN_UPDATE_ALL, toRaw(pluginNameList.value))
|
||||
}
|
||||
|
||||
@@ -576,14 +485,13 @@ onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners('hideLoading')
|
||||
ipcRenderer.removeAllListeners(PICGO_HANDLE_PLUGIN_DONE)
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'PluginPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
$darwinBg = #172426
|
||||
#plugin-view
|
||||
position absolute
|
||||
|
||||
@@ -1,29 +1,14 @@
|
||||
<template>
|
||||
<div id="rename-page">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form ref="formRef" :model="form" @submit.prevent>
|
||||
<el-form-item
|
||||
:label="$T('FILE_RENAME')"
|
||||
prop="fileName"
|
||||
:rules="[
|
||||
{ required: true, message: 'file name is required', trigger: 'blur' }
|
||||
]"
|
||||
:rules="[{ required: true, message: 'file name is required', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.fileName"
|
||||
size="small"
|
||||
autofocus
|
||||
@keyup.enter="confirmName"
|
||||
>
|
||||
<el-input v-model="form.fileName" size="small" autofocus @keyup.enter="confirmName">
|
||||
<template #suffix>
|
||||
<el-icon
|
||||
class="el-input__icon"
|
||||
style="cursor: pointer;"
|
||||
@click="form.fileName = ''"
|
||||
>
|
||||
<el-icon class="el-input__icon" style="cursor: pointer" @click="form.fileName = ''">
|
||||
<close />
|
||||
</el-icon>
|
||||
</template>
|
||||
@@ -32,19 +17,10 @@
|
||||
</el-form>
|
||||
<el-row>
|
||||
<div class="pull-right">
|
||||
<el-button
|
||||
round
|
||||
size="small"
|
||||
@click="cancel"
|
||||
>
|
||||
<el-button round size="small" @click="cancel">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
@click="confirmName"
|
||||
>
|
||||
<el-button type="primary" round size="small" @click="confirmName">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -84,15 +60,15 @@ onBeforeMount(() => {
|
||||
ipcRenderer.send(GET_RENAME_FILE_NAME)
|
||||
})
|
||||
|
||||
function confirmName () {
|
||||
formRef.value?.validate((valid) => {
|
||||
function confirmName() {
|
||||
formRef.value?.validate(valid => {
|
||||
if (valid) {
|
||||
sendToMain(`${RENAME_FILE_NAME}${id.value}`, form.fileName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function cancel () {
|
||||
function cancel() {
|
||||
// if cancel, use origin file name
|
||||
sendToMain(`${RENAME_FILE_NAME}${id.value}`, form.originName)
|
||||
}
|
||||
@@ -100,18 +76,17 @@ function cancel () {
|
||||
onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners(RENAME_FILE_NAME)
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'RenamePage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#rename-page
|
||||
padding 0 20px
|
||||
.pull-right
|
||||
float right
|
||||
.el-form-item__label
|
||||
color #ddd
|
||||
<style lang="stylus">
|
||||
#rename-page
|
||||
padding 0 20px
|
||||
.pull-right
|
||||
float right
|
||||
.el-form-item__label
|
||||
color #ddd
|
||||
</style>
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
{{ $T('SETTINGS_SET_SHORTCUT') }}
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-table
|
||||
class="shortcut-page-table-border"
|
||||
:data="list"
|
||||
@@ -15,42 +12,25 @@
|
||||
header-cell-class-name="shortcut-page-table-border"
|
||||
cell-class-name="shortcut-page-table-border"
|
||||
>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_NAME')"
|
||||
>
|
||||
<el-table-column :label="$T('SHORTCUT_NAME')">
|
||||
<template #default="scope">
|
||||
{{ scope.row.label ? scope.row.label : scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
width="160px"
|
||||
:label="$T('SHORTCUT_BIND')"
|
||||
prop="key"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_STATUS')"
|
||||
>
|
||||
<el-table-column width="160px" :label="$T('SHORTCUT_BIND')" prop="key" />
|
||||
<el-table-column :label="$T('SHORTCUT_STATUS')">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
size="small"
|
||||
:type="scope.row.enable ? 'success' : 'danger'"
|
||||
>
|
||||
<el-tag size="small" :type="scope.row.enable ? 'success' : 'danger'">
|
||||
{{ scope.row.enable ? $T('SHORTCUT_ENABLED') : $T('SHORTCUT_DISABLED') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_SOURCE')"
|
||||
width="100px"
|
||||
>
|
||||
<el-table-column :label="$T('SHORTCUT_SOURCE')" width="100px">
|
||||
<template #default="scope">
|
||||
{{ calcOriginShowName(scope.row.from) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_HANDLE')"
|
||||
width="100px"
|
||||
>
|
||||
<el-table-column :label="$T('SHORTCUT_HANDLE')" width="100px">
|
||||
<template #default="scope">
|
||||
<el-row>
|
||||
<el-button
|
||||
@@ -85,10 +65,7 @@
|
||||
:modal-append-to-body="false"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
label-position="top"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form label-position="top" label-width="80px">
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="shortKey"
|
||||
@@ -99,17 +76,10 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button
|
||||
round
|
||||
@click="cancelKeyBinding"
|
||||
>
|
||||
<el-button round @click="cancelKeyBinding">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
@click="confirmKeyBinding"
|
||||
>
|
||||
<el-button type="primary" round @click="confirmKeyBinding">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -148,38 +118,38 @@ watch(keyBindingVisible, (val: boolean) => {
|
||||
sendRPC(IRPCActionType.SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE, val)
|
||||
})
|
||||
|
||||
function calcOrigin (item: string) {
|
||||
function calcOrigin(item: string) {
|
||||
const [origin] = item.split(':')
|
||||
return origin
|
||||
}
|
||||
|
||||
function calcOriginShowName (item: string) {
|
||||
function calcOriginShowName(item: string) {
|
||||
return item.replace('picgo-plugin-', '')
|
||||
}
|
||||
|
||||
function toggleEnable (item: IShortKeyConfig) {
|
||||
function toggleEnable(item: IShortKeyConfig) {
|
||||
const status = !item.enable
|
||||
item.enable = status
|
||||
sendRPC(IRPCActionType.SHORTKEY_BIND_OR_UNBIND, item, item.from)
|
||||
}
|
||||
|
||||
function keyDetect (event: KeyboardEvent) {
|
||||
function keyDetect(event: KeyboardEvent) {
|
||||
shortKey.value = keyBinding(event).join('+')
|
||||
}
|
||||
|
||||
async function openKeyBindingDialog (config: IShortKeyConfig, index: number) {
|
||||
async function openKeyBindingDialog(config: IShortKeyConfig, index: number) {
|
||||
command.value = `${config.from}:${config.name}`
|
||||
shortKey.value = await getConfig(`settings.shortKey.${command.value}.key`) || ''
|
||||
shortKey.value = (await getConfig(`settings.shortKey.${command.value}.key`)) || ''
|
||||
currentIndex.value = index
|
||||
keyBindingVisible.value = true
|
||||
}
|
||||
|
||||
async function cancelKeyBinding () {
|
||||
async function cancelKeyBinding() {
|
||||
keyBindingVisible.value = false
|
||||
shortKey.value = await getConfig<string>(`settings.shortKey.${command.value}.key`) || ''
|
||||
shortKey.value = (await getConfig<string>(`settings.shortKey.${command.value}.key`)) || ''
|
||||
}
|
||||
|
||||
async function confirmKeyBinding () {
|
||||
async function confirmKeyBinding() {
|
||||
const oldKey = await getConfig<string>(`settings.shortKey.${command.value}.key`)
|
||||
const config = Object.assign({}, list.value[currentIndex.value])
|
||||
config.key = shortKey.value
|
||||
@@ -201,7 +171,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
#shortcut-page
|
||||
.shortcut-page-table-border
|
||||
border-color darken(#eee, 50%)
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
<template>
|
||||
<div class="toolbox">
|
||||
<el-row>
|
||||
<el-row
|
||||
class="toolbox-header"
|
||||
>
|
||||
<el-row class="toolbox-header">
|
||||
<el-row>
|
||||
<img
|
||||
class="toolbox-header__logo"
|
||||
:src="defaultLogo"
|
||||
>
|
||||
<img class="toolbox-header__logo" :src="defaultLogo" />
|
||||
<el-row class="toolbox-header__text">
|
||||
<el-row class="toolbox-header__title">
|
||||
{{ $T('TOOLBOX_TITLE') }}
|
||||
@@ -20,12 +15,7 @@
|
||||
</el-row>
|
||||
<el-row>
|
||||
<template v-if="progress !== 100">
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
:disabled="isLoading"
|
||||
@click="handleCheck"
|
||||
>
|
||||
<el-button type="primary" round :disabled="isLoading" @click="handleCheck">
|
||||
{{ $T('TOOLBOX_START_SCAN') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -36,23 +26,14 @@
|
||||
</template>
|
||||
<template v-else-if="!isAllSuccess">
|
||||
<template v-if="canFixLength !== 0">
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
@click="handleFix"
|
||||
>
|
||||
<el-button type="primary" round @click="handleFix">
|
||||
{{ $T('TOOLBOX_START_FIX') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="toolbox-cant-fix toolbox-tips">
|
||||
{{ $T('TOOLBOX_CANT_AUTO_FIX') }}
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
class="toolbox-cant-fix__btn"
|
||||
@click="handleCheck"
|
||||
>
|
||||
<el-button type="primary" round class="toolbox-cant-fix__btn" @click="handleCheck">
|
||||
{{ $T('TOOLBOX_RE_SCAN') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -62,23 +43,11 @@
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="progress">
|
||||
<el-progress
|
||||
:percentage="progress"
|
||||
:format="format"
|
||||
/>
|
||||
<el-progress :percentage="progress" :format="format" />
|
||||
</el-row>
|
||||
<el-collapse
|
||||
v-model="activeTypes"
|
||||
accordion
|
||||
>
|
||||
<el-collapse-item
|
||||
v-for="(item, key) in fixList"
|
||||
:key="key"
|
||||
:name="key"
|
||||
>
|
||||
<template #title>
|
||||
{{ item.title }} <toolbox-status-icon :status="item.status" />
|
||||
</template>
|
||||
<el-collapse v-model="activeTypes" accordion>
|
||||
<el-collapse-item v-for="(item, key) in fixList" :key="key" :name="key">
|
||||
<template #title> {{ item.title }} <toolbox-status-icon :status="item.status" /> </template>
|
||||
<div class="toolbox-item-msg">
|
||||
{{ item.msg || '' }}
|
||||
<template v-if="item.handler && item.handlerText && item.value">
|
||||
@@ -115,7 +84,7 @@ const fixList = reactive<IToolboxMap>({
|
||||
title: $T('TOOLBOX_CHECK_CONFIG_FILE_BROKEN'),
|
||||
status: IToolboxItemCheckStatus.INIT,
|
||||
handlerText: $T('SETTINGS_OPEN_CONFIG_FILE'),
|
||||
handler (value: string) {
|
||||
handler(value: string) {
|
||||
sendRPC(IRPCActionType.OPEN_FILE, value)
|
||||
}
|
||||
},
|
||||
@@ -127,7 +96,7 @@ const fixList = reactive<IToolboxMap>({
|
||||
title: $T('TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD'), // picgo-image-clipboard folder
|
||||
status: IToolboxItemCheckStatus.INIT,
|
||||
handlerText: $T('OPEN_FILE_PATH'),
|
||||
handler (value: string) {
|
||||
handler(value: string) {
|
||||
sendRPC(IRPCActionType.OPEN_FILE, value)
|
||||
}
|
||||
},
|
||||
@@ -144,7 +113,7 @@ const progress = computed(() => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
return status !== IToolboxItemCheckStatus.INIT && status !== IToolboxItemCheckStatus.LOADING
|
||||
}).length
|
||||
return done / total * 100
|
||||
return (done / total) * 100
|
||||
})
|
||||
|
||||
const isAllSuccess = computed(() => {
|
||||
@@ -192,37 +161,44 @@ const handleCheck = () => {
|
||||
}
|
||||
|
||||
const handleFix = async () => {
|
||||
const fixRes = await Promise.all(Object.keys(fixList).filter(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
|
||||
}).map(async key => {
|
||||
return triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key as IToolboxItemType)
|
||||
}))
|
||||
const fixRes = await Promise.all(
|
||||
Object.keys(fixList)
|
||||
.filter(key => {
|
||||
const status = fixList[key as IToolboxItemType].status
|
||||
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
|
||||
})
|
||||
.map(async key => {
|
||||
return triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key as IToolboxItemType)
|
||||
})
|
||||
)
|
||||
|
||||
fixRes.filter(item => item !== null).forEach(item => {
|
||||
if (item) {
|
||||
fixList[item.type].status = item.status
|
||||
fixList[item.type].msg = item.msg
|
||||
fixList[item.type].value = item.value
|
||||
}
|
||||
})
|
||||
fixRes
|
||||
.filter(item => item !== null)
|
||||
.forEach(item => {
|
||||
if (item) {
|
||||
fixList[item.type].status = item.status
|
||||
fixList[item.type].msg = item.msg
|
||||
fixList[item.type].value = item.value
|
||||
}
|
||||
})
|
||||
|
||||
$confirm($T('TOOLBOX_FIX_DONE_NEED_RELOAD'), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'info'
|
||||
}).then(() => {
|
||||
sendRPC(IRPCActionType.RELOAD_APP)
|
||||
}).catch(() => {})
|
||||
})
|
||||
.then(() => {
|
||||
sendRPC(IRPCActionType.RELOAD_APP)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ToolBoxPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
.toolbox
|
||||
padding 0 40px
|
||||
&-header
|
||||
|
||||
@@ -1,33 +1,16 @@
|
||||
<template>
|
||||
<div id="tray-page">
|
||||
<div
|
||||
class="open-main-window"
|
||||
@click="openSettingWindow"
|
||||
>
|
||||
<div class="open-main-window" @click="openSettingWindow">
|
||||
{{ $T('OPEN_MAIN_WINDOW') }}
|
||||
</div>
|
||||
<div class="content">
|
||||
<div
|
||||
v-if="clipboardFiles.length > 0"
|
||||
class="wait-upload-img"
|
||||
>
|
||||
<div v-if="clipboardFiles.length > 0" class="wait-upload-img">
|
||||
<div class="list-title">
|
||||
{{ $T('WAIT_TO_UPLOAD') }}
|
||||
</div>
|
||||
<div
|
||||
v-for="(item, index) in clipboardFiles"
|
||||
:key="index"
|
||||
class="img-list"
|
||||
>
|
||||
<div
|
||||
class="upload-img__container"
|
||||
:class="{ upload: uploadFlag }"
|
||||
@click="uploadClipboardFiles"
|
||||
>
|
||||
<img
|
||||
:src="item.imgUrl"
|
||||
class="upload-img"
|
||||
>
|
||||
<div v-for="(item, index) in clipboardFiles" :key="index" class="img-list">
|
||||
<div class="upload-img__container" :class="{ upload: uploadFlag }" @click="uploadClipboardFiles">
|
||||
<img :src="item.imgUrl" class="upload-img" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,23 +18,10 @@
|
||||
<div class="list-title">
|
||||
{{ $T('ALREADY_UPLOAD') }}
|
||||
</div>
|
||||
<div
|
||||
v-for="item in files"
|
||||
:key="item.imgUrl"
|
||||
class="img-list"
|
||||
>
|
||||
<div
|
||||
class="upload-img__container"
|
||||
@click="copyTheLink(item)"
|
||||
>
|
||||
<img
|
||||
v-lazy="item.imgUrl"
|
||||
class="upload-img"
|
||||
>
|
||||
<div
|
||||
class="upload-img__title"
|
||||
:title="item.fileName"
|
||||
>
|
||||
<div v-for="item in files" :key="item.imgUrl" class="img-list">
|
||||
<div class="upload-img__container" @click="copyTheLink(item)">
|
||||
<img v-lazy="item.imgUrl" class="upload-img" />
|
||||
<div class="upload-img__title" :title="item.fileName">
|
||||
{{ item.fileName }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,11 +55,11 @@ const notification = reactive({
|
||||
const clipboardFiles = ref<ImgInfo[]>([])
|
||||
const uploadFlag = ref(false)
|
||||
|
||||
function openSettingWindow () {
|
||||
function openSettingWindow() {
|
||||
sendRPC(IRPCActionType.OPEN_WINDOW, IWindowList.SETTING_WINDOW)
|
||||
}
|
||||
|
||||
async function getData () {
|
||||
async function getData() {
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
|
||||
}
|
||||
|
||||
@@ -112,8 +82,8 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
return customLink
|
||||
}
|
||||
|
||||
async function copyTheLink (item: ImgInfo) {
|
||||
const pasteStyle = await getConfig<IPasteStyle>(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
async function copyTheLink(item: ImgInfo) {
|
||||
const pasteStyle = (await getConfig<IPasteStyle>(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
|
||||
const customLink = await getConfig<string>(configPaths.settings.customLink)
|
||||
const txt = await pasteTemplate(pasteStyle, item, customLink)
|
||||
clipboard.writeText(txt)
|
||||
@@ -123,7 +93,7 @@ async function copyTheLink (item: ImgInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) {
|
||||
async function pasteTemplate(style: IPasteStyle, item: ImgInfo, customLink: string | undefined) {
|
||||
let url = item.url || item.imgUrl
|
||||
if (item.type === 'aws-s3' || item.type === 'aws-s3-plist') {
|
||||
url = item.imgUrl || item.url || ''
|
||||
@@ -131,9 +101,9 @@ async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: str
|
||||
if ((await getConfig(configPaths.settings.encodeOutputURL)) === true) {
|
||||
url = handleUrlEncode(url)
|
||||
}
|
||||
const useShortUrl = await getConfig(configPaths.settings.useShortUrl) || false
|
||||
const useShortUrl = (await getConfig(configPaths.settings.useShortUrl)) || false
|
||||
if (useShortUrl) {
|
||||
url = await triggerRPC<string>(IRPCActionType.TRAY_GET_SHORT_URL, url) || url
|
||||
url = (await triggerRPC<string>(IRPCActionType.TRAY_GET_SHORT_URL, url)) || url
|
||||
}
|
||||
notification.body = url
|
||||
const _customLink = customLink || ''
|
||||
@@ -150,18 +120,26 @@ async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: str
|
||||
return tpl[style]
|
||||
}
|
||||
|
||||
function disableDragFile () {
|
||||
window.addEventListener('dragover', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
window.addEventListener('drop', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
function disableDragFile() {
|
||||
window.addEventListener(
|
||||
'dragover',
|
||||
e => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
},
|
||||
false
|
||||
)
|
||||
window.addEventListener(
|
||||
'drop',
|
||||
e => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
},
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
function uploadClipboardFiles () {
|
||||
function uploadClipboardFiles() {
|
||||
if (uploadFlag.value) {
|
||||
return
|
||||
}
|
||||
@@ -177,13 +155,19 @@ onBeforeMount(() => {
|
||||
const item = _files[i]
|
||||
await $$db.insert(item)
|
||||
}
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
|
||||
files.value = (await $$db.get<ImgInfo>({
|
||||
orderBy: 'desc',
|
||||
limit: 5
|
||||
}))!.data
|
||||
})
|
||||
ipcRenderer.on('clipboardFiles', (_: Event, files: ImgInfo[]) => {
|
||||
clipboardFiles.value = files
|
||||
})
|
||||
ipcRenderer.on('uploadFiles', async () => {
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
|
||||
files.value = (await $$db.get<ImgInfo>({
|
||||
orderBy: 'desc',
|
||||
limit: 5
|
||||
}))!.data
|
||||
uploadFlag.value = false
|
||||
})
|
||||
ipcRenderer.on('updateFiles', () => {
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
<template>
|
||||
<div id="upload-view">
|
||||
<el-row
|
||||
:gutter="16"
|
||||
align="middle"
|
||||
>
|
||||
<el-col
|
||||
:span="24"
|
||||
>
|
||||
<el-row :gutter="16" align="middle">
|
||||
<el-col :span="24">
|
||||
<div class="view-title">
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
effect="light"
|
||||
:content="$T('UPLOAD_VIEW_HINT')"
|
||||
:persistent="false"
|
||||
teleported
|
||||
>
|
||||
<span
|
||||
id="upload-view-title"
|
||||
@click="handlePicBedNameClick(picBedName, picBedConfigName)"
|
||||
>
|
||||
<el-tooltip placement="top" effect="light" :content="$T('UPLOAD_VIEW_HINT')" :persistent="false" teleported>
|
||||
<span id="upload-view-title" @click="handlePicBedNameClick(picBedName, picBedConfigName)">
|
||||
{{ picBedName }} - {{ picBedConfigName || 'Default' }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-icon
|
||||
style="cursor: pointer; margin-left: 4px;"
|
||||
@click="handleChangePicBed"
|
||||
>
|
||||
<el-icon style="cursor: pointer; margin-left: 4px" @click="handleChangePicBed">
|
||||
<CaretBottom />
|
||||
</el-icon>
|
||||
<el-button
|
||||
@@ -46,29 +29,22 @@
|
||||
@dragover.prevent="dragover = true"
|
||||
@dragleave.prevent="dragover = false"
|
||||
>
|
||||
<div
|
||||
id="upload-dragger"
|
||||
@click="openUplodWindow"
|
||||
>
|
||||
<div id="upload-dragger" @click="openUplodWindow">
|
||||
<el-icon>
|
||||
<UploadFilled />
|
||||
</el-icon>
|
||||
<div class="upload-dragger__text">
|
||||
{{ $T('DRAG_FILE_TO_HERE') }} <span>{{ $T('CLICK_TO_UPLOAD') }}</span>
|
||||
{{ $T('DRAG_FILE_TO_HERE') }}
|
||||
<span>{{ $T('CLICK_TO_UPLOAD') }}</span>
|
||||
</div>
|
||||
<input
|
||||
id="file-uploader"
|
||||
type="file"
|
||||
multiple
|
||||
@change="onChange"
|
||||
>
|
||||
<input id="file-uploader" type="file" multiple @change="onChange" />
|
||||
</div>
|
||||
</div>
|
||||
<el-progress
|
||||
:percentage="progress"
|
||||
:show-text="false"
|
||||
class="upload-progress"
|
||||
:class="{ 'show': showProgress }"
|
||||
:class="{ show: showProgress }"
|
||||
:status="showError ? 'exception' : undefined"
|
||||
/>
|
||||
<div class="paste-style">
|
||||
@@ -76,35 +52,16 @@
|
||||
<div class="paste-style__text">
|
||||
{{ $T('LINK_FORMAT') }}
|
||||
</div>
|
||||
<el-radio-group
|
||||
v-model="pasteStyle"
|
||||
size="small"
|
||||
@change="handlePasteStyleChange"
|
||||
>
|
||||
<el-radio-button
|
||||
v-for="(item, key) in pasteFormatList"
|
||||
:key="key"
|
||||
:value="key"
|
||||
:title="item"
|
||||
>
|
||||
<el-radio-group v-model="pasteStyle" size="small" @change="handlePasteStyleChange">
|
||||
<el-radio-button v-for="(item, key) in pasteFormatList" :key="key" :value="key" :title="item">
|
||||
{{ key }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-radio-group
|
||||
v-model="useShortUrl"
|
||||
size="small"
|
||||
@change="handleUseShortUrlChange"
|
||||
>
|
||||
<el-radio-button
|
||||
:value="true"
|
||||
style="border-radius: 5px"
|
||||
>
|
||||
<el-radio-group v-model="useShortUrl" size="small" @change="handleUseShortUrlChange">
|
||||
<el-radio-button :value="true" style="border-radius: 5px">
|
||||
{{ $T('UPLOAD_SHORT_URL') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button
|
||||
:value="false"
|
||||
style="border-radius: 5px"
|
||||
>
|
||||
<el-radio-button :value="false" style="border-radius: 5px">
|
||||
{{ $T('UPLOAD_NORMAL_URL') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
@@ -146,9 +103,7 @@
|
||||
align-center
|
||||
append-to-body
|
||||
>
|
||||
<ImageProcessSetting
|
||||
v-model="imageProcessDialogVisible"
|
||||
/>
|
||||
<ImageProcessSetting v-model="imageProcessDialogVisible" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -168,14 +123,9 @@ import { sendRPC, triggerRPC } from '@/utils/common'
|
||||
import { getConfig, saveConfig } from '@/utils/dataSender'
|
||||
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
|
||||
|
||||
import {
|
||||
SHOW_INPUT_BOX,
|
||||
SHOW_INPUT_BOX_RESPONSE
|
||||
} from '#/events/constants'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
import { IPasteStyle, IRPCActionType } from '#/types/enum'
|
||||
import {
|
||||
isUrl
|
||||
} from '#/utils/common'
|
||||
import { isUrl } from '#/utils/common'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
const $router = useRouter()
|
||||
@@ -228,7 +178,7 @@ const handleImageProcess = () => {
|
||||
|
||||
watch(progress, onProgressChange)
|
||||
|
||||
function onProgressChange (val: number) {
|
||||
function onProgressChange(val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
showProgress.value = false
|
||||
@@ -240,10 +190,10 @@ function onProgressChange (val: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePicBedNameClick (_picBedName: string, picBedConfigName: string | undefined) {
|
||||
async function handlePicBedNameClick(_picBedName: string, picBedConfigName: string | undefined) {
|
||||
const formatedpicBedConfigName = picBedConfigName || 'Default'
|
||||
const currentPicBed = await getConfig<string>(configPaths.picBed.current)
|
||||
const currentPicBedConfig = await getConfig<any[]>(`uploader.${currentPicBed}`) as any || {}
|
||||
const currentPicBedConfig = ((await getConfig<any[]>(`uploader.${currentPicBed}`)) as any) || {}
|
||||
const configList = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, currentPicBed)
|
||||
const currentConfigList = configList?.configList ?? []
|
||||
const config = currentConfigList.find((item: any) => item._configName === formatedpicBedConfigName)
|
||||
@@ -265,19 +215,18 @@ onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners('syncPicBed')
|
||||
})
|
||||
|
||||
function onDrop (e: DragEvent) {
|
||||
function onDrop(e: DragEvent) {
|
||||
dragover.value = false
|
||||
const items = e.dataTransfer?.items!
|
||||
const files = e.dataTransfer?.files!
|
||||
|
||||
// send files first
|
||||
if (files?.length) {
|
||||
ipcSendFiles(e.dataTransfer?.files!)
|
||||
} else {
|
||||
if (e.dataTransfer?.files?.length) {
|
||||
ipcSendFiles(e.dataTransfer.files)
|
||||
} else if (e.dataTransfer?.items) {
|
||||
const items = e.dataTransfer.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
handleURLDrag(items, e.dataTransfer!)
|
||||
handleURLDrag(items, e.dataTransfer)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
const str = e.dataTransfer.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [{ path: str }])
|
||||
} else {
|
||||
@@ -287,7 +236,7 @@ function onDrop (e: DragEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
function handleURLDrag(items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
@@ -303,18 +252,18 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
|
||||
}
|
||||
}
|
||||
|
||||
function openUplodWindow () {
|
||||
function openUplodWindow() {
|
||||
document.getElementById('file-uploader')!.click()
|
||||
}
|
||||
|
||||
function onChange (e: any) {
|
||||
ipcSendFiles(e.target.files);
|
||||
(document.getElementById('file-uploader') as HTMLInputElement).value = ''
|
||||
function onChange(e: any) {
|
||||
ipcSendFiles(e.target.files)
|
||||
;(document.getElementById('file-uploader') as HTMLInputElement).value = ''
|
||||
}
|
||||
|
||||
function ipcSendFiles (files: FileList) {
|
||||
function ipcSendFiles(files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
Array.from(files).forEach(item => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
@@ -324,32 +273,32 @@ function ipcSendFiles (files: FileList) {
|
||||
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles)
|
||||
}
|
||||
|
||||
async function getPasteStyle () {
|
||||
pasteStyle.value = await getConfig(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
pasteFormatList.value.Custom = await getConfig(configPaths.settings.customLink) || ''
|
||||
async function getPasteStyle() {
|
||||
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
|
||||
pasteFormatList.value.Custom = (await getConfig(configPaths.settings.customLink)) || ''
|
||||
}
|
||||
|
||||
async function getUseShortUrl () {
|
||||
useShortUrl.value = await getConfig(configPaths.settings.useShortUrl) || false
|
||||
async function getUseShortUrl() {
|
||||
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl)) || false
|
||||
}
|
||||
|
||||
async function handleUseShortUrlChange () {
|
||||
async function handleUseShortUrlChange() {
|
||||
saveConfig({
|
||||
[configPaths.settings.useShortUrl]: useShortUrl.value
|
||||
})
|
||||
}
|
||||
|
||||
function handlePasteStyleChange (val: string | number | boolean | undefined) {
|
||||
function handlePasteStyleChange(val: string | number | boolean | undefined) {
|
||||
saveConfig({
|
||||
[configPaths.settings.pasteStyle]: val || IPasteStyle.MARKDOWN
|
||||
})
|
||||
}
|
||||
|
||||
function uploadClipboardFiles () {
|
||||
function uploadClipboardFiles() {
|
||||
sendRPC(IRPCActionType.UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE)
|
||||
}
|
||||
|
||||
async function uploadURLFiles () {
|
||||
async function uploadURLFiles() {
|
||||
const str = await navigator.clipboard.readText()
|
||||
$bus.emit(SHOW_INPUT_BOX, {
|
||||
value: isUrl(str) ? str : '',
|
||||
@@ -358,28 +307,30 @@ async function uploadURLFiles () {
|
||||
})
|
||||
}
|
||||
|
||||
function handleInputBoxValue (val: string) {
|
||||
function handleInputBoxValue(val: string) {
|
||||
if (val === '') return
|
||||
if (isUrl(val)) {
|
||||
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [{
|
||||
path: val
|
||||
}])
|
||||
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [
|
||||
{
|
||||
path: val
|
||||
}
|
||||
])
|
||||
} else {
|
||||
$message.error($T('TIPS_INPUT_VALID_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
async function getDefaultPicBed () {
|
||||
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`) || ''
|
||||
picBedConfigName.value = (await getConfig<string>(`picBed.${currentPicBed}._configName`)) || ''
|
||||
}
|
||||
|
||||
async function handleChangePicBed () {
|
||||
async function handleChangePicBed() {
|
||||
sendRPC(IRPCActionType.SHOW_UPLOAD_PAGE_MENU)
|
||||
}
|
||||
</script>
|
||||
@@ -390,7 +341,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
.view-title
|
||||
display flex
|
||||
color #eee
|
||||
|
||||
@@ -3,13 +3,7 @@
|
||||
<div class="view-title">
|
||||
{{ $T('SETTINGS') }}
|
||||
</div>
|
||||
<el-row
|
||||
:gutter="15"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
type="flex"
|
||||
class="config-list"
|
||||
>
|
||||
<el-row :gutter="15" justify="space-between" align="middle" type="flex" class="config-list">
|
||||
<el-col
|
||||
v-for="item in curConfigList"
|
||||
:key="item._id"
|
||||
@@ -30,17 +24,11 @@
|
||||
<div class="config-update-time">
|
||||
{{ formatTime(item._updatedAt) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="defaultConfigId === item._id"
|
||||
class="default-text"
|
||||
>
|
||||
<div v-if="defaultConfigId === item._id" class="default-text">
|
||||
{{ $T('SELECTED_SETTING_HINT') }}
|
||||
</div>
|
||||
<div class="operation-container">
|
||||
<el-icon
|
||||
class="el-icon-edit"
|
||||
@click="openEditPage(item._id)"
|
||||
>
|
||||
<el-icon class="el-icon-edit" @click="openEditPage(item._id)">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
@@ -61,24 +49,14 @@
|
||||
:lg="curConfigList.length === 1 ? 12 : 6"
|
||||
:xl="curConfigList.length === 1 ? 12 : 3"
|
||||
>
|
||||
<div
|
||||
class="config-item config-item-add"
|
||||
@click="addNewConfig"
|
||||
>
|
||||
<el-icon
|
||||
class="el-icon-plus"
|
||||
>
|
||||
<div class="config-item config-item-add" @click="addNewConfig">
|
||||
<el-icon class="el-icon-plus">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row
|
||||
type="flex"
|
||||
justify="center"
|
||||
:span="24"
|
||||
class="set-default-container"
|
||||
>
|
||||
<el-row type="flex" justify="center" :span="24" class="set-default-container">
|
||||
<el-button
|
||||
class="set-default-btn"
|
||||
type="success"
|
||||
@@ -115,16 +93,19 @@ const curConfigList = ref<IStringKeyMap[]>([])
|
||||
const defaultConfigId = ref('')
|
||||
const store = useStore()
|
||||
|
||||
async function selectItem (id: string) {
|
||||
async function selectItem(id: string) {
|
||||
await triggerRPC<void>(IRPCActionType.UPLOADER_SELECT, type.value, id)
|
||||
if (store?.state.defaultPicBed === type.value) {
|
||||
sendRPC(IRPCActionType.TRAY_SET_TOOL_TIP, `${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`)
|
||||
sendRPC(
|
||||
IRPCActionType.TRAY_SET_TOOL_TIP,
|
||||
`${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`
|
||||
)
|
||||
}
|
||||
defaultConfigId.value = id
|
||||
}
|
||||
|
||||
onBeforeRouteUpdate((to, _, next) => {
|
||||
if (to.params.type && (to.name === UPLOADER_CONFIG_PAGE)) {
|
||||
if (to.params.type && to.name === UPLOADER_CONFIG_PAGE) {
|
||||
type.value = to.params.type as string
|
||||
getCurrentConfigList()
|
||||
}
|
||||
@@ -136,13 +117,13 @@ onBeforeMount(() => {
|
||||
getCurrentConfigList()
|
||||
})
|
||||
|
||||
async function getCurrentConfigList () {
|
||||
async function getCurrentConfigList() {
|
||||
const configList = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value)
|
||||
curConfigList.value = configList?.configList ?? []
|
||||
defaultConfigId.value = configList?.defaultId ?? ''
|
||||
}
|
||||
|
||||
function openEditPage (configId: string) {
|
||||
function openEditPage(configId: string) {
|
||||
$router.push({
|
||||
name: PICBEDS_PAGE,
|
||||
params: {
|
||||
@@ -155,18 +136,18 @@ function openEditPage (configId: string) {
|
||||
})
|
||||
}
|
||||
|
||||
function formatTime (time: number): string {
|
||||
function formatTime(time: number): string {
|
||||
return dayjs(time).format('YY/MM/DD HH:mm')
|
||||
}
|
||||
|
||||
async function deleteConfig (id: string) {
|
||||
async function deleteConfig(id: string) {
|
||||
const res = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_DELETE_CONFIG, type.value, id)
|
||||
if (!res) return
|
||||
curConfigList.value = res.configList
|
||||
defaultConfigId.value = res.defaultId
|
||||
}
|
||||
|
||||
function addNewConfig () {
|
||||
function addNewConfig() {
|
||||
$router.push({
|
||||
name: PICBEDS_PAGE,
|
||||
params: {
|
||||
@@ -176,7 +157,7 @@ function addNewConfig () {
|
||||
})
|
||||
}
|
||||
|
||||
function setDefaultPicBed (type: string) {
|
||||
function setDefaultPicBed(type: string) {
|
||||
saveConfig({
|
||||
[configPaths.picBed.current]: type,
|
||||
[configPaths.picBed.uploader]: type
|
||||
@@ -198,7 +179,7 @@ export default {
|
||||
name: 'UploaderConfigPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
#config-list-view
|
||||
position absolute
|
||||
min-height 100%
|
||||
|
||||
@@ -1,57 +1,23 @@
|
||||
<template>
|
||||
<div id="picbeds-page">
|
||||
<el-row
|
||||
:gutter="20"
|
||||
class="setting-list"
|
||||
>
|
||||
<el-col
|
||||
:span="22"
|
||||
:offset="1"
|
||||
>
|
||||
<div
|
||||
class="view-title"
|
||||
>
|
||||
<span
|
||||
class="view-title-text"
|
||||
@click="handleNameClick"
|
||||
>
|
||||
{{ picBedName }} {{ $T('SETTINGS') }}</span>
|
||||
<el-row :gutter="20" class="setting-list">
|
||||
<el-col :span="22" :offset="1">
|
||||
<div class="view-title">
|
||||
<span class="view-title-text" @click="handleNameClick"> {{ picBedName }} {{ $T('SETTINGS') }}</span>
|
||||
<el-icon>
|
||||
<Link />
|
||||
</el-icon>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
style="margin-left: 6px"
|
||||
@click="handleCopyApi"
|
||||
>
|
||||
<el-button type="primary" round size="small" style="margin-left: 6px" @click="handleCopyApi">
|
||||
{{ $T('UPLOAD_PAGE_COPY_UPLOAD_API') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<config-form
|
||||
v-if="config.length > 0"
|
||||
:id="type"
|
||||
ref="$configForm"
|
||||
:config="config"
|
||||
type="uploader"
|
||||
>
|
||||
<config-form v-if="config.length > 0" :id="type" ref="$configForm" :config="config" type="uploader">
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button
|
||||
class="confirm-btn"
|
||||
type="info"
|
||||
round
|
||||
@click="handleReset"
|
||||
>
|
||||
<el-button class="confirm-btn" type="info" round @click="handleReset">
|
||||
{{ $T('RESET_PICBED_CONFIG') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
class="confirm-btn"
|
||||
type="success"
|
||||
round
|
||||
@click="handleConfirm"
|
||||
>
|
||||
<el-button class="confirm-btn" type="success" round @click="handleConfirm">
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -64,17 +30,13 @@
|
||||
<el-dropdown
|
||||
ref="$dropdown"
|
||||
placement="top"
|
||||
style="color: #fff; font-size: 12px;width: 100%;"
|
||||
style="color: #fff; font-size: 12px; width: 100%"
|
||||
:disabled="picBedConfigList.length === 0"
|
||||
teleported
|
||||
>
|
||||
{{ $T('MANAGE_LOGIN_PAGE_PANE_IMPORT') }}
|
||||
<template #dropdown>
|
||||
<el-dropdown-item
|
||||
v-for="i in picBedConfigList"
|
||||
:key="i._id"
|
||||
@click="handleConfigImport(i)"
|
||||
>
|
||||
<el-dropdown-item v-for="i in picBedConfigList" :key="i._id" @click="handleConfigImport(i)">
|
||||
{{ i._configName }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
@@ -83,10 +45,7 @@
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
</config-form>
|
||||
<div
|
||||
v-else
|
||||
class="single"
|
||||
>
|
||||
<div v-else class="single">
|
||||
<div class="notice">
|
||||
{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}
|
||||
</div>
|
||||
@@ -98,9 +57,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
clipboard
|
||||
} from 'electron'
|
||||
import { clipboard } from 'electron'
|
||||
import { ElDropdown, ElMessage } from 'element-plus'
|
||||
import { Link } from '@element-plus/icons-vue'
|
||||
import { ref, onBeforeMount } from 'vue'
|
||||
@@ -144,27 +101,27 @@ const handleConfirm = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
function handleMouseEnter () {
|
||||
function handleMouseEnter() {
|
||||
$dropdown.value?.handleOpen()
|
||||
}
|
||||
|
||||
function handleMouseLeave () {
|
||||
function handleMouseLeave() {
|
||||
$dropdown.value?.handleClose()
|
||||
}
|
||||
|
||||
async function getPicBeds () {
|
||||
async function getPicBeds() {
|
||||
const result = await triggerRPC<any>(IRPCActionType.PICBED_GET_PICBED_CONFIG, $route.params.type)
|
||||
config.value = result.config
|
||||
picBedName.value = result.name
|
||||
}
|
||||
|
||||
async function getPicBedConfigList () {
|
||||
const res = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value) || undefined
|
||||
async function getPicBedConfigList() {
|
||||
const res = (await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value)) || undefined
|
||||
const configList = res?.configList || []
|
||||
picBedConfigList.value = configList.filter((item) => item._id !== $route.params.configId)
|
||||
picBedConfigList.value = configList.filter(item => item._id !== $route.params.configId)
|
||||
}
|
||||
|
||||
async function handleConfigImport (configItem: IUploaderConfigListItem) {
|
||||
async function handleConfigImport(configItem: IUploaderConfigListItem) {
|
||||
const { _id, _configName, _updatedAt, _createdAt, ...rest } = configItem
|
||||
for (const key in rest) {
|
||||
if (Object.prototype.hasOwnProperty.call(rest, key)) {
|
||||
@@ -186,19 +143,19 @@ const handleReset = async () => {
|
||||
$router.back()
|
||||
}
|
||||
|
||||
async function handleNameClick () {
|
||||
const lang = await getConfig(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||
async function handleNameClick() {
|
||||
const lang = (await getConfig(configPaths.settings.language)) || II18nLanguage.ZH_CN
|
||||
const url = picBedManualUrlList[lang === II18nLanguage.EN ? 'en' : 'zh_cn'][$route.params.type as string]
|
||||
if (url) {
|
||||
sendRPC(IRPCActionType.OPEN_URL, url)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCopyApi () {
|
||||
async function handleCopyApi() {
|
||||
try {
|
||||
const { port = 36677, host = '127.0.0.1' } = await getConfig<IStringKeyMap>(configPaths.settings.server) || {}
|
||||
const serverKey = await getConfig(configPaths.settings.serverKey) || ''
|
||||
const uploader = await getConfig(configPaths.uploader) as IStringKeyMap || {}
|
||||
const { port = 36677, host = '127.0.0.1' } = (await getConfig<IStringKeyMap>(configPaths.settings.server)) || {}
|
||||
const serverKey = (await getConfig(configPaths.settings.serverKey)) || ''
|
||||
const uploader = ((await getConfig(configPaths.uploader)) as IStringKeyMap) || {}
|
||||
const picBedConfigList = uploader[$route.params.type as string].configList || []
|
||||
const picBedConfig = picBedConfigList.find((item: IUploaderConfigListItem) => item._id === $route.params.configId)
|
||||
if (!picBedConfig) {
|
||||
@@ -221,7 +178,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='stylus'>
|
||||
<style lang="stylus">
|
||||
#picbeds-page
|
||||
height 100%
|
||||
overflow-y auto
|
||||
|
||||
@@ -28,7 +28,7 @@ const setDefaultPicBed = (type: string) => {
|
||||
}
|
||||
|
||||
export const store = {
|
||||
install (app: App) {
|
||||
install(app: App) {
|
||||
app.provide(storeKey, {
|
||||
state: readonly(state),
|
||||
setDefaultPicBed
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { ipcRenderer } from 'electron'
|
||||
import {
|
||||
TALKING_DATA_APPID, TALKING_DATA_EVENT
|
||||
} from '#/events/constants'
|
||||
import { TALKING_DATA_APPID, TALKING_DATA_EVENT } from '#/events/constants'
|
||||
|
||||
import { handleTalkingDataEvent } from '@/utils/common'
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import mitt from 'mitt'
|
||||
import {
|
||||
SHOW_INPUT_BOX,
|
||||
SHOW_INPUT_BOX_RESPONSE
|
||||
} from '#/events/constants'
|
||||
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
|
||||
|
||||
type IEvent ={
|
||||
type IEvent = {
|
||||
[SHOW_INPUT_BOX_RESPONSE]: string
|
||||
[SHOW_INPUT_BOX]: {
|
||||
value: string
|
||||
|
||||
@@ -36,7 +36,7 @@ export const getRawData = (args: any): any => {
|
||||
return args
|
||||
}
|
||||
|
||||
export function sendToMain (channel: string, ...args: any[]) {
|
||||
export function sendToMain(channel: string, ...args: any[]) {
|
||||
const data = getRawData(args)
|
||||
ipcRenderer.send(channel, ...data)
|
||||
}
|
||||
@@ -46,26 +46,26 @@ export function sendToMain (channel: string, ...args: any[]) {
|
||||
*
|
||||
* or the response will be handled by other listener
|
||||
*/
|
||||
export function sendRPC (action: IRPCActionType, ...args: any[]): void {
|
||||
export function sendRPC(action: IRPCActionType, ...args: any[]): void {
|
||||
const data = getRawData(args)
|
||||
ipcRenderer.send(RPC_ACTIONS, action, data)
|
||||
}
|
||||
|
||||
export function sendRpcSync (action: IRPCActionType, ...args: any[]) {
|
||||
export function sendRpcSync(action: IRPCActionType, ...args: any[]) {
|
||||
const data = getRawData(args)
|
||||
return ipcRenderer.sendSync(RPC_ACTIONS, action, data)
|
||||
}
|
||||
|
||||
export function invokeToMain (channel: string, ...args: any[]) {
|
||||
export function invokeToMain(channel: string, ...args: any[]) {
|
||||
const data = getRawData(args)
|
||||
return ipcRenderer.invoke(channel, ...data)
|
||||
}
|
||||
|
||||
/**
|
||||
* trigger RPC action
|
||||
* TODO: create an isolate rpc handler
|
||||
*/
|
||||
export async function triggerRPC<T> (action: IRPCActionType, ...args: any[]): Promise<T | undefined> {
|
||||
* trigger RPC action
|
||||
* TODO: create an isolate rpc handler
|
||||
*/
|
||||
export async function triggerRPC<T>(action: IRPCActionType, ...args: any[]): Promise<T | undefined> {
|
||||
const data = getRawData(args)
|
||||
return await ipcRenderer.invoke(RPC_ACTIONS_INVOKE, action, data)
|
||||
}
|
||||
|
||||
@@ -5,17 +5,15 @@ import { sendRPC, triggerRPC } from '@/utils/common'
|
||||
import { RPC_ACTIONS } from '#/events/constants'
|
||||
import { IRPCActionType } from 'root/src/universal/types/enum'
|
||||
|
||||
export function saveConfig (config: IObj | string, value?: any) {
|
||||
const configObject = typeof config === 'string'
|
||||
? { [config]: value }
|
||||
: config
|
||||
export function saveConfig(config: IObj | string, value?: any) {
|
||||
const configObject = typeof config === 'string' ? { [config]: value } : config
|
||||
sendRPC(IRPCActionType.PICLIST_SAVE_CONFIG, configObject)
|
||||
}
|
||||
|
||||
export async function getConfig<T> (key?: string): Promise<T | undefined> {
|
||||
export async function getConfig<T>(key?: string): Promise<T | undefined> {
|
||||
return await triggerRPC<T>(IRPCActionType.PICLIST_GET_CONFIG, key)
|
||||
}
|
||||
|
||||
export async function getConfigSync<T> (key?: string): Promise<T | undefined> {
|
||||
export async function getConfigSync<T>(key?: string): Promise<T | undefined> {
|
||||
return await ipcRenderer.sendSync(RPC_ACTIONS, IRPCActionType.PICLIST_GET_CONFIG_SYNC, [key])
|
||||
}
|
||||
|
||||
@@ -6,37 +6,37 @@ import { IRPCActionType } from '#/types/enum'
|
||||
import { IGalleryDB } from '#/types/extra-vue'
|
||||
|
||||
export class GalleryDB implements IGalleryDB {
|
||||
async get<T> (filter?: IFilter): Promise<IGetResult<T> | undefined> {
|
||||
async get<T>(filter?: IFilter): Promise<IGetResult<T> | undefined> {
|
||||
const res = await this.#msgHandler<IGetResult<T>>(IRPCActionType.GALLERY_GET_DB, filter)
|
||||
return res
|
||||
}
|
||||
|
||||
async insert<T> (value: T): Promise<IResult<T> | undefined> {
|
||||
async insert<T>(value: T): Promise<IResult<T> | undefined> {
|
||||
const res = await this.#msgHandler<IResult<T>>(IRPCActionType.GALLERY_INSERT_DB, value)
|
||||
return res
|
||||
}
|
||||
|
||||
async insertMany<T> (value: T[]): Promise<IResult<T>[] | undefined> {
|
||||
async insertMany<T>(value: T[]): Promise<IResult<T>[] | undefined> {
|
||||
const res = await this.#msgHandler<IResult<T>[]>(IRPCActionType.GALLERY_INSERT_DB_BATCH, value)
|
||||
return res
|
||||
}
|
||||
|
||||
async updateById (id: string, value: IObject): Promise<boolean> {
|
||||
const res = await this.#msgHandler<boolean>(IRPCActionType.GALLERY_UPDATE_BY_ID_DB, id, value) || false
|
||||
async updateById(id: string, value: IObject): Promise<boolean> {
|
||||
const res = (await this.#msgHandler<boolean>(IRPCActionType.GALLERY_UPDATE_BY_ID_DB, id, value)) || false
|
||||
return res
|
||||
}
|
||||
|
||||
async getById<T> (id: string): Promise<IResult<T> | undefined> {
|
||||
async getById<T>(id: string): Promise<IResult<T> | undefined> {
|
||||
const res = await this.#msgHandler<IResult<T> | undefined>(IRPCActionType.GALLERY_GET_BY_ID_DB, id)
|
||||
return res
|
||||
}
|
||||
|
||||
async removeById (id: string): Promise<void> {
|
||||
async removeById(id: string): Promise<void> {
|
||||
const res = await this.#msgHandler<void>(IRPCActionType.GALLERY_REMOVE_BY_ID_DB, id)
|
||||
return res
|
||||
}
|
||||
|
||||
async #msgHandler<T> (method: IRPCActionType, ...args: any[]): Promise<T | undefined> {
|
||||
async #msgHandler<T>(method: IRPCActionType, ...args: any[]): Promise<T | undefined> {
|
||||
return await triggerRPC<T>(method, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,12 @@ const osGlobal = ref<string>(process.platform)
|
||||
const picBedGlobal = ref<IPicBedType[]>([])
|
||||
const pageReloadCount = ref(0)
|
||||
|
||||
async function updatePicBedGlobal () {
|
||||
async function updatePicBedGlobal() {
|
||||
picBedGlobal.value = (await triggerRPC<IPicBedType[]>(IRPCActionType.MAIN_GET_PICBED))!
|
||||
}
|
||||
|
||||
async function updatePageReloadCount () {
|
||||
async function updatePageReloadCount() {
|
||||
pageReloadCount.value++
|
||||
}
|
||||
|
||||
export {
|
||||
osGlobal,
|
||||
pageReloadCount,
|
||||
picBedGlobal,
|
||||
updatePicBedGlobal,
|
||||
updatePageReloadCount
|
||||
}
|
||||
export { osGlobal, pageReloadCount, picBedGlobal, updatePicBedGlobal, updatePageReloadCount }
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { ComponentOptions } from 'vue'
|
||||
|
||||
export const dragMixin: ComponentOptions = {
|
||||
mounted () {
|
||||
mounted() {
|
||||
this.disableDragEvent()
|
||||
},
|
||||
|
||||
methods: {
|
||||
disableDragEvent () {
|
||||
disableDragEvent() {
|
||||
window.addEventListener('dragenter', this.disableDrag, false)
|
||||
window.addEventListener('dragover', this.disableDrag)
|
||||
window.addEventListener('drop', this.disableDrag)
|
||||
},
|
||||
|
||||
disableDrag (e: DragEvent) {
|
||||
disableDrag(e: DragEvent) {
|
||||
const dropzone = document.getElementById('upload-area')
|
||||
if (dropzone === null || !dropzone.contains(<Node>e.target)) {
|
||||
e.preventDefault()
|
||||
@@ -22,7 +22,7 @@ export const dragMixin: ComponentOptions = {
|
||||
}
|
||||
},
|
||||
|
||||
beforeUnmount () {
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('dragenter', this.disableDrag, false)
|
||||
window.removeEventListener('dragover', this.disableDrag)
|
||||
window.removeEventListener('drop', this.disableDrag)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IStringKeyMap => {
|
||||
return Object.assign({
|
||||
_configName: 'Default'
|
||||
}, originData, {
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
})
|
||||
return Object.assign(
|
||||
{
|
||||
_configName: 'Default'
|
||||
},
|
||||
originData,
|
||||
{
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user