diff --git a/server/assets/graphql/questionList.graphql b/server/assets/graphql/questionList.graphql index 273ed77..bdad9c7 100644 --- a/server/assets/graphql/questionList.graphql +++ b/server/assets/graphql/questionList.graphql @@ -1,6 +1,13 @@ query GetQuestionList($locale: String!) { questions(filter: { status: { _eq: "published" } }) { id + type { + id + translations(filter: { languages_code: { code: { _eq: $locale } } }) { + id + name + } + } translations(filter: { languages_code: { code: { _eq: $locale } } }) { id title diff --git a/server/mappers/questionMapper.test.ts b/server/mappers/questionMapper.test.ts index b6d45e7..e97e2d5 100644 --- a/server/mappers/questionMapper.test.ts +++ b/server/mappers/questionMapper.test.ts @@ -1,5 +1,51 @@ import { describe, expect, test } from 'vitest'; -import { toProductQuestionView, toQuestionListView } from './questionMapper'; +import { + toProductQuestionView, + toQuestionListView, + toQuestionTypeView, +} from './questionMapper'; + +/** + * 单元测试: toQuestionTypeView + */ +describe('toQuestionTypeView', () => { + const baseData: QuestionType = { + id: 1, + translations: [{ id: 1, name: 'Type Name' }], + }; + + test('convert raw data to QuestionTypeView correctly', () => { + const rawData: QuestionType = { + ...baseData, + }; + + expect(toQuestionTypeView(rawData)).toEqual({ + id: '1', + type: 'Type Name', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: QuestionType = { + ...baseData, + translations: [], + }; + + expect(toQuestionTypeView(rawData)).toEqual({ + id: '1', + type: '', + }); + }); + + test('convert null input to default QuestionTypeView', () => { + const rawData: QuestionType | null = null; + + expect(toQuestionTypeView(rawData)).toEqual({ + id: '', + type: '', + }); + }); +}); /** * 单元测试: toProductQuestionView @@ -43,6 +89,10 @@ describe('toProductQuestionView', () => { describe('toQuestionListView', () => { const baseData: Question = { id: 1, + type: { + id: 1, + translations: [{ id: 1, name: 'Type Name' }], + }, translations: [ { id: 1, title: 'Question Title', content: 'Question Answer' }, ], @@ -68,6 +118,10 @@ describe('toQuestionListView', () => { expect(toQuestionListView(rawData)).toEqual({ id: '1', + type: { + id: '1', + type: 'Type Name', + }, title: 'Question Title', content: 'Question Answer', products: [ @@ -104,6 +158,10 @@ describe('toQuestionListView', () => { expect(toQuestionListView(rawData)).toEqual({ id: '1', + type: { + id: '1', + type: 'Type Name', + }, title: '', content: '', products: [ diff --git a/server/mappers/questionMapper.ts b/server/mappers/questionMapper.ts index f30def6..e81b543 100644 --- a/server/mappers/questionMapper.ts +++ b/server/mappers/questionMapper.ts @@ -1,5 +1,31 @@ import { isObject } from '../../server/utils/object'; +/** + * 将 Directus 返回的 QuestionType 类型转换为 QuestionTypeView 视图模型 + * + * @param raw: 原始的 QuestionType 数据 + * @returns 转换后的 QuestionTypeView 对象 + * + * @example + * const view = toQuestionTypeView(rawQuestionType); + */ +export function toQuestionTypeView( + raw: QuestionType | string | null +): QuestionTypeView { + if (typeof raw === 'string' || raw === null) { + return { + id: '', + type: '', + } satisfies QuestionTypeView; + } + const trans = raw.translations?.[0]; + + return { + id: raw.id.toString(), + type: trans?.name ?? '', + }; +} + /** * 将 Directus 返回的 Question 数据转换为 ProductQuestionView 视图模型 * @@ -31,6 +57,8 @@ export function toProductQuestionView(raw: Question): ProductQuestionView { export function toQuestionListView(raw: Question): QuestionListView { const trans = raw.translations?.[0]; + const type = toQuestionTypeView(raw.type ?? null); + const related_products: QuestionListProduct[] = (raw.products ?? []) .filter(isObject) .map((item) => item.products_id) @@ -57,6 +85,7 @@ export function toQuestionListView(raw: Question): QuestionListView { return { id: raw.id.toString(), + type: type, title: trans?.title ?? '', content: trans?.content ?? '', products: related_products, diff --git a/shared/types/views/question-list-view.ts b/shared/types/views/question-list-view.ts index 4ea843c..0a1755e 100644 --- a/shared/types/views/question-list-view.ts +++ b/shared/types/views/question-list-view.ts @@ -7,6 +7,18 @@ export interface QuestionListProductType { name: string; } +/** + * 问题类型 + * 用于在常见问题列表中提供产品筛选功能 + */ +export interface QuestionTypeView { + /** 唯一标识符 **/ + id: string; + + /** 类型名 **/ + type: string; +} + /** * 问题关联产品模型 * 用于在常见问题列表中提供产品筛选功能 @@ -25,6 +37,9 @@ export interface QuestionListView { /** 唯一标识符 **/ id: string; + /** 问题类型 **/ + type: QuestionTypeView; + /** 问题标题 **/ title: string;