From f4ec82a1504af27b4416edf9fcd5eb8d03011acc Mon Sep 17 00:00:00 2001 From: R2m1liA <15258427350@163.com> Date: Wed, 3 Dec 2025 15:53:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=B7=BB=E5=8A=A0=E9=97=AE=E9=A2=98=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 查询语句更改:添加type字段 - mapper增添:添加type字段的mapper - 视图模型更改:QuestionListView添加type字段 --- server/assets/graphql/questionList.graphql | 7 +++ server/mappers/questionMapper.test.ts | 60 +++++++++++++++++++++- server/mappers/questionMapper.ts | 29 +++++++++++ shared/types/views/question-list-view.ts | 15 ++++++ 4 files changed, 110 insertions(+), 1 deletion(-) 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;