Files
Mdeical_Sur_Report/server/prisma/seed.ts
admin 911b96b883 Add demo mode factory reset
- Align the backend seeded default surgery template with the report editor's default report content.

- Add backend demo defaults for the default template, Kimi provider, and Xunfei speech proxy configuration.

- Change system reset into a super-admin demo mode factory reset that clears reports, audit logs, files, custom templates, and non-default users.

- Keep only the default admin, manager, doctor, and default surgery template after demo reset.

- Replace the old local-only reset all data button with a two-confirmation backend reset flow.

- Add tests covering demo default alignment and database-backed demo reset behavior.

- Update docs to describe demo mode reset semantics and production credential cautions.
2026-05-02 02:52:30 +08:00

176 lines
4.3 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import argon2 from 'argon2';
import {
DEMO_DEFAULT_REPORT_CONTENT,
DEMO_SYSTEM_SETTINGS,
DEMO_TEMPLATE_ID,
} from '../src/demo/demo-defaults.js';
if (!process.env.DATABASE_URL) {
throw new Error('DATABASE_URL is required to seed the database');
}
const prisma = new PrismaClient({
adapter: new PrismaPg({
connectionString: process.env.DATABASE_URL,
}),
});
const main = async () => {
const tenant = await prisma.tenant.upsert({
where: { code: 'default' },
update: {},
create: {
code: 'default',
name: '默认医院',
},
});
const adminDepartment = await prisma.department.upsert({
where: { tenantId_code: { tenantId: tenant.id, code: 'admin' } },
update: {},
create: {
tenantId: tenant.id,
code: 'admin',
name: '管理部门',
},
});
const surgeryDepartment = await prisma.department.upsert({
where: { tenantId_code: { tenantId: tenant.id, code: 'surgery' } },
update: {},
create: {
tenantId: tenant.id,
code: 'surgery',
name: '外科',
},
});
const passwordHash = await argon2.hash('123456');
const adminUser = await prisma.user.upsert({
where: { tenantId_username: { tenantId: tenant.id, username: 'admin' } },
update: {},
create: {
tenantId: tenant.id,
departmentId: adminDepartment.id,
username: 'admin',
passwordHash,
role: 'SUPER',
name: '超级管理员',
},
});
await prisma.user.upsert({
where: { tenantId_username: { tenantId: tenant.id, username: 'manager' } },
update: {},
create: {
tenantId: tenant.id,
departmentId: surgeryDepartment.id,
username: 'manager',
passwordHash,
role: 'ADMIN',
name: '科室管理员',
},
});
await prisma.user.upsert({
where: { tenantId_username: { tenantId: tenant.id, username: '0001' } },
update: {},
create: {
tenantId: tenant.id,
departmentId: surgeryDepartment.id,
username: '0001',
passwordHash,
role: 'DOCTOR',
name: '张医生',
},
});
const defaultTemplate = await prisma.template.upsert({
where: { id: DEMO_TEMPLATE_ID },
update: {
name: '腹腔镜胆囊切除术报告',
description: '标准手术记录模板',
content: DEMO_DEFAULT_REPORT_CONTENT,
fields: [],
scope: 'DEPARTMENT',
ownerDepartmentId: surgeryDepartment.id,
ownerUserId: null,
},
create: {
id: DEMO_TEMPLATE_ID,
tenantId: tenant.id,
name: '腹腔镜胆囊切除术报告',
description: '标准手术记录模板',
content: DEMO_DEFAULT_REPORT_CONTENT,
fields: [],
scope: 'DEPARTMENT',
ownerDepartmentId: surgeryDepartment.id,
ownerUserId: null,
},
});
await prisma.templateDepartmentPermission.upsert({
where: {
templateId_departmentId: {
templateId: defaultTemplate.id,
departmentId: surgeryDepartment.id,
},
},
update: {
canUse: true,
canManage: true,
},
create: {
templateId: defaultTemplate.id,
departmentId: surgeryDepartment.id,
canUse: true,
canManage: true,
},
});
const existingSystemSettings = await prisma.systemSetting.findFirst({
where: { tenantId: tenant.id, scope: 'global', departmentId: null, key: 'systemSettings' },
});
if (existingSystemSettings) {
await prisma.systemSetting.update({
where: { id: existingSystemSettings.id },
data: { value: DEMO_SYSTEM_SETTINGS },
});
} else {
await prisma.systemSetting.create({
data: {
tenantId: tenant.id,
scope: 'global',
key: 'systemSettings',
value: DEMO_SYSTEM_SETTINGS,
},
});
}
await prisma.auditLog.create({
data: {
tenantId: tenant.id,
actorUserId: adminUser.id,
actorRole: 'super',
action: 'seed.default_template',
targetType: 'template',
targetId: defaultTemplate.id,
departmentId: surgeryDepartment.id,
metadata: { name: defaultTemplate.name },
},
}).catch(() => {});
};
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (error) => {
console.error(error);
await prisma.$disconnect();
process.exit(1);
});