airpredict/apps/api/prisma/seed.ts

148 lines
7.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcryptjs';
const prisma = new PrismaClient();
// 五项污染物默认散发参数生成器(占位值;真实数据由实验室检测导入)
function ep(y0: number) {
return {
hcho: { y0, yp: y0 * 1.5, b: 0.01 },
tvoc: { y0: y0 * 0.6, yp: y0 * 0.9, b: 0.01 },
benzene: { y0: y0 * 0.05, yp: y0 * 0.08, b: 0.005 },
toluene: { y0: y0 * 0.1, yp: y0 * 0.15, b: 0.005 },
xylene: { y0: y0 * 0.08, yp: y0 * 0.12, b: 0.005 },
};
}
// 取自原系统公共材料库前若干条(散发参数为占位)
const MATERIALS = [
{ id: 'PM13000003', name: '胶合板', category: '人造板/胶合板', brand: '东营正和', manufacturer: '东营正和', spec: '2.7SE', envGrade: 'E1', y0: 0.06 },
{ id: 'PM13000004', name: '胶合板', category: '人造板/胶合板', brand: '东营正和', manufacturer: '东营正和', spec: '3N-3mm', envGrade: 'E0', y0: 0.03 },
{ id: 'PM13000005', name: '胶合板', category: '人造板/胶合板', brand: '金秋', manufacturer: '河北金秋木业有限责任公司', spec: '8mm', envGrade: null, y0: 0.05 },
{ id: 'PM13000006', name: '胶合板', category: '人造板/胶合板', brand: '金秋', manufacturer: '河北金秋木业有限责任公司', spec: '12mm', envGrade: null, y0: 0.05 },
{ id: 'PM13000007', name: '胶合板', category: '人造板/胶合板', brand: '金秋', manufacturer: '河北金秋木业有限责任公司', spec: '15mm', envGrade: null, y0: 0.055 },
{ id: 'PM13000008', name: '胶合板', category: '人造板/胶合板', brand: '金秋', manufacturer: '河北金秋木业有限责任公司', spec: '18mm', envGrade: null, y0: 0.06 },
{ id: 'PM13000009', name: '阻燃胶合板', category: '人造板/阻燃胶合板', brand: '兔宝宝', manufacturer: '德华兔宝宝装饰新材股份有限公司', spec: null, envGrade: null, y0: 0.045 },
{ id: 'PM13000010', name: '阻燃板', category: '人造板/胶合板', brand: '福益安', manufacturer: '北京江夏木业有限公司', spec: null, envGrade: 'E1', y0: 0.05 },
{ id: 'PM13000011', name: '阻燃板', category: '人造板/阻燃胶合板', brand: '莫干山', manufacturer: '浙江升华云峰新材股份有限公司', spec: 'E1', envGrade: 'E1', y0: 0.05 },
{ id: 'PM13000012', name: '非醛多层基材胶合板', category: '人造板/胶合板', brand: '升达', manufacturer: '四川升达林产业股份有限公司', spec: null, envGrade: null, y0: 0.02 },
];
async function main() {
const passwordHash = await bcrypt.hash('CBMA123456', 10);
const org = await prisma.organization.upsert({
where: { username: 'YPJKKJ' },
update: {},
create: { username: 'YPJKKJ', name: '一品健康空间', passwordHash },
});
console.log('组织已就绪:', org.username, org.name);
for (let i = 0; i < MATERIALS.length; i++) {
const m = MATERIALS[i];
const healthGrade = ['A', 'B', 'C'][i % 3]; // 示例健康等级
const sortOrder = (i + 1) * 10; // 预留竞价排名(越小越靠前)
await prisma.material.upsert({
where: { id: m.id },
update: { healthGrade, sortOrder }, // 回填已存在的材料
create: {
id: m.id,
name: m.name,
category: m.category,
brand: m.brand,
manufacturer: m.manufacturer,
spec: m.spec ?? undefined,
envGrade: m.envGrade ?? undefined,
healthGrade,
sortOrder,
usageUnit: 'm²',
emissionParams: ep(m.y0),
isPublic: true,
},
});
}
console.log(`已导入 ${MATERIALS.length} 条公共材料(散发参数为占位值,待替换真实检测数据)`);
// 官方算例 6 种材料(真实 Y0/Yp/B5 污染物),供 C 端样板间 + 复现算例
const ep5 = (
hcho: number[], tvoc: number[], benzene: number[], toluene: number[], xylene: number[],
) => ({
hcho: { y0: hcho[0], yp: hcho[1], b: hcho[2] },
tvoc: { y0: tvoc[0], yp: tvoc[1], b: tvoc[2] },
benzene: { y0: benzene[0], yp: benzene[1], b: benzene[2] },
toluene: { y0: toluene[0], yp: toluene[1], b: toluene[2] },
xylene: { y0: xylene[0], yp: xylene[1], b: xylene[2] },
});
const REAL_MATERIALS = [
{ id: 'PM20000001', name: '多层实木复合地板', category: '木地板/实木地板', brand: '示例', healthGrade: 'B', ep: ep5([0.09, 0.4, 0.47], [0.074, 0.7, 0.205], [0.03, 0.186, 0.265], [0, 0, 0], [0, 0, 0]) },
{ id: 'PM20000002', name: '踢脚线', category: '其他', brand: '示例', healthGrade: 'C', ep: ep5([0.38, 2.3, 0.2], [0.25, 1.69, 0.113], [0.053, 0.446, 0.09], [0.05, 0.229, 0.1], [0.009, 0.35, 0.085]) },
{ id: 'PM20000003', name: '吸音板', category: '其他', brand: '示例', healthGrade: 'B', ep: ep5([0, 0, 0], [0.24, 1.71, 0.09], [0, 0, 0], [0, 0, 0], [0, 0, 0]) },
{ id: 'PM20000004', name: '乳胶漆涂料', category: '涂料/墙面漆', brand: '示例', healthGrade: 'A', ep: ep5([0, 0, 0], [0.04, 0.337, 0.288], [0, 0, 0], [0, 0, 0], [0, 0, 0]) },
{ id: 'PM20000005', name: '免漆木门', category: '其他', brand: '示例', healthGrade: 'C', ep: ep5([0, 0, 0], [0.46, 3.05, 0.132], [0.07, 0.53, 0.27], [0.05, 0.41, 0.29], [0.194, 1.24, 0.223]) },
{ id: 'PM20000006', name: '人造板家具', category: '家具', brand: '示例', healthGrade: 'C', ep: ep5([0.45, 2.63, 0.446], [0.14, 0.88, 0.36], [0, 0, 0], [0.08, 0.5, 0.39], [0, 0, 0]) },
];
for (let i = 0; i < REAL_MATERIALS.length; i++) {
const m = REAL_MATERIALS[i];
await prisma.material.upsert({
where: { id: m.id },
update: { emissionParams: m.ep, healthGrade: m.healthGrade },
create: {
id: m.id, name: m.name, category: m.category, brand: m.brand,
healthGrade: m.healthGrade, sortOrder: 1000 + i, usageUnit: 'm²',
emissionParams: m.ep, isPublic: true,
},
});
}
console.log(`已导入 ${REAL_MATERIALS.length} 条官方算例真实材料(PM2000000x)`);
// 一条公共项目模板(含 1 个空间 + 2 种材料),供模板库展示
const tplId = 'T13000001';
await prisma.project.upsert({
where: { id: tplId },
update: {},
create: {
id: tplId,
name: '标准住宅卧室模板',
type: '住宅',
province: '北京市',
city: '北京市',
area: 90,
isTemplate: true,
isPublic: true,
ownerOrgId: org.id,
status: 'report_generated',
rating: 'A',
spaces: {
create: [
{
id: 'TS13000001',
name: '主卧',
type: '卧室',
layout: 'uniform',
height: 2.8,
area: 15,
volume: 42,
temperature: 25,
humidity: 50,
ventilationRate: 0.5,
standard: 'GB50325-2020',
materials: {
create: [
{ materialId: 'PM13000004', usageUnit: 'm²', usageAmount: 30 },
{ materialId: 'PM13000012', usageUnit: 'm²', usageAmount: 20 },
],
},
},
],
},
},
});
console.log('已导入 1 条公共项目模板');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());