import { dirname, join } from 'node:path'; import { mkdir, writeFile } from 'node:fs/promises'; import type { ProjectType } from '../../shared/project-config'; import vitePackageJson from './project-templates/vite/package.json'; import vitePackageLock from './project-templates/vite/package-lock.json'; const VITE_CONFIG = `import { defineConfig } from 'vite'; export default defineConfig({ base: './', }); `; const MINI_GAME_FILES: Record = { 'index.html': ` Makelore 小游戏 `, 'game.json': `${JSON.stringify({ deviceOrientation: 'portrait', showStatusBar: false }, null, 2)}\n`, 'game.js': `const canvas = document.querySelector('#game'); const context = canvas.getContext('2d'); function render() { const ratio = window.devicePixelRatio || 1; const width = window.innerWidth; const height = window.innerHeight; canvas.width = Math.round(width * ratio); canvas.height = Math.round(height * ratio); context.setTransform(ratio, 0, 0, ratio, 0, 0); const gradient = context.createLinearGradient(0, 0, 0, height); gradient.addColorStop(0, '#10233d'); gradient.addColorStop(1, '#3a5578'); context.fillStyle = gradient; context.fillRect(0, 0, width, height); context.textAlign = 'center'; context.fillStyle = '#ffffff'; context.font = '700 28px system-ui, sans-serif'; context.fillText('Makelore 小游戏', width / 2, height / 2 - 10); context.fillStyle = '#f6b45f'; context.font = '16px system-ui, sans-serif'; context.fillText('点击画布,开始创造', width / 2, height / 2 + 26); } canvas.addEventListener('pointerdown', (event) => { context.beginPath(); context.fillStyle = '#f26a3d'; context.arc(event.clientX, event.clientY, 18, 0, Math.PI * 2); context.fill(); }); window.addEventListener('resize', render); render(); `, }; const MINI_PROGRAM_FILES: Record = { 'index.html': ` Makelore 小程序
`, 'app.json': `${JSON.stringify({ pages: ['pages/index/index'], window: { navigationBarTitleText: 'Makelore 小程序' } }, null, 2)}\n`, 'app.js': `export const app = { globalData: { platform: 'makelore', }, }; `, 'pages/index/index.json': `${JSON.stringify({ navigationBarTitleText: '首页' }, null, 2)}\n`, 'pages/index/index.css': `:root { color: #24364b; background: #f4f7fb; font-family: system-ui, sans-serif; } body { margin: 0; } .page { min-height: 100vh; display: grid; place-items: center; padding: 24px; } .card { width: min(420px, 100%); border: 1px solid #d8e1ec; border-radius: 20px; background: #fff; padding: 28px; text-align: center; box-shadow: 0 16px 48px rgb(36 54 75 / 10%); } button { border: 0; border-radius: 12px; background: #3a5578; color: #fff; padding: 12px 18px; font: inherit; font-weight: 700; cursor: pointer; } `, 'pages/index/index.js': `import { app } from '../../app.js'; import './index.css'; const root = document.querySelector('#app'); let count = 0; root.innerHTML = \`

运行于 \${app.globalData.platform}

Makelore 小程序

已点击 0 次

\`; root.querySelector('button').addEventListener('click', () => { count += 1; root.querySelector('#count').textContent = \`已点击 \${count} 次\`; }); `, }; function serializeJson(value: unknown): string { return `${JSON.stringify(value, null, 2)}\n`; } export async function createPublishableProjectTemplate( projectPath: string, projectType: Exclude, ): Promise { const files = projectType === 'mini_game' ? MINI_GAME_FILES : MINI_PROGRAM_FILES; const templateFiles: Record = { 'package.json': serializeJson(vitePackageJson), 'package-lock.json': serializeJson(vitePackageLock), 'vite.config.js': VITE_CONFIG, ...files, }; for (const [relativePath, content] of Object.entries(templateFiles)) { const filePath = join(projectPath, relativePath); await mkdir(dirname(filePath), { recursive: true }); await writeFile(filePath, content, { encoding: 'utf8', flag: 'wx' }); } }