feat(material): 管理端 /api/mtrl/pub|self 接入 ypt 排序与分组

This commit is contained in:
zty 2026-07-10 02:53:48 -04:00
parent d065ec21fa
commit 8f6002b8bb
1 changed files with 29 additions and 8 deletions

View File

@ -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)
}
)