feat: 问题列表添加问题类型筛选功能
All checks were successful
deploy to server / build-and-deploy (push) Successful in 3m4s
All checks were successful
deploy to server / build-and-deploy (push) Successful in 3m4s
- 功能添加:添加问题筛选功能 - 组件更改:将product-filter改为question-filter - 文本添加:i18n文本添加
This commit is contained in:
112
app/components/pages/support/QuestionFilter.vue
Normal file
112
app/components/pages/support/QuestionFilter.vue
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<div class="question-category">
|
||||||
|
<el-row class="hide-on-mobile" :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.question-type') }}
|
||||||
|
</span>
|
||||||
|
<el-select
|
||||||
|
v-model="model.selectedQuestionType"
|
||||||
|
:placeholder="$t('product-filter.select-question-type')"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="questionType in questionTypeOptions"
|
||||||
|
: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<QuestionListProductType>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
productOptions: {
|
||||||
|
type: Array as () => Array<QuestionListProduct>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
questionTypeOptions: {
|
||||||
|
type: Array as () => Array<QuestionTypeView>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const model = defineModel<{
|
||||||
|
selectedProduct: string | null;
|
||||||
|
selectedProductType: string | null;
|
||||||
|
selectedQuestionType: string | null;
|
||||||
|
keyword: string;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.question-category {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
||||||
@ -11,10 +11,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page-content">
|
<div class="page-content">
|
||||||
<product-filter
|
<question-filter
|
||||||
v-model="filters"
|
v-model="filters"
|
||||||
:product-type-options="productTypeOptions"
|
:product-type-options="productTypeOptions"
|
||||||
:product-options="productOptions"
|
:product-options="productOptions"
|
||||||
|
:question-type-options="questionTypeOptions"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<question-list :questions="paginatedQuestions" />
|
<question-list :questions="paginatedQuestions" />
|
||||||
@ -37,8 +38,9 @@
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const filters = reactive({
|
const filters = reactive({
|
||||||
selectedType: null as string | null,
|
selectedQuestionType: null as string | null,
|
||||||
selectedProduct: null as string | null,
|
selectedProduct: null as string | null,
|
||||||
|
selectedProductType: null as string | null,
|
||||||
keyword: '',
|
keyword: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,6 +59,23 @@
|
|||||||
|
|
||||||
const { data: questions, pending, error } = await useQuestionList();
|
const { data: questions, pending, error } = await useQuestionList();
|
||||||
|
|
||||||
|
const questionTypeOptions = computed(() => {
|
||||||
|
const types: QuestionTypeView[] = [];
|
||||||
|
questions.value.forEach((q: QuestionListView) => {
|
||||||
|
if (!types.some((t) => t.id === q.type.id)) {
|
||||||
|
if (q.type.id === '-1') {
|
||||||
|
types.push({
|
||||||
|
id: '-1',
|
||||||
|
name: $t('product-filter.misc'),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
types.push(q.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return types;
|
||||||
|
});
|
||||||
|
|
||||||
const productTypeOptions = computed(() => {
|
const productTypeOptions = computed(() => {
|
||||||
const types: QuestionListProductType[] = [];
|
const types: QuestionListProductType[] = [];
|
||||||
questions.value.forEach((q: QuestionListView) => {
|
questions.value.forEach((q: QuestionListView) => {
|
||||||
@ -71,12 +90,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const productOptions = computed(() => {
|
const productOptions = computed(() => {
|
||||||
if (!filters.selectedType) return [];
|
if (!filters.selectedProductType) return [];
|
||||||
const products: QuestionListProduct[] = [];
|
const products: QuestionListProduct[] = [];
|
||||||
questions.value.forEach((q: QuestionListView) => {
|
questions.value.forEach((q: QuestionListView) => {
|
||||||
q.products.forEach((product: QuestionListProduct) => {
|
q.products.forEach((product: QuestionListProduct) => {
|
||||||
if (
|
if (
|
||||||
product.type.id === filters.selectedType &&
|
product.type.id === filters.selectedProductType &&
|
||||||
!products.some((p) => p.id === product.id)
|
!products.some((p) => p.id === product.id)
|
||||||
) {
|
) {
|
||||||
products.push(product);
|
products.push(product);
|
||||||
@ -98,14 +117,18 @@
|
|||||||
(product: QuestionListProduct) =>
|
(product: QuestionListProduct) =>
|
||||||
product.id === filters.selectedProduct
|
product.id === filters.selectedProduct
|
||||||
)
|
)
|
||||||
: filters.selectedType
|
: filters.selectedProductType
|
||||||
? question.products?.some(
|
? question.products?.some(
|
||||||
(product: QuestionListProduct) =>
|
(product: QuestionListProduct) =>
|
||||||
product.type.id === filters.selectedType
|
product.type.id === filters.selectedProductType
|
||||||
)
|
)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
return matchProduct;
|
const matchQuestionType = filters.selectedQuestionType
|
||||||
|
? question.type.id === filters.selectedQuestionType
|
||||||
|
: true;
|
||||||
|
|
||||||
|
return matchProduct && matchQuestionType;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,7 +161,7 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => filters.selectedType,
|
() => filters.selectedProductType,
|
||||||
() => {
|
() => {
|
||||||
filters.selectedProduct = null;
|
filters.selectedProduct = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,12 @@
|
|||||||
"keyword": "Keyword",
|
"keyword": "Keyword",
|
||||||
"select-product-type": "Select product type",
|
"select-product-type": "Select product type",
|
||||||
"select-product-model": "Select product model",
|
"select-product-model": "Select product model",
|
||||||
"enter-keyword": "Enter keyword"
|
"enter-keyword": "Enter keyword",
|
||||||
|
"question-type": "Question Type",
|
||||||
|
"select-question-type": "Select question type",
|
||||||
|
"document-type": "Document Type",
|
||||||
|
"select-document-type": "Select document type",
|
||||||
|
"misc": "Misc"
|
||||||
},
|
},
|
||||||
"document-meta": {
|
"document-meta": {
|
||||||
"size": "Size",
|
"size": "Size",
|
||||||
|
|||||||
@ -78,7 +78,12 @@
|
|||||||
"keyword": "关键词",
|
"keyword": "关键词",
|
||||||
"select-product-type": "选择产品类型",
|
"select-product-type": "选择产品类型",
|
||||||
"select-product-model": "选择产品系列",
|
"select-product-model": "选择产品系列",
|
||||||
"enter-keyword": "输入关键词"
|
"enter-keyword": "输入关键词",
|
||||||
|
"question-type": "问题类型",
|
||||||
|
"select-question-type": "选择问题类型",
|
||||||
|
"document-type": "文档类型",
|
||||||
|
"select-document-type": "选择文档类型",
|
||||||
|
"misc": "其他"
|
||||||
},
|
},
|
||||||
"document-meta": {
|
"document-meta": {
|
||||||
"size": "大小",
|
"size": "大小",
|
||||||
|
|||||||
Reference in New Issue
Block a user