From 8f6002b8bb442fb070df50b566e8046a19e530a1 Mon Sep 17 00:00:00 2001 From: zty Date: Fri, 10 Jul 2026 02:53:48 -0400 Subject: [PATCH] =?UTF-8?q?feat(material):=20=E7=AE=A1=E7=90=86=E7=AB=AF?= =?UTF-8?q?=20/api/mtrl/pub|self=20=E6=8E=A5=E5=85=A5=20ypt=20=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E4=B8=8E=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iapip-svr/src/controllers/material.ts | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/空气质量预测/源码/服务端/iapip-svr/src/controllers/material.ts b/空气质量预测/源码/服务端/iapip-svr/src/controllers/material.ts index 4b63bb3..b701441 100644 --- a/空气质量预测/源码/服务端/iapip-svr/src/controllers/material.ts +++ b/空气质量预测/源码/服务端/iapip-svr/src/controllers/material.ts @@ -1049,12 +1049,12 @@ materialRouter.get( sort_key: { anyOf: [ { - enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at'] + enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at', 'ypt'] }, { type: 'array', items: { - enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at'] + enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at', 'ypt'] } } ] @@ -1079,6 +1079,10 @@ materialRouter.get( size: { type: 'number', minimum: 1 + }, + group_by_tier: { + type: 'number', + enum: [0, 1] } }, additionalProperties: false @@ -1086,7 +1090,8 @@ materialRouter.get( }, { coerceTypes: true }), async ctx => { const acctCert = ctx.state.acct_cert as AcctCert - const { collected, with_cltrs, ...query } = ctx.state.query + // group_by_tier 不是 Prisma 列,需从传给 dynSearch 的 query 中剔除,否则 findMany 报未知字段 + const { collected, with_cltrs, group_by_tier, ...query } = ctx.state.query const conditions: AnyObj = { ...dynSearch(query, { fuzzyFields: ['material_id', 'name', 'category', 'brand', 'factory', 'spec', 'creator_name'], @@ -1112,8 +1117,12 @@ materialRouter.get( } } } + delete conditions.take; delete conditions.skip if (!query.sort_key) { conditions.orderBy = [{ sort_order: 'asc' }, { updated_at: 'desc' }] + } else if (query.sort_key === 'ypt') { + // ypt 是内存计算字段,非 Prisma 列,不能下推为 orderBy + delete conditions.orderBy } if (!isNone(collected) && !acctCert.is_admin) { if (!conditions.where) { @@ -1136,7 +1145,8 @@ materialRouter.get( mtrl.collectors = [] }) } - ctx.body = materials + const classify = await loadTierClassifier() + ctx.body = rankAndPaginate(materials, { ...query, group_by_tier }, classify) } ) @@ -1802,12 +1812,12 @@ materialRouter.get( sort_key: { anyOf: [ { - enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'creator_name', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at'] + enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'creator_name', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at', 'ypt'] }, { type: 'array', items: { - enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'creator_name', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at'] + enum: ['name', 'category', 'brand', 'factory', 'spec', 'eco_level', 'health_level', 'sort_order', 'creator_name', 'methanal_be_area', 'tvoc_be_area', 'benzene_be_area', 'toluene_be_area', 'p_xylene_be_area', 'created_at', 'updated_at', 'ypt'] } } ] @@ -1832,6 +1842,10 @@ materialRouter.get( size: { type: 'number', minimum: 1 + }, + group_by_tier: { + type: 'number', + enum: [0, 1] } }, additionalProperties: false @@ -1839,7 +1853,8 @@ materialRouter.get( }, { coerceTypes: true }), async ctx => { const acctCert = ctx.state.acct_cert as AcctCert - const query = ctx.state.query + // group_by_tier 不是 Prisma 列,需从传给 dynSearch 的 query 中剔除,否则 findMany 报未知字段 + const { group_by_tier, ...query } = ctx.state.query if (!acctCert.is_admin) { query.creator_id = acctCert.id } @@ -1857,10 +1872,16 @@ materialRouter.get( } } } + delete conditions.take; delete conditions.skip if (!query.sort_key) { conditions.orderBy = [{ sort_order: 'asc' }, { updated_at: 'desc' }] + } else if (query.sort_key === 'ypt') { + // ypt 是内存计算字段,非 Prisma 列,不能下推为 orderBy + delete conditions.orderBy } - ctx.body = await db.selfMaterial.findMany(conditions as never) + const selfMaterials = await db.selfMaterial.findMany(conditions as never) + const classify = await loadTierClassifier() + ctx.body = rankAndPaginate(selfMaterials, { ...query, group_by_tier }, classify) } )