mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-06 20:42:57 +08:00
✨ Feature(custom): support upload multiple urls
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<div v-if="showInputBoxVisible" class="inputbox-overlay" @click="handleInputBoxCancel">
|
<div v-if="showInputBoxVisible" class="inputbox-overlay">
|
||||||
<div class="inputbox-container" @click.stop>
|
<div class="inputbox-container" @click.stop>
|
||||||
<div class="inputbox-header">
|
<div class="inputbox-header">
|
||||||
<h3 class="inputbox-title">
|
<h3 class="inputbox-title">
|
||||||
@@ -11,7 +11,17 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="inputbox-content">
|
<div class="inputbox-content">
|
||||||
|
<textarea
|
||||||
|
v-if="inputBoxOptions.multiLine"
|
||||||
|
v-model="inputBoxValue"
|
||||||
|
:placeholder="inputBoxOptions.placeholder"
|
||||||
|
class="inputbox-textarea"
|
||||||
|
rows="4"
|
||||||
|
@keyup.ctrl.enter="handleInputBoxConfirm"
|
||||||
|
@keyup.escape="handleInputBoxCancel"
|
||||||
|
/>
|
||||||
<input
|
<input
|
||||||
|
v-else
|
||||||
v-model="inputBoxValue"
|
v-model="inputBoxValue"
|
||||||
:placeholder="inputBoxOptions.placeholder"
|
:placeholder="inputBoxOptions.placeholder"
|
||||||
class="inputbox-input"
|
class="inputbox-input"
|
||||||
@@ -47,7 +57,8 @@ const inputBoxValue = ref('')
|
|||||||
const showInputBoxVisible = ref(false)
|
const showInputBoxVisible = ref(false)
|
||||||
const inputBoxOptions = reactive({
|
const inputBoxOptions = reactive({
|
||||||
title: '',
|
title: '',
|
||||||
placeholder: ''
|
placeholder: '',
|
||||||
|
multiLine: false
|
||||||
})
|
})
|
||||||
|
|
||||||
let removeInputBoxListenerCallback: () => void = () => {}
|
let removeInputBoxListenerCallback: () => void = () => {}
|
||||||
@@ -60,6 +71,7 @@ function initInputBoxValue(options: IShowInputBoxOption) {
|
|||||||
inputBoxValue.value = options.value || ''
|
inputBoxValue.value = options.value || ''
|
||||||
inputBoxOptions.title = options.title || ''
|
inputBoxOptions.title = options.title || ''
|
||||||
inputBoxOptions.placeholder = options.placeholder || ''
|
inputBoxOptions.placeholder = options.placeholder || ''
|
||||||
|
inputBoxOptions.multiLine = options.multiLine || false
|
||||||
showInputBoxVisible.value = true
|
showInputBoxVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +212,30 @@ export default {
|
|||||||
color: rgb(156 163 175);
|
color: rgb(156 163 175);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputbox-textarea {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid rgb(209 213 219);
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
background: white;
|
||||||
|
color: rgb(17 24 39);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-family: inherit;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
outline: none;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputbox-textarea:focus {
|
||||||
|
border-color: rgb(59 130 246);
|
||||||
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputbox-textarea::placeholder {
|
||||||
|
color: rgb(156 163 175);
|
||||||
|
}
|
||||||
|
|
||||||
:root.dark .inputbox-input,
|
:root.dark .inputbox-input,
|
||||||
:root.auto.dark .inputbox-input {
|
:root.auto.dark .inputbox-input {
|
||||||
background: rgb(55 65 81);
|
background: rgb(55 65 81);
|
||||||
@@ -218,6 +254,24 @@ export default {
|
|||||||
color: rgb(107 114 128);
|
color: rgb(107 114 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root.dark .inputbox-textarea,
|
||||||
|
:root.auto.dark .inputbox-textarea {
|
||||||
|
background: rgb(55 65 81);
|
||||||
|
border-color: rgb(75 85 99);
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .inputbox-textarea:focus,
|
||||||
|
:root.auto.dark .inputbox-textarea:focus {
|
||||||
|
border-color: rgb(59 130 246);
|
||||||
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .inputbox-textarea::placeholder,
|
||||||
|
:root.auto.dark .inputbox-textarea::placeholder {
|
||||||
|
color: rgb(107 114 128);
|
||||||
|
}
|
||||||
|
|
||||||
.inputbox-actions {
|
.inputbox-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|||||||
@@ -51,9 +51,12 @@
|
|||||||
"clipboardPicture": "Clipboard",
|
"clipboardPicture": "Clipboard",
|
||||||
"clickToUpload": "Click to Upload",
|
"clickToUpload": "Click to Upload",
|
||||||
"urlUpload": "URL Upload",
|
"urlUpload": "URL Upload",
|
||||||
"inputUrlTip": "Please enter URL",
|
"inputUrlTip": "Please enter URL(s)",
|
||||||
"httpPrefixTip": "Starts with http:// or https://",
|
"httpPrefixTip": "Starts with http:// or https://",
|
||||||
|
"multipleUrlsHint": "Each URL on a separate line for multiple uploads",
|
||||||
"inputValidUrl": "Please enter a valid URL",
|
"inputValidUrl": "Please enter a valid URL",
|
||||||
|
"invalidUrlsFound": "Invalid URLs found: {urls}",
|
||||||
|
"uploadingMultipleUrls": "Uploading {count} URLs...",
|
||||||
"linkFormat": "Link Format",
|
"linkFormat": "Link Format",
|
||||||
"outputFormat": "Output Format",
|
"outputFormat": "Output Format",
|
||||||
"urlType": { "title": "Link Type", "normal": "Long Link", "short": "Short Link" }
|
"urlType": { "title": "Link Type", "normal": "Long Link", "short": "Short Link" }
|
||||||
|
|||||||
@@ -51,9 +51,12 @@
|
|||||||
"clipboardPicture": "剪贴板图片",
|
"clipboardPicture": "剪贴板图片",
|
||||||
"clickToUpload": "点击上传",
|
"clickToUpload": "点击上传",
|
||||||
"urlUpload": "URL上传",
|
"urlUpload": "URL上传",
|
||||||
"inputUrlTip": "请输入URL",
|
"inputUrlTip": "请输入URL地址",
|
||||||
"httpPrefixTip": "http://或https://开头",
|
"httpPrefixTip": "http://或https://开头",
|
||||||
|
"multipleUrlsHint": "多个URL请分行输入",
|
||||||
"inputValidUrl": "请输入合法的URL",
|
"inputValidUrl": "请输入合法的URL",
|
||||||
|
"invalidUrlsFound": "发现无效的URL: {urls}",
|
||||||
|
"uploadingMultipleUrls": "正在上传 {count} 个URL...",
|
||||||
"linkFormat": "链接格式",
|
"linkFormat": "链接格式",
|
||||||
"outputFormat": "输出格式",
|
"outputFormat": "输出格式",
|
||||||
"urlType": { "title": "链接类型", "normal": "长链接", "short": "短链接" }
|
"urlType": { "title": "链接类型", "normal": "长链接", "short": "短链接" }
|
||||||
|
|||||||
@@ -51,9 +51,12 @@
|
|||||||
"clipboardPicture": "剪貼板圖片",
|
"clipboardPicture": "剪貼板圖片",
|
||||||
"clickToUpload": "點擊上傳",
|
"clickToUpload": "點擊上傳",
|
||||||
"urlUpload": "URL上傳",
|
"urlUpload": "URL上傳",
|
||||||
"inputUrlTip": "請輸入URL",
|
"inputUrlTip": "請輸入URL地址",
|
||||||
"httpPrefixTip": "以http://或https://開頭",
|
"httpPrefixTip": "以http://或https://開頭",
|
||||||
|
"multipleUrlsHint": "多個URL請分行輸入",
|
||||||
"inputValidUrl": "請輸入合法的URL",
|
"inputValidUrl": "請輸入合法的URL",
|
||||||
|
"invalidUrlsFound": "發現無效的URL: {urls}",
|
||||||
|
"uploadingMultipleUrls": "正在上傳 {count} 個URL...",
|
||||||
"linkFormat": "連結格式",
|
"linkFormat": "連結格式",
|
||||||
"outputFormat": "輸出格式",
|
"outputFormat": "輸出格式",
|
||||||
"urlType": { "title": "連結類型", "normal": "長連結", "short": "短連結" }
|
"urlType": { "title": "連結類型", "normal": "長連結", "short": "短連結" }
|
||||||
|
|||||||
@@ -354,20 +354,50 @@ async function uploadURLFiles() {
|
|||||||
$bus.emit(SHOW_INPUT_BOX, {
|
$bus.emit(SHOW_INPUT_BOX, {
|
||||||
value: isUrl(str) ? str : '',
|
value: isUrl(str) ? str : '',
|
||||||
title: t('pages.upload.inputUrlTip'),
|
title: t('pages.upload.inputUrlTip'),
|
||||||
placeholder: t('pages.upload.httpPrefixTip')
|
placeholder: t('pages.upload.httpPrefixTip') + '\n' + t('pages.upload.multipleUrlsHint'),
|
||||||
|
multiLine: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInputBoxValue(val: string) {
|
function handleInputBoxValue(val: string) {
|
||||||
if (val === '') return
|
if (val === '') return
|
||||||
if (isUrl(val)) {
|
|
||||||
window.electron.sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [
|
const urls = val
|
||||||
{
|
.split('\n')
|
||||||
path: val
|
.map(url => url.trim())
|
||||||
}
|
.filter(url => url !== '')
|
||||||
])
|
|
||||||
} else {
|
if (urls.length === 0) return
|
||||||
message.error(t('pages.upload.inputValidUrl'))
|
|
||||||
|
const invalidUrls: string[] = []
|
||||||
|
const validUrls: string[] = []
|
||||||
|
|
||||||
|
urls.forEach(url => {
|
||||||
|
if (isUrl(url)) {
|
||||||
|
validUrls.push(url)
|
||||||
|
} else {
|
||||||
|
invalidUrls.push(url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (invalidUrls.length > 0) {
|
||||||
|
const errorMessage =
|
||||||
|
invalidUrls.length === 1
|
||||||
|
? t('pages.upload.inputValidUrl') + ': ' + invalidUrls[0]
|
||||||
|
: t('pages.upload.invalidUrlsFound', {
|
||||||
|
count: invalidUrls.length,
|
||||||
|
urls: invalidUrls.slice(0, 3).join(', ') + (invalidUrls.length > 3 ? '...' : '')
|
||||||
|
})
|
||||||
|
message.error(errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validUrls.length > 0) {
|
||||||
|
const filesToUpload = validUrls.map(url => ({ path: url }))
|
||||||
|
window.electron.sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, filesToUpload)
|
||||||
|
|
||||||
|
if (validUrls.length > 1) {
|
||||||
|
message.success(t('pages.upload.uploadingMultipleUrls', { count: validUrls.length }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type IEvent = {
|
|||||||
value: string
|
value: string
|
||||||
title: string
|
title: string
|
||||||
placeholder: string
|
placeholder: string
|
||||||
|
multiLine?: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ export interface IShowInputBoxOption {
|
|||||||
value?: string
|
value?: string
|
||||||
title: string
|
title: string
|
||||||
placeholder: string
|
placeholder: string
|
||||||
|
multiLine?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IShowFileExplorerOption = IObj
|
export type IShowFileExplorerOption = IObj
|
||||||
|
|||||||
Reference in New Issue
Block a user