feat: 文档库页面添加文档类型筛选功能

- 功能添加:添加按照文档类型筛选文档的功能
- 组件更改:将筛选器由product-filter改为document-filter
This commit is contained in:
2025-12-03 17:47:57 +08:00
parent 815df40745
commit 53f3e99d90
2 changed files with 147 additions and 15 deletions

View File

@ -0,0 +1,113 @@
<template>
<div class="document-category">
<el-row :gutter="12">
<el-col :span="12" :xs="12">
<span class="select-label">{{
$t('product-filter.product-type')
}}</span>
<el-select
v-model="model.selectedProductType"
:placeholder="$t('product-filter.select-product-type')"
clearable
>
<el-option
v-for="type in productTypeOptions"
:key="type.id"
:label="type.name"
:value="type.id"
/>
</el-select>
</el-col>
<el-col :span="12" :xs="12">
<span class="select-label">{{
$t('product-filter.product-model')
}}</span>
<el-select
v-model="model.selectedProduct"
:placeholder="$t('product-filter.select-product-model')"
clearable
>
<el-option
v-for="product in productOptions"
:key="product.id"
:label="product.name"
:value="product.id"
/>
</el-select>
</el-col>
<el-col :span="12" :xs="24">
<span class="select-label">
{{ $t('product-filter.document-type') }}
</span>
<el-select
v-model="model.selectedDocumentType"
:placeholder="$t('product-filter.select-document-type')"
clearable
>
<el-option
v-for="questionType in documentTypeOptions"
:key="questionType.id"
:label="questionType.name"
:value="questionType.id"
/>
</el-select>
</el-col>
<el-col :span="12" :xs="24">
<span class="select-label">{{ $t('product-filter.keyword') }}</span>
<el-input
v-model="model.keyword"
:placeholder="$t('product-filter.enter-keyword')"
clearable
:prefix-icon="Search"
/>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue';
defineProps({
productTypeOptions: {
type: Array as () => Array<DocumentListProductType>,
default: () => [],
},
productOptions: {
type: Array as () => Array<DocumentListProduct>,
default: () => [],
},
documentTypeOptions: {
type: Array as () => Array<DocumentTypeView>,
default: () => [],
},
});
const model = defineModel<{
selectedProduct: string | null;
selectedProductType: string | null;
selectedDocumentType: string | null;
keyword: string;
}>();
</script>
<style scoped>
.document-category {
margin-bottom: 1rem;
padding: 0 0;
}
.select-label {
color: var(--el-text-color-secondary);
font-size: 0.9rem;
}
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
height: 40px;
font-size: 0.9rem;
}
</style>

View File

@ -10,13 +10,15 @@
<app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
</div>
<div class="page-content">
<product-filter
<document-filter
v-model="filters"
:product-type-options="productTypeOptions"
:product-options="productOptions"
:document-type-options="documentTypeOptions"
/>
<!-- <document-list :documents="filteredDocuments" /> -->
<document-list :documents="paginatedDocuments" />
<el-pagination
v-model:current-page="page"
class="justify-center pagination-container"
@ -39,7 +41,8 @@
];
const filters = reactive({
selectedType: null as string | null,
selectedDocumentType: null as string | null,
selectedProductType: null as string | null,
selectedProduct: null as string | null,
keyword: '',
});
@ -49,6 +52,24 @@
const { data: documents, pending, error } = await useDocumentList();
const documentTypeOptions = computed(() => {
const types: DocumentTypeView[] = [];
documents.value.forEach((doc: DocumentListView) => {
if (!types.some((item) => item.id === doc.type.id)) {
if (doc.type.id === '-1') {
types.push({
id: '-1',
name: $t('product-filter.misc'),
});
} else {
types.push(doc.type);
}
}
});
return types;
});
const productTypeOptions = computed(() => {
const types: DocumentListProductType[] = [];
documents.value.forEach((doc: DocumentListView) => {
@ -64,13 +85,13 @@
});
const productOptions = computed(() => {
if (!filters.selectedType) return [];
if (!filters.selectedProductType) return [];
const products: DocumentListProduct[] = [];
documents.value.forEach((doc: DocumentListView) => {
doc.products?.forEach((product: DocumentListProduct) => {
if (
product.type.id === filters.selectedType &&
product.type.id === filters.selectedProductType &&
!products.some((item) => item.id === product.id)
) {
products.push(product);
@ -93,14 +114,18 @@
(product: DocumentListProduct) =>
product.id === filters.selectedProduct
)
: filters.selectedType
: filters.selectedProductType
? doc.products?.some(
(product: DocumentListProduct) =>
product.type?.id === filters.selectedType
product.type?.id === filters.selectedProductType
)
: true;
return matchProduct;
const matchDocumentType = filters.selectedDocumentType
? doc.type.id === filters.selectedDocumentType
: true;
return matchProduct && matchDocumentType;
});
});
@ -112,7 +137,7 @@
});
watch(
() => filters.selectedType,
() => filters.selectedProductType,
() => {
filters.selectedProduct = null;
}
@ -152,12 +177,6 @@
margin-left: auto;
}
.document-category {
padding: 0rem 2rem;
gap: 4px;
margin-bottom: 0.5rem;
}
.page-content {
padding: 1rem 2rem 2rem;
}