fix(ui): 自定义工具表单 overflow-y-scroll→auto + 认证方式NONE翻译改为'无' + Captain文档爬虫/同步后端

This commit is contained in:
Rogee
2026-08-01 21:25:55 +08:00
parent 1446cfe701
commit 3a62f01942
20 changed files with 756 additions and 56 deletions
@@ -25,13 +25,11 @@ const emitChange = () => emit('change');
const handleSourceSelect = sourceKey => {
source.value = sourceKey;
if (sourceKey !== 'web') status.value = null;
emitChange();
};
const handleStatusSelect = statusKey => {
status.value = statusKey;
if (statusKey) source.value = 'web';
emitChange();
};
@@ -28,6 +28,7 @@ const MENU_CONFIG = [
{ labelKey: 'SOURCE.ALL', value: 'all', icon: 'i-lucide-files' },
{ labelKey: 'SOURCE.WEB', value: 'web', icon: 'i-lucide-link' },
{ labelKey: 'SOURCE.PDF', value: 'pdf', icon: 'i-lucide-file-text' },
{ labelKey: 'SOURCE.TEXT', value: 'text', icon: 'i-lucide-type' },
],
},
{
@@ -78,9 +79,7 @@ const MENU_CONFIG = [
];
const filterMenus = computed(() =>
MENU_CONFIG.filter(
menu => !(menu.key === 'status' && props.activeSourceFilter === 'pdf')
).map(menu => {
MENU_CONFIG.map(menu => {
const active = props[menu.activeKey];
const items = menu.options.map(opt => ({
label: t(`CAPTAIN.DOCUMENTS.FILTERS.${opt.labelKey}`),
@@ -179,7 +179,7 @@ const handleTest = async () => {
<template>
<form
class="flex flex-col px-4 -mx-4 gap-4 max-h-[calc(100vh-200px)] overflow-y-scroll"
class="flex flex-col px-4 -mx-4 gap-4 max-h-[calc(100vh-200px)] overflow-y-auto"
@submit.prevent="handleSubmit"
>
<Input
@@ -30,6 +30,7 @@ const formState = {
const initialState = {
name: '',
url: '',
content: '',
documentType: 'url',
pdfFile: null,
};
@@ -46,11 +47,18 @@ const validationRules = {
pdfFile: {
required: requiredIf(() => state.documentType === 'pdf'),
},
content: {
required: requiredIf(() => state.documentType === 'content'),
minLength: requiredIf(
() => state.documentType === 'content' && minLength(10)
),
},
};
const documentTypeOptions = [
{ value: 'url', label: t('CAPTAIN.DOCUMENTS.FORM.TYPE.URL') },
{ value: 'pdf', label: t('CAPTAIN.DOCUMENTS.FORM.TYPE.PDF') },
{ value: 'content', label: t('CAPTAIN.DOCUMENTS.FORM.TYPE.CONTENT') },
];
const v$ = useVuelidate(validationRules, state);
@@ -58,6 +66,7 @@ const v$ = useVuelidate(validationRules, state);
const isLoading = computed(() => formState.uiFlags.value.creatingItem);
const hasPdfFileError = computed(() => v$.value.pdfFile.$error);
const hasContentError = computed(() => v$.value.content.$error);
const getErrorMessage = (field, errorKey) => {
return v$.value[field].$error
@@ -68,6 +77,7 @@ const getErrorMessage = (field, errorKey) => {
const formErrors = computed(() => ({
url: getErrorMessage('url', 'URL'),
pdfFile: getErrorMessage('pdfFile', 'PDF_FILE'),
content: getErrorMessage('content', 'CONTENT'),
}));
const handleCancel = () => emit('cancel');
@@ -107,13 +117,19 @@ const prepareDocumentDetails = () => {
if (state.documentType === 'url') {
formData.append('document[external_link]', state.url);
formData.append('document[name]', state.name || state.url);
} else {
} else if (state.documentType === 'pdf') {
formData.append('document[pdf_file]', state.pdfFile);
formData.append(
'document[name]',
state.name || state.pdfFile.name.replace('.pdf', '')
);
// No need to send external_link for PDF - it's auto-generated in the backend
} else if (state.documentType === 'content') {
formData.append('document[content]', state.content);
formData.append(
'document[name]',
state.name || t('CAPTAIN.DOCUMENTS.FORM.CONTENT.DEFAULT_NAME')
);
}
return formData;
@@ -208,6 +224,24 @@ const handleSubmit = async () => {
</p>
</div>
<div v-if="state.documentType === 'content'" class="flex flex-col gap-1">
<label class="text-sm font-medium text-n-slate-12">
{{ t('CAPTAIN.DOCUMENTS.FORM.CONTENT.LABEL') }}
</label>
<textarea
v-model="state.content"
rows="8"
:placeholder="t('CAPTAIN.DOCUMENTS.FORM.CONTENT.PLACEHOLDER')"
class="w-full px-3 py-2 text-sm border rounded-lg resize-y bg-n-alpha-1 border-n-alpha-3 text-n-slate-12 focus:outline-none focus:border-n-blue-8"
/>
<p class="text-xs text-n-slate-11">
{{ t('CAPTAIN.DOCUMENTS.FORM.CONTENT.HELP_TEXT') }}
</p>
<p v-if="formErrors.content" class="text-xs text-n-ruby-9">
{{ formErrors.content }}
</p>
</div>
<Input
v-model="state.name"
:label="t('CAPTAIN.DOCUMENTS.FORM.NAME.LABEL')"
@@ -765,7 +765,8 @@
"SOURCE": {
"ALL": "All sources",
"WEB": "Web pages",
"PDF": "PDFs"
"PDF": "PDFs",
"TEXT": "Text"
},
"STATUS": {
"ANY": "Any status",
@@ -810,7 +811,8 @@
"TYPE": {
"LABEL": "Document Type",
"URL": "URL",
"PDF": "PDF File"
"PDF": "PDF File",
"CONTENT": "Text / Markdown"
},
"URL": {
"LABEL": "URL",
@@ -828,6 +830,13 @@
"NAME": {
"LABEL": "Document Name (Optional)",
"PLACEHOLDER": "Enter a name for the document"
},
"CONTENT": {
"LABEL": "Content",
"PLACEHOLDER": "Enter or paste the document content (supports Markdown)",
"HELP_TEXT": "Enter the text content directly. Markdown formatting is supported.",
"ERROR": "Please enter at least 10 characters of content",
"DEFAULT_NAME": "Inline Document"
}
},
"DELETE": {
@@ -837,7 +846,6 @@
"SUCCESS_MESSAGE": "The document has been successfully deleted",
"ERROR_MESSAGE": "There was an error deleting the document, please try again."
},
"OPTIONS": {
"VIEW_RELATED_RESPONSES": "View Related Responses",
"SYNC_NOW": "Refresh now",
@@ -764,7 +764,8 @@
"SOURCE": {
"ALL": "全部来源",
"WEB": "网页",
"PDF": "PDF"
"PDF": "PDF",
"TEXT": "文本"
},
"STATUS": {
"ANY": "任意状态",
@@ -809,7 +810,8 @@
"TYPE": {
"LABEL": "文档类型",
"URL": "网址",
"PDF": "PDF 文件"
"PDF": "PDF 文件",
"CONTENT": "文本 / Markdown"
},
"URL": {
"LABEL": "网址",
@@ -827,6 +829,13 @@
"NAME": {
"LABEL": "文档名称(可选)",
"PLACEHOLDER": "输入文档的名称"
},
"CONTENT": {
"LABEL": "内容",
"PLACEHOLDER": "输入或粘贴文档内容(支持 Markdown",
"HELP_TEXT": "直接输入文本内容,支持 Markdown 格式。",
"ERROR": "请输入至少 10 个字符的内容",
"DEFAULT_NAME": "内联文档"
}
},
"DELETE": {
@@ -928,7 +937,7 @@
"LABEL": "认证方式"
},
"AUTH_TYPES": {
"NONE": "啥都没有",
"NONE": "",
"BEARER": "Bearer Token",
"BASIC": "Basic Auth",
"API_KEY": "API 密钥"