feat(document): 为文档添加下载与预览界面:
All checks were successful
deploy to server / build-and-deploy (push) Successful in 2m58s
All checks were successful
deploy to server / build-and-deploy (push) Successful in 2m58s
- 添加路由: download路由用于下载文件, preview路由用于文件预览 - 添加组件: FilePreviewer封装了若干格式文件的预览功能(目前支持pdf, image, text, video等) - 服务端API: 添加download和file分别用于处理文件下载请求与元数据获取请求 - 类型标注调整: 将原先位于app/types内的类型标注文件移至shared/types内,让app与server共享类型标注 - 国际化文本添加: 为相关页面添加国际化文本
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
v-for="(doc, index) in documents"
|
||||
:key="index"
|
||||
class="document-card"
|
||||
@click="handleClick(doc.fileId)"
|
||||
>
|
||||
<div class="document-info">
|
||||
<h3>{{ doc.title }}</h3>
|
||||
@ -15,13 +16,6 @@
|
||||
>格式:
|
||||
{{ formatFileExtension(getFileExtension(doc.filename)) }}</span
|
||||
>
|
||||
<el-button
|
||||
class="download-button"
|
||||
type="primary"
|
||||
@click="handleDownload(doc.title, doc.url)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -36,18 +30,13 @@
|
||||
},
|
||||
});
|
||||
|
||||
const handleDownload = async (fileName: string, fileUrl: string) => {
|
||||
const response = await fetch(fileUrl);
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const localePath = useLocalePath();
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = fileName;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
const handleClick = (id: string) => {
|
||||
// 获取路由参数
|
||||
if (id) {
|
||||
navigateTo(localePath(`/download/${id}`));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -59,6 +48,16 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.document-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.document-card:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.document-meta {
|
||||
font-size: 0.8rem;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
177
app/components/FilePreviewer.vue
Normal file
177
app/components/FilePreviewer.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<section class="h-screen flex flex-col">
|
||||
<!-- 头部工具栏 -->
|
||||
<header
|
||||
v-if="showToolbar && fileMeta"
|
||||
class="p-3 border-b flex items-center justify-between"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<h2 class="truncate font-medium" :title="fileMeta.filename_download">
|
||||
{{ fileMeta.filename_download }}
|
||||
</h2>
|
||||
<p class="text-xs text-gray-500">
|
||||
{{ fileMeta.type }} · {{ formatedSize }} · {{ formatedDate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="shrink-0 flex items-center gap-2">
|
||||
<button
|
||||
class="px-3 py-1.5 rounded border hover:bg-gray-50"
|
||||
type="button"
|
||||
:disabled="!fileMeta"
|
||||
@click="openInNewTab"
|
||||
>
|
||||
在新标签打开
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1.5 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
type="button"
|
||||
:disabled="!fileMeta"
|
||||
@click="download"
|
||||
>
|
||||
下载
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="pending" class="h-48 grid place-items-center border rounded">
|
||||
正在加载...
|
||||
</div>
|
||||
<div
|
||||
v-else-if="errorText"
|
||||
class="h-48 grid place-items-center border rounded text-red-600"
|
||||
>
|
||||
{{ errorText }}
|
||||
</div>
|
||||
<!-- 文件预览 -->
|
||||
<ClientOnly v-else>
|
||||
<div
|
||||
v-if="fileMeta && previewable"
|
||||
class="h-full w-full flex justify-center bg-gray-50"
|
||||
>
|
||||
<!-- 图片 -->
|
||||
<el-image
|
||||
v-if="isImage"
|
||||
fit="contain"
|
||||
class="max-w-full max-h-full select-none"
|
||||
:src="src"
|
||||
:alt="fileMeta.title || fileMeta.filename_download"
|
||||
/>
|
||||
|
||||
<!-- PDF -->
|
||||
<iframe
|
||||
v-else-if="isPdf"
|
||||
:src="src"
|
||||
title="PDF 预览"
|
||||
class="w-full h-full border-0"
|
||||
/>
|
||||
|
||||
<!-- 视频 -->
|
||||
<video
|
||||
v-else-if="isVideo"
|
||||
:src="src"
|
||||
controls
|
||||
class="w-full bg-black"
|
||||
/>
|
||||
|
||||
<!-- 文本(简单方式用 iframe;如需代码高亮可改为拉取文本并渲染 <pre>) -->
|
||||
<iframe
|
||||
v-else-if="isText"
|
||||
:src="src"
|
||||
title="文本预览"
|
||||
class="w-full h-full border-0"
|
||||
/>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/** 预览的文件 ID */
|
||||
fileId?: string;
|
||||
file?: FileMeta;
|
||||
|
||||
/** 是否显示上方工具栏(文件名、大小、按钮) */
|
||||
showToolbar?: boolean;
|
||||
|
||||
/** 下载 API 基础路径(你的后端流接口),用于“下载”按钮 */
|
||||
downloadApiBase?: string;
|
||||
|
||||
/** 追加到 file.url 的查询(如临时 token),形如 { token: 'xxx' } */
|
||||
extraQuery?: Record<string, string | number | boolean>;
|
||||
}>(),
|
||||
{
|
||||
fileId: undefined,
|
||||
file: undefined,
|
||||
showToolbar: true,
|
||||
downloadApiBase: '/api/download',
|
||||
extraQuery: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
const { data, pending, error } = await useFetch<FileMeta>(
|
||||
() => (props.file ? null : `/api/file/${props.fileId}`),
|
||||
{ server: true }
|
||||
);
|
||||
|
||||
const errorText = computed(() => error.value?.message ?? null);
|
||||
const fileMeta = computed(() => props.file ?? data.value ?? null);
|
||||
|
||||
/** 预览源地址:支持在 file.url 上追加额外 query(如临时 token、inline) */
|
||||
const src = computed<string>(() => {
|
||||
if (!fileMeta.value) return '';
|
||||
const url = new URL(fileMeta.value.url, window?.location?.origin);
|
||||
if (props.extraQuery) {
|
||||
Object.entries(props.extraQuery).forEach(([k, v]) =>
|
||||
url.searchParams.set(k, String(v))
|
||||
);
|
||||
}
|
||||
return url.toString();
|
||||
});
|
||||
|
||||
/** 类型判定 */
|
||||
const isImage = computed(
|
||||
() => fileMeta.value?.type.startsWith('image/') === true
|
||||
);
|
||||
const isPdf = computed(() => fileMeta.value?.type === 'application/pdf');
|
||||
const isVideo = computed(
|
||||
() => fileMeta.value?.type.startsWith('video/') === true
|
||||
);
|
||||
const isText = computed(
|
||||
() => fileMeta.value?.type.startsWith('text/') === true
|
||||
);
|
||||
const previewable = computed(() => fileMeta.value?.previewable === true);
|
||||
|
||||
const formatedSize = computed(() => {
|
||||
const size = fileMeta.value?.filesize ?? 0;
|
||||
return formatFileSize(size);
|
||||
});
|
||||
|
||||
const formatedDate = computed(() => {
|
||||
if (!fileMeta.value?.uploaded_on) return '';
|
||||
return new Date(fileMeta.value.uploaded_on).toLocaleDateString();
|
||||
});
|
||||
|
||||
/** 下载动作:走你自己的流式后端,避免直链暴露(便于权限与统计) */
|
||||
function download(): void {
|
||||
if (!fileMeta.value) return;
|
||||
const id = fileMeta.value.id;
|
||||
const a = document.createElement('a');
|
||||
a.href = `${props.downloadApiBase}/${encodeURIComponent(id)}`;
|
||||
a.download = fileMeta.value.filename_download;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
/** 新标签打开(直接访问直链,适合预览失败时的兜底体验) */
|
||||
function openInNewTab(): void {
|
||||
if (!src.value) return;
|
||||
window.open(src.value, '_blank', 'noopener,noreferrer');
|
||||
}
|
||||
</script>
|
||||
5
app/layouts/preview.vue
Normal file
5
app/layouts/preview.vue
Normal file
@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@ -23,6 +23,7 @@ export function toProductDocumentView(
|
||||
|
||||
return {
|
||||
id: raw.id,
|
||||
fileId: fileId,
|
||||
filename: file.filename_download,
|
||||
title: trans.title,
|
||||
url: url,
|
||||
@ -68,6 +69,7 @@ export function toDocumentListView(raw: ProductDocument): DocumentListView {
|
||||
|
||||
return {
|
||||
id: raw.id,
|
||||
fileId: fileId,
|
||||
filename: file.filename_download,
|
||||
title: trans.title,
|
||||
url: url,
|
||||
|
||||
@ -25,6 +25,9 @@ export interface DocumentListView {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 文件UUID **/
|
||||
fileId: string;
|
||||
|
||||
/** 文件名 **/
|
||||
filename: string;
|
||||
|
||||
|
||||
@ -6,6 +6,9 @@ export interface ProductDocumentView {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 文件UUID **/
|
||||
fileId: string;
|
||||
|
||||
/** 文件名 **/
|
||||
filename: string;
|
||||
|
||||
|
||||
133
app/pages/download/[id].vue
Normal file
133
app/pages/download/[id].vue
Normal file
@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">文件下载</h1>
|
||||
<el-breadcrumb class="breadcrumb">
|
||||
<el-breadcrumb-item class="text-md opacity-50">
|
||||
<NuxtLink :to="$localePath('/')">{{
|
||||
$t('navigation.home')
|
||||
}}</NuxtLink>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item class="text-md opacity-50">
|
||||
<NuxtLink :to="$localePath('/products')">{{
|
||||
$t('navigation.downloads')
|
||||
}}</NuxtLink>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div v-if="!pending" class="page-content">
|
||||
<el-card shadow="hover" class="p-4">
|
||||
<template #header>
|
||||
<div class="header-content">
|
||||
<el-icon class="header-icon"><ElIconDocument /></el-icon>
|
||||
<span class="truncate font-medium">{{
|
||||
file.filename_download
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
<dl class="text-gray-600 space-y-1 mb-6">
|
||||
<div>
|
||||
<dt class="font-semibold inline">类型:</dt>
|
||||
<dd class="inline">{{ file.type }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="font-semibold inline">大小:</dt>
|
||||
<dd class="inline">{{ formatFileSize(file.filesize) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="font-semibold inline">上传时间:</dt>
|
||||
<dd class="inline">
|
||||
{{ new Date(file.uploaded_on).toLocaleDateString() }}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<template #footer>
|
||||
<div class="button-group">
|
||||
<el-button type="primary" @click="handleDownload">下载</el-button>
|
||||
<el-button v-if="file.previewable" @click="handlePreview"
|
||||
>预览</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-card>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-skeleton :rows="6" animated />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 获取路由参数
|
||||
const id = computed(() => route.params.id as string);
|
||||
|
||||
const {
|
||||
data: file,
|
||||
pending,
|
||||
error,
|
||||
} = await useFetch<FileMeta>(`/api/file/${id.value}`);
|
||||
|
||||
if (error.value || !file.value) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: '文件未找到',
|
||||
});
|
||||
}
|
||||
|
||||
function handleDownload() {
|
||||
const link = document.createElement('a');
|
||||
link.href = `/api/download/${id.value}`;
|
||||
link.download = file.value?.filename_download ?? 'download';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
function handlePreview() {
|
||||
router.push(`/preview/${id.value}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
padding: 2rem;
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
color: var(--el-color-primary);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.header-icon {
|
||||
font-size: 1.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: baseline;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
13
app/pages/preview/[id].vue
Normal file
13
app/pages/preview/[id].vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<file-previewer :file-id="id" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'preview',
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const id = computed(() => route.params.id as string);
|
||||
</script>
|
||||
@ -1,7 +0,0 @@
|
||||
export type JsonPrimitive = string | number | boolean | null;
|
||||
|
||||
export type JsonArray = JsonValue[];
|
||||
|
||||
export type JsonObject = { [key: string]: JsonValue };
|
||||
|
||||
export type JsonValue = JsonPrimitive | JsonArray | JsonObject;
|
||||
@ -1 +0,0 @@
|
||||
export * from './my-schema';
|
||||
@ -1,842 +0,0 @@
|
||||
export interface CompanyProfile {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
translations?: CompanyProfileTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface CompanyProfileTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
company_profile_id?: CompanyProfile | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
content?: string | null;
|
||||
}
|
||||
|
||||
export interface ContactInfo {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
translations?: ContactInfoTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface ContactInfoTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
contact_info_id?: ContactInfo | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
content?: string | null;
|
||||
}
|
||||
|
||||
export interface DocumentsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
languages_code?: Language | string | null;
|
||||
title?: string | null;
|
||||
}
|
||||
|
||||
export interface Homepage {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
carousel?: HomepageFile[] | string[];
|
||||
recommend_products?: Product[] | string[];
|
||||
recommend_solutions?: Solution[] | string[];
|
||||
}
|
||||
|
||||
export interface HomepageFile {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
homepage_id?: Homepage | string | null;
|
||||
directus_files_id?: DirectusFile | string | null;
|
||||
}
|
||||
|
||||
export interface Language {
|
||||
/** @primaryKey */
|
||||
code: string;
|
||||
name?: string | null;
|
||||
direction?: 'ltr' | 'rtl' | null;
|
||||
}
|
||||
|
||||
export interface ProductDocument {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
file?: DirectusFile | string | null;
|
||||
products?: ProductsProductDocument[] | string[];
|
||||
translations?: ProductDocumentsTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface ProductDocumentsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product_documents_id?: ProductDocument | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
title?: string | null;
|
||||
}
|
||||
|
||||
export interface ProductImage {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
image?: DirectusFile | string | null;
|
||||
translations?: ProductImagesTranslation[] | null;
|
||||
products?: ProductsProductImage[] | string[];
|
||||
}
|
||||
|
||||
export interface ProductImagesTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product_images_id?: ProductImage | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
caption?: string | null;
|
||||
}
|
||||
|
||||
export interface ProductSpecGroup {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product?: Product | string | null;
|
||||
sort?: number | null;
|
||||
translations?: ProductSpecGroupsTranslation[] | null;
|
||||
specs?: ProductSpec[] | string[];
|
||||
}
|
||||
|
||||
export interface ProductSpecGroupsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product_spec_groups_id?: ProductSpecGroup | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
name?: string | null;
|
||||
}
|
||||
|
||||
export interface ProductSpec {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
group?: ProductSpecGroup | string | null;
|
||||
sort?: number | null;
|
||||
value?: string | null;
|
||||
translations?: ProductSpecsTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface ProductSpecsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product_specs_id?: ProductSpec | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
key?: string | null;
|
||||
}
|
||||
|
||||
export interface ProductType {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
/** @description 当前产品条目的状态 */
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
/** @description i18n文本 */
|
||||
translations?: ProductTypesTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface ProductTypesTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
product_types_id?: ProductType | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
/** @required */
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
/** @description 当前产品条目的状态 */
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
product_type?: ProductType | string | null;
|
||||
/** @description 在产品列表中显示 */
|
||||
cover?: DirectusFile | string | null;
|
||||
homepage_recommend?: Homepage | string | null;
|
||||
recommend_sort?: number | null;
|
||||
/** @description i18n字段 */
|
||||
translations?: ProductsTranslation[] | null;
|
||||
faqs?: ProductsQuestion[] | string[];
|
||||
documents?: ProductsProductDocument[] | string[];
|
||||
/** @description 在产品详情页中展示 */
|
||||
images?: ProductsProductImage[] | string[];
|
||||
specs?: ProductSpecGroup[] | string[];
|
||||
}
|
||||
|
||||
export interface ProductsProductDocument {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
products_id?: Product | string | null;
|
||||
product_documents_id?: ProductDocument | string | null;
|
||||
}
|
||||
|
||||
export interface ProductsProductImage {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
products_id?: Product | string | null;
|
||||
product_images_id?: ProductImage | string | null;
|
||||
sort?: number | null;
|
||||
}
|
||||
|
||||
export interface ProductsQuestion {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
products_id?: Product | string | null;
|
||||
questions_id?: Question | string | null;
|
||||
sort?: number | null;
|
||||
}
|
||||
|
||||
export interface ProductsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
products_id?: Product | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
/** @required */
|
||||
name: string;
|
||||
summary?: string | null;
|
||||
description?: string | null;
|
||||
}
|
||||
|
||||
export interface Question {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
/** @description i18n字段 */
|
||||
translations?: QuestionsTranslation[] | null;
|
||||
products?: ProductsQuestion[] | string[];
|
||||
}
|
||||
|
||||
export interface QuestionsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
questions_id?: Question | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
/** @required */
|
||||
title: string;
|
||||
content?: string | null;
|
||||
}
|
||||
|
||||
export interface SolutionType {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
/** @description i18n字段 */
|
||||
translations?: SolutionTypesTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface SolutionTypesTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
solution_types_id?: SolutionType | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
name?: string | null;
|
||||
}
|
||||
|
||||
export interface Solution {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
status?: 'published' | 'draft' | 'archived';
|
||||
type?: SolutionType | string | null;
|
||||
cover?: DirectusFile | string | null;
|
||||
homepage_recommend?: Homepage | string | null;
|
||||
recommend_sort?: number | null;
|
||||
/** @description 条目创建时自动生成 */
|
||||
create_at?: string | null;
|
||||
translations?: SolutionsTranslation[] | null;
|
||||
}
|
||||
|
||||
export interface SolutionsTranslation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
solutions_id?: Solution | string | null;
|
||||
languages_code?: Language | string | null;
|
||||
title?: string | null;
|
||||
summary?: string | null;
|
||||
content?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusAccess {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
role?: DirectusRole | string | null;
|
||||
user?: DirectusUser | string | null;
|
||||
policy?: DirectusPolicy | string;
|
||||
sort?: number | null;
|
||||
}
|
||||
|
||||
export interface DirectusActivity {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
action?: string;
|
||||
user?: DirectusUser | string | null;
|
||||
timestamp?: string;
|
||||
ip?: string | null;
|
||||
user_agent?: string | null;
|
||||
collection?: string;
|
||||
item?: string;
|
||||
origin?: string | null;
|
||||
revisions?: DirectusRevision[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusCollection {
|
||||
/** @primaryKey */
|
||||
collection: string;
|
||||
icon?: string | null;
|
||||
note?: string | null;
|
||||
display_template?: string | null;
|
||||
hidden?: boolean;
|
||||
singleton?: boolean;
|
||||
translations?: Array<{
|
||||
language: string;
|
||||
translation: string;
|
||||
singular: string;
|
||||
plural: string;
|
||||
}> | null;
|
||||
archive_field?: string | null;
|
||||
archive_app_filter?: boolean;
|
||||
archive_value?: string | null;
|
||||
unarchive_value?: string | null;
|
||||
sort_field?: string | null;
|
||||
accountability?: 'all' | 'activity' | null | null;
|
||||
color?: string | null;
|
||||
item_duplication_fields?: 'json' | null;
|
||||
sort?: number | null;
|
||||
group?: DirectusCollection | string | null;
|
||||
collapse?: string;
|
||||
preview_url?: string | null;
|
||||
versioning?: boolean;
|
||||
}
|
||||
|
||||
export interface DirectusComment {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
collection?: DirectusCollection | string;
|
||||
item?: string;
|
||||
comment?: string;
|
||||
date_created?: string | null;
|
||||
date_updated?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
user_updated?: DirectusUser | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusField {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
collection?: DirectusCollection | string;
|
||||
field?: string;
|
||||
special?: string[] | null;
|
||||
interface?: string | null;
|
||||
options?: 'json' | null;
|
||||
display?: string | null;
|
||||
display_options?: 'json' | null;
|
||||
readonly?: boolean;
|
||||
hidden?: boolean;
|
||||
sort?: number | null;
|
||||
width?: string | null;
|
||||
translations?: 'json' | null;
|
||||
note?: string | null;
|
||||
conditions?: 'json' | null;
|
||||
required?: boolean | null;
|
||||
group?: DirectusField | string | null;
|
||||
validation?: 'json' | null;
|
||||
validation_message?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusFile {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
storage?: string;
|
||||
filename_disk?: string | null;
|
||||
filename_download?: string;
|
||||
title?: string | null;
|
||||
type?: string | null;
|
||||
folder?: DirectusFolder | string | null;
|
||||
uploaded_by?: DirectusUser | string | null;
|
||||
created_on?: string;
|
||||
modified_by?: DirectusUser | string | null;
|
||||
modified_on?: string;
|
||||
charset?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
duration?: number | null;
|
||||
embed?: string | null;
|
||||
description?: string | null;
|
||||
location?: string | null;
|
||||
tags?: string[] | null;
|
||||
metadata?: 'json' | null;
|
||||
focal_point_x?: number | null;
|
||||
focal_point_y?: number | null;
|
||||
tus_id?: string | null;
|
||||
tus_data?: 'json' | null;
|
||||
uploaded_on?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusFolder {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
name?: string;
|
||||
parent?: DirectusFolder | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusMigration {
|
||||
/** @primaryKey */
|
||||
version: string;
|
||||
name?: string;
|
||||
timestamp?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusPermission {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
collection?: string;
|
||||
action?: string;
|
||||
permissions?: 'json' | null;
|
||||
validation?: 'json' | null;
|
||||
presets?: 'json' | null;
|
||||
fields?: string[] | null;
|
||||
policy?: DirectusPolicy | string;
|
||||
}
|
||||
|
||||
export interface DirectusPolicy {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
/** @required */
|
||||
name: string;
|
||||
icon?: string;
|
||||
description?: string | null;
|
||||
ip_access?: string[] | null;
|
||||
enforce_tfa?: boolean;
|
||||
admin_access?: boolean;
|
||||
app_access?: boolean;
|
||||
permissions?: DirectusPermission[] | string[];
|
||||
users?: DirectusAccess[] | string[];
|
||||
roles?: DirectusAccess[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusPreset {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
bookmark?: string | null;
|
||||
user?: DirectusUser | string | null;
|
||||
role?: DirectusRole | string | null;
|
||||
collection?: string | null;
|
||||
search?: string | null;
|
||||
layout?: string | null;
|
||||
layout_query?: 'json' | null;
|
||||
layout_options?: 'json' | null;
|
||||
refresh_interval?: number | null;
|
||||
filter?: 'json' | null;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusRelation {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
many_collection?: string;
|
||||
many_field?: string;
|
||||
one_collection?: string | null;
|
||||
one_field?: string | null;
|
||||
one_collection_field?: string | null;
|
||||
one_allowed_collections?: string[] | null;
|
||||
junction_field?: string | null;
|
||||
sort_field?: string | null;
|
||||
one_deselect_action?: string;
|
||||
}
|
||||
|
||||
export interface DirectusRevision {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
activity?: DirectusActivity | string;
|
||||
collection?: string;
|
||||
item?: string;
|
||||
data?: 'json' | null;
|
||||
delta?: 'json' | null;
|
||||
parent?: DirectusRevision | string | null;
|
||||
version?: DirectusVersion | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusRole {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
/** @required */
|
||||
name: string;
|
||||
icon?: string;
|
||||
description?: string | null;
|
||||
parent?: DirectusRole | string | null;
|
||||
children?: DirectusRole[] | string[];
|
||||
policies?: DirectusAccess[] | string[];
|
||||
users?: DirectusUser[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusSession {
|
||||
/** @primaryKey */
|
||||
token: string;
|
||||
user?: DirectusUser | string | null;
|
||||
expires?: string;
|
||||
ip?: string | null;
|
||||
user_agent?: string | null;
|
||||
share?: DirectusShare | string | null;
|
||||
origin?: string | null;
|
||||
next_token?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusSettings {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
project_name?: string;
|
||||
project_url?: string | null;
|
||||
project_color?: string;
|
||||
project_logo?: DirectusFile | string | null;
|
||||
public_foreground?: DirectusFile | string | null;
|
||||
public_background?: DirectusFile | string | null;
|
||||
public_note?: string | null;
|
||||
auth_login_attempts?: number | null;
|
||||
auth_password_policy?:
|
||||
| null
|
||||
| `/^.{8,}$/`
|
||||
| `/(?=^.{8,}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{';'?>.<,])(?!.*\\s).*$/`
|
||||
| null;
|
||||
storage_asset_transform?: 'all' | 'none' | 'presets' | null;
|
||||
storage_asset_presets?: Array<{
|
||||
key: string;
|
||||
fit: 'contain' | 'cover' | 'inside' | 'outside';
|
||||
width: number;
|
||||
height: number;
|
||||
quality: number;
|
||||
withoutEnlargement: boolean;
|
||||
format: 'auto' | 'jpeg' | 'png' | 'webp' | 'tiff' | 'avif';
|
||||
transforms: 'json';
|
||||
}> | null;
|
||||
custom_css?: string | null;
|
||||
storage_default_folder?: DirectusFolder | string | null;
|
||||
basemaps?: Array<{
|
||||
name: string;
|
||||
type: 'raster' | 'tile' | 'style';
|
||||
url: string;
|
||||
tileSize: number;
|
||||
attribution: string;
|
||||
}> | null;
|
||||
mapbox_key?: string | null;
|
||||
module_bar?: 'json' | null;
|
||||
project_descriptor?: string | null;
|
||||
default_language?: string;
|
||||
custom_aspect_ratios?: Array<{ text: string; value: number }> | null;
|
||||
public_favicon?: DirectusFile | string | null;
|
||||
default_appearance?: 'auto' | 'light' | 'dark';
|
||||
default_theme_light?: string | null;
|
||||
theme_light_overrides?: 'json' | null;
|
||||
default_theme_dark?: string | null;
|
||||
theme_dark_overrides?: 'json' | null;
|
||||
report_error_url?: string | null;
|
||||
report_bug_url?: string | null;
|
||||
report_feature_url?: string | null;
|
||||
public_registration?: boolean;
|
||||
public_registration_verify_email?: boolean;
|
||||
public_registration_role?: DirectusRole | string | null;
|
||||
public_registration_email_filter?: 'json' | null;
|
||||
visual_editor_urls?: Array<{ url: string }> | null;
|
||||
accepted_terms?: boolean | null;
|
||||
project_id?: string | null;
|
||||
mcp_enabled?: boolean;
|
||||
mcp_allow_deletes?: boolean;
|
||||
mcp_prompts_collection?: string | null;
|
||||
mcp_system_prompt_enabled?: boolean;
|
||||
mcp_system_prompt?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusUser {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
first_name?: string | null;
|
||||
last_name?: string | null;
|
||||
email?: string | null;
|
||||
password?: string | null;
|
||||
location?: string | null;
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
tags?: string[] | null;
|
||||
avatar?: DirectusFile | string | null;
|
||||
language?: string | null;
|
||||
tfa_secret?: string | null;
|
||||
status?:
|
||||
| 'draft'
|
||||
| 'invited'
|
||||
| 'unverified'
|
||||
| 'active'
|
||||
| 'suspended'
|
||||
| 'archived';
|
||||
role?: DirectusRole | string | null;
|
||||
token?: string | null;
|
||||
last_access?: string | null;
|
||||
last_page?: string | null;
|
||||
provider?: string;
|
||||
external_identifier?: string | null;
|
||||
auth_data?: 'json' | null;
|
||||
email_notifications?: boolean | null;
|
||||
appearance?: null | 'auto' | 'light' | 'dark' | null;
|
||||
theme_dark?: string | null;
|
||||
theme_light?: string | null;
|
||||
theme_light_overrides?: 'json' | null;
|
||||
theme_dark_overrides?: 'json' | null;
|
||||
text_direction?: 'auto' | 'ltr' | 'rtl';
|
||||
policies?: DirectusAccess[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusWebhook {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
name?: string;
|
||||
method?: null;
|
||||
url?: string;
|
||||
status?: 'active' | 'inactive';
|
||||
data?: boolean;
|
||||
actions?: 'create' | 'update' | 'delete';
|
||||
collections?: string[];
|
||||
headers?: Array<{ header: string; value: string }> | null;
|
||||
was_active_before_deprecation?: boolean;
|
||||
migrated_flow?: DirectusFlow | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusDashboard {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
name?: string;
|
||||
icon?: string;
|
||||
note?: string | null;
|
||||
date_created?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
color?: string | null;
|
||||
panels?: DirectusPanel[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusPanel {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
dashboard?: DirectusDashboard | string;
|
||||
name?: string | null;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
show_header?: boolean;
|
||||
note?: string | null;
|
||||
type?: string;
|
||||
position_x?: number;
|
||||
position_y?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
options?: 'json' | null;
|
||||
date_created?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusNotification {
|
||||
/** @primaryKey */
|
||||
id: number;
|
||||
timestamp?: string | null;
|
||||
status?: string | null;
|
||||
recipient?: DirectusUser | string;
|
||||
sender?: DirectusUser | string | null;
|
||||
subject?: string;
|
||||
message?: string | null;
|
||||
collection?: string | null;
|
||||
item?: string | null;
|
||||
}
|
||||
|
||||
export interface DirectusShare {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
name?: string | null;
|
||||
collection?: DirectusCollection | string;
|
||||
item?: string;
|
||||
role?: DirectusRole | string | null;
|
||||
password?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
date_created?: string | null;
|
||||
date_start?: string | null;
|
||||
date_end?: string | null;
|
||||
times_used?: number | null;
|
||||
max_uses?: number | null;
|
||||
}
|
||||
|
||||
export interface DirectusFlow {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
name?: string;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
description?: string | null;
|
||||
status?: string;
|
||||
trigger?: string | null;
|
||||
accountability?: string | null;
|
||||
options?: 'json' | null;
|
||||
operation?: DirectusOperation | string | null;
|
||||
date_created?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
operations?: DirectusOperation[] | string[];
|
||||
}
|
||||
|
||||
export interface DirectusOperation {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
name?: string | null;
|
||||
key?: string;
|
||||
type?: string;
|
||||
position_x?: number;
|
||||
position_y?: number;
|
||||
options?: 'json' | null;
|
||||
resolve?: DirectusOperation | string | null;
|
||||
reject?: DirectusOperation | string | null;
|
||||
flow?: DirectusFlow | string;
|
||||
date_created?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
}
|
||||
|
||||
export interface DirectusTranslation {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
/** @required */
|
||||
language: string;
|
||||
/** @required */
|
||||
key: string;
|
||||
/** @required */
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface DirectusVersion {
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
key?: string;
|
||||
name?: string | null;
|
||||
collection?: DirectusCollection | string;
|
||||
item?: string;
|
||||
hash?: string | null;
|
||||
date_created?: string | null;
|
||||
date_updated?: string | null;
|
||||
user_created?: DirectusUser | string | null;
|
||||
user_updated?: DirectusUser | string | null;
|
||||
delta?: 'json' | null;
|
||||
}
|
||||
|
||||
export interface DirectusExtension {
|
||||
enabled?: boolean;
|
||||
/** @primaryKey */
|
||||
id: string;
|
||||
folder?: string;
|
||||
source?: string;
|
||||
bundle?: string | null;
|
||||
}
|
||||
|
||||
export interface Schema {
|
||||
company_profile: CompanyProfile;
|
||||
company_profile_translations: CompanyProfileTranslation[];
|
||||
contact_info: ContactInfo;
|
||||
contact_info_translations: ContactInfoTranslation[];
|
||||
documents_translations: DocumentsTranslation[];
|
||||
homepage: Homepage;
|
||||
homepage_files: HomepageFile[];
|
||||
languages: Language[];
|
||||
product_documents: ProductDocument[];
|
||||
product_documents_translations: ProductDocumentsTranslation[];
|
||||
product_images: ProductImage[];
|
||||
product_images_translations: ProductImagesTranslation[];
|
||||
product_spec_groups: ProductSpecGroup[];
|
||||
product_spec_groups_translations: ProductSpecGroupsTranslation[];
|
||||
product_specs: ProductSpec[];
|
||||
product_specs_translations: ProductSpecsTranslation[];
|
||||
product_types: ProductType[];
|
||||
product_types_translations: ProductTypesTranslation[];
|
||||
products: Product[];
|
||||
products_product_documents: ProductsProductDocument[];
|
||||
products_product_images: ProductsProductImage[];
|
||||
products_questions: ProductsQuestion[];
|
||||
products_translations: ProductsTranslation[];
|
||||
questions: Question[];
|
||||
questions_translations: QuestionsTranslation[];
|
||||
solution_types: SolutionType[];
|
||||
solution_types_translations: SolutionTypesTranslation[];
|
||||
solutions: Solution[];
|
||||
solutions_translations: SolutionsTranslation[];
|
||||
directus_access: DirectusAccess[];
|
||||
directus_activity: DirectusActivity[];
|
||||
directus_collections: DirectusCollection[];
|
||||
directus_comments: DirectusComment[];
|
||||
directus_fields: DirectusField[];
|
||||
directus_files: DirectusFile[];
|
||||
directus_folders: DirectusFolder[];
|
||||
directus_migrations: DirectusMigration[];
|
||||
directus_permissions: DirectusPermission[];
|
||||
directus_policies: DirectusPolicy[];
|
||||
directus_presets: DirectusPreset[];
|
||||
directus_relations: DirectusRelation[];
|
||||
directus_revisions: DirectusRevision[];
|
||||
directus_roles: DirectusRole[];
|
||||
directus_sessions: DirectusSession[];
|
||||
directus_settings: DirectusSettings;
|
||||
directus_users: DirectusUser[];
|
||||
directus_webhooks: DirectusWebhook[];
|
||||
directus_dashboards: DirectusDashboard[];
|
||||
directus_panels: DirectusPanel[];
|
||||
directus_notifications: DirectusNotification[];
|
||||
directus_shares: DirectusShare[];
|
||||
directus_flows: DirectusFlow[];
|
||||
directus_operations: DirectusOperation[];
|
||||
directus_translations: DirectusTranslation[];
|
||||
directus_versions: DirectusVersion[];
|
||||
directus_extensions: DirectusExtension[];
|
||||
}
|
||||
|
||||
export enum CollectionNames {
|
||||
company_profile = 'company_profile',
|
||||
company_profile_translations = 'company_profile_translations',
|
||||
contact_info = 'contact_info',
|
||||
contact_info_translations = 'contact_info_translations',
|
||||
documents_translations = 'documents_translations',
|
||||
homepage = 'homepage',
|
||||
homepage_files = 'homepage_files',
|
||||
languages = 'languages',
|
||||
product_documents = 'product_documents',
|
||||
product_documents_translations = 'product_documents_translations',
|
||||
product_images = 'product_images',
|
||||
product_images_translations = 'product_images_translations',
|
||||
product_spec_groups = 'product_spec_groups',
|
||||
product_spec_groups_translations = 'product_spec_groups_translations',
|
||||
product_specs = 'product_specs',
|
||||
product_specs_translations = 'product_specs_translations',
|
||||
product_types = 'product_types',
|
||||
product_types_translations = 'product_types_translations',
|
||||
products = 'products',
|
||||
products_product_documents = 'products_product_documents',
|
||||
products_product_images = 'products_product_images',
|
||||
products_questions = 'products_questions',
|
||||
products_translations = 'products_translations',
|
||||
questions = 'questions',
|
||||
questions_translations = 'questions_translations',
|
||||
solution_types = 'solution_types',
|
||||
solution_types_translations = 'solution_types_translations',
|
||||
solutions = 'solutions',
|
||||
solutions_translations = 'solutions_translations',
|
||||
directus_access = 'directus_access',
|
||||
directus_activity = 'directus_activity',
|
||||
directus_collections = 'directus_collections',
|
||||
directus_comments = 'directus_comments',
|
||||
directus_fields = 'directus_fields',
|
||||
directus_files = 'directus_files',
|
||||
directus_folders = 'directus_folders',
|
||||
directus_migrations = 'directus_migrations',
|
||||
directus_permissions = 'directus_permissions',
|
||||
directus_policies = 'directus_policies',
|
||||
directus_presets = 'directus_presets',
|
||||
directus_relations = 'directus_relations',
|
||||
directus_revisions = 'directus_revisions',
|
||||
directus_roles = 'directus_roles',
|
||||
directus_sessions = 'directus_sessions',
|
||||
directus_settings = 'directus_settings',
|
||||
directus_users = 'directus_users',
|
||||
directus_webhooks = 'directus_webhooks',
|
||||
directus_dashboards = 'directus_dashboards',
|
||||
directus_panels = 'directus_panels',
|
||||
directus_notifications = 'directus_notifications',
|
||||
directus_shares = 'directus_shares',
|
||||
directus_flows = 'directus_flows',
|
||||
directus_operations = 'directus_operations',
|
||||
directus_translations = 'directus_translations',
|
||||
directus_versions = 'directus_versions',
|
||||
directus_extensions = 'directus_extensions',
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
export * from './meili-index';
|
||||
export * from './search-result';
|
||||
@ -1,88 +0,0 @@
|
||||
/**
|
||||
* 产品索引文档结构
|
||||
*/
|
||||
export interface MeiliProductIndex {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 产品名称 **/
|
||||
name: string;
|
||||
|
||||
/** 产品简介 **/
|
||||
summary: string;
|
||||
|
||||
/** 产品详情 **/
|
||||
description: string;
|
||||
|
||||
/** 产品类型 **/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决方案索引文档结构
|
||||
*/
|
||||
export interface MeiliSolutionIndex {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 解决方案标题 **/
|
||||
title: string;
|
||||
|
||||
/** 解决方案摘要 **/
|
||||
summary: string;
|
||||
|
||||
/** 解决方案内容 **/
|
||||
content: string;
|
||||
|
||||
/** 解决方案类型 **/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 相关问题索引文档结构
|
||||
*/
|
||||
export interface MeiliQuestionIndex {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 问题标题 **/
|
||||
title: string;
|
||||
|
||||
/** 问题内容 **/
|
||||
content: string;
|
||||
|
||||
/** 相关产品 **/
|
||||
products: string[];
|
||||
|
||||
/** 相关产品类型 **/
|
||||
product_types: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 相关文档索引文档结构
|
||||
*/
|
||||
export interface MeiliProductDocumentIndex {
|
||||
/** 唯一标识符 **/
|
||||
id: number;
|
||||
|
||||
/** 文档标题 **/
|
||||
title: string;
|
||||
|
||||
/** 相关产品 **/
|
||||
products: string[];
|
||||
|
||||
/** 相关产品类型 **/
|
||||
product_types: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 索引名与类型映射
|
||||
*/
|
||||
export interface MeiliIndexMap {
|
||||
products: MeiliProductIndex;
|
||||
solutions: MeiliSolutionIndex;
|
||||
questions: MeiliQuestionIndex;
|
||||
product_documents: MeiliProductDocumentIndex;
|
||||
}
|
||||
|
||||
export type MeiliSearchItemType = keyof MeiliIndexMap;
|
||||
@ -1,42 +0,0 @@
|
||||
import type { SearchResponse } from 'meilisearch';
|
||||
|
||||
/**
|
||||
* 原始搜索分段结果
|
||||
* @template T 索引类型
|
||||
*/
|
||||
export interface RawSearchSection<T> {
|
||||
/** 索引名 **/
|
||||
indexUid: string;
|
||||
|
||||
/** 响应数据 **/
|
||||
response: SearchResponse<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索结果
|
||||
*/
|
||||
export interface SearchHit extends Record<string, unknown> {
|
||||
objectID?: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索分段结果
|
||||
* @template T 索引类型
|
||||
*/
|
||||
export interface SearchSection<T> {
|
||||
/** 索引名 **/
|
||||
indexUid: string;
|
||||
|
||||
/** 原始索引名 **/
|
||||
rawIndex: MeiliSearchItemType;
|
||||
|
||||
/** 命中条目 **/
|
||||
hits: T[];
|
||||
// hits: SearchHit[];
|
||||
|
||||
/** 条目总数 **/
|
||||
estimatedTotalHits: number;
|
||||
|
||||
/** 处理时间 **/
|
||||
processingTimeMs: number;
|
||||
}
|
||||
Reference in New Issue
Block a user