mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-25 10:10:21 +08:00
✨ Feature: add video,text file and markdown file preview
This commit is contained in:
@@ -18,6 +18,11 @@ import vue3PhotoPreview from 'vue3-photo-preview'
|
||||
import 'vue3-photo-preview/dist/index.css'
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
||||
import hljsCommon from 'highlight.js/lib/common'
|
||||
import VueVideoPlayer from '@videojs-player/vue'
|
||||
import 'video.js/dist/video-js.css'
|
||||
|
||||
webFrame.setVisualZoomLevelLimits(1, 1)
|
||||
|
||||
@@ -60,6 +65,9 @@ app.use(store)
|
||||
app.use(vue3PhotoPreview)
|
||||
app.use(pinia)
|
||||
app.use(ContextMenu)
|
||||
console.log(hljsCommon.highlightAuto('<h1>Highlight.js has been registered successfully!</h1>').value)
|
||||
app.use(hljsVuePlugin)
|
||||
app.use(VueVideoPlayer)
|
||||
app.mount('#app')
|
||||
|
||||
initTalkingData()
|
||||
|
||||
@@ -6,6 +6,7 @@ import SmmsApi from './smms'
|
||||
import GithubApi from './github'
|
||||
import ImgurApi from './imgur'
|
||||
import S3plistApi from './s3plist'
|
||||
import WebdavplistApi from './webdavplist'
|
||||
|
||||
export default {
|
||||
TcyunApi,
|
||||
@@ -15,5 +16,6 @@ export default {
|
||||
SmmsApi,
|
||||
GithubApi,
|
||||
ImgurApi,
|
||||
S3plistApi
|
||||
S3plistApi,
|
||||
WebdavplistApi
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
||||
import https from 'https'
|
||||
import http from 'http'
|
||||
import { ManageLogger } from '../utils/logger'
|
||||
import { formatError, getAgent, getFileMimeType, gotDownload } from '../utils/common'
|
||||
import { formatEndpoint, formatError, getAgent, getFileMimeType, gotDownload } from '../utils/common'
|
||||
import { isImage } from '@/manage/utils/common'
|
||||
import { HttpsProxyAgent, HttpProxyAgent } from 'hpagent'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
@@ -64,7 +64,7 @@ class S3plistApi {
|
||||
accessKeyId,
|
||||
secretAccessKey
|
||||
},
|
||||
endpoint: endpoint ? this.formatEndpoint(endpoint, sslEnabled) : undefined,
|
||||
endpoint: endpoint ? formatEndpoint(endpoint, sslEnabled) : undefined,
|
||||
sslEnabled,
|
||||
s3ForcePathStyle,
|
||||
httpOptions: {
|
||||
@@ -75,9 +75,6 @@ class S3plistApi {
|
||||
this.agent = this.setAgent(proxy, sslEnabled)
|
||||
}
|
||||
|
||||
formatEndpoint = (endpoint: string, sslEnabled: boolean): string =>
|
||||
!/^https?:\/\//.test(endpoint) ? `${sslEnabled ? 'https' : 'http'}://${endpoint}` : endpoint
|
||||
|
||||
setAgent (proxy: string | undefined, sslEnabled: boolean) : HttpProxyAgent | HttpsProxyAgent | undefined {
|
||||
if (sslEnabled) {
|
||||
const agent = getAgent(proxy, true).https
|
||||
|
||||
130
src/main/manage/apis/webdavplist.ts
Normal file
130
src/main/manage/apis/webdavplist.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import ManageLogger from '../utils/logger'
|
||||
import { createClient, WebDAVClient, FileStat } from 'webdav'
|
||||
import { formatError, formatEndpoint, getInnerAgent } from '../utils/common'
|
||||
import { isImage } from '@/manage/utils/common'
|
||||
import http from 'http'
|
||||
import https from 'https'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { ipcMain, IpcMainEvent } from 'electron'
|
||||
|
||||
class WebdavplistApi {
|
||||
endpoint: string
|
||||
username: string
|
||||
password: string
|
||||
sslEnabled: boolean
|
||||
proxy: string | undefined
|
||||
logger: ManageLogger
|
||||
agent: https.Agent | http.Agent
|
||||
ctx: WebDAVClient
|
||||
|
||||
constructor (endpoint: string, username: string, password: string, sslEnabled: boolean, proxy: string | undefined, logger: ManageLogger) {
|
||||
this.endpoint = formatEndpoint(endpoint, sslEnabled)
|
||||
this.username = username
|
||||
this.password = password
|
||||
this.sslEnabled = sslEnabled
|
||||
this.proxy = proxy
|
||||
this.logger = logger
|
||||
this.agent = getInnerAgent(proxy, sslEnabled).agent
|
||||
this.ctx = createClient(
|
||||
this.endpoint,
|
||||
{
|
||||
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
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
logParam = (error:any, method: string) =>
|
||||
this.logger.error(formatError(error, { class: 'WebdavplistApi', method }))
|
||||
|
||||
formatFolder (item: FileStat, urlPrefix: string) {
|
||||
return {
|
||||
...item,
|
||||
key: item.filename.replace(/^\/+/, ''),
|
||||
fileName: item.basename,
|
||||
fileSize: 0,
|
||||
Key: item.filename.replace(/^\/+/, ''),
|
||||
formatedTime: '',
|
||||
isDir: true,
|
||||
checked: false,
|
||||
isImage: false,
|
||||
match: false,
|
||||
url: `${urlPrefix}${item.filename}`
|
||||
}
|
||||
}
|
||||
|
||||
formatFile (item: FileStat, urlPrefix: string) {
|
||||
return {
|
||||
...item,
|
||||
key: item.filename.replace(/^\/+/, ''),
|
||||
fileName: item.basename,
|
||||
fileSize: item.size,
|
||||
Key: item.filename.replace(/^\/+/, ''),
|
||||
formatedTime: new Date(item.lastmod).toLocaleString(),
|
||||
isDir: false,
|
||||
checked: false,
|
||||
match: false,
|
||||
isImage: isImage(item.basename),
|
||||
url: `${urlPrefix}${item.filename}`
|
||||
}
|
||||
}
|
||||
|
||||
isRequestSuccess = (code: number) => code >= 200 && code < 300
|
||||
|
||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||
const { prefix, customUrl, cancelToken } = configMap
|
||||
const urlPrefix = customUrl || this.endpoint
|
||||
const cancelTask = [false]
|
||||
ipcMain.on('cancelLoadingFileList', (_evt: IpcMainEvent, token: string) => {
|
||||
if (token === cancelToken) {
|
||||
cancelTask[0] = true
|
||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||
}
|
||||
})
|
||||
let res = {} as any
|
||||
const result = {
|
||||
fullList: <any>[],
|
||||
success: false,
|
||||
finished: false
|
||||
}
|
||||
try {
|
||||
res = await this.ctx.getDirectoryContents(prefix, {
|
||||
deep: false,
|
||||
details: true
|
||||
})
|
||||
if (this.isRequestSuccess(res.status)) {
|
||||
if (res.data && res.data.length) {
|
||||
res.data.forEach((item: FileStat) => {
|
||||
if (item.type === 'directory') {
|
||||
result.fullList.push(this.formatFolder(item, urlPrefix))
|
||||
} else {
|
||||
result.fullList.push(this.formatFile(item, urlPrefix))
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
result.finished = true
|
||||
window.webContents.send('refreshFileTransferList', result)
|
||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
this.logParam(error, 'getBucketListBackstage')
|
||||
result.finished = true
|
||||
window.webContents.send('refreshFileTransferList', result)
|
||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||
}
|
||||
result.success = true
|
||||
result.finished = true
|
||||
window.webContents.send('refreshFileTransferList', result)
|
||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||
}
|
||||
}
|
||||
|
||||
export default WebdavplistApi
|
||||
@@ -69,6 +69,8 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
return new API.ImgurApi(this.currentPicBedConfig.imgurUserName, this.currentPicBedConfig.accessToken, this.currentPicBedConfig.proxy, this.logger)
|
||||
case 's3plist':
|
||||
return new API.S3plistApi(this.currentPicBedConfig.accessKeyId, this.currentPicBedConfig.secretAccessKey, this.currentPicBedConfig.endpoint, this.currentPicBedConfig.sslEnabled, this.currentPicBedConfig.s3ForcePathStyle, this.currentPicBedConfig.proxy, this.logger)
|
||||
case 'webdavplist':
|
||||
return new API.WebdavplistApi(this.currentPicBedConfig.endpoint, this.currentPicBedConfig.username, this.currentPicBedConfig.password, this.currentPicBedConfig.sslEnabled, this.currentPicBedConfig.proxy, this.logger)
|
||||
default:
|
||||
return {} as any
|
||||
}
|
||||
@@ -172,6 +174,12 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
Location: 'smms',
|
||||
CreationDate: new Date().toISOString()
|
||||
}]
|
||||
case 'webdavplist':
|
||||
return [{
|
||||
Name: 'webdav',
|
||||
Location: 'webdav',
|
||||
CreationDate: new Date().toISOString()
|
||||
}]
|
||||
default:
|
||||
console.log(param)
|
||||
return []
|
||||
@@ -309,6 +317,7 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
case 'github':
|
||||
case 'imgur':
|
||||
case 's3plist':
|
||||
case 'webdavplist':
|
||||
try {
|
||||
client = this.createClient() as any
|
||||
return await client.getBucketListBackstage(param!)
|
||||
|
||||
@@ -14,8 +14,10 @@ import UpDownTaskQueue,
|
||||
downloadTaskSpecialStatus
|
||||
} from '../datastore/upDownTaskQueue'
|
||||
import { ManageLogger } from '../utils/logger'
|
||||
import { formatHttpProxy } from '@/manage/utils/common'
|
||||
import { formatHttpProxy, IHTTPProxy } from '@/manage/utils/common'
|
||||
import { HttpsProxyAgent, HttpProxyAgent } from 'hpagent'
|
||||
import http from 'http'
|
||||
import https from 'https'
|
||||
|
||||
export const getFSFile = async (
|
||||
filePath: string,
|
||||
@@ -244,6 +246,47 @@ export const getAgent = (proxy:any, https: boolean = true) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const getInnerAgent = (proxy: any, sslEnabled: boolean = true) => {
|
||||
const formatProxy = formatHttpProxy(proxy, 'object') as IHTTPProxy
|
||||
if (sslEnabled) {
|
||||
return formatProxy
|
||||
? {
|
||||
agent: new https.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
rejectUnauthorized: false,
|
||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined,
|
||||
host: formatProxy.host,
|
||||
port: formatProxy.port
|
||||
})
|
||||
}
|
||||
: {
|
||||
agent: new https.Agent({
|
||||
rejectUnauthorized: false,
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getOptions (
|
||||
method?: string,
|
||||
headers?: IStringKeyMap,
|
||||
@@ -270,3 +313,10 @@ export function getOptions (
|
||||
})
|
||||
return options
|
||||
}
|
||||
|
||||
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string =>
|
||||
!/^https?:\/\//.test(endpoint)
|
||||
? `${sslEnabled ? 'https' : 'http'}://${endpoint}`
|
||||
: sslEnabled
|
||||
? endpoint.replace('http://', 'https://')
|
||||
: endpoint.replace('https://', 'http://')
|
||||
|
||||
BIN
src/renderer/manage/pages/assets/webdavplist.png
Normal file
BIN
src/renderer/manage/pages/assets/webdavplist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 196 KiB |
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
ea/*
|
||||
*UI布局和部分样式代码参考了https://github.com/willnewii/qiniuClient
|
||||
*感谢作者@willnewii
|
||||
*/
|
||||
@@ -29,7 +29,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-else-if="['aliyun', 'qiniu', 'tcyun', 's3plist'].includes(currentPicBedName)"
|
||||
v-else-if="showCustomUrlInput"
|
||||
v-model="currentCustomUrl"
|
||||
placeholder="请输入自定义域名"
|
||||
style="width: 200px;"
|
||||
@@ -764,18 +764,97 @@ https://www.baidu.com/img/bd_logo1.png"
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-drawer>
|
||||
<el-dialog
|
||||
v-model="isShowMarkDownDialog"
|
||||
title="预览MD"
|
||||
center
|
||||
align-center
|
||||
draggable
|
||||
fullscreen
|
||||
close-on-press-escape
|
||||
show-close
|
||||
destroy-on-close
|
||||
>
|
||||
<div
|
||||
style="-webkit-user-select: text"
|
||||
v-html="markDownContent"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Close"
|
||||
size="large"
|
||||
style="position: fixed;bottom: 10px;right: 15px"
|
||||
circle
|
||||
@click="() => {isShowMarkDownDialog = false}"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="isShowTextFileDialog"
|
||||
title="预览"
|
||||
center
|
||||
align-center
|
||||
draggable
|
||||
fullscreen
|
||||
close-on-press-escape
|
||||
show-close
|
||||
destroy-on-close
|
||||
>
|
||||
<highlightjs
|
||||
style="-webkit-user-select: text;"
|
||||
language="js"
|
||||
:code="textfileContent"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Close"
|
||||
size="large"
|
||||
style="position: fixed;bottom: 10px;right: 15px"
|
||||
circle
|
||||
@click="() => {isShowTextFileDialog = false}"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="isShowVideoFileDialog"
|
||||
title="播放"
|
||||
center
|
||||
align-center
|
||||
draggable
|
||||
fullscreen
|
||||
close-on-press-escape
|
||||
show-close
|
||||
destroy-on-close
|
||||
>
|
||||
<video-player
|
||||
:src="videoFileUrl"
|
||||
controls
|
||||
:loop="true"
|
||||
:volume="0.6"
|
||||
:autoplay="true"
|
||||
:width="1100"
|
||||
:height="700"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Close"
|
||||
size="large"
|
||||
style="position: fixed;bottom: 10px;right: 15px"
|
||||
circle
|
||||
@click="() => {isShowVideoFileDialog = false}"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
import { ref, reactive, watch, onBeforeMount, computed, onBeforeUnmount } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, DocumentAdd, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
||||
import { Close, Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, DocumentAdd, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
||||
import { useManageStore } from '../store/manageStore'
|
||||
import { renameFile, formatLink, formatFileName, getFileIconPath, formatFileSize, getExtension, isValidUrl } from '../utils/common'
|
||||
import { ipcRenderer, clipboard, IpcRendererEvent } from 'electron'
|
||||
import { fileCacheDbInstance } from '../store/bucketFileDb'
|
||||
import { trimPath } from '~/main/manage/utils/common'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
ElMessage, ElMessageBox, ElNotification,
|
||||
ElButton,
|
||||
@@ -798,7 +877,9 @@ import path from 'path'
|
||||
import { IUploadTask, IDownloadTask } from '~/main/manage/datastore/upDownTaskQueue'
|
||||
import fs from 'fs-extra'
|
||||
import { getConfig, saveConfig } from '../utils/dataSender'
|
||||
|
||||
import { marked } from 'marked'
|
||||
import { textFileExt } from '../utils/textfile'
|
||||
import { videoExt } from '../utils/videofile'
|
||||
/*
|
||||
configMap:{
|
||||
prefix: string, -> baseDir
|
||||
@@ -871,12 +952,20 @@ const isLoadingUploadPanelFiles = ref(false)
|
||||
const tableData = reactive([] as any[])
|
||||
const customUrlList = ref([] as any[])
|
||||
const currentCustomUrl = ref('')
|
||||
const isShowMarkDownDialog = ref(false)
|
||||
const markDownContent = ref('')
|
||||
const isShowTextFileDialog = ref(false)
|
||||
const textfileContent = ref('')
|
||||
const isShowVideoFileDialog = ref(false)
|
||||
const videoFileUrl = ref('')
|
||||
|
||||
const showCustomUrlSelectList = computed(() => ['tcyun', 'aliyun', 'qiniu', 'github'].includes(currentPicBedName.value))
|
||||
|
||||
const showCreateNewFolder = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 'github', 's3plist'].includes(currentPicBedName.value))
|
||||
const showCustomUrlInput = computed(() => ['aliyun', 'qiniu', 'tcyun', 's3plist', 'webdavplist'].includes(currentPicBedName.value))
|
||||
|
||||
const showRenameFileIcon = computed(() => ['tcyun', 'aliyun', 'qiniu', 'upyun', 's3plist'].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'].includes(currentPicBedName.value))
|
||||
|
||||
@@ -1177,6 +1266,40 @@ async function handleClickFile (item: any) {
|
||||
showLoadingPage.value = true
|
||||
await resetParam(false)
|
||||
showLoadingPage.value = false
|
||||
} else if (item.fileName.endsWith('.md')) {
|
||||
try {
|
||||
ElMessage({
|
||||
message: '开始获取文件',
|
||||
duration: 300,
|
||||
type: 'success'
|
||||
})
|
||||
const fileUrl = item.url
|
||||
const res = await axios.get(fileUrl)
|
||||
const content = res.data
|
||||
markDownContent.value = marked(content)
|
||||
isShowMarkDownDialog.value = true
|
||||
} catch (error) {
|
||||
ElMessage.error('获取文件内容失败')
|
||||
}
|
||||
} else if (textFileExt.includes(path.extname(item.fileName).toLowerCase()) ||
|
||||
textFileExt.includes(item.fileName.toLowerCase())
|
||||
) {
|
||||
try {
|
||||
ElMessage({
|
||||
message: '开始获取文件',
|
||||
duration: 300,
|
||||
type: 'success'
|
||||
})
|
||||
const fileUrl = item.url
|
||||
const res = await axios.get(fileUrl)
|
||||
textfileContent.value = res.data
|
||||
isShowTextFileDialog.value = true
|
||||
} catch (error) {
|
||||
ElMessage.error('获取文件内容失败')
|
||||
}
|
||||
} else if (videoExt.includes(path.extname(item.fileName).toLowerCase())) {
|
||||
videoFileUrl.value = item.url
|
||||
isShowVideoFileDialog.value = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,7 +1329,7 @@ async function handelChangeCustomUrl () {
|
||||
showLoadingPage.value = true
|
||||
await resetParam(true)
|
||||
showLoadingPage.value = false
|
||||
} else if (['aliyun', 'tcyun', 'qiniu', 's3plist'].includes(currentPicBedName.value)) {
|
||||
} 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 ?? '{}')
|
||||
@@ -1297,6 +1420,20 @@ async function initCustomUrlList () {
|
||||
}
|
||||
}
|
||||
handelChangeCustomUrl()
|
||||
} else if (currentPicBedName.value === 'webdavplist') {
|
||||
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
|
||||
} else {
|
||||
let endpoint = manageStore.config.picBed[configMap.alias].endpoint
|
||||
if (!/^https?:\/\//.test(endpoint)) {
|
||||
endpoint = 'http://' + endpoint
|
||||
}
|
||||
currentCustomUrl.value = endpoint
|
||||
}
|
||||
handelChangeCustomUrl()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@
|
||||
v-if="supportedPicBedList[item.icon].configOptions[option].type === 'string'"
|
||||
v-model.trim="configResult[item.icon + '.' + option]"
|
||||
:placeholder="supportedPicBedList[item.icon].configOptions[option].placeholder"
|
||||
:disabled="!!supportedPicBedList[item.icon].configOptions[option].disabled"
|
||||
/>
|
||||
<el-switch
|
||||
v-else-if="supportedPicBedList[item.icon].configOptions[option].type === 'boolean'"
|
||||
|
||||
@@ -316,7 +316,8 @@ const urlMap : IStringKeyMap = {
|
||||
qiniu: 'https://portal.qiniu.com',
|
||||
tcyun: 'https://console.cloud.tencent.com/cos',
|
||||
upyun: 'https://console.upyun.com',
|
||||
s3plist: 'https://aws.amazon.com/cn/s3/'
|
||||
s3plist: 'https://aws.amazon.com/cn/s3/',
|
||||
webdavplist: 'https://baike.baidu.com/item/WebDAV/4610909'
|
||||
}
|
||||
|
||||
const openPicBedUrl = () => shell.openExternal(urlMap[currentPagePicBedConfig.picBedName])
|
||||
@@ -442,7 +443,8 @@ const menuTitleMap:IStringKeyMap = {
|
||||
s3plist: '存储桶',
|
||||
smms: '相册',
|
||||
imgur: '相册',
|
||||
github: '仓库'
|
||||
github: '仓库',
|
||||
webdavplist: ''
|
||||
}
|
||||
|
||||
const showNewIconList = ['aliyun', 'qiniu', 'tcyun']
|
||||
|
||||
@@ -27,15 +27,16 @@ export class FileCacheDb extends Dexie {
|
||||
upyun: Table<IFileCache, string>
|
||||
imgur: Table<IFileCache, string>
|
||||
s3plist: Table<IFileCache, string>
|
||||
webdavplist: Table<IFileCache, string>
|
||||
|
||||
constructor () {
|
||||
super('bucketFileDb')
|
||||
const tableNames = ['tcyun', 'aliyun', 'qiniu', 'github', 'smms', 'upyun', 'imgur', 's3plist']
|
||||
const tableNames = ['tcyun', 'aliyun', 'qiniu', 'github', 'smms', 'upyun', 'imgur', 's3plist', 'webdavplist']
|
||||
const tableNamesMap = tableNames.reduce((acc, cur) => {
|
||||
acc[cur] = '&key, value'
|
||||
return acc
|
||||
}, {} as IStringKeyMap)
|
||||
this.version(1).stores(tableNamesMap)
|
||||
this.version(2).stores(tableNamesMap)
|
||||
this.tcyun = this.table('tcyun')
|
||||
this.aliyun = this.table('aliyun')
|
||||
this.qiniu = this.table('qiniu')
|
||||
@@ -44,6 +45,7 @@ export class FileCacheDb extends Dexie {
|
||||
this.upyun = this.table('upyun')
|
||||
this.imgur = this.table('imgur')
|
||||
this.s3plist = this.table('s3plist')
|
||||
this.webdavplist = this.table('webdavplist')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -661,5 +661,100 @@ export const supportedPicBedList: IStringKeyMap = {
|
||||
options: ['alias', 'accessKeyId', 'secretAccessKey', 'endpoint', 'sslEnabled', 's3ForcePathStyle', 'proxy', 'aclForUpload', 'bucketName', 'baseDir', 'paging', 'itemsPerPage'],
|
||||
refLink: 'https://github.com/wayjam/picgo-plugin-s3',
|
||||
referenceText: '配置教程请参考:'
|
||||
},
|
||||
webdavplist: {
|
||||
name: 'WebDAV',
|
||||
icon: 'webdavplist',
|
||||
configOptions: {
|
||||
alias: {
|
||||
required: true,
|
||||
description: '配置别名-必需',
|
||||
placeholder: '该配置的唯一标识',
|
||||
type: 'string',
|
||||
rule: aliasRule,
|
||||
default: 'webdavplist-A',
|
||||
tooltip: aliasTooltip
|
||||
},
|
||||
endpoint: {
|
||||
required: true,
|
||||
description: '地址-必需',
|
||||
placeholder: '例如:https://example.com/dav',
|
||||
type: 'string',
|
||||
rule: defaultBaseRule('rootDomain'),
|
||||
tooltip: '请填写完整的WebDAV地址,例如:https://example.com/dav'
|
||||
},
|
||||
username: {
|
||||
required: true,
|
||||
description: '用户名-必需',
|
||||
placeholder: '请输入用户名',
|
||||
type: 'string',
|
||||
rule: defaultBaseRule('username')
|
||||
},
|
||||
bucketName: {
|
||||
required: true,
|
||||
description: '特殊配置',
|
||||
placeholder: '例如:bucket1',
|
||||
type: 'string',
|
||||
default: 'webdav',
|
||||
disabled: true,
|
||||
tooltip: '此处不可修改,仅为软件兼容性考虑'
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
description: '密码-必需',
|
||||
placeholder: '请输入密码',
|
||||
type: 'string',
|
||||
rule: defaultBaseRule('password')
|
||||
},
|
||||
baseDir: {
|
||||
required: false,
|
||||
description: '起始目录-可选',
|
||||
placeholder: '例如:/test1',
|
||||
type: 'string',
|
||||
default: '/',
|
||||
tooltip: baseDirTooltip
|
||||
},
|
||||
customUrl: {
|
||||
required: false,
|
||||
description: '自定义域名-可选',
|
||||
placeholder: '例如:https://example.com',
|
||||
type: 'string',
|
||||
tooltip: '如果您的WebDAV服务器支持自定义域名,请填写完整的自定义域名,例如:https://example.com',
|
||||
rule: [
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (value) {
|
||||
if (!/^https?:\/\/.+/.test(value)) {
|
||||
callback(new Error('自定义域名请以http://或https://开头'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
proxy: {
|
||||
required: false,
|
||||
description: '代理-可选',
|
||||
placeholder: '例如:http://127.0.0.1:1080',
|
||||
type: 'string',
|
||||
tooltip: '如果需要特殊网络环境才能访问,请使用代理'
|
||||
},
|
||||
sslEnabled: {
|
||||
required: true,
|
||||
description: '使用HTTPS连接',
|
||||
default: true,
|
||||
type: 'boolean',
|
||||
tooltip: '根据WebDAV服务器的配置,如果您的服务器不支持HTTPS,请关闭该选项'
|
||||
}
|
||||
},
|
||||
explain: 'WebDAV配置',
|
||||
options: ['alias', 'endpoint', 'username', 'password', 'bucketName', 'baseDir', 'customUrl', 'proxy', 'sslEnabled'],
|
||||
refLink: 'https://pichoro.horosama.com/#/PicHoroDocs/configure?id=webdav',
|
||||
referenceText: '配置教程请参考:'
|
||||
}
|
||||
}
|
||||
|
||||
41
src/renderer/manage/utils/textfile.ts
Normal file
41
src/renderer/manage/utils/textfile.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export const textFileExt = [
|
||||
'.bat',
|
||||
'.c',
|
||||
'.cmd',
|
||||
'.conf',
|
||||
'.config',
|
||||
'.cpp',
|
||||
'.css',
|
||||
'.csv',
|
||||
'.dart',
|
||||
'.gitattributes',
|
||||
'.gitconfig',
|
||||
'.gitignore',
|
||||
'.gitkeep',
|
||||
'.gitmodules',
|
||||
'.go',
|
||||
'.h',
|
||||
'.hpp',
|
||||
'.htm',
|
||||
'.html',
|
||||
'.ini',
|
||||
'.java',
|
||||
'.js',
|
||||
'.json',
|
||||
'.log',
|
||||
'.php',
|
||||
'.prop',
|
||||
'.properties',
|
||||
'.py',
|
||||
'.rc',
|
||||
'.sh',
|
||||
'.tsv',
|
||||
'.txt',
|
||||
'.xml',
|
||||
'.yaml',
|
||||
'.yml',
|
||||
'.ts',
|
||||
'.yarnrc',
|
||||
'.condarc',
|
||||
'license'
|
||||
]
|
||||
29
src/renderer/manage/utils/videofile.ts
Normal file
29
src/renderer/manage/utils/videofile.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
export const videoExt = [
|
||||
'.aac',
|
||||
'.amv',
|
||||
'.avi',
|
||||
'.flac',
|
||||
'.flv',
|
||||
'.m2ts',
|
||||
'.m4a',
|
||||
'.m4v',
|
||||
'.mp3',
|
||||
'.mpeg',
|
||||
'.mpg',
|
||||
'.mts',
|
||||
'.ogg',
|
||||
'.ogv',
|
||||
'.vob',
|
||||
'.wav',
|
||||
'.webm',
|
||||
'.mp4',
|
||||
'.3g2',
|
||||
'.3gp',
|
||||
'.asf',
|
||||
'.mov',
|
||||
'.mxf',
|
||||
'.rm',
|
||||
'.rmvb',
|
||||
'.wmv',
|
||||
'.mkv'
|
||||
]
|
||||
@@ -906,7 +906,7 @@ function handleLanguageChange (val: string) {
|
||||
}
|
||||
|
||||
function goConfigPage () {
|
||||
sendToMain(OPEN_URL, 'https://picgo.github.io/PicGo-Doc/zh/guide/config.html#picgo设置')
|
||||
sendToMain(OPEN_URL, 'https://piclist.cn/configure.html')
|
||||
}
|
||||
|
||||
function goShortCutPage () {
|
||||
|
||||
Reference in New Issue
Block a user