())
+ /** 图片编号 → 网址(blob:)。运行器每张图只发一次,控件属性里只带编号 */
+ const images = shallowReactive(new Map())
let socket: WebSocket | undefined
/** 正在建立或已建立的连接;同时多处调用 connect() 时共用同一个 */
let connecting: Promise | undefined
@@ -76,7 +86,10 @@ export function createRunSession() {
state.errors = []
state.forms = []
state.messageBoxes = []
+ state.savedImages = []
nodes.clear()
+ for (const url of images.values()) URL.revokeObjectURL(url)
+ images.clear()
send({ type: 'run', files })
}
@@ -173,6 +186,14 @@ export function createRunSession() {
case 'messageBox':
state.messageBoxes.push(message)
break
+ case 'image': {
+ const bytes = Uint8Array.from(atob(message.data), (c) => c.charCodeAt(0))
+ images.set(message.key, URL.createObjectURL(new Blob([bytes], { type: message.mime })))
+ break
+ }
+ case 'imageSaved':
+ state.savedImages.push({ path: message.path, image: message.image })
+ break
case 'board':
state.board = message.state
break
@@ -197,7 +218,7 @@ export function createRunSession() {
socket?.close()
}
- return { state, connect, run, stop, act, replyMessageBox, setBoard, resetBoard, close }
+ return { state, images, connect, run, stop, act, replyMessageBox, setBoard, resetBoard, close }
}
export type RunSession = ReturnType
diff --git a/web/src/scene/TrainingBoard.vue b/web/src/scene/TrainingBoard.vue
index 26c8521..37c5cb7 100644
--- a/web/src/scene/TrainingBoard.vue
+++ b/web/src/scene/TrainingBoard.vue
@@ -77,6 +77,10 @@ const relays = computed(() => props.board?.relays ?? [])
const streetLampOn = computed(() => props.board?.zigbee[1] === true)
const alarmOn = computed(() => relays.value[0] === true)
const ledText = computed(() => props.board?.ledText ?? '')
+const camera = computed(() => props.board?.camera ?? { on: false, x: 3, y: 1 })
+const cameraTitle = computed(() =>
+ camera.value.on ? `网络摄像头:正在传送画面(云台左右 ${camera.value.x + 1}/7,上下 ${camera.value.y + 1}/3)` : '网络摄像头(项目 4 使用):未开启',
+)
@@ -121,7 +125,7 @@ const ledText = computed(() => props.board?.ledText ?? '')
警示灯
-
+
+
+ > = Symbol('runImages')
+
+/** 控件 Image 属性的值(见 runtime/Sim.WinForms/Host/PropValue.cs) */
+export interface ImageValue {
+ key: string
+ width: number
+ height: number
+}
diff --git a/web/src/winforms/winforms.css b/web/src/winforms/winforms.css
index b6dab36..a16b2ac 100644
--- a/web/src/winforms/winforms.css
+++ b/web/src/winforms/winforms.css
@@ -151,6 +151,26 @@
color: #fff;
}
+.wf-picturebox {
+ overflow: hidden;
+}
+
+.wf-picturebox img {
+ position: absolute;
+ left: 0;
+ top: 0;
+ display: block;
+ user-select: none;
+}
+
+.wf-picturebox-border-FixedSingle {
+ border: 1px solid #646464;
+}
+
+.wf-picturebox-border-Fixed3D {
+ border: 2px inset #a0a0a0;
+}
+
.wf-listbox {
overflow-y: auto;
overflow-x: hidden;