Initialize backendized SurClaw report system
- Add React/Vite frontend for login, dashboard, reports, templates, users, settings, AI, speech, and media workflows. - Add NestJS/Prisma/PostgreSQL backend with auth, dashboard stats, reports, templates, users, departments, settings, files, AI, speech, audit logs, and HTML sanitization. - Add Prisma schema, migrations, seed data, persistent app sessions, Docker/Nginx deployment files, and upload volume configuration. - Add Vitest, Playwright, backend integration tests, and project documentation for requirements, design, permissions, API contracts, testing, deployment, security, and progress. - Configure production local fallback switch and remove unused Gemini direct dependency/env wiring.
This commit is contained in:
153
server/prisma/seed.ts
Normal file
153
server/prisma/seed.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
import argon2 from 'argon2';
|
||||
|
||||
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 defaultTemplateContent = `
|
||||
<h1 style="text-align:center;">手术记录</h1>
|
||||
<p>患者姓名:<span class="field-value" data-bind="patientName" contenteditable="true"></span></p>
|
||||
<p>住院号:<span class="field-value" data-bind="hospitalId" contenteditable="true"></span></p>
|
||||
<p>手术名称:<span class="field-value" data-bind="title" contenteditable="true"></span></p>
|
||||
<div class="ai-region" data-ai-id="手术步骤" data-ai-title="手术步骤">
|
||||
<div class="ai-content"><p>请在此处填写手术步骤。</p></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
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: 'tpl_default_surgery' },
|
||||
update: {},
|
||||
create: {
|
||||
id: 'tpl_default_surgery',
|
||||
tenantId: tenant.id,
|
||||
name: '腹腔镜胆囊切除术报告',
|
||||
description: '标准手术记录模板',
|
||||
content: defaultTemplateContent,
|
||||
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,
|
||||
},
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user