refactor: 重构项目的数据获取方法 #72

Manually merged
remilia merged 13 commits from refactor/graphql into master 2025-11-11 17:07:41 +08:00
14 changed files with 278 additions and 146 deletions
Showing only changes of commit 691dd34127 - Show all commits

View File

@ -1,4 +1,5 @@
import { readItem } from '@directus/sdk';
import GetProduct from '@/graphql/product.graphql';
import { print } from 'graphql';
export const useProduct = (id: string) => {
const { $directus } = useNuxtApp();
@ -7,104 +8,111 @@ export const useProduct = (id: string) => {
const locale = getDirectusLocale();
return useAsyncData(`product-${id}-${locale}`, async () => {
return await $directus.request(
readItem('products', id, {
fields: [
'id',
{ translations: ['id', 'name', 'summary', 'description'] },
{
images: [
'id',
{
product_images_id: [
'id',
'image',
{ translations: ['id', 'caption'] },
],
},
],
},
{
specs: [
'id',
{
translations: ['*'],
},
{
specs: [
'id',
{
translations: ['id', 'key', 'value'],
},
],
},
],
},
{
faqs: [
'id',
{
questions_id: [
'id',
{
translations: ['id', 'title', 'content'],
},
],
},
],
},
{
documents: [
'id',
{
product_documents_id: [
'id',
{
file: ['id', 'filesize', 'filename_download'],
},
{
translations: ['id', 'title'],
},
],
},
],
},
],
deep: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
images: {
product_images_id: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
},
},
faqs: {
questions_id: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
},
},
documents: {
documents_id: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
},
},
},
})
return await $directus.query<{ products_by_id: Product }>(
print(GetProduct),
{
id: id,
locale: locale,
}
);
// return await $directus.request(
// readItem('products', id, {
// fields: [
// 'id',
// { translations: ['id', 'name', 'summary', 'description'] },
// {
// images: [
// 'id',
// {
// product_images_id: [
// 'id',
// 'image',
// { translations: ['id', 'caption'] },
// ],
// },
// ],
// },
// {
// specs: [
// 'id',
// {
// translations: ['*'],
// },
// {
// specs: [
// 'id',
// {
// translations: ['id', 'key', 'value'],
// },
// ],
// },
// ],
// },
// {
// faqs: [
// 'id',
// {
// questions_id: [
// 'id',
// {
// translations: ['id', 'title', 'content'],
// },
// ],
// },
// ],
// },
// {
// documents: [
// 'id',
// {
// product_documents_id: [
// 'id',
// {
// file: ['id', 'filesize', 'filename_download'],
// },
// {
// translations: ['id', 'title'],
// },
// ],
// },
// ],
// },
// ],
// deep: {
// translations: {
// _filter: {
// languages_code: { _eq: locale },
// },
// },
// images: {
// product_images_id: {
// translations: {
// _filter: {
// languages_code: { _eq: locale },
// },
// },
// },
// },
// faqs: {
// questions_id: {
// translations: {
// _filter: {
// languages_code: { _eq: locale },
// },
// },
// },
// },
// documents: {
// documents_id: {
// translations: {
// _filter: {
// languages_code: { _eq: locale },
// },
// },
// },
// },
// },
// })
// );
});
};

View File

