fix: 问题列表无法聚焦问题 #84

Manually merged
remilia merged 2 commits from fix/focus into master 2025-11-15 16:38:59 +08:00
28 changed files with 92 additions and 93 deletions

View File

@ -45,7 +45,7 @@
// 确保渲染完成后再操作 DOM
await nextTick();
const target = props.questions.find((q) => q.id === Number(focusId));
const target = props.questions.find((q) => q.id === focusId);
if (!target) return;
// 展开目标项

View File

@ -1,3 +1,2 @@
export * from './directus';
export * from './useLocalizations';
export * from './useMeilisearch';

View File

@ -16,7 +16,7 @@ describe('companyProfileMapper', () => {
};
expect(toCompanyProfileView(rawData)).toEqual({
id: 1,
id: '1',
content: 'This is raw data of company profile',
});
});
@ -27,7 +27,7 @@ describe('companyProfileMapper', () => {
};
expect(toCompanyProfileView(rawData)).toEqual({
id: 1,
id: '1',
content: '',
});
});

View File

@ -11,7 +11,7 @@ export function toCompanyProfileView(raw: CompanyProfile): CompanyProfileView {
const trans = raw.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
content: trans?.content ?? '',
};
}

View File

@ -15,7 +15,7 @@ describe('contactInfoMapper', () => {
};
expect(toContactInfoView(rawData)).toEqual({
id: 1,
id: '1',
content: 'This is raw data of contact info',
});
});
@ -27,7 +27,7 @@ describe('contactInfoMapper', () => {
};
expect(toContactInfoView(rawData)).toEqual({
id: 1,
id: '1',
content: '',
});
});

View File

@ -11,7 +11,7 @@ export function toContactInfoView(raw: ContactInfo): ContactInfoView {
const trans = raw.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
content: trans?.content ?? '',
};
}

View File

