mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-02-02 11:08:13 -05:00
Merge remote-tracking branch 'origin/dev' into release
This commit is contained in:
commit
d0becbd9c2
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,3 +1,19 @@
|
|||||||
|
## :tada: 2.6.1 (2023-09-13)
|
||||||
|
|
||||||
|
|
||||||
|
### :sparkles: Features
|
||||||
|
|
||||||
|
* gif will be converted to animated webp now ([09a636f](https://github.com/Kuingsmile/PicList/commit/09a636f))
|
||||||
|
* manual page now open in a new window ([b197b32](https://github.com/Kuingsmile/PicList/commit/b197b32))
|
||||||
|
* webdav picbed now support digest auth ([2e655a4](https://github.com/Kuingsmile/PicList/commit/2e655a4))
|
||||||
|
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
|
||||||
|
* fix an issue of check box in manage page ([d776600](https://github.com/Kuingsmile/PicList/commit/d776600))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# :tada: 2.6.0 (2023-09-11)
|
# :tada: 2.6.0 (2023-09-11)
|
||||||
|
|
||||||
|
|
||||||
|
18
package.json
18
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "piclist",
|
"name": "piclist",
|
||||||
"version": "2.6.0",
|
"version": "2.6.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Kuingsmile",
|
"name": "Kuingsmile",
|
||||||
"email": "pkukuing@gmail.com"
|
"email": "pkukuing@gmail.com"
|
||||||
@ -34,16 +34,16 @@
|
|||||||
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/background.ts"
|
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/background.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.409.0",
|
"@aws-sdk/client-s3": "^3.410.0",
|
||||||
"@aws-sdk/lib-storage": "^3.409.0",
|
"@aws-sdk/lib-storage": "^3.410.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.409.0",
|
"@aws-sdk/s3-request-presigner": "^3.410.0",
|
||||||
"@element-plus/icons-vue": "^2.1.0",
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
"@highlightjs/vue-plugin": "^2.1.0",
|
"@highlightjs/vue-plugin": "^2.1.0",
|
||||||
"@nodelib/fs.walk": "^2.0.0",
|
"@nodelib/fs.walk": "^2.0.0",
|
||||||
"@octokit/rest": "^19.0.7",
|
"@octokit/rest": "^19.0.7",
|
||||||
"@picgo/i18n": "^1.0.0",
|
"@picgo/i18n": "^1.0.0",
|
||||||
"@picgo/store": "^2.1.0",
|
"@picgo/store": "^2.1.0",
|
||||||
"@smithy/node-http-handler": "^2.1.2",
|
"@smithy/node-http-handler": "^2.1.3",
|
||||||
"@types/mime-types": "^2.1.1",
|
"@types/mime-types": "^2.1.1",
|
||||||
"@videojs-player/vue": "^1.0.0",
|
"@videojs-player/vue": "^1.0.0",
|
||||||
"ali-oss": "^6.18.1",
|
"ali-oss": "^6.18.1",
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"node-ssh-no-cpu-features": "^1.0.1",
|
"node-ssh-no-cpu-features": "^1.0.1",
|
||||||
"nodejs-file-downloader": "^4.12.1",
|
"nodejs-file-downloader": "^4.12.1",
|
||||||
"piclist": "^1.0.4",
|
"piclist": "^1.1.1",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"pinia-plugin-persistedstate": "^3.2.0",
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
"qiniu": "^7.9.0",
|
"qiniu": "^7.9.0",
|
||||||
@ -102,8 +102,8 @@
|
|||||||
"@types/upyun": "^3.4.1",
|
"@types/upyun": "^3.4.1",
|
||||||
"@types/uuid": "^9.0.3",
|
"@types/uuid": "^9.0.3",
|
||||||
"@types/write-file-atomic": "^4.0.0",
|
"@types/write-file-atomic": "^4.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
"@typescript-eslint/eslint-plugin": "^6.7.0",
|
||||||
"@typescript-eslint/parser": "^6.6.0",
|
"@typescript-eslint/parser": "^6.7.0",
|
||||||
"@vue/cli-plugin-babel": "^5.0.8",
|
"@vue/cli-plugin-babel": "^5.0.8",
|
||||||
"@vue/cli-plugin-eslint": "^5.0.8",
|
"@vue/cli-plugin-eslint": "^5.0.8",
|
||||||
"@vue/cli-plugin-router": "^5.0.8",
|
"@vue/cli-plugin-router": "^5.0.8",
|
||||||
@ -126,7 +126,7 @@
|
|||||||
"eslint-plugin-vue": "^9.17.0",
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
"husky": "^3.1.0",
|
"husky": "^3.1.0",
|
||||||
"node-loader": "^2.0.0",
|
"node-loader": "^2.0.0",
|
||||||
"npm-check-updates": "^16.13.3",
|
"npm-check-updates": "^16.14.0",
|
||||||
"stylus": "^0.59.0",
|
"stylus": "^0.59.0",
|
||||||
"stylus-loader": "^7.1.3",
|
"stylus-loader": "^7.1.3",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
@ -617,6 +617,7 @@ MANAGE_CONSTANT_WEBDAV_PROXY_PLACEHOLDER: 'e.g. http://127.0.0.1:1080'
|
|||||||
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: If special network environment is required to access, please use proxy
|
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: If special network environment is required to access, please use proxy
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_DESC: Use HTTPS Connection
|
MANAGE_CONSTANT_WEBDAV_SSL_DESC: Use HTTPS Connection
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: Depending on the configuration of your WebDAV server, if your server does not support HTTPS, please turn off this option
|
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: Depending on the configuration of your WebDAV server, if your server does not support HTTPS, please turn off this option
|
||||||
|
MANAGE_CONSTANT_WEBDAV_AUTH_TYPE_DESC: Authentication Type
|
||||||
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV Configuration'
|
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV Configuration'
|
||||||
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: 'Refer to:'
|
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: 'Refer to:'
|
||||||
|
|
||||||
|
@ -620,6 +620,7 @@ MANAGE_CONSTANT_WEBDAV_PROXY_PLACEHOLDER: '例如:http://127.0.0.1:1080'
|
|||||||
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: 如果需要特殊网络环境才能访问,请使用代理
|
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: 如果需要特殊网络环境才能访问,请使用代理
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_DESC: 使用HTTPS连接
|
MANAGE_CONSTANT_WEBDAV_SSL_DESC: 使用HTTPS连接
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: 根据WebDAV服务器的配置,如果您的服务器不支持HTTPS,请关闭该选项
|
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: 根据WebDAV服务器的配置,如果您的服务器不支持HTTPS,请关闭该选项
|
||||||
|
MANAGE_CONSTANT_WEBDAV_AUTH_TYPE_DESC: 认证类型
|
||||||
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV配置'
|
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV配置'
|
||||||
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: '配置教程请参考: '
|
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: '配置教程请参考: '
|
||||||
|
|
||||||
|
@ -617,6 +617,7 @@ MANAGE_CONSTANT_WEBDAV_PROXY_PLACEHOLDER: '例如:http://127.0.0.1:1080'
|
|||||||
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: 如果需要特殊網路環境才能訪問,請使用代理
|
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: 如果需要特殊網路環境才能訪問,請使用代理
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_DESC: 使用HTTPS連線
|
MANAGE_CONSTANT_WEBDAV_SSL_DESC: 使用HTTPS連線
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: 根據WebDAV伺服器的配置,如果您的伺服器不支援HTTPS,請關閉該選項
|
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: 根據WebDAV伺服器的配置,如果您的伺服器不支援HTTPS,請關閉該選項
|
||||||
|
MANAGE_CONSTANT_WEBDAV_AUTH_TYPE_DESC: 認證類型
|
||||||
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV配置'
|
MANAGE_CONSTANT_WEBDAV_EXPLAIN: 'WebDAV配置'
|
||||||
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: '配置教程請參考: '
|
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: '配置教程請參考: '
|
||||||
|
|
||||||
|
@ -19,3 +19,7 @@ export const RENAME_WINDOW_URL = process.env.NODE_ENV === 'development'
|
|||||||
export const TOOLBOX_WINDOW_URL = process.env.NODE_ENV === 'development'
|
export const TOOLBOX_WINDOW_URL = process.env.NODE_ENV === 'development'
|
||||||
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#toolbox-page`
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#toolbox-page`
|
||||||
: 'picgo://./index.html#toolbox-page'
|
: 'picgo://./index.html#toolbox-page'
|
||||||
|
|
||||||
|
export const MANUAL_WINDOW_URL = process.env.NODE_ENV === 'development'
|
||||||
|
? `${(process.env.WEBPACK_DEV_SERVER_URL as string)}#documents`
|
||||||
|
: 'picgo://./index.html#documents'
|
||||||
|
@ -13,7 +13,8 @@ import {
|
|||||||
TRAY_WINDOW_URL,
|
TRAY_WINDOW_URL,
|
||||||
MINI_WINDOW_URL,
|
MINI_WINDOW_URL,
|
||||||
RENAME_WINDOW_URL,
|
RENAME_WINDOW_URL,
|
||||||
TOOLBOX_WINDOW_URL
|
TOOLBOX_WINDOW_URL,
|
||||||
|
MANUAL_WINDOW_URL
|
||||||
} from './constants'
|
} from './constants'
|
||||||
|
|
||||||
// Custom types/enums
|
// Custom types/enums
|
||||||
@ -57,6 +58,27 @@ const trayWindowOptions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const manualWindowOptions = {
|
||||||
|
height: 800,
|
||||||
|
width: 1200,
|
||||||
|
show: false,
|
||||||
|
frame: true,
|
||||||
|
center: true,
|
||||||
|
fullscreenable: true,
|
||||||
|
resizable: true,
|
||||||
|
title: 'Manual',
|
||||||
|
vibrancy: 'ultra-dark',
|
||||||
|
transparent: false,
|
||||||
|
webPreferences: {
|
||||||
|
webviewTag: true,
|
||||||
|
backgroundThrottling: false,
|
||||||
|
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
|
||||||
|
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
|
||||||
|
nodeIntegrationInWorker: true,
|
||||||
|
webSecurity: false
|
||||||
|
}
|
||||||
|
} as IBrowserWindowOptions
|
||||||
|
|
||||||
const settingWindowOptions = {
|
const settingWindowOptions = {
|
||||||
height: defaultWindowHeight,
|
height: defaultWindowHeight,
|
||||||
width: defaultWindowWidth,
|
width: defaultWindowWidth,
|
||||||
@ -169,6 +191,16 @@ windowList.set(IWindowList.TRAY_WINDOW, {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
windowList.set(IWindowList.MANUAL_WINDOW, {
|
||||||
|
isValid: true,
|
||||||
|
multiple: false,
|
||||||
|
options: () => manualWindowOptions,
|
||||||
|
callback (window) {
|
||||||
|
window.loadURL(handleWindowParams(MANUAL_WINDOW_URL))
|
||||||
|
window.focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
windowList.set(IWindowList.SETTING_WINDOW, {
|
windowList.set(IWindowList.SETTING_WINDOW, {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
@ -306,6 +306,10 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('openManualWindow', () => {
|
||||||
|
windowManager.get(IWindowList.MANUAL_WINDOW)!.show()
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.on('openMiniWindow', () => {
|
ipcMain.on('openMiniWindow', () => {
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import ManageLogger from '../utils/logger'
|
import ManageLogger from '../utils/logger'
|
||||||
|
|
||||||
// WebDAV 客户端库
|
// WebDAV 客户端库
|
||||||
import { createClient, WebDAVClient, FileStat, ProgressEvent } from 'webdav'
|
import { createClient, WebDAVClient, FileStat, ProgressEvent, AuthType, WebDAVClientOptions } from 'webdav'
|
||||||
|
|
||||||
// 错误格式化函数、端点地址格式化函数、获取内部代理、新的下载器、并发异步任务池
|
// 错误格式化函数、端点地址格式化函数、获取内部代理、新的下载器、并发异步任务池
|
||||||
import { formatError, formatEndpoint, getInnerAgent, NewDownloader, ConcurrencyPromisePool } from '../utils/common'
|
import { formatError, formatEndpoint, getInnerAgent, NewDownloader, ConcurrencyPromisePool } from '../utils/common'
|
||||||
@ -34,6 +34,7 @@ import path from 'path'
|
|||||||
|
|
||||||
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
// 取消下载任务的加载文件列表、刷新下载文件传输列表
|
||||||
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||||
|
|
||||||
class WebdavplistApi {
|
class WebdavplistApi {
|
||||||
endpoint: string
|
endpoint: string
|
||||||
@ -42,29 +43,35 @@ class WebdavplistApi {
|
|||||||
sslEnabled: boolean
|
sslEnabled: boolean
|
||||||
proxy: string | undefined
|
proxy: string | undefined
|
||||||
proxyStr: string | undefined
|
proxyStr: string | undefined
|
||||||
|
authType: 'basic' | 'digest' | undefined
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
agent: https.Agent | http.Agent
|
agent: https.Agent | http.Agent
|
||||||
ctx: WebDAVClient
|
ctx: WebDAVClient
|
||||||
|
|
||||||
constructor (endpoint: string, username: string, password: string, sslEnabled: boolean, proxy: string | undefined, logger: ManageLogger) {
|
constructor (endpoint: string, username: string, password: string, sslEnabled: boolean, proxy: string | undefined, authType: 'basic' | 'digest' | undefined, logger: ManageLogger) {
|
||||||
this.endpoint = formatEndpoint(endpoint, sslEnabled)
|
this.endpoint = formatEndpoint(endpoint, sslEnabled)
|
||||||
this.username = username
|
this.username = username
|
||||||
this.password = password
|
this.password = password
|
||||||
this.sslEnabled = sslEnabled
|
this.sslEnabled = sslEnabled
|
||||||
this.proxy = proxy
|
this.proxy = proxy
|
||||||
this.proxyStr = formatHttpProxy(proxy, 'string') as string | undefined
|
this.proxyStr = formatHttpProxy(proxy, 'string') as string | undefined
|
||||||
|
this.authType = authType || 'basic'
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
this.agent = getInnerAgent(proxy, sslEnabled).agent
|
this.agent = getInnerAgent(proxy, sslEnabled).agent
|
||||||
|
const options: WebDAVClientOptions = {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
maxBodyLength: 4 * 1024 * 1024 * 1024,
|
||||||
|
maxContentLength: 4 * 1024 * 1024 * 1024,
|
||||||
|
httpsAgent: sslEnabled ? this.agent : undefined,
|
||||||
|
httpAgent: !sslEnabled ? this.agent : undefined
|
||||||
|
}
|
||||||
|
if (this.authType === 'digest') {
|
||||||
|
options.authType = AuthType.Digest
|
||||||
|
}
|
||||||
this.ctx = createClient(
|
this.ctx = createClient(
|
||||||
this.endpoint,
|
this.endpoint,
|
||||||
{
|
options
|
||||||
username: this.username,
|
|
||||||
password: this.password,
|
|
||||||
maxBodyLength: 4 * 1024 * 1024 * 1024,
|
|
||||||
maxContentLength: 4 * 1024 * 1024 * 1024,
|
|
||||||
httpsAgent: sslEnabled ? this.agent : undefined,
|
|
||||||
httpAgent: !sslEnabled ? this.agent : undefined
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +282,7 @@ class WebdavplistApi {
|
|||||||
})
|
})
|
||||||
this.ctx.putFileContents(
|
this.ctx.putFileContents(
|
||||||
key,
|
key,
|
||||||
fs.createReadStream(filePath),
|
this.authType === 'digest' ? fs.readFileSync(filePath) : fs.createReadStream(filePath),
|
||||||
{
|
{
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
onUploadProgress: (progressEvent: ProgressEvent) => {
|
onUploadProgress: (progressEvent: ProgressEvent) => {
|
||||||
@ -347,12 +354,21 @@ class WebdavplistApi {
|
|||||||
sourceFileName: fileName,
|
sourceFileName: fileName,
|
||||||
targetFilePath: savedFilePath
|
targetFilePath: savedFilePath
|
||||||
})
|
})
|
||||||
const preSignedUrl = await this.getPreSignedUrl({
|
let preSignedUrl = await this.getPreSignedUrl({
|
||||||
key
|
key
|
||||||
})
|
})
|
||||||
const base64Str = Buffer.from(`${this.username}:${this.password}`).toString('base64')
|
let headers = {} as IStringKeyMap
|
||||||
const headers = {
|
if (this.authType === 'basic' || !this.authType) {
|
||||||
Authorization: `Basic ${base64Str}`
|
const base64Str = Buffer.from(`${this.username}:${this.password}`).toString('base64')
|
||||||
|
headers = {
|
||||||
|
Authorization: `Basic ${base64Str}`
|
||||||
|
}
|
||||||
|
} else if (this.authType === 'digest') {
|
||||||
|
const authHeader = await getAuthHeader('GET', this.endpoint, `/${key.replace(/^\/+/, '')}`, this.username, this.password)
|
||||||
|
headers = {
|
||||||
|
Authorization: authHeader
|
||||||
|
}
|
||||||
|
preSignedUrl = `${this.endpoint}/${key.replace(/^\/+/, '')}`
|
||||||
}
|
}
|
||||||
promises.push(() => new Promise((resolve, reject) => {
|
promises.push(() => new Promise((resolve, reject) => {
|
||||||
NewDownloader(instance, preSignedUrl, id, savedFilePath, this.logger, this.proxyStr, headers)
|
NewDownloader(instance, preSignedUrl, id, savedFilePath, this.logger, this.proxyStr, headers)
|
||||||
|
@ -75,7 +75,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
case 'upyun':
|
case 'upyun':
|
||||||
return new API.UpyunApi(this.currentPicBedConfig.bucketName, this.currentPicBedConfig.operator, this.currentPicBedConfig.password, this.logger, this.currentPicBedConfig.antiLeechToken, this.currentPicBedConfig.expireTime)
|
return new API.UpyunApi(this.currentPicBedConfig.bucketName, this.currentPicBedConfig.operator, this.currentPicBedConfig.password, this.logger, this.currentPicBedConfig.antiLeechToken, this.currentPicBedConfig.expireTime)
|
||||||
case 'webdavplist':
|
case 'webdavplist':
|
||||||
return new API.WebdavplistApi(this.currentPicBedConfig.endpoint, this.currentPicBedConfig.username, this.currentPicBedConfig.password, this.currentPicBedConfig.sslEnabled, this.currentPicBedConfig.proxy, this.logger)
|
return new API.WebdavplistApi(this.currentPicBedConfig.endpoint, this.currentPicBedConfig.username, this.currentPicBedConfig.password, this.currentPicBedConfig.sslEnabled, this.currentPicBedConfig.proxy, this.currentPicBedConfig.authType, this.logger)
|
||||||
default:
|
default:
|
||||||
return {} as any
|
return {} as any
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
import { createClient } from 'webdav'
|
import { AuthType, WebDAVClientOptions, createClient } from 'webdav'
|
||||||
import { formatEndpoint } from '~/main/manage/utils/common'
|
import { formatEndpoint } from '~/main/manage/utils/common'
|
||||||
|
|
||||||
export default class WebdavApi {
|
export default class WebdavApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileName, config: { host, username, password, path, sslEnabled } } = configMap
|
const { fileName, config: { host, username, password, path, sslEnabled, authType } } = configMap
|
||||||
const endpoint = formatEndpoint(host, sslEnabled)
|
const endpoint = formatEndpoint(host, sslEnabled)
|
||||||
|
const options: WebDAVClientOptions = {
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
}
|
||||||
|
if (authType === 'digest') {
|
||||||
|
options.authType = AuthType.Digest
|
||||||
|
}
|
||||||
const ctx = createClient(
|
const ctx = createClient(
|
||||||
endpoint,
|
endpoint,
|
||||||
{
|
options
|
||||||
username,
|
|
||||||
password
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
let key
|
let key
|
||||||
if (path === '/' || !path) {
|
if (path === '/' || !path) {
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
import { ref, onMounted, watch, computed } from 'vue'
|
import { ref, onMounted, watch, computed } from 'vue'
|
||||||
import { getFileIconPath } from '@/manage/utils/common'
|
import { getFileIconPath } from '@/manage/utils/common'
|
||||||
import { Loading } from '@element-plus/icons-vue'
|
import { Loading } from '@element-plus/icons-vue'
|
||||||
|
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||||
|
import { formatEndpoint } from '~/main/manage/utils/common'
|
||||||
|
|
||||||
const base64Url = ref('')
|
const base64Url = ref('')
|
||||||
const success = ref(false)
|
const success = ref(false)
|
||||||
@ -41,7 +43,7 @@ const props = defineProps(
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
headers: {
|
config: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
@ -56,9 +58,31 @@ const imageSource = computed(() => {
|
|||||||
|
|
||||||
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 getheaderOfWebdav (key: string) {
|
||||||
|
let headers = {} as any
|
||||||
|
if (props.config.authType === 'digest') {
|
||||||
|
const authHeader = await getAuthHeader(
|
||||||
|
'GET',
|
||||||
|
formatEndpoint(props.config.endpoint, props.config.sslEnabled || false),
|
||||||
|
`/${key.replace(/^\//, '')}`,
|
||||||
|
props.config.username,
|
||||||
|
props.config.password
|
||||||
|
)
|
||||||
|
headers = {
|
||||||
|
Authorization: authHeader
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
headers = {
|
||||||
|
Authorization: 'Basic ' + Buffer.from(`${props.config.username}:${props.config.password}`).toString('base64')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
const fetchImage = async () => {
|
const fetchImage = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(props.url, { method: 'GET', headers: props.headers })
|
const headers = await getheaderOfWebdav(props.item.key)
|
||||||
|
const res = await fetch(props.url, { method: 'GET', headers })
|
||||||
if (res.status >= 200 && res.status < 300) {
|
if (res.status >= 200 && res.status < 300) {
|
||||||
const blob = await res.blob()
|
const blob = await res.blob()
|
||||||
success.value = true
|
success.value = true
|
||||||
@ -72,7 +96,7 @@ const fetchImage = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => [props.url, props.headers], fetchImage, { deep: true })
|
watch(() => [props.url, props.item], fetchImage, { deep: true })
|
||||||
|
|
||||||
onMounted(fetchImage)
|
onMounted(fetchImage)
|
||||||
|
|
||||||
|
102
src/renderer/components/ImageWebdavTsx.tsx
Normal file
102
src/renderer/components/ImageWebdavTsx.tsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { defineComponent, ref, onMounted, watch, computed } from 'vue'
|
||||||
|
import { getFileIconPath } from '@/manage/utils/common'
|
||||||
|
import { Loading } from '@element-plus/icons-vue'
|
||||||
|
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||||
|
import { formatEndpoint } from '~/main/manage/utils/common'
|
||||||
|
import { ElImage, ElIcon } from 'element-plus'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
isShowThumbnail: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup (props) {
|
||||||
|
const base64Url = ref('')
|
||||||
|
const success = ref(false)
|
||||||
|
|
||||||
|
const imageSource = computed(() => {
|
||||||
|
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 getheaderOfWebdav (key: string) {
|
||||||
|
let headers = {} as any
|
||||||
|
if (props.config.authType === 'digest') {
|
||||||
|
const authHeader = await getAuthHeader(
|
||||||
|
'GET',
|
||||||
|
formatEndpoint(props.config.endpoint, props.config.sslEnabled || false),
|
||||||
|
`/${key.replace(/^\//, '')}`,
|
||||||
|
props.config.username,
|
||||||
|
props.config.password
|
||||||
|
)
|
||||||
|
headers = {
|
||||||
|
Authorization: authHeader
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
headers = {
|
||||||
|
Authorization: 'Basic ' + Buffer.from(`${props.config.username}:${props.config.password}`).toString('base64')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchImage = async () => {
|
||||||
|
try {
|
||||||
|
const headers = await getheaderOfWebdav(props.item.key)
|
||||||
|
const res = await fetch(props.url, { method: 'GET', headers })
|
||||||
|
if (res.status >= 200 && res.status < 300) {
|
||||||
|
const blob = await res.blob()
|
||||||
|
success.value = true
|
||||||
|
base64Url.value = URL.createObjectURL(blob)
|
||||||
|
} else {
|
||||||
|
throw new Error('Network response was not ok.')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
success.value = false
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(() => [props.url, props.item], fetchImage, { deep: true })
|
||||||
|
onMounted(fetchImage)
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<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;"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</ElImage>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
@ -358,6 +358,10 @@ const handleGetPicPeds = () => {
|
|||||||
|
|
||||||
const handleSelect = (index: string) => {
|
const handleSelect = (index: string) => {
|
||||||
defaultActive.value = index
|
defaultActive.value = index
|
||||||
|
if (index === routerConfig.DocumentPage) {
|
||||||
|
ipcRenderer.send('openManualWindow')
|
||||||
|
return
|
||||||
|
}
|
||||||
const type = index.match(routerConfig.UPLOADER_CONFIG_PAGE)
|
const type = index.match(routerConfig.UPLOADER_CONFIG_PAGE)
|
||||||
if (type === null) {
|
if (type === null) {
|
||||||
$router.push({
|
$router.push({
|
||||||
|
@ -546,7 +546,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
v-else-if="!item.isDir && currentPicBedName === 'webdavplist' && item.isImage"
|
v-else-if="!item.isDir && currentPicBedName === 'webdavplist' && item.isImage"
|
||||||
:is-show-thumbnail="isShowThumbnail"
|
:is-show-thumbnail="isShowThumbnail"
|
||||||
:item="item"
|
:item="item"
|
||||||
:headers="getBase64ofWebdav()"
|
:config="handleGetWebdavConfig()"
|
||||||
:url="item.url"
|
:url="item.url"
|
||||||
@click="handleClickFile(item)"
|
@click="handleClickFile(item)"
|
||||||
/>
|
/>
|
||||||
@ -705,7 +705,6 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-model="item.checked"
|
v-model="item.checked"
|
||||||
size="large"
|
size="large"
|
||||||
@change="handleCheckChangeOther(item)"
|
|
||||||
/>
|
/>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -719,6 +718,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
:initial-index="getCurrentPreviewIndex"
|
:initial-index="getCurrentPreviewIndex"
|
||||||
infinite
|
infinite
|
||||||
hide-on-click-modal
|
hide-on-click-modal
|
||||||
|
teleported
|
||||||
@close="isShowImagePreview = false"
|
@close="isShowImagePreview = false"
|
||||||
/>
|
/>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@ -1543,6 +1543,7 @@ import { videoExt } from '../utils/videofile'
|
|||||||
// 组件
|
// 组件
|
||||||
import ImageWebdav from '@/components/ImageWebdav.vue'
|
import ImageWebdav from '@/components/ImageWebdav.vue'
|
||||||
import ImageLocal from '@/components/ImageLocal.vue'
|
import ImageLocal from '@/components/ImageLocal.vue'
|
||||||
|
import ImageWebdavTsx from '@/components/ImageWebdavTsx'
|
||||||
|
|
||||||
// 国际化函数
|
// 国际化函数
|
||||||
import { T as $T } from '@/i18n'
|
import { T as $T } from '@/i18n'
|
||||||
@ -1661,6 +1662,8 @@ const batchRenameReplace = ref('')
|
|||||||
const isRenameIncludeExt = ref(false)
|
const isRenameIncludeExt = ref(false)
|
||||||
const isSingleRename = ref(false)
|
const isSingleRename = ref(false)
|
||||||
const itemToBeRenamed = ref({} as any)
|
const itemToBeRenamed = ref({} as any)
|
||||||
|
let fileTransferInterval: NodeJS.Timer | null = null
|
||||||
|
let downloadInterval: NodeJS.Timer | null = null
|
||||||
|
|
||||||
// 当前页面信息相关
|
// 当前页面信息相关
|
||||||
const currentPicBedName = computed<string>(() => manageStore.config.picBed[configMap.alias].picBedName)
|
const currentPicBedName = computed<string>(() => manageStore.config.picBed[configMap.alias].picBedName)
|
||||||
@ -1712,6 +1715,10 @@ function stopRefreshUploadTask () {
|
|||||||
refreshUploadTaskId.value && clearInterval(refreshUploadTaskId.value)
|
refreshUploadTaskId.value && clearInterval(refreshUploadTaskId.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleGetWebdavConfig () {
|
||||||
|
return manageStore.config.picBed[configMap.alias]
|
||||||
|
}
|
||||||
|
|
||||||
// 下载相关函数
|
// 下载相关函数
|
||||||
|
|
||||||
function showDownloadDialog () {
|
function showDownloadDialog () {
|
||||||
@ -1737,13 +1744,6 @@ function handleViewChange (val: 'list' | 'grid') {
|
|||||||
layoutStyle.value = val
|
layoutStyle.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 openFileSelectDialog () {
|
function openFileSelectDialog () {
|
||||||
@ -2469,13 +2469,13 @@ async function handleFolderBatchDownload (item: any) {
|
|||||||
ipcRenderer.on(refreshDownloadFileTransferList, (evt: IpcRendererEvent, data) => {
|
ipcRenderer.on(refreshDownloadFileTransferList, (evt: IpcRendererEvent, data) => {
|
||||||
downloadFileTransferStore.refreshDownloadFileTransferList(data)
|
downloadFileTransferStore.refreshDownloadFileTransferList(data)
|
||||||
})
|
})
|
||||||
const interval = setInterval(() => {
|
downloadInterval = setInterval(() => {
|
||||||
const currentFileList = downloadFileTransferStore.getDownloadFileTransferList()
|
const currentFileList = downloadFileTransferStore.getDownloadFileTransferList()
|
||||||
currentDownloadFileList.length = 0
|
currentDownloadFileList.length = 0
|
||||||
currentDownloadFileList.push(...currentFileList)
|
currentDownloadFileList.push(...currentFileList)
|
||||||
if (downloadFileTransferStore.isFinished()) {
|
if (downloadFileTransferStore.isFinished() && downloadInterval) {
|
||||||
clearInterval(interval)
|
|
||||||
isLoadingDownloadData.value = false
|
isLoadingDownloadData.value = false
|
||||||
|
clearInterval(downloadInterval)
|
||||||
if (downloadFileTransferStore.isSuccess()) {
|
if (downloadFileTransferStore.isSuccess()) {
|
||||||
ElNotification.success({
|
ElNotification.success({
|
||||||
title: $T('MANAGE_BUCKET_DOWNLOAD_FOLDER_BOX_TIP'),
|
title: $T('MANAGE_BUCKET_DOWNLOAD_FOLDER_BOX_TIP'),
|
||||||
@ -2846,7 +2846,7 @@ async function getBucketFileListBackStage () {
|
|||||||
ipcRenderer.on('refreshFileTransferList', (evt: IpcRendererEvent, data) => {
|
ipcRenderer.on('refreshFileTransferList', (evt: IpcRendererEvent, data) => {
|
||||||
fileTransferStore.refreshFileTransferList(data)
|
fileTransferStore.refreshFileTransferList(data)
|
||||||
})
|
})
|
||||||
const interval = setInterval(() => {
|
fileTransferInterval = setInterval(() => {
|
||||||
const currentFileList = fileTransferStore.getFileTransferList()
|
const currentFileList = fileTransferStore.getFileTransferList()
|
||||||
currentPageFilesInfo.splice(0, currentPageFilesInfo.length, ...currentFileList)
|
currentPageFilesInfo.splice(0, currentPageFilesInfo.length, ...currentFileList)
|
||||||
const sortType = localStorage.getItem('sortType') as sortTypeList || 'init'
|
const sortType = localStorage.getItem('sortType') as sortTypeList || 'init'
|
||||||
@ -2858,9 +2858,9 @@ async function getBucketFileListBackStage () {
|
|||||||
fullList: currentPageFilesInfo
|
fullList: currentPageFilesInfo
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
if (fileTransferStore.isFinished()) {
|
if (fileTransferStore.isFinished() && fileTransferInterval) {
|
||||||
clearInterval(interval)
|
|
||||||
isLoadingData.value = false
|
isLoadingData.value = false
|
||||||
|
clearInterval(fileTransferInterval)
|
||||||
if (fileTransferStore.isSuccess()) {
|
if (fileTransferStore.isSuccess()) {
|
||||||
ElNotification.success({
|
ElNotification.success({
|
||||||
title: $T('MANAGE_BUCKET_GET_FILE_BS_NOT_TITLE'),
|
title: $T('MANAGE_BUCKET_GET_FILE_BS_NOT_TITLE'),
|
||||||
@ -3392,7 +3392,6 @@ const columns: Column<any>[] = [
|
|||||||
cellRenderer: ({ rowData: item }) => (
|
cellRenderer: ({ rowData: item }) => (
|
||||||
<ElCheckbox
|
<ElCheckbox
|
||||||
v-model={item.checked}
|
v-model={item.checked}
|
||||||
onChange={() => handleCheckChangeOther(item)}
|
|
||||||
>
|
>
|
||||||
</ElCheckbox>
|
</ElCheckbox>
|
||||||
)
|
)
|
||||||
@ -3413,23 +3412,36 @@ const columns: Column<any>[] = [
|
|||||||
{{
|
{{
|
||||||
reference: () => (
|
reference: () => (
|
||||||
!item.isDir
|
!item.isDir
|
||||||
? <ElImage
|
? currentPicBedName.value !== 'webdavplist'
|
||||||
src={isShowThumbnail.value ? item.isImage ? item.url : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`) : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
? <ElImage
|
||||||
fit="contain"
|
src={isShowThumbnail.value ? item.isImage ? item.url : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`) : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||||
style={{ width: '20px', height: '20px' }}
|
fit="contain"
|
||||||
>
|
style={{ width: '20px', height: '20px' }}
|
||||||
{{
|
>
|
||||||
placeholder: () => <ElIcon>
|
{{
|
||||||
<Loading />
|
placeholder: () => <ElIcon>
|
||||||
</ElIcon>,
|
<Loading />
|
||||||
error: () =>
|
</ElIcon>,
|
||||||
<ElImage
|
error: () =>
|
||||||
src={require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
<ElImage
|
||||||
fit="contain"
|
src={require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||||
style={{ width: '20px', height: '20px' }}
|
fit="contain"
|
||||||
/>
|
style={{ width: '20px', height: '20px' }}
|
||||||
}}
|
/>
|
||||||
</ElImage>
|
}}
|
||||||
|
</ElImage>
|
||||||
|
: item.isImage
|
||||||
|
? <ImageWebdavTsx
|
||||||
|
isShowThumbnail={isShowThumbnail.value}
|
||||||
|
item={item}
|
||||||
|
config={handleGetWebdavConfig()}
|
||||||
|
url={item.url}
|
||||||
|
/>
|
||||||
|
: <ElImage
|
||||||
|
src={require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)}
|
||||||
|
fit="contain"
|
||||||
|
style={{ width: '20px', height: '20px' }}
|
||||||
|
></ElImage>
|
||||||
: <ElImage
|
: <ElImage
|
||||||
src={require('./assets/icons/folder.webp')}
|
src={require('./assets/icons/folder.webp')}
|
||||||
fit="contain"
|
fit="contain"
|
||||||
@ -3437,22 +3449,29 @@ const columns: Column<any>[] = [
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
default: () => (
|
default: () => (
|
||||||
<ElImage
|
currentPicBedName.value === 'webdavplist' && item.isImage
|
||||||
src={item.isImage ? item.url : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`) }
|
? <ImageWebdavTsx
|
||||||
fit="contain"
|
isShowThumbnail={isShowThumbnail.value}
|
||||||
>
|
item={item}
|
||||||
{{
|
config={handleGetWebdavConfig()}
|
||||||
placeholder: () => (<ElIcon>
|
url={item.url}
|
||||||
<Loading />
|
/>
|
||||||
</ElIcon>
|
: <ElImage
|
||||||
),
|
src={item.isImage ? item.url : require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`) }
|
||||||
error: () => (
|
fit="contain"
|
||||||
<ElIcon>
|
>
|
||||||
<CircleClose />
|
{{
|
||||||
|
placeholder: () => (<ElIcon>
|
||||||
|
<Loading />
|
||||||
</ElIcon>
|
</ElIcon>
|
||||||
)
|
),
|
||||||
}}
|
error: () => (
|
||||||
</ElImage>
|
<ElIcon>
|
||||||
|
<CircleClose />
|
||||||
|
</ElIcon>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</ElImage>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</ElPopover>
|
</ElPopover>
|
||||||
@ -3672,6 +3691,10 @@ onBeforeMount(async () => {
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
document.removeEventListener('keydown', handleDetectShiftKey)
|
document.removeEventListener('keydown', handleDetectShiftKey)
|
||||||
document.removeEventListener('keyup', handleDetectShiftKey)
|
document.removeEventListener('keyup', handleDetectShiftKey)
|
||||||
|
fileTransferInterval && clearInterval(fileTransferInterval)
|
||||||
|
downloadInterval && clearInterval(downloadInterval)
|
||||||
|
refreshUploadTaskId.value && clearInterval(refreshUploadTaskId.value)
|
||||||
|
refreshDownloadTaskId.value && clearInterval(refreshDownloadTaskId.value)
|
||||||
if (isLoadingData.value) {
|
if (isLoadingData.value) {
|
||||||
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
||||||
}
|
}
|
||||||
|
@ -576,17 +576,20 @@ async function getCurrentConfigList () {
|
|||||||
const config = configList[pb]
|
const config = configList[pb]
|
||||||
return config?.configList?.length ? config.configList.map((item: any) => ({ ...item, type: pb })) : []
|
return config?.configList?.length ? config.configList.map((item: any) => ({ ...item, type: pb })) : []
|
||||||
})
|
})
|
||||||
await getAllConfigAliasArray()
|
|
||||||
const autoImport = await getPicBedsConfig<boolean>('settings.autoImport') || false
|
const autoImport = await getPicBedsConfig<boolean>('settings.autoImport') || false
|
||||||
if (!autoImport) return
|
if (autoImport) {
|
||||||
const autoImportPicBed = initArray(await getPicBedsConfig<string | string[]>('settings.autoImportPicBed') || '', [])
|
const autoImportPicBed = initArray(await getPicBedsConfig<string | string[]>('settings.autoImportPicBed') || '', [])
|
||||||
await Promise.all(filteredConfigList.flatMap((config) => transUpToManage(config, config.type, autoImportPicBed)))
|
await Promise.all(filteredConfigList.flatMap((config) => transUpToManage(config, config.type, autoImportPicBed)))
|
||||||
if (Object.keys(importedNewConfig).length > 0) {
|
if (Object.keys(importedNewConfig).length > 0) {
|
||||||
const oldConfig = await getConfig<any>('picBed')
|
const oldConfig = await getConfig<any>('picBed')
|
||||||
const newConfig = { ...oldConfig, ...importedNewConfig }
|
const newConfig = { ...oldConfig, ...importedNewConfig }
|
||||||
saveConfig('picBed', newConfig)
|
saveConfig('picBed', newConfig)
|
||||||
await manageStore.refreshConfig()
|
await manageStore.refreshConfig()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await getAllConfigAliasArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
function isImported (alias: string) {
|
function isImported (alias: string) {
|
||||||
@ -721,6 +724,7 @@ async function transUpToManage (config: IUploaderConfigListItem, picBedName: str
|
|||||||
webPath: config.webpath || '',
|
webPath: config.webpath || '',
|
||||||
customUrl: config.customUrl || '',
|
customUrl: config.customUrl || '',
|
||||||
sslEnabled: !!config.sslEnabled,
|
sslEnabled: !!config.sslEnabled,
|
||||||
|
authType: config.authType || 'basic',
|
||||||
proxy: '',
|
proxy: '',
|
||||||
transformedConfig: JSON.stringify({
|
transformedConfig: JSON.stringify({
|
||||||
webdav: {
|
webdav: {
|
||||||
|
@ -779,10 +779,20 @@ export const supportedPicBedList: IStringKeyMap = {
|
|||||||
default: true,
|
default: true,
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
tooltip: $T('MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP')
|
tooltip: $T('MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP')
|
||||||
|
},
|
||||||
|
authType: {
|
||||||
|
required: true,
|
||||||
|
description: $T('MANAGE_CONSTANT_WEBDAV_AUTH_TYPE_DESC'),
|
||||||
|
default: 'basic',
|
||||||
|
type: 'select',
|
||||||
|
selectOptions: {
|
||||||
|
basic: 'Basic',
|
||||||
|
digest: 'Digest'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
explain: $T('MANAGE_CONSTANT_WEBDAV_EXPLAIN'),
|
explain: $T('MANAGE_CONSTANT_WEBDAV_EXPLAIN'),
|
||||||
options: ['alias', 'endpoint', 'username', 'password', 'bucketName', 'baseDir', 'customUrl', 'webPath', 'proxy', 'sslEnabled'],
|
options: ['alias', 'endpoint', 'username', 'password', 'bucketName', 'baseDir', 'customUrl', 'webPath', 'proxy', 'sslEnabled', 'authType'],
|
||||||
refLink: 'https://piclist.cn/manage.html#webdav',
|
refLink: 'https://piclist.cn/manage.html#webdav',
|
||||||
referenceText: $T('MANAGE_CONSTANT_WEBDAV_REFER_TEXT')
|
referenceText: $T('MANAGE_CONSTANT_WEBDAV_REFER_TEXT')
|
||||||
},
|
},
|
||||||
|
74
src/renderer/manage/utils/digestAuth.ts
Normal file
74
src/renderer/manage/utils/digestAuth.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import crypto from 'crypto'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const AUTH_KEY_VALUE_RE = /(\w+)=["']?([^'"]{1,10000})["']?/
|
||||||
|
let NC = 0
|
||||||
|
const NC_PAD = '00000000'
|
||||||
|
|
||||||
|
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) {
|
||||||
|
const parts = wwwAuthenticate.split(',')
|
||||||
|
const opts = {} as IStringKeyMap
|
||||||
|
for (let i = 0; i < parts.length; i++) {
|
||||||
|
const m = AUTH_KEY_VALUE_RE.exec(parts[i])
|
||||||
|
if (m) {
|
||||||
|
opts[m[1]] = m[2].replace(/["']/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.realm || !opts.nonce) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
let qop = opts.qop || ''
|
||||||
|
|
||||||
|
const userpassArray = [username, password]
|
||||||
|
|
||||||
|
let nc = String(++NC)
|
||||||
|
nc = NC_PAD.substring(nc.length) + nc
|
||||||
|
const cnonce = crypto.randomBytes(8).toString('hex')
|
||||||
|
|
||||||
|
const ha1 = md5(userpassArray[0] + ':' + opts.realm + ':' + userpassArray[1])
|
||||||
|
const ha2 = md5(method.toUpperCase() + ':' + uri)
|
||||||
|
let s = ha1 + ':' + opts.nonce
|
||||||
|
if (qop) {
|
||||||
|
qop = qop.split(',')[0]
|
||||||
|
s += ':' + nc + ':' + cnonce + ':' + qop
|
||||||
|
}
|
||||||
|
s += ':' + ha2
|
||||||
|
const response = md5(s)
|
||||||
|
let authstring =
|
||||||
|
'Digest username="' +
|
||||||
|
userpassArray[0] +
|
||||||
|
'", realm="' +
|
||||||
|
opts.realm +
|
||||||
|
'", nonce="' +
|
||||||
|
opts.nonce +
|
||||||
|
'", uri="' +
|
||||||
|
uri +
|
||||||
|
'", response="' +
|
||||||
|
response +
|
||||||
|
'"'
|
||||||
|
if (opts.opaque) {
|
||||||
|
authstring += ', opaque="' + opts.opaque + '"'
|
||||||
|
}
|
||||||
|
if (qop) {
|
||||||
|
authstring += ', qop=' + qop + ', nc=' + nc + ', cnonce="' + cnonce + '"'
|
||||||
|
}
|
||||||
|
return authstring
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAuthHeader (method: string, host: string, uri: string, username: string, password: string) {
|
||||||
|
try {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -79,11 +79,6 @@ export default createRouter({
|
|||||||
component: () => import(/* webpackChunkName: "Plugin" */ '@/pages/Plugin.vue'),
|
component: () => import(/* webpackChunkName: "Plugin" */ '@/pages/Plugin.vue'),
|
||||||
name: config.PLUGIN_PAGE
|
name: config.PLUGIN_PAGE
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'documents',
|
|
||||||
component: () => import(/* webpackChunkName: "DocumentPage" */ '@/pages/DocumentPage.vue'),
|
|
||||||
name: config.DocumentPage
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'shortKey',
|
path: 'shortKey',
|
||||||
component: () => import(/* webpackChunkName: "ShortkeyPage" */ '@/pages/ShortKey.vue'),
|
component: () => import(/* webpackChunkName: "ShortkeyPage" */ '@/pages/ShortKey.vue'),
|
||||||
@ -96,6 +91,11 @@ export default createRouter({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/documents',
|
||||||
|
component: () => import(/* webpackChunkName: "DocumentPage" */ '@/pages/DocumentPage.vue'),
|
||||||
|
name: config.DocumentPage
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/toolbox-page',
|
path: '/toolbox-page',
|
||||||
name: config.TOOLBOX_CONFIG_PAGE,
|
name: config.TOOLBOX_CONFIG_PAGE,
|
||||||
|
@ -33,7 +33,8 @@ export enum IWindowList {
|
|||||||
TRAY_WINDOW = 'TRAY_WINDOW',
|
TRAY_WINDOW = 'TRAY_WINDOW',
|
||||||
MINI_WINDOW = 'MINI_WINDOW',
|
MINI_WINDOW = 'MINI_WINDOW',
|
||||||
RENAME_WINDOW = 'RENAME_WINDOW',
|
RENAME_WINDOW = 'RENAME_WINDOW',
|
||||||
TOOLBOX_WINDOW = 'TOOLBOX_WINDOW'
|
TOOLBOX_WINDOW = 'TOOLBOX_WINDOW',
|
||||||
|
MANUAL_WINDOW = 'MANUAL_WINDOW'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IRemoteNoticeActionType {
|
export enum IRemoteNoticeActionType {
|
||||||
|
1
src/universal/types/i18n.d.ts
vendored
1
src/universal/types/i18n.d.ts
vendored
@ -579,6 +579,7 @@ interface ILocales {
|
|||||||
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: string
|
MANAGE_CONSTANT_WEBDAV_PROXY_TOOLTIP: string
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_DESC: string
|
MANAGE_CONSTANT_WEBDAV_SSL_DESC: string
|
||||||
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: string
|
MANAGE_CONSTANT_WEBDAV_SSL_TOOLTIP: string
|
||||||
|
MANAGE_CONSTANT_WEBDAV_AUTH_TYPE_DESC: string
|
||||||
MANAGE_CONSTANT_WEBDAV_EXPLAIN: string
|
MANAGE_CONSTANT_WEBDAV_EXPLAIN: string
|
||||||
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: string
|
MANAGE_CONSTANT_WEBDAV_REFER_TEXT: string
|
||||||
MANAGE_CONSTANT_LOCAL_NAME: string
|
MANAGE_CONSTANT_LOCAL_NAME: string
|
||||||
|
Loading…
Reference in New Issue
Block a user