@ -1,4 +1,5 @@
import { readItems } from '@directus/sdk';
import GetProductList from '@/graphql/productList.graphql';
import { print } from 'graphql';
export const useProductList = () => {
const { $directus } = useNuxtApp();
@ -7,37 +8,11 @@ export const useProductList = () => {
const locale = getDirectusLocale();
return useAsyncData(`product-list-${locale}`, async () => {
return await $directus.request(
readItems('products', {
fields: [
'id',
{ translations: ['id', 'name', 'summary'] },
'cover',
{
product_type: [
'id',
{
translations: ['id', 'name'],
},
'sort',
],
},
],
deep: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
product_type: {
translations: {
_filter: {
languages_code: { _eq: locale },
},
},
},
},
})
return await $directus.query<{ products: Product[] }>(
print(GetProductList),
{
locale: locale,
}
);
});
};

View File

@ -0,0 +1,66 @@
query GetProduct($id: ID!, $locale: String!) {
products_by_id(id: $id) {
id
status
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
name
summary
description
}
images {
id
product_images_id {
id
image {
id
}
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
caption
}
}
}
specs {
id
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
name
}
specs {
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
key
value
}
}
}
faqs {
id
questions_id {
id
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
title
content
}
}
}
documents {
id
product_documents_id {
id
file {
id
filesize
filename_download
}
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
title
}
}
}
}
}

View File

@ -0,0 +1,22 @@
query GetProductList($locale: String!) {
products(filter: { status: { _eq: "in-production" } }) {
id
status
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
name
summary
}
cover {
id
}
product_type {
id
translations(filter: { languages_code: { code: { _eq: $locale } } }) {
id
name
}
sort
}
}
}

View File

@ -10,7 +10,9 @@ describe('toProductListView', () => {
translations: [
{ id: 10, name: 'Product Name', summary: 'Product Summary' },
],
cover: 'cover-file-uuid-1234',
cover: {
id: 'cover-file-uuid-1234',
},
product_type: {
id: 1,
translations: [{ id: 20, name: 'Type Name' }],
@ -35,7 +37,9 @@ describe('toProductListView', () => {
const rawData: Product = {
id: 1,
translations: [],
cover: 'cover-file-uuid-1234',
cover: {
id: 'cover-file-uuid-1234',
},
product_type: {
id: 20,
translations: [],

View File

@ -33,12 +33,14 @@ export function toProductListView(raw: Product): ProductListView {
? toProductTypeView(raw.product_type)
: undefined;
const cover = isObject<DirectusFile>(raw.cover) ? raw.cover.id : '';
return {
id: raw.id,
product_type: type,
name: trans.name,
summary: trans.summary,
cover: raw.cover.toString(),
cover: cover,
};
}
@ -110,9 +112,10 @@ export function toProductView(raw: Product): ProductView {
.map((item) => item.product_images_id)
.filter(isObject<ProductImage>)
.map((item) => {
const image = isObject<DirectusFile>(item.image) ? item.image.id : '';
return {
id: item.id,
image: item.image.toString(),
image: image,
caption: item.translations?.[0]?.caption || '',
};
});

View File

@ -35,11 +35,12 @@
const localePath = useLocalePath();
//
const id = computed(() => route.params.slug as string);
const id = route.params.slug as string;
const { data, pending, error } = await useProduct(id.value);
const { data, pending, error } = await useProduct(id);
const rawProduct = computed(() => data.value.products_by_id ?? null);
const rawProduct = computed(() => data.value ?? null);
const product = computed(() => {
if (rawProduct.value === null) {
return null;
@ -60,10 +61,10 @@
});
// SEO
usePageSeo({
title: product.value.name || $t('page-title.products'),
description: product.value.summary || '',
});
// usePageSeo({
// title: product.value.name || $t('page-title.products'),
// description: product.value.summary || '',
// });
</script>
<style scoped>

View File

@ -37,7 +37,7 @@
const localePath = useLocalePath();
const { getImageUrl } = useDirectusImage();
const { data, pending, error } = useProductList();
const { data, pending, error } = await useProductList();
const activeNames = ref<string[]>([]);
@ -46,12 +46,13 @@
{ label: $t('navigation.products') },
];
const productsRaw = computed(() => data.value ?? []);
const productsRaw = computed(() => data.value.products ?? []);
const products = computed(() =>
productsRaw.value.map((item) => toProductListView(item))
);
logger.debug('products: ', products.value);
logger.debug('产品列表数据: ', products.value);
// 按类型分组
const groupedProducts = computed(() => {