fix(frontend): normalize script import input and move mode toggle to top
Reorder the add-connection dialog so the script mode switch appears before basic information to improve entry flow. Normalize script-mode pasted content by trimming lines, removing empty lines, and ignoring Markdown code fence markers before parsing. Also update token splitting to handle any whitespace separator, improving compatibility with varied pasted formats.
This commit is contained in:
@@ -104,6 +104,44 @@ const handleHostIconMouseLeave = () => {
|
||||
<h3 class="text-xl font-semibold text-center mb-6 flex-shrink-0">{{ formTitle }}</h3> <!-- Title -->
|
||||
<form @submit.prevent="handleSubmit" class="flex-grow overflow-y-auto pr-2 space-y-6"> <!-- Form with scroll and spacing -->
|
||||
|
||||
<!-- Script Mode Section Toggle -->
|
||||
<div v-if="!isEditMode" class="space-y-4 p-4 border border-border rounded-md bg-header/30">
|
||||
<div class="flex justify-between items-center">
|
||||
<h4 class="text-base font-semibold">{{ t('connections.form.sectionScriptMode', '脚本模式') }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
@click="isScriptModeActive = !isScriptModeActive"
|
||||
:class="[
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary',
|
||||
isScriptModeActive ? 'bg-primary' : 'bg-gray-300 dark:bg-gray-600'
|
||||
]"
|
||||
role="switch"
|
||||
:aria-checked="isScriptModeActive"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
:class="[
|
||||
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200',
|
||||
isScriptModeActive ? 'translate-x-5' : 'translate-x-0'
|
||||
]"
|
||||
></span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isScriptModeActive" class="mt-4">
|
||||
<textarea
|
||||
id="conn-script-input"
|
||||
v-model="scriptInputText"
|
||||
rows="10"
|
||||
wrap="off"
|
||||
class="w-full px-3 py-2 border border-border rounded-md shadow-sm bg-background text-foreground focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary"
|
||||
:placeholder="t('connections.form.scriptModePlaceholder')"
|
||||
></textarea>
|
||||
<p class="mt-1 text-xs text-text-secondary whitespace-pre-line">
|
||||
{{ scriptModeFormatInfo }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Regular Form Sections (conditionally rendered) -->
|
||||
<template v-if="!isScriptModeActive">
|
||||
<AddConnectionFormBasicInfo :form-data="formData" />
|
||||
@@ -125,44 +163,6 @@ const handleHostIconMouseLeave = () => {
|
||||
@delete-tag="handleDeleteTag"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- Script Mode Section Toggle -->
|
||||
<div v-if="!isEditMode" class="space-y-4 p-4 border border-border rounded-md bg-header/30 mt-6">
|
||||
<div class="flex justify-between items-center">
|
||||
<h4 class="text-base font-semibold">{{ t('connections.form.sectionScriptMode', '脚本模式') }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
@click="isScriptModeActive = !isScriptModeActive"
|
||||
:class="[
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary',
|
||||
isScriptModeActive ? 'bg-primary' : 'bg-gray-300 dark:bg-gray-600'
|
||||
]"
|
||||
role="switch"
|
||||
:aria-checked="isScriptModeActive"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
:class="[
|
||||
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200',
|
||||
isScriptModeActive ? 'translate-x-5' : 'translate-x-0'
|
||||
]"
|
||||
></span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="isScriptModeActive" class="mt-4">
|
||||
<textarea
|
||||
id="conn-script-input"
|
||||
v-model="scriptInputText"
|
||||
rows="10"
|
||||
wrap="off"
|
||||
class="w-full px-3 py-2 border border-border rounded-md shadow-sm bg-background text-foreground focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary"
|
||||
:placeholder="t('connections.form.scriptModePlaceholder')"
|
||||
></textarea>
|
||||
<p class="mt-1 text-xs text-text-secondary whitespace-pre-line">
|
||||
{{ scriptModeFormatInfo }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error message DIV removed -->
|
||||
|
||||
|
||||
@@ -286,9 +286,9 @@ export function useAddConnectionForm(props: AddConnectionFormProps, emit: AddCon
|
||||
}
|
||||
|
||||
// 1. Extract user@host:port
|
||||
const firstSpaceIndex = line.indexOf(' ');
|
||||
const userHostPortPart = firstSpaceIndex === -1 ? line : line.substring(0, firstSpaceIndex);
|
||||
const optionsString = firstSpaceIndex === -1 ? '' : line.substring(firstSpaceIndex + 1).trim();
|
||||
const firstWhitespaceIndex = line.search(/\s/);
|
||||
const userHostPortPart = firstWhitespaceIndex === -1 ? line : line.substring(0, firstWhitespaceIndex);
|
||||
const optionsString = firstWhitespaceIndex === -1 ? '' : line.substring(firstWhitespaceIndex).trim();
|
||||
|
||||
// 2. Validate user@host:port (allow user@host without port)
|
||||
const userHostPortRegex = /^([^@\s]+)@([^:\s]+)(?::([0-9]+))?$/;
|
||||
@@ -398,9 +398,24 @@ export function useAddConnectionForm(props: AddConnectionFormProps, emit: AddCon
|
||||
return { type, userHostPort: userHostPortPart, name, password, keyName, proxyName, tags, note };
|
||||
};
|
||||
|
||||
const normalizeScriptModeInput = (rawInput: string): { cleanedText: string; lines: string[] } => {
|
||||
const lines = rawInput
|
||||
.replace(/\r\n?/g, '\n')
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0 && !line.startsWith('```'));
|
||||
|
||||
return {
|
||||
cleanedText: lines.join('\n'),
|
||||
lines,
|
||||
};
|
||||
};
|
||||
|
||||
// 处理表单提交
|
||||
const handleScriptModeSubmit = async () => {
|
||||
const lines = scriptInputText.value.split('\n').filter(line => line.trim() !== '');
|
||||
const normalizedScriptInput = normalizeScriptModeInput(scriptInputText.value);
|
||||
const lines = normalizedScriptInput.lines;
|
||||
scriptInputText.value = normalizedScriptInput.cleanedText;
|
||||
|
||||
if (lines.length === 0) {
|
||||
uiNotificationsStore.showError(t('connections.form.scriptModeEmpty', '脚本输入不能为空。'));
|
||||
|
||||
Reference in New Issue
Block a user