refactor: update knowledge document types and API client interfaces
- Refactored types in `Knowledge/types.ts` to introduce new interfaces for document handling. - Added `KnowledgeDocItem`, `KnowledgeDocsListResponse`, `KnowledgeDocsUploadInput`, `KnowledgeDocsUploadResponse`, and `KnowledgeDocsDeleteResponse` for better structure and clarity. - Updated `KnowledgeDocsApiClient` interface to include methods for listing, uploading, and deleting documents. fix: replace deprecated icons in AccountSettingsPanel and SettingMenu - Replaced `CheckCircleIcon` with `CheckCircle` from `lucide-react` in `AccountSettingsPanel.tsx`. - Updated `SettingMenu.tsx` to use `Settings` and `User` from `lucide-react` instead of custom icons. test: add tests for knowledge docs routes and KnowledgePage - Created `knowledge-docs-routes.test.ts` to test API routes for listing, uploading, and deleting knowledge documents. - Added `knowledge-page.test.tsx` to test the rendering and functionality of the KnowledgePage component, including document loading and deletion.
This commit is contained in:
89
src/pages/Knowledge/components/KnowledgeDocsTable.tsx
Normal file
89
src/pages/Knowledge/components/KnowledgeDocsTable.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export type KnowledgeDocRow = {
|
||||
id: string;
|
||||
fileName: string;
|
||||
size: number;
|
||||
modifiedAt: string;
|
||||
fileType: string;
|
||||
};
|
||||
|
||||
type KnowledgeDocsTableProps = {
|
||||
docs: KnowledgeDocRow[];
|
||||
deletingId: string | null;
|
||||
onDelete: (doc: KnowledgeDocRow) => void;
|
||||
deleteLabel: string;
|
||||
deletingLabel: string;
|
||||
fileNameLabel: string;
|
||||
sizeLabel: string;
|
||||
modifiedLabel: string;
|
||||
typeLabel: string;
|
||||
actionLabel: string;
|
||||
formatBytes: (value: number | null | undefined) => string;
|
||||
formatDateTime: (value: string | null | undefined) => string;
|
||||
trashIcon: ReactNode;
|
||||
};
|
||||
|
||||
export default function KnowledgeDocsTable({
|
||||
docs,
|
||||
deletingId,
|
||||
onDelete,
|
||||
deleteLabel,
|
||||
deletingLabel,
|
||||
fileNameLabel,
|
||||
sizeLabel,
|
||||
modifiedLabel,
|
||||
typeLabel,
|
||||
actionLabel,
|
||||
formatBytes,
|
||||
formatDateTime,
|
||||
trashIcon,
|
||||
}: KnowledgeDocsTableProps) {
|
||||
return (
|
||||
<div className="overflow-hidden rounded-[24px] border border-black/5 bg-[#fcfcfd] dark:border-[#2a2a2d] dark:bg-[#222225]">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-black/5 text-left text-xs uppercase tracking-[0.18em] text-[#99A0AE] dark:border-[#2a2a2d] dark:text-gray-500">
|
||||
<th className="px-5 py-4">{fileNameLabel}</th>
|
||||
<th className="px-5 py-4">{sizeLabel}</th>
|
||||
<th className="px-5 py-4">{modifiedLabel}</th>
|
||||
<th className="px-5 py-4">{typeLabel}</th>
|
||||
<th className="px-5 py-4">{actionLabel}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{docs.map((doc) => {
|
||||
const pending = deletingId === doc.id;
|
||||
return (
|
||||
<tr key={doc.id} className="border-b border-black/5 align-top last:border-b-0 dark:border-[#2a2a2d]">
|
||||
<td className="px-5 py-4">
|
||||
<div className="font-semibold text-[#171717] dark:text-[#f3f4f6]">{doc.fileName}</div>
|
||||
</td>
|
||||
<td className="px-5 py-4 text-sm text-[#525866] dark:text-gray-300">{formatBytes(doc.size)}</td>
|
||||
<td className="px-5 py-4 text-sm text-[#525866] dark:text-gray-300">{formatDateTime(doc.modifiedAt)}</td>
|
||||
<td className="px-5 py-4">
|
||||
<span className="inline-flex rounded-xl border border-[#E5E8EE] bg-white px-3 py-2 text-sm text-[#525866] dark:border-[#2a2a2d] dark:bg-[#1b1b1d] dark:text-gray-300">
|
||||
{doc.fileType}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-5 py-4">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex h-9 items-center rounded-full border border-red-500/20 px-4 text-sm font-medium text-red-600 transition-colors hover:bg-red-50 disabled:cursor-not-allowed disabled:opacity-60 dark:text-red-300 dark:hover:bg-red-900/20"
|
||||
onClick={() => onDelete(doc)}
|
||||
disabled={pending}
|
||||
>
|
||||
{trashIcon}
|
||||
<span className="ml-2">{pending ? deletingLabel : deleteLabel}</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
26
src/pages/Knowledge/components/KnowledgeEmptyState.tsx
Normal file
26
src/pages/Knowledge/components/KnowledgeEmptyState.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type KnowledgeEmptyStateProps = {
|
||||
icon: ReactNode;
|
||||
title: string;
|
||||
description: string;
|
||||
actionLabel: string;
|
||||
onAction: () => void;
|
||||
};
|
||||
|
||||
export default function KnowledgeEmptyState({ icon, title, description, actionLabel, onAction }: KnowledgeEmptyStateProps) {
|
||||
return (
|
||||
<div className="flex min-h-[420px] flex-col items-center justify-center rounded-[24px] border border-dashed border-black/10 bg-[#f8fafc] px-6 text-center dark:border-[#2a2a2d] dark:bg-[#222225]">
|
||||
<div className="mb-4 text-[#99A0AE] dark:text-gray-500">{icon}</div>
|
||||
<p className="mb-3 text-lg font-medium text-[#171717] dark:text-[#f3f4f6]">{title}</p>
|
||||
<p className="max-w-lg text-sm leading-6 text-[#525866] dark:text-gray-400">{description}</p>
|
||||
<button
|
||||
type="button"
|
||||
className="mt-6 inline-flex h-10 items-center rounded-full bg-[#2B7FFF] px-4 text-sm font-medium text-white transition-colors hover:bg-[#2369db]"
|
||||
onClick={onAction}
|
||||
>
|
||||
{actionLabel}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
22
src/pages/Knowledge/components/KnowledgeFeedbackBanner.tsx
Normal file
22
src/pages/Knowledge/components/KnowledgeFeedbackBanner.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type KnowledgeFeedbackBannerProps = {
|
||||
kind: 'success' | 'warning' | 'error' | 'info';
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function toneClasses(kind: KnowledgeFeedbackBannerProps['kind']): string {
|
||||
if (kind === 'success') return 'border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300';
|
||||
if (kind === 'warning') return 'border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300';
|
||||
if (kind === 'error') return 'border-red-500/30 bg-red-500/10 text-red-700 dark:text-red-300';
|
||||
return 'border-black/10 bg-white text-[#525866] dark:border-gray-700 dark:bg-[#222225] dark:text-gray-300';
|
||||
}
|
||||
|
||||
export default function KnowledgeFeedbackBanner({ kind, className, children }: KnowledgeFeedbackBannerProps) {
|
||||
return (
|
||||
<div className={[className, 'max-w-[360px] rounded-xl border px-4 py-3 text-sm shadow-[0_12px_30px_rgba(15,23,42,0.14)]', toneClasses(kind)].filter(Boolean).join(' ')}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
42
src/pages/Knowledge/components/KnowledgePageHeader.tsx
Normal file
42
src/pages/Knowledge/components/KnowledgePageHeader.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
export type KnowledgePageHeaderProps = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
totalCount: number;
|
||||
totalSize: string;
|
||||
documentsLabel: string;
|
||||
storageLabel: string;
|
||||
};
|
||||
|
||||
export default function KnowledgePageHeader({
|
||||
title,
|
||||
subtitle,
|
||||
totalCount,
|
||||
totalSize,
|
||||
documentsLabel,
|
||||
storageLabel,
|
||||
}: KnowledgePageHeaderProps) {
|
||||
return (
|
||||
<div className="mb-6 flex shrink-0 flex-col justify-between gap-4 md:flex-row md:items-start">
|
||||
<div>
|
||||
<h1
|
||||
className="mb-3 text-5xl font-normal tracking-tight text-[#171717] dark:text-[#f3f4f6] md:text-6xl"
|
||||
style={{ fontFamily: "Georgia, Cambria, 'Times New Roman', Times, serif" }}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-[17px] font-medium text-[#171717]/70 dark:text-gray-400">{subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-2 md:mt-2 md:min-w-[320px]">
|
||||
<div className="rounded-[24px] bg-[#f4f7fb] px-5 py-4 dark:bg-[#222225]">
|
||||
<div className="text-xs uppercase tracking-[0.18em] text-[#99A0AE] dark:text-gray-500">{documentsLabel}</div>
|
||||
<div className="mt-3 text-3xl font-semibold text-[#171717] dark:text-[#f3f4f6]">{totalCount}</div>
|
||||
</div>
|
||||
<div className="rounded-[24px] bg-[#fff7ed] px-5 py-4 dark:bg-[#31251a]">
|
||||
<div className="text-xs uppercase tracking-[0.18em] text-[#6b7280] dark:text-gray-400">{storageLabel}</div>
|
||||
<div className="mt-3 text-3xl font-semibold text-[#171717] dark:text-[#f3f4f6]">{totalSize}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
58
src/pages/Knowledge/components/KnowledgeToolbar.tsx
Normal file
58
src/pages/Knowledge/components/KnowledgeToolbar.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type KnowledgeToolbarProps = {
|
||||
description: string;
|
||||
loading: boolean;
|
||||
refreshing: boolean;
|
||||
uploading: boolean;
|
||||
onRefresh: () => void;
|
||||
onUploadClick: () => void;
|
||||
refreshLabel: string;
|
||||
uploadLabel: string;
|
||||
uploadingLabel: string;
|
||||
refreshIcon: ReactNode;
|
||||
uploadIcon: ReactNode;
|
||||
};
|
||||
|
||||
export default function KnowledgeToolbar({
|
||||
description,
|
||||
loading,
|
||||
refreshing,
|
||||
uploading,
|
||||
onRefresh,
|
||||
onUploadClick,
|
||||
refreshLabel,
|
||||
uploadLabel,
|
||||
uploadingLabel,
|
||||
refreshIcon,
|
||||
uploadIcon,
|
||||
}: KnowledgeToolbarProps) {
|
||||
return (
|
||||
<div className="mb-5 flex shrink-0 flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<p className="max-w-2xl text-sm leading-6 text-[#525866] dark:text-gray-400">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3 md:mt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex h-9 items-center rounded-full border border-black/10 px-4 text-[13px] font-medium text-[#171717]/80 transition-colors hover:bg-black/5 hover:text-[#171717] disabled:cursor-not-allowed disabled:opacity-60 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-[#f3f4f6]"
|
||||
onClick={onRefresh}
|
||||
disabled={loading || refreshing}
|
||||
>
|
||||
{refreshIcon}
|
||||
<span className="ml-2">{refreshLabel}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex h-9 items-center rounded-full bg-[#2B7FFF] px-4 text-[13px] font-medium text-white transition-colors hover:bg-[#2369db] disabled:cursor-not-allowed disabled:opacity-60"
|
||||
onClick={onUploadClick}
|
||||
disabled={uploading}
|
||||
>
|
||||
{uploadIcon}
|
||||
<span className="ml-2">{uploading ? uploadingLabel : uploadLabel}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
6
src/pages/Knowledge/components/index.ts
Normal file
6
src/pages/Knowledge/components/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export { default as KnowledgeDocsTable } from './KnowledgeDocsTable';
|
||||
export type { KnowledgeDocRow } from './KnowledgeDocsTable';
|
||||
export { default as KnowledgeEmptyState } from './KnowledgeEmptyState';
|
||||
export { default as KnowledgeFeedbackBanner } from './KnowledgeFeedbackBanner';
|
||||
export { default as KnowledgePageHeader } from './KnowledgePageHeader';
|
||||
export { default as KnowledgeToolbar } from './KnowledgeToolbar';
|
||||
@@ -14,53 +14,39 @@ function normalizeKnowledgePath(path: string): string {
|
||||
}
|
||||
|
||||
const EN_KNOWLEDGE_MESSAGES: MessageTree = {
|
||||
title: 'Knowledge Management',
|
||||
desc: 'Content Management',
|
||||
roomTypeManager: 'Room Type Management',
|
||||
eventManager: 'Event Management',
|
||||
event: {
|
||||
addEvent: 'Add Event',
|
||||
eventName: 'Event Name',
|
||||
eventDesc: 'Event Description',
|
||||
effectiveTime: 'Effective Time',
|
||||
endTime: 'End Time',
|
||||
relatedImage: 'Related Image',
|
||||
enableDisable: 'Enable/Disable',
|
||||
operation: 'Operation',
|
||||
viewImage: 'View Image',
|
||||
uploadImage: 'Upload Image',
|
||||
pleaseEnter: 'Please enter',
|
||||
effectiveTimeRange: 'Effective Time Range',
|
||||
to: 'to',
|
||||
startDate: 'Start Date',
|
||||
endDate: 'End Date',
|
||||
pleaseEnterEventName: 'Please enter the event name',
|
||||
lengthValidation: 'Length between 3 and 50 characters',
|
||||
pleaseEnterEventDesc: 'Please enter the event description',
|
||||
pleaseSelectTimeRange: 'Please select the effective time range',
|
||||
title: 'Knowledge Docs',
|
||||
subtitle: 'Upload, review, and delete local documentation files stored in the knowledge directory.',
|
||||
refresh: 'Refresh',
|
||||
upload: 'Upload document',
|
||||
uploadHint: 'This page fully replaces the previous Knowledge demo and now focuses on local docs only.',
|
||||
documentsLabel: 'Documents',
|
||||
storageLabel: 'Storage',
|
||||
emptyTitle: 'No documents yet',
|
||||
emptyDescription: 'Upload a file to start managing the local knowledge docs directory.',
|
||||
deleteConfirm: 'Delete this document?',
|
||||
table: {
|
||||
name: 'Name',
|
||||
size: 'Size',
|
||||
modifiedAt: 'Modified At',
|
||||
type: 'Type',
|
||||
actions: 'Actions',
|
||||
delete: 'Delete',
|
||||
},
|
||||
upload: {
|
||||
title: 'Upload Image',
|
||||
step1: 'Upload Image 1',
|
||||
step2: 'Image Description 2',
|
||||
dragText: 'Choose a file or drag and drop it here',
|
||||
formatDesc: 'JPEG, PNG, PDF, and MP4 formats up to 50MB.',
|
||||
tipText: "If you don't want to enter prompt words for now, click confirm and operate in the list",
|
||||
pleaseUploadFirst: 'Please upload an image first',
|
||||
uploadSuccess: 'Image uploaded successfully',
|
||||
pleaseEnter: 'Please enter',
|
||||
dialog: {
|
||||
title: 'Upload document',
|
||||
description: 'Choose a file and save it into the local knowledge docs directory.',
|
||||
fileLabel: 'File',
|
||||
fileHint: 'The uploaded file will be written with its file name and metadata preserved.',
|
||||
cancel: 'Cancel',
|
||||
confirm: 'Upload',
|
||||
},
|
||||
eventPic: {
|
||||
copySuccess: 'Copied successfully',
|
||||
copyFail: 'Copy failed',
|
||||
backToEvent: 'Back to Event Management',
|
||||
},
|
||||
roomType: {
|
||||
ctrip: 'Ctrip',
|
||||
fliggy: 'Fliggy',
|
||||
douyinHotel: 'Douyin (Xifeng Nanshan Tianmu Hot Spring Hotel)',
|
||||
douyinHotSpring: 'Douyin (Xifeng Nanshan Tianmu Hot Spring)',
|
||||
meituan: 'Meituan',
|
||||
status: {
|
||||
loading: 'Loading documents...',
|
||||
uploading: 'Uploading...',
|
||||
deleting: 'Deleting...',
|
||||
uploadSuccess: 'Document uploaded successfully',
|
||||
deleteSuccess: 'Document deleted successfully',
|
||||
failed: 'Knowledge docs request failed: {error}',
|
||||
},
|
||||
common: {
|
||||
cancel: 'Cancel',
|
||||
@@ -69,53 +55,39 @@ const EN_KNOWLEDGE_MESSAGES: MessageTree = {
|
||||
};
|
||||
|
||||
const ZH_KNOWLEDGE_MESSAGES: MessageTree = {
|
||||
title: '知识库管理',
|
||||
desc: '内容管理',
|
||||
roomTypeManager: '房型管理',
|
||||
eventManager: '事件管理',
|
||||
event: {
|
||||
addEvent: '添加事件',
|
||||
eventName: '事件名称',
|
||||
eventDesc: '事件描述',
|
||||
effectiveTime: '生效时间',
|
||||
endTime: '结束时间',
|
||||
relatedImage: '关联图片',
|
||||
enableDisable: '启用/停用',
|
||||
operation: '操作',
|
||||
viewImage: '查看图片',
|
||||
uploadImage: '上传图片',
|
||||
pleaseEnter: '请输入',
|
||||
effectiveTimeRange: '生效时间段',
|
||||
to: '至',
|
||||
startDate: '开始日期',
|
||||
endDate: '结束日期',
|
||||
pleaseEnterEventName: '请输入活动名称',
|
||||
lengthValidation: '长度在 3 到 50 个字符之间',
|
||||
pleaseEnterEventDesc: '请输入活动描述',
|
||||
pleaseSelectTimeRange: '请选择生效时间段',
|
||||
title: '知识文档管理',
|
||||
subtitle: '上传、查看和删除保存在知识目录中的本地文档文件。',
|
||||
refresh: '刷新',
|
||||
upload: '上传文档',
|
||||
uploadHint: '此页面已完全替换旧 Knowledge demo,只保留本地文档管理能力。',
|
||||
documentsLabel: '文档数量',
|
||||
storageLabel: '占用空间',
|
||||
emptyTitle: '暂无文档',
|
||||
emptyDescription: '先上传一个文件,开始管理本地知识文档目录。',
|
||||
deleteConfirm: '确定要删除此文档吗?',
|
||||
table: {
|
||||
name: '名称',
|
||||
size: '大小',
|
||||
modifiedAt: '修改时间',
|
||||
type: '类型',
|
||||
actions: '操作',
|
||||
delete: '删除',
|
||||
},
|
||||
upload: {
|
||||
title: '上传图片',
|
||||
step1: '上传图片 1',
|
||||
step2: '图片描述 2',
|
||||
dragText: '选择一个文件或将其拖放到此处',
|
||||
formatDesc: '支持 JPEG、PNG、PDF 和 MP4,大小不超过 50MB。',
|
||||
tipText: '如果暂时不想输入提示词,可点击确认后到列表操作。',
|
||||
pleaseUploadFirst: '请先上传图片',
|
||||
uploadSuccess: '图片上传成功',
|
||||
pleaseEnter: '请输入',
|
||||
dialog: {
|
||||
title: '上传文档',
|
||||
description: '选择一个文件并保存到本地知识文档目录中。',
|
||||
fileLabel: '文件',
|
||||
fileHint: '上传后的文件会保留文件名和元信息。',
|
||||
cancel: '取消',
|
||||
confirm: '上传',
|
||||
},
|
||||
eventPic: {
|
||||
copySuccess: '复制成功',
|
||||
copyFail: '复制失败',
|
||||
backToEvent: '返回事件管理',
|
||||
},
|
||||
roomType: {
|
||||
ctrip: '携程',
|
||||
fliggy: '飞猪',
|
||||
douyinHotel: '抖音(息烽南山天沐温泉酒店)',
|
||||
douyinHotSpring: '抖音(息烽南山天沐温泉)',
|
||||
meituan: '美团',
|
||||
status: {
|
||||
loading: '正在加载文档...',
|
||||
uploading: '上传中...',
|
||||
deleting: '删除中...',
|
||||
uploadSuccess: '文档上传成功',
|
||||
deleteSuccess: '文档删除成功',
|
||||
failed: '知识文档请求失败:{error}',
|
||||
},
|
||||
common: {
|
||||
cancel: '取消',
|
||||
@@ -124,53 +96,39 @@ const ZH_KNOWLEDGE_MESSAGES: MessageTree = {
|
||||
};
|
||||
|
||||
const JA_KNOWLEDGE_MESSAGES: MessageTree = {
|
||||
title: 'ナレッジ管理',
|
||||
desc: 'コンテンツ管理',
|
||||
roomTypeManager: '部屋タイプ管理',
|
||||
eventManager: 'イベント管理',
|
||||
event: {
|
||||
addEvent: 'イベントを追加',
|
||||
eventName: 'イベント名',
|
||||
eventDesc: 'イベントの説明',
|
||||
effectiveTime: '有効時間',
|
||||
endTime: '終了時間',
|
||||
relatedImage: '関連画像',
|
||||
enableDisable: '有効/無効',
|
||||
operation: '操作',
|
||||
viewImage: '画像を表示',
|
||||
uploadImage: '画像をアップロード',
|
||||
pleaseEnter: '入力してください',
|
||||
effectiveTimeRange: '有効期間',
|
||||
to: 'から',
|
||||
startDate: '開始日',
|
||||
endDate: '終了日',
|
||||
pleaseEnterEventName: 'イベント名を入力してください',
|
||||
lengthValidation: '3〜50文字で入力してください',
|
||||
pleaseEnterEventDesc: 'イベントの説明を入力してください',
|
||||
pleaseSelectTimeRange: '有効期間を選択してください',
|
||||
title: 'Knowledge Docs',
|
||||
subtitle: 'ローカルのナレッジ文書をアップロード、確認、削除できます。',
|
||||
refresh: '更新',
|
||||
upload: '文書をアップロード',
|
||||
uploadHint: 'このページは旧 Knowledge デモを置き換え、ローカル文書管理に専念します。',
|
||||
documentsLabel: 'Documents',
|
||||
storageLabel: 'Storage',
|
||||
emptyTitle: '文書がありません',
|
||||
emptyDescription: 'まずファイルをアップロードして、ローカルの knowledge docs を管理してください。',
|
||||
deleteConfirm: 'この文書を削除しますか?',
|
||||
table: {
|
||||
name: '名前',
|
||||
size: 'サイズ',
|
||||
modifiedAt: '更新日時',
|
||||
type: '種類',
|
||||
actions: '操作',
|
||||
delete: '削除',
|
||||
},
|
||||
upload: {
|
||||
title: '画像をアップロード',
|
||||
step1: '画像のアップロード 1',
|
||||
step2: '画像の説明 2',
|
||||
dragText: 'ファイルを選択するか、ここにドラッグ&ドロップしてください',
|
||||
formatDesc: 'JPEG、PNG、PDF、MP4 形式に対応し、最大 50MB です。',
|
||||
tipText: '今はプロンプトを入力しない場合でも、確認後に一覧で操作できます。',
|
||||
pleaseUploadFirst: '先に画像をアップロードしてください',
|
||||
uploadSuccess: '画像のアップロードに成功しました',
|
||||
pleaseEnter: '入力してください',
|
||||
dialog: {
|
||||
title: '文書をアップロード',
|
||||
description: 'ファイルを選んでローカルの knowledge docs ディレクトリに保存します。',
|
||||
fileLabel: 'ファイル',
|
||||
fileHint: 'アップロードしたファイルはファイル名とメタデータを保持します。',
|
||||
cancel: 'キャンセル',
|
||||
confirm: 'アップロード',
|
||||
},
|
||||
eventPic: {
|
||||
copySuccess: 'コピーに成功しました',
|
||||
copyFail: 'コピーに失敗しました',
|
||||
backToEvent: 'イベント管理に戻る',
|
||||
},
|
||||
roomType: {
|
||||
ctrip: 'Ctrip',
|
||||
fliggy: 'Fliggy',
|
||||
douyinHotel: 'Douyin (Xifeng Nanshan Tianmu Hot Spring Hotel)',
|
||||
douyinHotSpring: 'Douyin (Xifeng Nanshan Tianmu Hot Spring)',
|
||||
meituan: 'Meituan',
|
||||
status: {
|
||||
loading: '文書を読み込み中...',
|
||||
uploading: 'アップロード中...',
|
||||
deleting: '削除中...',
|
||||
uploadSuccess: '文書をアップロードしました',
|
||||
deleteSuccess: '文書を削除しました',
|
||||
failed: 'Knowledge docs のリクエストに失敗しました: {error}',
|
||||
},
|
||||
common: {
|
||||
cancel: 'キャンセル',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,35 @@
|
||||
import type { RoomTypeMapping } from '../../api/types';
|
||||
|
||||
export type KnowledgeTabKey = 'roomType' | 'event';
|
||||
|
||||
export type FeedbackTone = 'success' | 'warning' | 'error' | 'info';
|
||||
|
||||
export type FeedbackState = {
|
||||
id: number;
|
||||
tone: FeedbackTone;
|
||||
message: string;
|
||||
} | null;
|
||||
|
||||
export type RoomTypeRow = RoomTypeMapping & {
|
||||
dyHotSpringName?: string;
|
||||
dyHotSrpingName?: string;
|
||||
};
|
||||
|
||||
export type KnowledgeImageKind = 'image' | 'document' | 'video';
|
||||
|
||||
export type KnowledgeImage = {
|
||||
id: string;
|
||||
export interface KnowledgeDocItem {
|
||||
name: string;
|
||||
url: string;
|
||||
description: string;
|
||||
sourceUrl: string;
|
||||
createdAt: string;
|
||||
kind: KnowledgeImageKind;
|
||||
objectUrl?: boolean;
|
||||
};
|
||||
size: number;
|
||||
modifiedAt: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export type KnowledgeEvent = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
startAt: string;
|
||||
endAt: string;
|
||||
enabled: boolean;
|
||||
images: KnowledgeImage[];
|
||||
};
|
||||
export interface KnowledgeDocsListResponse {
|
||||
success?: boolean;
|
||||
files?: KnowledgeDocItem[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export type AddEventInput = {
|
||||
name: string;
|
||||
description: string;
|
||||
startAt: string;
|
||||
endAt: string;
|
||||
};
|
||||
export interface KnowledgeDocsUploadInput {
|
||||
fileName: string;
|
||||
base64: string;
|
||||
mimeType?: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeDocsUploadResponse {
|
||||
success?: boolean;
|
||||
file?: KnowledgeDocItem;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeDocsDeleteResponse {
|
||||
success?: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeDocsApiClient {
|
||||
list: () => Promise<KnowledgeDocItem[]>;
|
||||
upload: (input: KnowledgeDocsUploadInput) => Promise<KnowledgeDocItem>;
|
||||
delete: (name: string) => Promise<void>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user