mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-06-09 17:49:53 +08:00
✨ Feature: migrate from aws-sdk v2 to v3
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Electron 相关
|
||||
import {
|
||||
app,
|
||||
ipcMain,
|
||||
@@ -8,16 +9,38 @@ import {
|
||||
screen,
|
||||
IpcMainInvokeEvent
|
||||
} from 'electron'
|
||||
|
||||
// 窗口管理器
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
// 枚举类型声明
|
||||
import { IWindowList } from '#/types/enum'
|
||||
|
||||
// 上传器
|
||||
import uploader from 'apis/app/uploader'
|
||||
|
||||
// 粘贴模板函数
|
||||
import pasteTemplate from '~/main/utils/pasteTemplate'
|
||||
|
||||
// 数据存储库和类型声明
|
||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||
|
||||
// 服务器模块
|
||||
import server from '~/main/server'
|
||||
|
||||
// 获取图片床模块
|
||||
import getPicBeds from '~/main/utils/getPicBeds'
|
||||
|
||||
// 快捷键处理器
|
||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||
|
||||
// 全局事件总线
|
||||
import bus from '@core/bus'
|
||||
|
||||
// 文件系统库
|
||||
import fs from 'fs-extra'
|
||||
|
||||
// 事件常量
|
||||
import {
|
||||
TOGGLE_SHORTKEY_MODIFIED_MODE,
|
||||
OPEN_DEVTOOLS,
|
||||
@@ -34,19 +57,46 @@ import {
|
||||
GET_PICBEDS,
|
||||
HIDE_DOCK
|
||||
} from '#/events/constants'
|
||||
|
||||
// 上传剪贴板文件和已选文件的函数
|
||||
import {
|
||||
uploadClipboardFiles,
|
||||
uploadChoosedFiles
|
||||
} from '~/main/apis/app/uploader/apis'
|
||||
|
||||
// 核心 IPC 模块
|
||||
import picgoCoreIPC from './picgoCoreIPC'
|
||||
|
||||
// 处理复制的 URL 和生成短链接的函数
|
||||
import { handleCopyUrl, generateShortUrl } from '~/main/utils/common'
|
||||
|
||||
// 构建主页面、迷你页面、插件页面、图片床列表的菜单函数
|
||||
import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedListMenu } from './remotes/menu'
|
||||
|
||||
// 路径处理库
|
||||
import path from 'path'
|
||||
|
||||
// i18n 模块
|
||||
import { T } from '~/main/i18n'
|
||||
|
||||
// 同步设置的上传和下载文件函数
|
||||
import { uploadFile, downloadFile } from '../utils/syncSettings'
|
||||
|
||||
// SSH 客户端模块
|
||||
import SSHClient from '../utils/sshClient'
|
||||
|
||||
// Sftp 配置类型声明
|
||||
import { ISftpPlistConfig } from 'piclist'
|
||||
|
||||
// AWS S3 相关模块
|
||||
import { S3Client, DeleteObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3'
|
||||
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
||||
import http, { AgentOptions } from 'http'
|
||||
import https from 'https'
|
||||
|
||||
// 通用获取 Agent 函数
|
||||
import { getAgent } from '../manage/utils/common'
|
||||
|
||||
const STORE_PATH = app.getPath('userData')
|
||||
|
||||
export default {
|
||||
@@ -137,6 +187,66 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('delete-aws-s3-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => {
|
||||
try {
|
||||
const { imgUrl, config: { accessKeyID, secretAccessKey, bucketName, region, endpoint, pathStyleAccess, rejectUnauthorized, proxy } } = configMap
|
||||
console.log(JSON.stringify(configMap, null, 2))
|
||||
const url = new URL(!/^https?:\/\//.test(imgUrl) ? `http://${imgUrl}` : imgUrl)
|
||||
const fileKey = url.pathname.replace(/^\/+/, '')
|
||||
const endpointUrl: string | undefined = endpoint
|
||||
? /^https?:\/\//.test(endpoint)
|
||||
? endpoint
|
||||
: `http://${endpoint}`
|
||||
: undefined
|
||||
const sslEnabled = endpointUrl ? endpointUrl.startsWith('https') : true
|
||||
const agent = getAgent(proxy, sslEnabled)
|
||||
const commonOptions: AgentOptions = {
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
||||
}
|
||||
const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {}
|
||||
const handler = sslEnabled
|
||||
? new NodeHttpHandler({
|
||||
httpsAgent: agent.https
|
||||
? agent.https
|
||||
: new https.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
: new NodeHttpHandler({
|
||||
httpAgent: agent.http
|
||||
? agent.http
|
||||
: new http.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
const s3Options: S3ClientConfig = {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyID,
|
||||
secretAccessKey
|
||||
},
|
||||
endpoint: endpointUrl,
|
||||
tls: sslEnabled,
|
||||
forcePathStyle: pathStyleAccess,
|
||||
region,
|
||||
requestHandler: handler
|
||||
}
|
||||
const client = new S3Client(s3Options)
|
||||
const command = new DeleteObjectCommand({
|
||||
Bucket: bucketName,
|
||||
Key: fileKey
|
||||
})
|
||||
const result = await client.send(command)
|
||||
return result.$metadata.httpStatusCode === 204
|
||||
} catch (err: any) {
|
||||
console.error(err)
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('migrateFromPicGo', async () => {
|
||||
const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo')
|
||||
const fileToMigration = [
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
ListBucketsCommand,
|
||||
ListObjectsV2Command,
|
||||
GetBucketLocationCommand,
|
||||
S3ClientConfig,
|
||||
_Object,
|
||||
CommonPrefix,
|
||||
ListObjectsV2CommandOutput,
|
||||
@@ -12,7 +11,8 @@ import {
|
||||
GetObjectCommand,
|
||||
DeleteObjectCommand,
|
||||
DeleteObjectsCommand,
|
||||
PutObjectCommand
|
||||
PutObjectCommand,
|
||||
S3ClientConfig
|
||||
} from '@aws-sdk/client-s3'
|
||||
|
||||
// AWS S3 上传和进度
|
||||
@@ -23,7 +23,8 @@ import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
||||
|
||||
// HTTP 和 HTTPS 模块
|
||||
import https from 'https'
|
||||
import http from 'http'
|
||||
import http, { AgentOptions } from 'http'
|
||||
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
||||
|
||||
// 日志记录器
|
||||
import { ManageLogger } from '../utils/logger'
|
||||
@@ -34,9 +35,6 @@ import { formatEndpoint, formatError, getAgent, getFileMimeType, NewDownloader,
|
||||
// 是否为图片的判断函数、HTTP 代理格式化函数
|
||||
import { isImage, formatHttpProxy } from '@/manage/utils/common'
|
||||
|
||||
// HTTP 和 HTTPS 代理库
|
||||
import { HttpsProxyAgent, HttpProxyAgent } from 'hpagent'
|
||||
|
||||
// 窗口管理器
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
|
||||
@@ -58,21 +56,8 @@ import path from 'path'
|
||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||
|
||||
interface S3plistApiOptions {
|
||||
credentials: {
|
||||
accessKeyId: string
|
||||
secretAccessKey: string
|
||||
}
|
||||
endpoint?: string
|
||||
sslEnabled: boolean
|
||||
s3ForcePathStyle: boolean
|
||||
httpOptions?: {
|
||||
agent: https.Agent
|
||||
}
|
||||
}
|
||||
|
||||
class S3plistApi {
|
||||
baseOptions: S3plistApiOptions
|
||||
baseOptions: S3ClientConfig
|
||||
logger: ManageLogger
|
||||
agent: any
|
||||
proxy: string | undefined
|
||||
@@ -92,26 +77,39 @@ class S3plistApi {
|
||||
secretAccessKey
|
||||
},
|
||||
endpoint: endpoint ? formatEndpoint(endpoint, sslEnabled) : undefined,
|
||||
sslEnabled,
|
||||
s3ForcePathStyle,
|
||||
httpOptions: {
|
||||
agent: this.setAgent(proxy, sslEnabled)
|
||||
}
|
||||
} as S3plistApiOptions
|
||||
tls: sslEnabled,
|
||||
forcePathStyle: s3ForcePathStyle,
|
||||
requestHandler: this.setAgent(proxy, sslEnabled)
|
||||
}
|
||||
this.logger = logger
|
||||
this.agent = this.setAgent(proxy, sslEnabled)
|
||||
this.proxy = formatHttpProxy(proxy, 'string') as string | undefined
|
||||
}
|
||||
|
||||
setAgent (proxy: string | undefined, sslEnabled: boolean) : HttpProxyAgent | HttpsProxyAgent | undefined {
|
||||
const protocol = sslEnabled ? 'https' : 'http'
|
||||
const agent = getAgent(proxy, sslEnabled)[protocol]
|
||||
const commonOptions = { keepAlive: true }
|
||||
setAgent (proxy: string | undefined, sslEnabled: boolean) : NodeHttpHandler {
|
||||
const agent = getAgent(proxy, sslEnabled)
|
||||
const commonOptions: AgentOptions = {
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
||||
}
|
||||
const extraOptions = sslEnabled ? { rejectUnauthorized: false } : {}
|
||||
return agent ?? new (sslEnabled ? https.Agent : http.Agent)({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
return sslEnabled
|
||||
? new NodeHttpHandler({
|
||||
httpsAgent: agent.https
|
||||
? agent.https
|
||||
: new https.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
: new NodeHttpHandler({
|
||||
httpAgent: agent.http
|
||||
? agent.http
|
||||
: new http.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
logParam = (error:any, method: string) =>
|
||||
|
||||
@@ -4,7 +4,7 @@ import mime from 'mime-types'
|
||||
import axios from 'axios'
|
||||
import { app } from 'electron'
|
||||
import crypto from 'crypto'
|
||||
import got, { RequestError } from 'got'
|
||||
import got, { OptionsOfTextResponseBody, RequestError } from 'got'
|
||||
import { Stream } from 'stream'
|
||||
import { promisify } from 'util'
|
||||
import UpDownTaskQueue,
|
||||
@@ -40,20 +40,13 @@ export const getFSFile = async (
|
||||
}
|
||||
}
|
||||
|
||||
export const isInputConfigValid = (config: any): boolean => {
|
||||
if (
|
||||
typeof config === 'object' &&
|
||||
export function isInputConfigValid (config: any): boolean {
|
||||
return typeof config === 'object' &&
|
||||
!Array.isArray(config) &&
|
||||
Object.keys(config).length > 0
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const getFileMimeType = (filePath: string): string => {
|
||||
return mime.lookup(filePath) || 'application/octet-stream'
|
||||
}
|
||||
export const getFileMimeType = (filePath: string): string => mime.lookup(filePath) || 'application/octet-stream'
|
||||
|
||||
const checkTempFolderExist = async () => {
|
||||
const tempPath = path.join(app.getPath('downloads'), 'piclistTemp')
|
||||
@@ -131,7 +124,7 @@ export const NewDownloader = async (
|
||||
})
|
||||
return true
|
||||
} catch (e: any) {
|
||||
logger && logger.error(formatError(e, { method: 'NewDownloader' }))
|
||||
logger?.error(formatError(e, { method: 'NewDownloader' }))
|
||||
fs.remove(savedFilePath)
|
||||
instance.updateDownloadTask({
|
||||
id,
|
||||
@@ -179,13 +172,13 @@ export const gotUpload = async (
|
||||
.then((res: any) => {
|
||||
instance.updateUploadTask({
|
||||
id,
|
||||
progress: res && (res.statusCode === 200 || res.statusCode === 201) ? 100 : 0,
|
||||
status: res && (res.statusCode === 200 || res.statusCode === 201) ? uploadTaskSpecialStatus.uploaded : commonTaskStatus.failed,
|
||||
progress: res?.statusCode === 200 || res?.statusCode === 201 ? 100 : 0,
|
||||
status: res?.statusCode === 200 || res?.statusCode === 201 ? uploadTaskSpecialStatus.uploaded : commonTaskStatus.failed,
|
||||
finishTime: new Date().toLocaleString()
|
||||
})
|
||||
})
|
||||
.catch((err: any) => {
|
||||
logger && logger.error(formatError(err, { method: 'gotUpload' }))
|
||||
logger?.error(formatError(err, { method: 'gotUpload' }))
|
||||
instance.updateUploadTask({
|
||||
id,
|
||||
progress: 0,
|
||||
@@ -213,42 +206,46 @@ export const formatError = (err: any, params:IStringKeyMap) => {
|
||||
message: err.message ?? '',
|
||||
stack: err.stack ?? ''
|
||||
}
|
||||
} else {
|
||||
if (typeof err === 'object') {
|
||||
return JSON.stringify(err) + JSON.stringify(params)
|
||||
} else {
|
||||
return String(err) + JSON.stringify(params)
|
||||
}
|
||||
}
|
||||
if (typeof err === 'object') {
|
||||
return `${JSON.stringify(err)}${JSON.stringify(params)}`
|
||||
}
|
||||
return `${String(err)}${JSON.stringify(params)}`
|
||||
}
|
||||
|
||||
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
||||
|
||||
export const getAgent = (proxy:any, https: boolean = true) => {
|
||||
const commonOptions = {
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
||||
} as any
|
||||
|
||||
export const getAgent = (proxy:any, https: boolean = true): {
|
||||
https?: HttpsProxyAgent
|
||||
http?: HttpProxyAgent
|
||||
} => {
|
||||
const formatProxy = formatHttpProxy(proxy, 'string') as any
|
||||
const commonResult = {
|
||||
https: undefined,
|
||||
http: undefined
|
||||
}
|
||||
if (!formatProxy) return commonResult
|
||||
commonOptions.proxy = formatProxy.replace('127.0.0.1', 'localhost')
|
||||
if (https) {
|
||||
return formatProxy
|
||||
? {
|
||||
https: new HttpsProxyAgent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
rejectUnauthorized: false,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined,
|
||||
proxy: formatProxy.replace('127.0.0.1', 'localhost')
|
||||
})
|
||||
}
|
||||
: {}
|
||||
} else {
|
||||
return formatProxy
|
||||
? {
|
||||
http: new HttpProxyAgent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined,
|
||||
proxy: formatProxy.replace('127.0.0.1', 'localhost')
|
||||
})
|
||||
}
|
||||
: {}
|
||||
return {
|
||||
https: new HttpsProxyAgent({
|
||||
...commonOptions,
|
||||
rejectUnauthorized: false
|
||||
}),
|
||||
http: undefined
|
||||
}
|
||||
}
|
||||
return {
|
||||
http: new HttpProxyAgent({
|
||||
...commonOptions
|
||||
}),
|
||||
https: undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,10 +255,8 @@ export const getInnerAgent = (proxy: any, sslEnabled: boolean = true) => {
|
||||
return formatProxy
|
||||
? {
|
||||
agent: new https.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
...commonOptions,
|
||||
rejectUnauthorized: false,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined,
|
||||
host: formatProxy.host,
|
||||
port: formatProxy.port
|
||||
})
|
||||
@@ -272,25 +267,20 @@ export const getInnerAgent = (proxy: any, sslEnabled: boolean = true) => {
|
||||
keepAlive: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return formatProxy
|
||||
? {
|
||||
agent: new http.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined,
|
||||
host: formatProxy.host,
|
||||
port: formatProxy.port
|
||||
})
|
||||
}
|
||||
: {
|
||||
agent: new http.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
return formatProxy
|
||||
? {
|
||||
agent: new http.Agent({
|
||||
...commonOptions,
|
||||
host: formatProxy.host,
|
||||
port: formatProxy.port
|
||||
})
|
||||
}
|
||||
: {
|
||||
agent: new http.Agent({
|
||||
...commonOptions
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function getOptions (
|
||||
@@ -301,23 +291,17 @@ export function getOptions (
|
||||
body?: any,
|
||||
timeout?: number,
|
||||
proxy?: any
|
||||
) {
|
||||
const options = {
|
||||
method: method?.toUpperCase(),
|
||||
headers,
|
||||
searchParams,
|
||||
agent: getAgent(proxy),
|
||||
timeout: {
|
||||
request: timeout || 30000
|
||||
},
|
||||
body,
|
||||
throwHttpErrors: false,
|
||||
responseType
|
||||
} as IStringKeyMap
|
||||
Object.keys(options).forEach(key => {
|
||||
options[key] === undefined && delete options[key]
|
||||
})
|
||||
return options
|
||||
): OptionsOfTextResponseBody {
|
||||
return {
|
||||
...(method && { method: method.toUpperCase() }),
|
||||
...(headers && { headers }),
|
||||
...(searchParams && { searchParams }),
|
||||
...(body && { body }),
|
||||
...(responseType && { responseType }),
|
||||
...(timeout !== undefined ? { timeout: { request: timeout } } : { timeout: { request: 30000 } }),
|
||||
...(proxy && { agent: Object.fromEntries(Object.entries(getAgent(proxy)).filter(([, v]) => v !== undefined)) }),
|
||||
throwHttpErrors: false
|
||||
}
|
||||
}
|
||||
|
||||
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string =>
|
||||
|
||||
@@ -1,44 +1,13 @@
|
||||
import { S3 } from 'aws-sdk'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { getRawData } from '~/renderer/utils/common'
|
||||
|
||||
export default class AwsS3Api {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { imgUrl, config: { accessKeyID, secretAccessKey, bucketName, region, endpoint, pathStyleAccess, bucketEndpoint, rejectUnauthorized } } = configMap
|
||||
try {
|
||||
const url = new URL(!/^https?:\/\//.test(imgUrl) ? `http://${imgUrl}` : imgUrl)
|
||||
const fileKey = url.pathname
|
||||
let endpointUrl
|
||||
if (endpoint) {
|
||||
if (!/^https?:\/\//.test(endpoint)) {
|
||||
endpointUrl = `http://${endpoint}`
|
||||
} else {
|
||||
endpointUrl = endpoint
|
||||
}
|
||||
}
|
||||
let sslEnabled = true
|
||||
if (endpointUrl) {
|
||||
sslEnabled = endpointUrl.startsWith('https')
|
||||
}
|
||||
const http = sslEnabled ? require('https') : require('http')
|
||||
const client = new S3({
|
||||
accessKeyId: accessKeyID,
|
||||
secretAccessKey,
|
||||
endpoint: endpointUrl,
|
||||
s3ForcePathStyle: pathStyleAccess,
|
||||
sslEnabled,
|
||||
region,
|
||||
s3BucketEndpoint: bucketEndpoint,
|
||||
httpOptions: {
|
||||
agent: new http.Agent({
|
||||
rejectUnauthorized,
|
||||
timeout: 30000
|
||||
})
|
||||
}
|
||||
})
|
||||
const result = await client.deleteObject({
|
||||
Bucket: bucketName,
|
||||
Key: fileKey.replace(/^\/+/, '')
|
||||
}).promise()
|
||||
return result.$response.httpResponse.statusCode === 204
|
||||
const deleteResult = await ipcRenderer.invoke('delete-aws-s3-file',
|
||||
getRawData(configMap)
|
||||
)
|
||||
return deleteResult
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
|
||||
@@ -4,7 +4,7 @@ ea/*
|
||||
*/
|
||||
<template>
|
||||
<div
|
||||
v-loading="showLoadingPage"
|
||||
v-loading="isShowLoadingPage"
|
||||
:element-loading-text="$T('MANAGE_BUCKET_PAGE_LOADING_TEXT')"
|
||||
:element-loading-spinner="svg"
|
||||
element-loading-svg-view-box="0, 0, 50, 50"
|
||||
@@ -15,22 +15,22 @@ ea/*
|
||||
style="flex-grow: 1;margin-left: 16px"
|
||||
>
|
||||
<el-select
|
||||
v-if="showCustomUrlSelectList && customUrlList.length > 1 && isAutoCustomUrl"
|
||||
v-model="currentCustomUrl"
|
||||
v-if="isShowCustomDomainSelectList && customDomainList.length > 1 && isAutoCustomDomain"
|
||||
v-model="currentCustomDomain"
|
||||
:placeholder="$T('MANAGE_BUCKET_PAGE_CUSTOM_URL_SELECT_PLACEHOLDER')"
|
||||
style="width: 200px;"
|
||||
@change="handleChangeCustomUrl"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customUrlList"
|
||||
v-for="item in customDomainList"
|
||||
:key="item"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-else-if="showCustomUrlInput"
|
||||
v-model="currentCustomUrl"
|
||||
v-else-if="isShowCustomDomainInput"
|
||||
v-model="currentCustomDomain"
|
||||
:placeholder="$T('MANAGE_BUCKET_PAGE_CUSTOM_URL_INPUT_PLACEHOLDER')"
|
||||
style="width: 200px;"
|
||||
@blur="handleChangeCustomUrl"
|
||||
@@ -39,9 +39,9 @@ ea/*
|
||||
v-else
|
||||
:underline="false"
|
||||
type="primary"
|
||||
@click="copyToClipboard(currentCustomUrl)"
|
||||
@click="copyToClipboard(currentCustomDomain)"
|
||||
>
|
||||
{{ currentCustomUrl }}
|
||||
{{ currentCustomDomain }}
|
||||
</el-link>
|
||||
</div>
|
||||
<div
|
||||
@@ -86,7 +86,7 @@ ea/*
|
||||
</el-button>
|
||||
</div>
|
||||
<div
|
||||
v-if="showCreateNewFolder"
|
||||
v-if="isShowCreateNewFolder"
|
||||
>
|
||||
<el-button
|
||||
type="text"
|
||||
@@ -167,9 +167,9 @@ ea/*
|
||||
<Link />
|
||||
</el-icon>
|
||||
<template #dropdown>
|
||||
<template v-if="showPresignedUrl">
|
||||
<template v-if="isShowPresignedUrl">
|
||||
<el-dropdown-item
|
||||
v-for="i in [...linkArray, { key: 'preSignURL', value: 'preSignedUrl' }]"
|
||||
v-for="i in [...linkFormatArray, { key: 'preSignURL', value: 'preSignedUrl' }]"
|
||||
:key="i.key"
|
||||
@click="handleBatchCopyLink(i.value)"
|
||||
>
|
||||
@@ -177,7 +177,7 @@ ea/*
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
<el-dropdown-item
|
||||
v-for="i in linkArray"
|
||||
v-for="i in linkFormatArray"
|
||||
v-else
|
||||
:key="i.value+i.key"
|
||||
@click="handleBatchCopyLink(i.value)"
|
||||
@@ -402,18 +402,18 @@ ea/*
|
||||
>
|
||||
<el-button
|
||||
:icon="Grid"
|
||||
:type="showFileStyle === 'grid' ? 'primary' : 'info'"
|
||||
:type="layoutStyle === 'grid' ? 'primary' : 'info'"
|
||||
@click="handleViewChange('grid')"
|
||||
/>
|
||||
<el-button
|
||||
:icon="Fold"
|
||||
:type="showFileStyle === 'list' ? 'primary' : 'info'"
|
||||
:type="layoutStyle === 'list' ? 'primary' : 'info'"
|
||||
@click="handleViewChange('list')"
|
||||
/>
|
||||
</el-button-group>
|
||||
<el-input-number
|
||||
v-if="paging"
|
||||
v-model="currentPage"
|
||||
v-model="currentPageNumber"
|
||||
:min="1"
|
||||
size="small"
|
||||
:disabled="!paging"
|
||||
@@ -451,7 +451,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</template>
|
||||
</el-dialog>
|
||||
<div
|
||||
v-show="showFileStyle === 'list'"
|
||||
v-show="layoutStyle === 'list'"
|
||||
class="layout-table"
|
||||
style="margin: 0 15px 15px 15px;overflow-y: auto;overflow-x: hidden;height: 80vh;"
|
||||
>
|
||||
@@ -460,7 +460,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
#default="{ height, width }"
|
||||
>
|
||||
<el-table-v2
|
||||
ref="elTable"
|
||||
ref="fileTable"
|
||||
:columns="columns "
|
||||
:data="currentPageFilesInfo"
|
||||
:row-class="rowClass"
|
||||
@@ -471,7 +471,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</el-auto-resizer>
|
||||
</div>
|
||||
<div
|
||||
v-show="showFileStyle === 'grid'"
|
||||
v-show="layoutStyle === 'grid'"
|
||||
class="layout-grid"
|
||||
style="margin: 0 15px 15px 15px;overflow-y: auto;overflow-x: hidden;height: 80vh;"
|
||||
>
|
||||
@@ -558,7 +558,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
>
|
||||
<el-row>
|
||||
<el-icon
|
||||
v-if="!item.isDir && showRenameFileIcon"
|
||||
v-if="!item.isDir && isShowRenameFileIcon"
|
||||
size="20"
|
||||
style="cursor: pointer;"
|
||||
color="#409EFF"
|
||||
@@ -633,7 +633,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
{{ $T('MANAGE_BUCKET_URL_FORMAT_CUSTOM') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="showPresignedUrl"
|
||||
v-if="isShowPresignedUrl"
|
||||
@click="async () => {
|
||||
copyToClipboard(await getPreSignedUrl(item))
|
||||
}"
|
||||
@@ -672,12 +672,12 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</el-col>
|
||||
</div>
|
||||
<el-image-viewer
|
||||
v-if="showImagePreview"
|
||||
v-if="isShowImagePreview"
|
||||
:url-list="ImagePreviewList"
|
||||
:initial-index="getCurrentPreviewIndex"
|
||||
infinite
|
||||
hide-on-click-modal
|
||||
@close="showImagePreview = false"
|
||||
@close="isShowImagePreview = false"
|
||||
/>
|
||||
<el-dialog
|
||||
v-model="isShowFileInfo"
|
||||
@@ -690,7 +690,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="copyToClipboard(JSON.stringify(showedFileInfo,null,2))"
|
||||
@click="copyToClipboard(JSON.stringify(currentShowedFileInfo,null,2))"
|
||||
>
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
@@ -701,7 +701,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</el-button>
|
||||
</template>
|
||||
<el-row
|
||||
v-for="(value, key) in showedFileInfo"
|
||||
v-for="(value, key) in currentShowedFileInfo"
|
||||
:key="key"
|
||||
:gutter="20"
|
||||
:style="{ margin: '10px 0', textAlign: 'center', fontFamily: 'Arial, Helvetica, sans-serif' }"
|
||||
@@ -766,11 +766,11 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</template>
|
||||
<div
|
||||
id="upload-area"
|
||||
:class="{ 'is-dragover': dragover }"
|
||||
:class="{ 'is-dragover': isDragover }"
|
||||
styel="position: fixed;bottom: 0;right: 0;heigth: 100%;width: 100%;"
|
||||
@drop.prevent="onDrop"
|
||||
@dragover.prevent="dragover = true"
|
||||
@dragleave.prevent="dragover = false"
|
||||
@dragover.prevent="isDragover = true"
|
||||
@dragleave.prevent="isDragover = false"
|
||||
@click="openFileSelectDialog"
|
||||
>
|
||||
<div
|
||||
@@ -1503,7 +1503,7 @@ configMap:{
|
||||
}
|
||||
*/
|
||||
|
||||
const linkArray = [
|
||||
const linkFormatArray = [
|
||||
{ key: 'Url', value: 'url' },
|
||||
{ key: 'Markdown', value: 'markdown' },
|
||||
{ key: 'Markdown-link', value: 'markdown-with-link' },
|
||||
@@ -1512,50 +1512,74 @@ const linkArray = [
|
||||
{ key: 'Custom', value: 'custom' }
|
||||
]
|
||||
|
||||
// 路由相关
|
||||
const route = useRoute()
|
||||
// 页面状态变量相关
|
||||
const manageStore = useManageStore()
|
||||
const configMap = reactive(JSON.parse(route.query.configMap as string))
|
||||
// 页面布局控制
|
||||
const isLoadingData = ref(false)
|
||||
const isShowLoadingPage = ref(false)
|
||||
const isShowImagePreview = ref(false)
|
||||
const layoutStyle = ref<'list' | 'grid'>('grid')
|
||||
// 文件信息相关
|
||||
const fileTable = ref(null as any)
|
||||
const isShowFileInfo = ref(false)
|
||||
const currentShowedFileInfo = ref({} as any)
|
||||
// 分页相关
|
||||
const currentPageNumber = ref(1)
|
||||
const pagingMarker = ref('')
|
||||
const pagingMarkerStack = reactive([] as string[])
|
||||
const currentPrefix = ref('/')
|
||||
const currentPage = ref(1)
|
||||
const fileSortNameReverse = ref(false)
|
||||
const fileSortTimeReverse = ref(false)
|
||||
const fileSortSizeReverse = ref(false)
|
||||
const fileSortExtReverse = ref(false)
|
||||
const currentPageFilesInfo = reactive([] as any[])
|
||||
const currentDownloadFileList = reactive([] as any[])
|
||||
const route = useRoute()
|
||||
const configMap = reactive(JSON.parse(route.query.configMap as string))
|
||||
const selectedItems = reactive([] as any[])
|
||||
// 当前路径前缀
|
||||
const currentPrefix = ref('/')
|
||||
// 文件排序控制
|
||||
const fileSortExtReverse = ref(false)
|
||||
const fileSortNameReverse = ref(false)
|
||||
const fileSortSizeReverse = ref(false)
|
||||
const fileSortTimeReverse = ref(false)
|
||||
// 页面搜索相关
|
||||
const searchText = ref('')
|
||||
const urlToUpload = ref('')
|
||||
const selectedItems = reactive([] as any[])
|
||||
// 上传页面相关
|
||||
const isDragover = ref(false)
|
||||
const tableData = reactive([] as any[])
|
||||
const isShowUploadPanel = ref(false)
|
||||
const activeUpLoadTab = ref('uploading')
|
||||
const uploadTaskList = ref([] as IUploadTask[])
|
||||
const refreshUploadTaskId = ref<NodeJS.Timer | null>(null)
|
||||
const uploadPanelFilesList = ref([] as any[])
|
||||
const cancelToken = ref('')
|
||||
const isLoadingUploadPanelFiles = ref(false)
|
||||
const isUploadKeepDirStructure = computed(() => manageStore.config.settings.isUploadKeepDirStructure ?? true)
|
||||
const uploadingTaskList = computed(() => uploadTaskList.value.filter(item => ['uploading', 'queuing', 'paused'].includes(item.status)))
|
||||
const uploadedTaskList = computed(() => uploadTaskList.value.filter(item => ['uploaded', 'failed', 'canceled'].includes(item.status)))
|
||||
// 下载页面相关
|
||||
const isShowDownloadPanel = ref(false)
|
||||
const isLoadingDownloadData = ref(false)
|
||||
const activeDownLoadTab = ref('downloading')
|
||||
const currentDownloadFileList = reactive([] as any[])
|
||||
const downloadTaskList = ref([] as IDownloadTask[])
|
||||
const refreshDownloadTaskId = ref<NodeJS.Timer | null>(null)
|
||||
const downloadCancelToken = ref('')
|
||||
const downloadingTaskList = computed(() => downloadTaskList.value.filter(item => ['downloading', 'queuing', 'paused'].includes(item.status)))
|
||||
const downloadedTaskList = computed(() => downloadTaskList.value.filter(item => ['downloaded', 'failed', 'canceled'].includes(item.status)))
|
||||
// 上传文件相关
|
||||
const dialogVisible = ref(false)
|
||||
const showLoadingPage = ref(false)
|
||||
const showImagePreview = ref(false)
|
||||
const urlToUpload = ref('')
|
||||
// 图片预览相关
|
||||
const previewedImage = ref('')
|
||||
const isShowFileInfo = ref(false)
|
||||
const showedFileInfo = ref({} as any)
|
||||
const elTable = ref(null as any)
|
||||
const ImagePreviewList = computed(() => currentPageFilesInfo.filter(item => item.isImage).map(item => item.url))
|
||||
// 快捷键相关
|
||||
const isShiftKeyPress = ref<boolean>(false)
|
||||
const lastChoosed = ref<number>(-1)
|
||||
const isLoadingData = ref(false)
|
||||
const isLoadingDownloadData = ref(false)
|
||||
const cancelToken = ref('')
|
||||
const downloadCancelToken = ref('')
|
||||
const isShowUploadPanel = ref(false)
|
||||
const isShowDownloadPanel = ref(false)
|
||||
const dragover = ref(false)
|
||||
const activeUpLoadTab = ref('uploading')
|
||||
const activeDownLoadTab = ref('downloading')
|
||||
// 上传任务列表
|
||||
const uploadTaskList = ref([] as IUploadTask[])
|
||||
const downloadTaskList = ref([] as IDownloadTask[])
|
||||
const refreshUploadTaskId = ref<NodeJS.Timer | null>(null)
|
||||
const refreshDownloadTaskId = ref<NodeJS.Timer | null>(null)
|
||||
const uploadPanelFilesList = ref([] as any[])
|
||||
const isLoadingUploadPanelFiles = ref(false)
|
||||
const tableData = reactive([] as any[])
|
||||
const customUrlList = ref([] as any[])
|
||||
const currentCustomUrl = ref('')
|
||||
// 自定义域名相关
|
||||
const customDomainList = ref([] as any[])
|
||||
const currentCustomDomain = ref('')
|
||||
const isShowCustomDomainSelectList = computed(() => ['tcyun', 'aliyun', 'qiniu', 'github'].includes(currentPicBedName.value))
|
||||
const isShowCustomDomainInput = computed(() => ['aliyun', 'qiniu', 'tcyun', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
const isAutoCustomDomain = computed(() => manageStore.config.picBed[configMap.alias].isAutoCustomUrl === undefined ? true : manageStore.config.picBed[configMap.alias].isAutoCustomUrl)
|
||||
// 文件预览相关
|
||||
const isShowMarkDownDialog = ref(false)
|
||||
const markDownContent = ref('')
|
||||
const isShowTextFileDialog = ref(false)
|
||||
@@ -1563,50 +1587,28 @@ const textfileContent = ref('')
|
||||
const isShowVideoFileDialog = ref(false)
|
||||
const videoFileUrl = ref('')
|
||||
const videoPlayerHeaders = ref({})
|
||||
const showFileStyle = ref<'list' | 'grid'>('grid')
|
||||
const isUploadKeepDirStructure = computed(() => manageStore.config.settings.isUploadKeepDirStructure ?? true)
|
||||
// 重命名相关
|
||||
const isShowRenameFileIcon = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
const isShowBatchRenameDialog = ref(false)
|
||||
const batchRenameMatch = ref('')
|
||||
const batchRenameReplace = ref('')
|
||||
const isRenameIncludeExt = ref(false)
|
||||
const isSingleRename = ref(false)
|
||||
const itemToBeRenamed = ref({} as any)
|
||||
// 新建文件夹相关
|
||||
const isShowCreateNewFolder = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 'github', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showCustomUrlSelectList = computed(() => ['tcyun', 'aliyun', 'qiniu', 'github'].includes(currentPicBedName.value))
|
||||
const isShowPresignedUrl = computed(() => ['tcyun', 'aliyun', 'qiniu', 'github', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showCustomUrlInput = computed(() => ['aliyun', 'qiniu', 'tcyun', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showCreateNewFolder = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 'github', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showRenameFileIcon = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showPresignedUrl = computed(() => ['tcyun', 'aliyun', 'qiniu', 'github', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const uploadingTaskList = computed(() => uploadTaskList.value.filter(item => ['uploading', 'queuing', 'paused'].includes(item.status)))
|
||||
|
||||
const uploadedTaskList = computed(() => uploadTaskList.value.filter(item => ['uploaded', 'failed', 'canceled'].includes(item.status)))
|
||||
|
||||
const downloadingTaskList = computed(() => downloadTaskList.value.filter(item => ['downloading', 'queuing', 'paused'].includes(item.status)))
|
||||
|
||||
const downloadedTaskList = computed(() => downloadTaskList.value.filter(item => ['downloaded', 'failed', 'canceled'].includes(item.status)))
|
||||
|
||||
const isAutoCustomUrl = computed(() => manageStore.config.picBed[configMap.alias].isAutoCustomUrl === undefined ? true : manageStore.config.picBed[configMap.alias].isAutoCustomUrl)
|
||||
// 上传相关函数
|
||||
|
||||
function handleUploadKeepDirChange (val: any) {
|
||||
saveConfig('settings.isUploadKeepDirStructure', !!val)
|
||||
manageStore.refreshConfig()
|
||||
}
|
||||
|
||||
function handleViewChange (val: 'list' | 'grid') {
|
||||
saveConfig('settings.isShowList', val === 'list')
|
||||
showFileStyle.value = val
|
||||
}
|
||||
|
||||
function getBase64ofWebdav () {
|
||||
const headers = {
|
||||
Authorization: 'Basic ' + Buffer.from(`${manageStore.config.picBed[configMap.alias].username}:${manageStore.config.picBed[configMap.alias].password}`).toString('base64')
|
||||
}
|
||||
return headers
|
||||
function showUploadDialog () {
|
||||
isShowUploadPanel.value = true
|
||||
}
|
||||
|
||||
function startRefreshUploadTask () {
|
||||
@@ -1617,6 +1619,16 @@ function startRefreshUploadTask () {
|
||||
}, 300)
|
||||
}
|
||||
|
||||
function stopRefreshUploadTask () {
|
||||
refreshUploadTaskId.value && clearInterval(refreshUploadTaskId.value)
|
||||
}
|
||||
|
||||
// 下载相关函数
|
||||
|
||||
function showDownloadDialog () {
|
||||
isShowDownloadPanel.value = true
|
||||
}
|
||||
|
||||
function startRefreshDownloadTask () {
|
||||
refreshDownloadTaskId.value = setInterval(() => {
|
||||
ipcRenderer.invoke('getDownloadTaskList').then((res: any) => {
|
||||
@@ -1625,21 +1637,24 @@ function startRefreshDownloadTask () {
|
||||
}, 300)
|
||||
}
|
||||
|
||||
const stopRefreshUploadTask = () => refreshUploadTaskId.value && clearInterval(refreshUploadTaskId.value)
|
||||
function stopRefreshDownloadTask () {
|
||||
refreshDownloadTaskId.value && clearInterval(refreshDownloadTaskId.value)
|
||||
}
|
||||
|
||||
const stopRefreshDownloadTask = () => refreshDownloadTaskId.value && clearInterval(refreshDownloadTaskId.value)
|
||||
function handleViewChange (val: 'list' | 'grid') {
|
||||
saveConfig('settings.isShowList', val === 'list')
|
||||
layoutStyle.value = val
|
||||
}
|
||||
|
||||
const ImagePreviewList = computed(() => currentPageFilesInfo.filter(item => item.isImage).map(item => item.url))
|
||||
function getBase64ofWebdav () {
|
||||
const headers = {
|
||||
Authorization: 'Basic ' + Buffer.from(`${manageStore.config.picBed[configMap.alias].username}:${manageStore.config.picBed[configMap.alias].password}`).toString('base64')
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
const getCurrentPreviewIndex = computed(() => ImagePreviewList.value.indexOf(previewedImage.value))
|
||||
|
||||
const showUploadDialog = () => {
|
||||
isShowUploadPanel.value = true
|
||||
}
|
||||
const showDownloadDialog = () => {
|
||||
isShowDownloadPanel.value = true
|
||||
}
|
||||
|
||||
function openFileSelectDialog () {
|
||||
ipcRenderer.invoke('openFileSelectDialog').then((res: any) => {
|
||||
if (res) {
|
||||
@@ -1664,7 +1679,7 @@ function openFileSelectDialog () {
|
||||
}
|
||||
|
||||
function onDrop (e: DragEvent) {
|
||||
dragover.value = false
|
||||
isDragover.value = false
|
||||
const items = e.dataTransfer?.items
|
||||
if (items) {
|
||||
webkitReadDataTransfer(e.dataTransfer as DataTransfer)
|
||||
@@ -1837,7 +1852,7 @@ function uploadFiles () {
|
||||
filePath: item.path,
|
||||
fileSize: item.size,
|
||||
fileName: item.rawName,
|
||||
githubBranch: currentCustomUrl.value,
|
||||
githubBranch: currentCustomDomain.value,
|
||||
aclForUpload: manageStore.config.picBed[configMap.alias].aclForUpload
|
||||
})
|
||||
})
|
||||
@@ -1878,7 +1893,7 @@ const handleOpenDownloadedFolder = () => ipcRenderer.send('OpenDownloadedFolder'
|
||||
|
||||
function handleShowFileInfo (item: any) {
|
||||
isShowFileInfo.value = true
|
||||
showedFileInfo.value = item
|
||||
currentShowedFileInfo.value = item
|
||||
}
|
||||
|
||||
async function handleBreadcrumbClick (index: number) {
|
||||
@@ -1888,9 +1903,9 @@ async function handleBreadcrumbClick (index: number) {
|
||||
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
||||
}
|
||||
configMap.prefix = targetPrefix
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
resetParam(false)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
}
|
||||
|
||||
async function handleClickFile (item: any) {
|
||||
@@ -1902,16 +1917,16 @@ async function handleClickFile (item: any) {
|
||||
}
|
||||
if (item.isImage) {
|
||||
previewedImage.value = item.url
|
||||
showImagePreview.value = true
|
||||
isShowImagePreview.value = true
|
||||
} else if (item.isDir) {
|
||||
if (isLoadingData.value) {
|
||||
isLoadingData.value = false
|
||||
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
||||
}
|
||||
configMap.prefix = `/${item.key}`
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
await resetParam(false)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
} else if (item.fileName.endsWith('.md')) {
|
||||
try {
|
||||
ElMessage({
|
||||
@@ -1964,7 +1979,7 @@ const isIgnoreCase = computed(() => manageStore.config.settings.isIgnoreCase ??
|
||||
|
||||
async function handleChangeCustomUrl () {
|
||||
if (currentPicBedName.value === 'github') {
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
if (isLoadingData.value) {
|
||||
ElNotification({
|
||||
title: $T('MANAGE_BUCKET_CHANGE_CUSTOM_URL_TITLE'),
|
||||
@@ -1973,18 +1988,18 @@ async function handleChangeCustomUrl () {
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
await resetParam(true)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
} else if (['aliyun', 'tcyun', 'qiniu', 's3plist', 'webdavplist'].includes(currentPicBedName.value)) {
|
||||
const currentConfigs = await getConfig<any>('picBed')
|
||||
const currentConfig = currentConfigs[configMap.alias]
|
||||
const currentTransformedConfig = JSON.parse(currentConfig.transformedConfig ?? '{}')
|
||||
if (currentTransformedConfig[configMap.bucketName]) {
|
||||
currentTransformedConfig[configMap.bucketName].customUrl = currentCustomUrl.value
|
||||
currentTransformedConfig[configMap.bucketName].customUrl = currentCustomDomain.value
|
||||
} else {
|
||||
currentTransformedConfig[configMap.bucketName] = {
|
||||
customUrl: currentCustomUrl.value
|
||||
customUrl: currentCustomDomain.value
|
||||
}
|
||||
}
|
||||
currentConfig.transformedConfig = JSON.stringify(currentTransformedConfig)
|
||||
@@ -1993,8 +2008,8 @@ async function handleChangeCustomUrl () {
|
||||
}
|
||||
}
|
||||
|
||||
// when the current picBed is github, the customUrlList is used to store the github repo branches
|
||||
async function initCustomUrlList () {
|
||||
// when the current picBed is github, the customDomainList is used to store the github repo branches
|
||||
async function initCustomDomainList () {
|
||||
if ((['aliyun', 'tcyun', 'qiniu'].includes(currentPicBedName.value) &&
|
||||
(manageStore.config.picBed[configMap.alias].isAutoCustomUrl === undefined || manageStore.config.picBed[configMap.alias].isAutoCustomUrl === true)) ||
|
||||
['github', 'smms', 'upyun', 'imgur'].includes(currentPicBedName.value)) {
|
||||
@@ -2012,46 +2027,46 @@ async function initCustomUrlList () {
|
||||
}
|
||||
const res = await ipcRenderer.invoke('getBucketDomain', configMap.alias, param)
|
||||
if (res.length > 0) {
|
||||
customUrlList.value.length = 0
|
||||
customDomainList.value.length = 0
|
||||
res.forEach((item: any) => {
|
||||
if (!/^https?:\/\//.test(item) && currentPicBedName.value !== 'github') {
|
||||
item = manageStore.config.settings.isForceCustomUrlHttps ? `https://${item}` : `http://${item}`
|
||||
}
|
||||
customUrlList.value.push({
|
||||
customDomainList.value.push({
|
||||
label: item,
|
||||
value: item
|
||||
})
|
||||
})
|
||||
defaultUrl !== '' && currentPicBedName.value !== 'github' && customUrlList.value.push({
|
||||
defaultUrl !== '' && currentPicBedName.value !== 'github' && customDomainList.value.push({
|
||||
label: defaultUrl,
|
||||
value: defaultUrl
|
||||
})
|
||||
currentCustomUrl.value = customUrlList.value[0].value
|
||||
currentCustomDomain.value = customDomainList.value[0].value
|
||||
} else {
|
||||
customUrlList.value.length = 0
|
||||
customUrlList.value = [
|
||||
customDomainList.value.length = 0
|
||||
customDomainList.value = [
|
||||
{
|
||||
label: defaultUrl,
|
||||
value: defaultUrl
|
||||
}
|
||||
]
|
||||
currentCustomUrl.value = defaultUrl
|
||||
currentCustomDomain.value = defaultUrl
|
||||
}
|
||||
} else if (['aliyun', 'tcyun', 'qiniu'].includes(currentPicBedName.value)) {
|
||||
const currentConfigs = await getConfig<any>('picBed')
|
||||
const currentConfig = currentConfigs[configMap.alias]
|
||||
const currentTransformedConfig = JSON.parse(currentConfig.transformedConfig ?? '{}')
|
||||
if (currentTransformedConfig[configMap.bucketName]) {
|
||||
currentCustomUrl.value = currentTransformedConfig[configMap.bucketName].customUrl ?? ''
|
||||
currentCustomDomain.value = currentTransformedConfig[configMap.bucketName].customUrl ?? ''
|
||||
} else {
|
||||
currentCustomUrl.value = ''
|
||||
currentCustomDomain.value = ''
|
||||
}
|
||||
} else if (currentPicBedName.value === 's3plist') {
|
||||
const currentConfigs = await getConfig<any>('picBed')
|
||||
const currentConfig = currentConfigs[configMap.alias]
|
||||
const currentTransformedConfig = JSON.parse(currentConfig.transformedConfig ?? '{}')
|
||||
if (currentTransformedConfig[configMap.bucketName]) {
|
||||
currentCustomUrl.value = currentTransformedConfig[configMap.bucketName].customUrl ?? ''
|
||||
currentCustomDomain.value = currentTransformedConfig[configMap.bucketName].customUrl ?? ''
|
||||
} else {
|
||||
if (manageStore.config.picBed[configMap.alias].endpoint) {
|
||||
const endpoint = manageStore.config.picBed[configMap.alias].endpoint
|
||||
@@ -2061,9 +2076,9 @@ async function initCustomUrlList () {
|
||||
} else {
|
||||
url = new URL(manageStore.config.picBed[configMap.alias].sslEnabled ? 'https://' + endpoint : 'http://' + endpoint)
|
||||
}
|
||||
currentCustomUrl.value = `${url.protocol}//${configMap.bucketName}.${url.hostname}`
|
||||
currentCustomDomain.value = `${url.protocol}//${configMap.bucketName}.${url.hostname}`
|
||||
} else {
|
||||
currentCustomUrl.value = `https://${configMap.bucketName}.s3.amazonaws.com`
|
||||
currentCustomDomain.value = `https://${configMap.bucketName}.s3.amazonaws.com`
|
||||
}
|
||||
}
|
||||
handleChangeCustomUrl()
|
||||
@@ -2072,13 +2087,13 @@ async function initCustomUrlList () {
|
||||
const currentConfig = currentConfigs[configMap.alias]
|
||||
const currentTransformedConfig = JSON.parse(currentConfig.transformedConfig ?? '{}')
|
||||
if (currentTransformedConfig[configMap.bucketName] && currentTransformedConfig[configMap.bucketName]?.customUrl) {
|
||||
currentCustomUrl.value = currentTransformedConfig[configMap.bucketName].customUrl
|
||||
currentCustomDomain.value = currentTransformedConfig[configMap.bucketName].customUrl
|
||||
} else {
|
||||
let endpoint = manageStore.config.picBed[configMap.alias].endpoint
|
||||
if (!/^https?:\/\//.test(endpoint)) {
|
||||
endpoint = 'http://' + endpoint
|
||||
}
|
||||
currentCustomUrl.value = endpoint
|
||||
currentCustomDomain.value = endpoint
|
||||
}
|
||||
handleChangeCustomUrl()
|
||||
}
|
||||
@@ -2096,18 +2111,18 @@ async function resetParam (force: boolean = false) {
|
||||
cancelToken.value = ''
|
||||
pagingMarker.value = ''
|
||||
currentPrefix.value = configMap.prefix
|
||||
currentPage.value = 1
|
||||
currentPageNumber.value = 1
|
||||
currentPageFilesInfo.length = 0
|
||||
currentDownloadFileList.length = 0
|
||||
selectedItems.length = 0
|
||||
searchText.value = ''
|
||||
urlToUpload.value = ''
|
||||
dialogVisible.value = false
|
||||
showImagePreview.value = false
|
||||
isShowImagePreview.value = false
|
||||
previewedImage.value = ''
|
||||
isShowFileInfo.value = false
|
||||
lastChoosed.value = -1
|
||||
showFileStyle.value = manageStore.config.settings.isShowList ? 'list' : 'grid'
|
||||
layoutStyle.value = manageStore.config.settings.isShowList ? 'list' : 'grid'
|
||||
if (!isAutoRefresh.value && !force && !paging.value) {
|
||||
const cachedData = await searchExistFileList()
|
||||
if (cachedData.length > 0) {
|
||||
@@ -2116,7 +2131,7 @@ async function resetParam (force: boolean = false) {
|
||||
if (['name', 'time', 'size', 'ext'].includes(sortType as string)) {
|
||||
sortFile(sortType)
|
||||
}
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -2140,7 +2155,7 @@ async function resetParam (force: boolean = false) {
|
||||
if (res.isTruncated && paging.value) {
|
||||
pagingMarkerStack.push(pagingMarker.value)
|
||||
pagingMarker.value = res.nextMarker
|
||||
} else if (paging.value && currentPage.value > 1) {
|
||||
} else if (paging.value && currentPageNumber.value > 1) {
|
||||
ElNotification({
|
||||
title: $T('MANAGE_BUCKET_LAST_PAGE_TITLE'),
|
||||
message: $T('MANAGE_BUCKET_LAST_PAGE_MSG'),
|
||||
@@ -2168,14 +2183,14 @@ async function resetParam (force: boolean = false) {
|
||||
|
||||
watch(route, async (newRoute) => {
|
||||
if (newRoute.query.configMap) {
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
const query = newRoute.query.configMap as string
|
||||
for (const key in JSON.parse(query)) {
|
||||
configMap[key] = JSON.parse(query)[key]
|
||||
}
|
||||
await initCustomUrlList()
|
||||
await initCustomDomainList()
|
||||
await resetParam(false)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2189,31 +2204,31 @@ async function forceRefreshFileList () {
|
||||
})
|
||||
return
|
||||
}
|
||||
showLoadingPage.value = true
|
||||
isShowLoadingPage.value = true
|
||||
await resetParam(true)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
}
|
||||
|
||||
watch(currentPage, () => {
|
||||
if (typeof currentPage.value !== 'number' || currentPage.value === null) {
|
||||
currentPage.value = 1
|
||||
watch(currentPageNumber, () => {
|
||||
if (typeof currentPageNumber.value !== 'number' || currentPageNumber.value === null) {
|
||||
currentPageNumber.value = 1
|
||||
}
|
||||
})
|
||||
|
||||
const changePage = async (cur: number | undefined, prev: number | undefined) => {
|
||||
if (!cur || !prev) {
|
||||
currentPage.value = 1
|
||||
currentPageNumber.value = 1
|
||||
} else {
|
||||
if (cur > prev) {
|
||||
showLoadingPage.value = true
|
||||
currentPage.value = prev + 1
|
||||
isShowLoadingPage.value = true
|
||||
currentPageNumber.value = prev + 1
|
||||
currentPageFilesInfo.length = 0
|
||||
selectedItems.length = 0
|
||||
searchText.value = ''
|
||||
urlToUpload.value = ''
|
||||
dialogVisible.value = false
|
||||
const res = await getBucketFileList() as IStringKeyMap
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
if (res.success) {
|
||||
res.fullList.sort((a: any) => {
|
||||
return a.isDir ? -1 : 1
|
||||
@@ -2243,8 +2258,8 @@ const changePage = async (cur: number | undefined, prev: number | undefined) =>
|
||||
})
|
||||
}
|
||||
} else if (cur < prev) {
|
||||
showLoadingPage.value = true
|
||||
currentPage.value = prev - 1
|
||||
isShowLoadingPage.value = true
|
||||
currentPageNumber.value = prev - 1
|
||||
currentPageFilesInfo.length = 0
|
||||
selectedItems.length = 0
|
||||
searchText.value = ''
|
||||
@@ -2254,7 +2269,7 @@ const changePage = async (cur: number | undefined, prev: number | undefined) =>
|
||||
pagingMarkerStack.pop()
|
||||
pagingMarkerStack.pop()
|
||||
const res = await getBucketFileList() as IStringKeyMap
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
if (res.success) {
|
||||
res.fullList.sort((a: any) => {
|
||||
return a.isDir ? -1 : 1
|
||||
@@ -2292,7 +2307,7 @@ const changePage = async (cur: number | undefined, prev: number | undefined) =>
|
||||
watch(searchText, () => searchAndSort())
|
||||
|
||||
function searchAndSort () {
|
||||
elTable.value.scrollToRow(0)
|
||||
fileTable.value.scrollToRow(0)
|
||||
if (searchText.value) {
|
||||
if (isIgnoreCase.value) {
|
||||
currentPageFilesInfo.forEach((item: any) => {
|
||||
@@ -2455,8 +2470,8 @@ async function handleFolderBatchDownload (item: any) {
|
||||
prefix: `/${item.key.replace(/^\/+|\/+$/, '')}/`,
|
||||
marker: pagingMarker.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
customUrl: currentCustomUrl.value,
|
||||
currentPage: currentPage.value,
|
||||
customUrl: currentCustomDomain.value,
|
||||
currentPage: currentPageNumber.value,
|
||||
cancelToken: cancelToken.value,
|
||||
cdnUrl: configMap.cdnUrl
|
||||
}
|
||||
@@ -2488,7 +2503,7 @@ async function handleFolderBatchDownload (item: any) {
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
fileName: [undefined, true].includes(manageStore.config.settings.isDownloadFolderKeepDirStructure) ? `/${item.key.replace(/^\/+|\/+$/, '')}` : item.fileName,
|
||||
customUrl: currentCustomUrl.value,
|
||||
customUrl: currentCustomDomain.value,
|
||||
downloadUrl: item.downloadUrl,
|
||||
githubUrl: item.url,
|
||||
githubPrivate: configMap.bucketConfig.private
|
||||
@@ -2531,7 +2546,7 @@ async function handleBatchDownload () {
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
fileName: manageStore.config.settings.isDownloadFileKeepDirStructure ? `/${item.key.replace(/^\/+|\/+$/, '')}` : item.fileName,
|
||||
customUrl: currentCustomUrl.value,
|
||||
customUrl: currentCustomDomain.value,
|
||||
downloadUrl: item.downloadUrl,
|
||||
githubUrl: item.url,
|
||||
githubPrivate: configMap.bucketConfig.private
|
||||
@@ -2589,7 +2604,7 @@ function handleCreateFolder () {
|
||||
bucketName: configMap.bucketName,
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: currentPrefix.value.slice(1) + formatedPath + '/',
|
||||
githubBranch: currentCustomUrl.value
|
||||
githubBranch: currentCustomDomain.value
|
||||
}
|
||||
const res = await ipcRenderer.invoke('createBucketFolder', configMap.alias, param)
|
||||
if (res) {
|
||||
@@ -2690,7 +2705,7 @@ async function BatchRename () {
|
||||
region: configMap.bucketConfig.Location,
|
||||
oldKey: item.key,
|
||||
newKey: (item.key.slice(0, item.key.lastIndexOf('/') + 1) + item.newName).replaceAll('//', '/'),
|
||||
customUrl: currentCustomUrl.value
|
||||
customUrl: currentCustomDomain.value
|
||||
}
|
||||
ipcRenderer.invoke('renameBucketFile', configMap.alias, param).then((res: any) => {
|
||||
if (res) {
|
||||
@@ -2710,7 +2725,7 @@ async function BatchRename () {
|
||||
item.fileName = item.newName
|
||||
}
|
||||
item.key = (item.key.slice(0, item.key.lastIndexOf('/') + 1) + item.newName).replaceAll('//', '/')
|
||||
item.url = `${currentCustomUrl.value}${currentPrefix.value}${item.newName}`
|
||||
item.url = `${currentCustomDomain.value}${currentPrefix.value}${item.newName}`
|
||||
item.formatedTime = new Date().toLocaleString()
|
||||
if (!paging.value) {
|
||||
const table = fileCacheDbInstance.table(currentPicBedName.value)
|
||||
@@ -2726,7 +2741,7 @@ async function BatchRename () {
|
||||
i.fileName = item.newName
|
||||
}
|
||||
i.key = (i.key.slice(0, i.key.lastIndexOf('/') + 1) + item.newName).replaceAll('//', '/')
|
||||
i.url = `${currentCustomUrl.value}${currentPrefix.value}${item.newName}`
|
||||
i.url = `${currentCustomDomain.value}${currentPrefix.value}${item.newName}`
|
||||
i.formatedTime = new Date().toLocaleString()
|
||||
}
|
||||
})
|
||||
@@ -2832,8 +2847,8 @@ async function getBucketFileListBackStage () {
|
||||
prefix: currentPrefix.value,
|
||||
marker: pagingMarker.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
customUrl: currentCustomUrl.value,
|
||||
currentPage: currentPage.value,
|
||||
customUrl: currentCustomDomain.value,
|
||||
currentPage: currentPageNumber.value,
|
||||
cancelToken: cancelToken.value,
|
||||
cdnUrl: configMap.cdnUrl
|
||||
} as IStringKeyMap
|
||||
@@ -2904,8 +2919,8 @@ async function getBucketFileList () {
|
||||
prefix: currentPrefix.value,
|
||||
marker: pagingMarker.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
customUrl: currentCustomUrl.value,
|
||||
currentPage: currentPage.value
|
||||
customUrl: currentCustomDomain.value,
|
||||
currentPage: currentPageNumber.value
|
||||
}
|
||||
const res = await ipcRenderer.invoke('getBucketFileList', configMap.alias, param)
|
||||
return res
|
||||
@@ -2931,7 +2946,7 @@ function handleBatchDeleteInfo () {
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: copyedSelectedItems[i].key,
|
||||
DeleteHash: copyedSelectedItems[i].sha,
|
||||
githubBranch: currentCustomUrl.value
|
||||
githubBranch: currentCustomDomain.value
|
||||
}
|
||||
res = await ipcRenderer.invoke('deleteBucketFile', configMap.alias, param)
|
||||
} else {
|
||||
@@ -2940,7 +2955,7 @@ function handleBatchDeleteInfo () {
|
||||
bucketName: configMap.bucketName,
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: copyedSelectedItems[i].key,
|
||||
githubBranch: currentCustomUrl.value,
|
||||
githubBranch: currentCustomDomain.value,
|
||||
DeleteHash: copyedSelectedItems[i].sha
|
||||
}
|
||||
res = await ipcRenderer.invoke('deleteBucketFolder', configMap.alias, param)
|
||||
@@ -2999,7 +3014,7 @@ function handleDeleteFile (item: any) {
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
DeleteHash: item.sha,
|
||||
githubBranch: currentCustomUrl.value
|
||||
githubBranch: currentCustomDomain.value
|
||||
}
|
||||
res = await ipcRenderer.invoke('deleteBucketFile', configMap.alias, param)
|
||||
} else {
|
||||
@@ -3009,7 +3024,7 @@ function handleDeleteFile (item: any) {
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
DeleteHash: item.sha,
|
||||
githubBranch: currentCustomUrl.value
|
||||
githubBranch: currentCustomDomain.value
|
||||
}
|
||||
ElNotification.info({
|
||||
title: $T('MANAGE_BUCKET_DELETE_ERROR_MSG_TITLE'),
|
||||
@@ -3066,7 +3081,7 @@ function singleRename () {
|
||||
region: configMap.bucketConfig.Location,
|
||||
oldKey: item.key,
|
||||
newKey: (item.key.slice(0, item.key.lastIndexOf('/') + 1) + itemToBeRenamed.value.newName).replaceAll('//', '/'),
|
||||
customUrl: currentCustomUrl.value
|
||||
customUrl: currentCustomDomain.value
|
||||
}
|
||||
ipcRenderer.invoke('renameBucketFile', configMap.alias, param).then((res: any) => {
|
||||
if (res) {
|
||||
@@ -3084,7 +3099,7 @@ function singleRename () {
|
||||
item.fileName = itemToBeRenamed.value.newName
|
||||
}
|
||||
item.key = (item.key.slice(0, item.key.lastIndexOf('/') + 1) + itemToBeRenamed.value.newName).replaceAll('//', '/')
|
||||
item.url = `${currentCustomUrl.value}${currentPrefix.value}${itemToBeRenamed.value.newName}`
|
||||
item.url = `${currentCustomDomain.value}${currentPrefix.value}${itemToBeRenamed.value.newName}`
|
||||
item.formatedTime = new Date().toLocaleString()
|
||||
if (!paging.value) {
|
||||
const table = fileCacheDbInstance.table(currentPicBedName.value)
|
||||
@@ -3100,7 +3115,7 @@ function singleRename () {
|
||||
i.fileName = itemToBeRenamed.value.newName
|
||||
}
|
||||
i.key = (i.key.slice(0, i.key.lastIndexOf('/') + 1) + itemToBeRenamed.value.newName).replaceAll('//', '/')
|
||||
i.url = `${currentCustomUrl.value}${currentPrefix.value}${itemToBeRenamed.value.newName}`
|
||||
i.url = `${currentCustomDomain.value}${currentPrefix.value}${itemToBeRenamed.value.newName}`
|
||||
i.formatedTime = new Date().toLocaleString()
|
||||
}
|
||||
})
|
||||
@@ -3119,7 +3134,7 @@ async function getPreSignedUrl (item: any) {
|
||||
bucketName: configMap.bucketName,
|
||||
region: configMap.bucketConfig.Location,
|
||||
key: item.key,
|
||||
customUrl: currentCustomUrl.value,
|
||||
customUrl: currentCustomDomain.value,
|
||||
expires: manageStore.config.settings.PreSignedExpire,
|
||||
githubPrivate: configMap.bucketConfig.private,
|
||||
rawUrl: item.url
|
||||
@@ -3137,7 +3152,7 @@ function getTableKeyOfDb () {
|
||||
let tableKey
|
||||
if (currentPicBedName.value === 'github') {
|
||||
// customUrl is branch
|
||||
tableKey = `${configMap.alias}@${configMap.bucketConfig.githubUsername}@${configMap.bucketName}@${currentCustomUrl.value}@${currentPrefix.value}`
|
||||
tableKey = `${configMap.alias}@${configMap.bucketConfig.githubUsername}@${configMap.bucketName}@${currentCustomDomain.value}@${currentPrefix.value}`
|
||||
} else {
|
||||
tableKey = `${configMap.alias}@${configMap.bucketName}@${currentPrefix.value}`
|
||||
}
|
||||
@@ -3525,7 +3540,7 @@ const columns: Column<any>[] = [
|
||||
width: 30,
|
||||
cellRenderer: ({ rowData: item }) => (
|
||||
item.match || !searchText.value
|
||||
? item.isDir || !showRenameFileIcon.value
|
||||
? item.isDir || !isShowRenameFileIcon.value
|
||||
? item.isDir
|
||||
? <ElIcon
|
||||
size="20"
|
||||
@@ -3606,7 +3621,7 @@ const columns: Column<any>[] = [
|
||||
>
|
||||
Custom
|
||||
</ElDropdownItem>
|
||||
{ showPresignedUrl.value
|
||||
{ isShowPresignedUrl.value
|
||||
? <ElDropdownItem
|
||||
onClick={async () => {
|
||||
const res = await getPreSignedUrl(item)
|
||||
@@ -3712,10 +3727,10 @@ const columns: Column<any>[] = [
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await manageStore.refreshConfig()
|
||||
showLoadingPage.value = true
|
||||
await initCustomUrlList()
|
||||
isShowLoadingPage.value = true
|
||||
await initCustomDomainList()
|
||||
await resetParam(false)
|
||||
showLoadingPage.value = false
|
||||
isShowLoadingPage.value = false
|
||||
document.addEventListener('keydown', handleDetectShiftKey)
|
||||
document.addEventListener('keyup', handleDetectShiftKey)
|
||||
})
|
||||
|
||||
@@ -134,7 +134,7 @@ export interface IHTTPProxy {
|
||||
}
|
||||
|
||||
export const formatHttpProxy = (proxy: string | undefined, type: 'object' | 'string'): IHTTPProxy | undefined | string => {
|
||||
if (proxy === undefined || proxy === '') return undefined
|
||||
if (!proxy) return undefined
|
||||
if (/^https?:\/\//.test(proxy)) {
|
||||
const { protocol, hostname, port } = new URL(proxy)
|
||||
return type === 'string'
|
||||
@@ -144,16 +144,15 @@ export const formatHttpProxy = (proxy: string | undefined, type: 'object' | 'str
|
||||
port: Number(port),
|
||||
protocol: protocol.slice(0, -1)
|
||||
}
|
||||
} else {
|
||||
const [host, port] = proxy.split(':')
|
||||
return type === 'string'
|
||||
? `http://${host}:${port}`
|
||||
: {
|
||||
host,
|
||||
port: port ? Number(port) : 80,
|
||||
protocol: 'http'
|
||||
}
|
||||
}
|
||||
const [host, port] = proxy.split(':')
|
||||
return type === 'string'
|
||||
? `http://${host}:${port}`
|
||||
: {
|
||||
host,
|
||||
port: port ? Number(port) : 80,
|
||||
protocol: 'http'
|
||||
}
|
||||
}
|
||||
|
||||
export const svg = `
|
||||
|
||||
Reference in New Issue
Block a user