From 59f6956b50469e9982639d0a1eb9eda14d1eec08 Mon Sep 17 00:00:00 2001 From: cocos02 Date: Sun, 14 Jun 2026 20:38:12 +0800 Subject: [PATCH] chore: editor store, graph, and vite config updates --- editor/App.vue | 2 +- editor/composables/useGraphEditor.ts | 1 + editor/stores/editorStore.ts | 21 ++++++++++++++++++++- vite.config.ts | 27 +++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/editor/App.vue b/editor/App.vue index 8c7abbc..018066b 100644 --- a/editor/App.vue +++ b/editor/App.vue @@ -49,7 +49,7 @@ function importJSON() { } function testScene(id: string) { - window.open('/?scene=/scenes/demo.json&startScene=' + id, '_blank') + window.open('/?scene=' + store.sourcePath + '&startScene=' + id, '_blank') } async function onFileSelected(e: Event) { diff --git a/editor/composables/useGraphEditor.ts b/editor/composables/useGraphEditor.ts index 37ca236..d2a67a9 100644 --- a/editor/composables/useGraphEditor.ts +++ b/editor/composables/useGraphEditor.ts @@ -18,6 +18,7 @@ export function useGraphEditor() { scenes: { ...store.gameData.scenes, [source]: { ...scene, choices: newChoices } }, } store.markDirty() + store.autoSave() } return { diff --git a/editor/stores/editorStore.ts b/editor/stores/editorStore.ts index e9cd443..b4265e3 100644 --- a/editor/stores/editorStore.ts +++ b/editor/stores/editorStore.ts @@ -7,6 +7,7 @@ export const useEditorStore = defineStore('editor', () => { const selectedNodeId = ref(null) const startSceneId = ref('') const dirty = ref(false) + const sourcePath = ref('/scenes/demo.json') const selectedScene = computed(() => { if (!selectedNodeId.value) return null @@ -44,6 +45,7 @@ export const useEditorStore = defineStore('editor', () => { } triggerRef(gameData) dirty.value = true + autoSave() return id } @@ -71,6 +73,7 @@ export const useEditorStore = defineStore('editor', () => { triggerRef(gameData) dirty.value = true if (selectedNodeId.value === id) selectedNodeId.value = null + autoSave() } function updateScene(id: string, partial: Partial) { @@ -82,6 +85,7 @@ export const useEditorStore = defineStore('editor', () => { } triggerRef(gameData) dirty.value = true + autoSave() } function addChoice(sourceId: string) { @@ -96,6 +100,7 @@ export const useEditorStore = defineStore('editor', () => { } triggerRef(gameData) dirty.value = true + autoSave() } function updateChoice(sourceId: string, index: number, partial: Partial) { @@ -108,6 +113,7 @@ export const useEditorStore = defineStore('editor', () => { } triggerRef(gameData) dirty.value = true + autoSave() } function deleteChoice(sourceId: string, index: number) { @@ -124,9 +130,22 @@ export const useEditorStore = defineStore('editor', () => { dirty.value = true } + function setSourcePath(p: string) { sourcePath.value = p } + + async function autoSave() { + try { + await fetch('/api/save', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ path: sourcePath.value, data: gameData.value }), + }) + } catch { /* dev server not running */ } + } + return { - gameData, selectedNodeId, selectedScene, startSceneId, dirty, + gameData, selectedNodeId, selectedScene, startSceneId, dirty, sourcePath, markDirty, loadJSON, exportJSON, addScene, deleteScene, updateScene, addChoice, updateChoice, deleteChoice, generateId, + setSourcePath, autoSave, } }) diff --git a/vite.config.ts b/vite.config.ts index 820aa25..c595336 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' +import fs from 'fs' export default defineConfig({ plugins: [vue()], @@ -18,4 +19,30 @@ export default defineConfig({ }, }, }, + server: { + configureServer(server) { + server.middlewares.use('/api/save', (req, res) => { + if (req.method !== 'POST') { res.writeHead(405); res.end(); return } + let body = '' + req.on('data', (c: string) => body += c) + req.on('end', () => { + try { + const { path, data } = JSON.parse(body) + if (!path || typeof path !== 'string' || !path.startsWith('/scenes/')) { + res.writeHead(400) + res.end(JSON.stringify({ error: 'invalid path' })) + return + } + const safePath = resolve(__dirname, 'public', '.' + path) + fs.writeFileSync(safePath, JSON.stringify(data, null, 2)) + res.writeHead(200, { 'Content-Type': 'application/json' }) + res.end(JSON.stringify({ ok: true })) + } catch (e: any) { + res.writeHead(400) + res.end(JSON.stringify({ error: e.message })) + } + }) + }) + }, + }, })