@ -18,7 +18,7 @@ describe('toProductDocumentView', () => {
test('convert raw data with fileMeta to ProductDocumentView correctly', () => {
const rawData: ProductDocument = { ...baseData };
expect(toProductDocumentView(rawData)).toEqual({
id: 1,
id: '1',
fileId: 'rand-om__-uuid-1234',
filename: 'document.pdf',
title: 'Document Title',
@ -34,7 +34,7 @@ describe('toProductDocumentView', () => {
};
expect(toProductDocumentView(rawData)).toEqual({
id: 1,
id: '1',
fileId: '',
filename: '',
title: 'Document Title',
@ -49,7 +49,7 @@ describe('toProductDocumentView', () => {
translations: [],
};
expect(toProductDocumentView(rawData)).toEqual({
id: 1,
id: '1',
fileId: 'rand-om__-uuid-1234',
filename: 'document.pdf',
title: '',
@ -88,7 +88,7 @@ describe('toDocumentListView', () => {
test('convert raw data with fileMeta to DocumentListView correctly', () => {
const rawData: ProductDocument = { ...baseData };
expect(toDocumentListView(rawData)).toEqual({
id: 1,
id: '1',
fileId: 'rand-om__-uuid-1234',
filename: 'document.pdf',
title: 'Document Title',
@ -96,10 +96,10 @@ describe('toDocumentListView', () => {
size: 2048,
products: [
{
id: 1,
id: '1',
name: 'Product A',
type: {
id: 1,
id: '1',
name: 'Type A',
},
},

View File

@ -19,7 +19,7 @@ export function toProductDocumentView(
const url = `/api/assets/${fileId}`;
return {
id: raw.id,
id: raw.id.toString(),
fileId: fileId,
filename: file?.filename_download ?? '',
title: trans?.title ?? '',
@ -52,22 +52,22 @@ export function toDocumentListView(raw: ProductDocument): DocumentListView {
.map((item) => {
const productType = isObject<ProductType>(item.product_type)
? ({
id: item.product_type.id,
id: item.product_type.id.toString(),
name: item.product_type.translations?.[0]?.name ?? '',
} satisfies DocumentListProductType)
: ({
id: -1,
id: '',
name: '',
} satisfies DocumentListProductType);
return {
id: item.id,
id: item.id.toString(),
name: item.translations?.[0]?.name ?? '',
type: productType,
};
});
return {
id: raw.id,
id: raw.id.toString(),
fileId: fileId,
filename: file?.filename_download ?? '',
title: trans?.title ?? '',

View File

@ -50,17 +50,17 @@ describe('toHomepageView', () => {
};
expect(toHomepageView(rawData)).toEqual({
id: 1,
id: '1',
carousel: ['file-uuid-1', 'file-uuid-2'],
recommendProducts: [
{
id: 1,
id: '1',
name: 'Product 1',
summary: 'Summary 1',
cover: 'cover-file-uuid-1',
},
{
id: 2,
id: '2',
name: 'Product 2',
summary: 'Summary 2',
cover: 'cover-file-uuid-2',
@ -68,7 +68,7 @@ describe('toHomepageView', () => {
],
recommendSolutions: [
{
id: 1,
id: '1',
title: 'Solution 1',
summary: 'Summary 1',
cover: 'cover-file-uuid-1',
@ -86,10 +86,10 @@ describe('toHomepageView', () => {
};
expect(toHomepageView(rawData)).toEqual({
id: 1,
id: '1',
carousel: [],
recommendProducts: [{ id: 1, name: '', summary: '', cover: '' }],
recommendSolutions: [{ id: 1, title: '', summary: '', cover: '' }],
recommendProducts: [{ id: '1', name: '', summary: '', cover: '' }],
recommendSolutions: [{ id: '1', title: '', summary: '', cover: '' }],
});
});
});

View File

@ -24,7 +24,7 @@ export function toHomepageView(raw: Homepage): HomepageView {
const cover = isObject<DirectusFile>(item.cover) ? item.cover.id : '';
return {
id: item.id,
id: item.id.toString(),
name: trans?.name ?? '',
summary: trans?.summary ?? '',
cover: cover,
@ -38,7 +38,7 @@ export function toHomepageView(raw: Homepage): HomepageView {
const cover = isObject<DirectusFile>(item.cover) ? item.cover.id : '';
return {
id: item.id,
id: item.id.toString(),
title: trans?.title ?? '',
summary: trans?.summary ?? '',
cover: cover,
@ -46,7 +46,7 @@ export function toHomepageView(raw: Homepage): HomepageView {
});
return {
id: raw.id,
id: raw.id.toString(),
carousel: carousel ?? [],
recommendProducts: products ?? [],
recommendSolutions: solutions ?? [],

View File

@ -27,12 +27,12 @@ describe('toProductListView', () => {
};
expect(toProductListView(rawData)).toEqual({
id: 1,
id: '1',
name: 'Product Name',
summary: 'Product Summary',
cover: 'cover-file-uuid-1234',
product_type: {
id: 1,
id: '1',
name: 'Type Name',
sort: 1,
},
@ -54,12 +54,12 @@ describe('toProductListView', () => {
};
expect(toProductListView(rawData)).toEqual({
id: 1,
id: '1',
name: '',
summary: '',
cover: 'cover-file-uuid-1234',
product_type: {
id: 20,
id: '20',
name: '',
sort: 1,
},
@ -78,7 +78,7 @@ describe('toProductSpecView', () => {
};
expect(toProductSpecView(rawData)).toEqual({
id: 1,
id: '1',
key: 'Key',
value: 'Value',
});
@ -91,7 +91,7 @@ describe('toProductSpecView', () => {
};
expect(toProductSpecView(rawData)).toEqual({
id: 1,
id: '1',
key: '',
value: '',
});
@ -113,11 +113,11 @@ describe('toProductSpecGroupView', () => {
};
expect(toProductSpecGroupView(rawData)).toEqual({
id: 1,
id: '1',
name: 'Group Name',
specs: [
{ id: 1, key: 'Key1', value: 'Value1' },
{ id: 2, key: 'Key2', value: 'Value2' },
{ id: '1', key: 'Key1', value: 'Value1' },
{ id: '2', key: 'Key2', value: 'Value2' },
],
});
});
@ -130,7 +130,7 @@ describe('toProductSpecGroupView', () => {
};
expect(toProductSpecGroupView(rawData)).toEqual({
id: 1,
id: '1',
name: '',
specs: [],
});
@ -155,7 +155,7 @@ describe('toProductView', () => {
};
expect(toProductView(rawData)).toEqual({
id: 1,
id: '1',
name: 'Product Name',
summary: 'Product Summary',
description: 'Product Description',
@ -174,7 +174,7 @@ describe('toProductView', () => {
};
expect(toProductView(rawData)).toEqual({
id: 1,
id: '1',
name: '',
summary: '',
description: '',

View File

@ -15,7 +15,7 @@ export function toProductTypeView(raw: ProductType): ProductTypeView {
const trans = raw.translations?.[0] ?? { name: '' };
return {
id: raw.id,
id: raw.id.toString(),
name: trans.name,
sort: raw?.sort ?? 999,
};
@ -36,7 +36,7 @@ export function toProductListView(raw: Product): ProductListView {
const type = isObject<ProductType>(raw.product_type)
? toProductTypeView(raw.product_type)
: ({
id: -1,
id: '',
name: '',
sort: 999,
} satisfies ProductTypeView);
@ -44,7 +44,7 @@ export function toProductListView(raw: Product): ProductListView {
const cover = isObject<DirectusFile>(raw.cover) ? raw.cover.id : '';
return {
id: raw.id,
id: raw.id.toString(),
product_type: type,
name: trans?.name ?? '',
summary: trans?.summary ?? '',
@ -69,7 +69,7 @@ export function toProductSpecGroupView(
const specs = raw.specs ?? [];
return {
id: raw.id,
id: raw.id.toString(),
name: trans?.name ?? '',
specs: specs
.filter(isObject<ProductSpec>)
@ -90,7 +90,7 @@ export function toProductSpecView(raw: ProductSpec): ProductSpecView {
const trans = raw.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
key: trans?.key ?? '',
value: trans?.value ?? '',
};
@ -115,7 +115,7 @@ export function toProductView(raw: Product): ProductView {
.map((item) => {
const image = isObject<DirectusFile>(item.image) ? item.image.id : '';
return {
id: item.id,
id: item.id.toString(),
image: image,
caption: item.translations?.[0]?.caption || '',
};
@ -142,7 +142,7 @@ export function toProductView(raw: Product): ProductView {
.map((item) => toProductDocumentView(item));
return {
id: raw.id,
id: raw.id.toString(),
product_type: type,
name: trans?.name ?? '',
summary: trans?.summary ?? '',

View File

@ -17,7 +17,7 @@ describe('toProductQuestionView', () => {
};
expect(toProductQuestionView(rawData)).toEqual({
id: 1,
id: '1',
title: 'Question Title',
content: 'Question Answer',
});
@ -30,7 +30,7 @@ describe('toProductQuestionView', () => {
};
expect(toProductQuestionView(rawData)).toEqual({
id: 1,
id: '1',
title: '',
content: '',
});
@ -67,15 +67,15 @@ describe('toQuestionListView', () => {
};
expect(toQuestionListView(rawData)).toEqual({
id: 1,
id: '1',
title: 'Question Title',
content: 'Question Answer',
products: [
{
id: 1,
id: '1',
name: 'Product Name',
type: {
id: 1,
id: '1',
name: 'Type Name',
},
},
@ -103,15 +103,15 @@ describe('toQuestionListView', () => {
};
expect(toQuestionListView(rawData)).toEqual({
id: 1,
id: '1',
title: '',
content: '',
products: [
{
id: 1,
id: '1',
name: '',
type: {
id: 1,
id: '1',
name: '',
},
},

View File

@ -13,7 +13,7 @@ export function toProductQuestionView(raw: Question): ProductQuestionView {
const trans = raw.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
title: trans?.title ?? '',
content: trans?.content ?? '',
};
@ -40,23 +40,23 @@ export function toQuestionListView(raw: Question): QuestionListView {
const product_type = isObject<ProductType>(item.product_type)
? ({
id: item.product_type.id,
id: item.product_type.id.toString(),
name: item.product_type.translations?.[0]?.name ?? '',
} satisfies QuestionListProductType)
: ({
id: -1,
id: '',
name: '',
} satisfies QuestionListProductType);
return {
id: item.id,
id: item.id.toString(),
name: translations?.name ?? '',
type: product_type,
};
});
return {
id: raw.id,
id: raw.id.toString(),
title: trans?.title ?? '',
content: trans?.content ?? '',
products: related_products,

View File

@ -20,11 +20,11 @@ describe('toSolutionListView', () => {
const rawData: Solution = { ...baseData };
expect(toSolutionListView(rawData)).toEqual({
id: 1,
id: '1',
title: 'Solution Title',
summary: 'Solution Summary',
solution_type: {
id: 1,
id: '1',
name: 'Type Name',
sort: 1,
},
@ -39,11 +39,11 @@ describe('toSolutionListView', () => {
};
expect(toSolutionListView(rawData)).toEqual({
id: 1,
id: '1',
title: '',
summary: '',
solution_type: {
id: 1,
id: '1',
name: 'Type Name',
sort: 1,
},
@ -75,7 +75,7 @@ describe('toSolutionView', () => {
};
expect(toSolutionView(rawData)).toEqual({
id: 1,
id: '1',
title: 'Solution Title',
summary: 'Solution Summary',
content: 'Solution Content',
@ -90,7 +90,7 @@ describe('toSolutionView', () => {
};
expect(toSolutionView(rawData)).toEqual({
id: 1,
id: '1',
title: '',
summary: '',
content: '',

View File

@ -15,7 +15,7 @@ export function toSolutionTypeView(raw: SolutionType): SolutionTypeView {
const trans = raw?.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
name: trans?.name ?? '',
sort: raw?.sort ?? 999,
};
@ -38,7 +38,7 @@ export function toSolutionListView(raw: Solution): SolutionListView {
const type = isObject<SolutionType>(raw.type)
? toSolutionTypeView(raw.type)
: ({
id: -1,
id: '',
name: 'uncategory',
sort: 999,
} satisfies SolutionTypeView);
@ -46,7 +46,7 @@ export function toSolutionListView(raw: Solution): SolutionListView {
const cover = isObject<DirectusFile>(raw.cover) ? (raw?.cover.id ?? '') : '';
return {
id: raw.id,
id: raw.id.toString(),
title: trans?.title ?? '',
summary: trans?.summary ?? '',
solution_type: type,
@ -69,7 +69,7 @@ export function toSolutionView(raw: Solution): SolutionView {
const trans = raw.translations?.[0];
return {
id: raw.id,
id: raw.id.toString(),
title: trans?.title ?? '',
summary: trans?.summary ?? '',
content: trans?.content ?? '',

View File

@ -3,7 +3,7 @@
*/
export interface CompanyProfileView {
/** 唯一标识符 **/
id: number;
id: string;
/** 内容 **/
content: string;

View File

@ -3,7 +3,7 @@
*/
export interface ContactInfoView {
/** 唯一标识符 **/
id: number;
id: string;
/** 内容 **/
content: string;

View File

@ -3,7 +3,7 @@
* 用于在文档库中提供产品筛选功能
*/
export interface DocumentListProductType {
id: number;
id: string;
name: string;
}
@ -12,7 +12,7 @@ export interface DocumentListProductType {
* 用于在文档库中提供产品筛选功能
*/
export interface DocumentListProduct {
id: number;
id: string;
name: string;
type: DocumentListProductType;
}
@ -23,7 +23,7 @@ export interface DocumentListProduct {
*/
export interface DocumentListView {
/** 唯一标识符 **/
id: number;
id: string;
/** 文件UUID **/
fileId: string;

View File

@ -3,7 +3,7 @@
*/
export interface HomepageProductView {
/** 唯一标识符 **/
id: number;
id: string;
/** 产品名称 **/
name: string;
@ -20,7 +20,7 @@ export interface HomepageProductView {
*/
export interface HomepageSolutionView {
/** 唯一标识符 **/
id: number;
id: string;
/** 解决方案标题 **/
title: string;
@ -37,7 +37,7 @@ export interface HomepageSolutionView {
*/
export interface HomepageView {
/** 唯一标识符 **/
id: number;
id: string;
/** 首页图片 **/
carousel: string[];

View File

@ -4,7 +4,7 @@
*/
export interface ProductDocumentView {
/** 唯一标识符 **/
id: number;
id: string;
/** 文件UUID **/
fileId: string;

View File

@ -4,7 +4,7 @@
*/
export interface ProductTypeView {
/** 唯一标识符 **/
id: number;
id: string;
/** 类型名 **/
name: string;
@ -19,7 +19,7 @@ export interface ProductTypeView {
*/
export interface ProductListView {
/** 唯一标识符 **/
id: number;
id: string;
/** 产品名称 **/
name: string;

View File

@ -4,7 +4,7 @@
*/
export interface ProductQuestionView {
/** 唯一标识符 **/
id: number;
id: string;
/** 问题标题 **/
title: string;

View File

@ -4,7 +4,7 @@
*/
export interface ProductSpecView {
/** 唯一标识符 **/
id: number;
id: string;
/** 规格名称 **/
key: string;
@ -19,7 +19,7 @@ export interface ProductSpecView {
*/
export interface ProductSpecGroupView {
/** 唯一标识符 **/
id: number;
id: string;
/** 规格组名称 **/
name: string;

View File

@ -3,7 +3,7 @@ import type { ProductQuestionView } from './product-question-view';
import type { ProductDocumentView } from './product-document-view';
interface ImageView {
id: number;
id: string;
image: string;
caption: string;
}
@ -14,7 +14,7 @@ interface ImageView {
*/
export interface ProductView {
/** 唯一标识符 **/
id: number;
id: string;
/** 产品名称 **/
name: string;

View File

@ -3,7 +3,7 @@
* 用于在常见问题列表中提供产品筛选功能
*/
export interface QuestionListProductType {
id: number;
id: string;
name: string;
}
@ -12,7 +12,7 @@ export interface QuestionListProductType {
* 用于在常见问题列表中提供产品筛选功能
*/
export interface QuestionListProduct {
id: number;
id: string;
name: string;
type: QuestionListProductType;
}
@ -23,7 +23,7 @@ export interface QuestionListProduct {
*/
export interface QuestionListView {
/** 唯一标识符 **/
id: number;
id: string;
/** 问题标题 **/
title: string;

View File

@ -4,7 +4,7 @@
*/
export interface SolutionTypeView {
/** 唯一标识符 **/
id: number;
id: string;
/** 类型名 **/
name: string;
@ -19,7 +19,7 @@ export interface SolutionTypeView {
*/
export interface SolutionListView {
/** 唯一标识符 **/
id: number;
id: string;
/** 标题 **/
title: string;

View File

@ -4,7 +4,7 @@
*/
export interface SolutionView {
/** 唯一标识符 **/
id: number;
id: string;
/** 标题 **/
title: string;