diff --git a/src/App.vue b/src/App.vue index 6518085..594e46b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -16,7 +16,7 @@ const worldRef = ref(null) const showAI = ref(true) const state = reactive({ - scale: 1, + scale: 0.8, minScale: 0.2, maxScale: 3, translateX: 0, @@ -128,7 +128,8 @@ function onCanvasDrop(e: DragEvent) { const props: Record = {} ; (item.propertySchemas || []).forEach((p) => { props[p.key] = p.default }) const inst: Instance = { id: String(++idSeq), key: item.key, url: item.url, x: x, y: y, size: defSize, rotation: 0, props } - if (item.stateImages) inst.state = 'off' + // 仍保留 state 字段用于灯泡等展示,但对于开关用 props.state 作为真值 + if (item.stateImages) inst.state = String(props['state'] ?? 'off') as any instances.push(inst) } @@ -447,7 +448,7 @@ function buildNet(): BuiltNet { const n1 = getNode(inst, 1) const key = meta.key - if (key === 'battery') { + if (key === 'battery') { const V = safeNum(inst.props?.['voltage'], 0) const Rint = safeNum(inst.props?.['internalResistance'], 0.1) // 用内部节点将电压源与内阻串联:n0 --[V]--> nInt --[Rint]--> n1 @@ -464,7 +465,8 @@ function buildNet(): BuiltNet { vsrcs.push({ inst, nPlus: n0, nMinus: nInt, V }) resistors.push({ inst, nPlus: nInt, nMinus: n1, R: Math.max(1e-9, Rint) }) } else if (key === 'switch') { - if (inst.state === 'on') { + const sw = (inst.props?.['state'] as any) === 'on' || inst.state === 'on' + if (sw) { vsrcs.push({ inst, nPlus: n0, nMinus: n1, V: 0 }) } // off = open, 忽略 @@ -820,6 +822,13 @@ function loadFromJSONText(text: string) { rotation: safeNumber(r.rotation, 0), props: rawProps, state: r.state === 'on' || r.state === 'off' ? r.state : undefined, + } + // 兼容老文件:若为开关且 props.state 缺失,则使用 legacy state 或默认 off + if (inst.key === 'switch') { + const cur = String((inst.props as any)['state'] ?? '') + if (cur !== 'on' && cur !== 'off') { + (inst.props as any)['state'] = (inst.state === 'on' ? 'on' : 'off') + } } // 暂存连接信息在实例对象上(不入 props)以便后续重建导线 ; (inst as any).__savedConnections = savedConnections @@ -951,10 +960,10 @@ function deleteSelected() { -
@@ -980,19 +989,32 @@ function deleteSelected() {
+ @contextmenu.prevent="() => { + const meta = elements.find(e => e.key === inst.key); + if (!meta?.stateImages) return; + if (inst.key === 'switch') { + const cur = String(inst.props['state'] ?? 'off'); + inst.props['state'] = cur === 'on' ? 'off' : 'on' + } else { + inst.state = inst.state === 'on' ? 'off' : 'on' + } + }" /> pin + }" @pointerdown.stop="() => { sliderDraggingId = inst.id }" />
@@ -1083,8 +1105,13 @@ function deleteSelected() { {{ schema.label }} - - {{ schema.unit }} + + + {{ (schema as any).unit }}
@@ -1105,6 +1132,8 @@ function deleteSelected() { /* 左栏 / 画布 / AI 辅助 */ grid-template-rows: 100vh; overflow: hidden; + touch-action: none; + user-select: none; } .sidebar { diff --git a/src/elements.ts b/src/elements.ts index 24f9036..4e9c893 100644 --- a/src/elements.ts +++ b/src/elements.ts @@ -35,13 +35,27 @@ export type CircuitElement = { pinUrl?: string } -export type PropertySchema = { - key: string - label: string - type: 'number' | 'text' - unit?: string - default: number | string -} +export type PropertySchema = + | { + key: string + label: string + type: 'number' + unit?: string + default: number + } + | { + key: string + label: string + type: 'text' + default: string + } + | { + key: string + label: string + type: 'select' + options: Array<{ label?: string; value: string }> | string[] + default: string + } // 预设定义:展示名称 + 要覆盖的属性值 export type Preset = { @@ -85,11 +99,13 @@ export const elements: CircuitElement[] = [ defaultSize: 130, connectionPoints: [ { x: 0.05, y: 0.7, name: 'A' }, - { x: 0.83, y: 0.7, name: 'B' }, + { x: 0.95, y: 0.7, name: 'B' }, ], // 点击元件切换 on/off 显示 stateImages: { on: switchOn, off: switchOff }, - // 开关没有额外可编辑属性 + propertySchemas: [ + { key: 'state', label: '状态', type: 'select', options: ['off', 'on'], default: 'off' }, + ], }, { key: 'light_bulb', diff --git a/vite.config.ts b/vite.config.ts index bbcf80c..e85f074 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,4 +4,7 @@ import vue from '@vitejs/plugin-vue' // https://vite.dev/config/ export default defineConfig({ plugins: [vue()], + server:{ + host: '0.0.0.0' + } })