add turtle
Some checks failed
Deploy / build-and-deploy (push) Has been cancelled

This commit is contained in:
2025-09-16 17:37:43 +08:00
parent d9bcb81109
commit 4b59d1cf17
9 changed files with 277 additions and 176 deletions

View File

@@ -5,6 +5,7 @@ import { code } from "../composables/code"
const LANGS = [
["python", "Python"],
["turtle", "海龟绘图"],
["c", "C 语言"],
["cpp", "C++"],
]
@@ -35,6 +36,6 @@ const languages: SelectOption[] = LANGS.map((it) => ({
</template>
<style scoped>
.select {
width: 120px;
width: 125px;
}
</style>

View File

@@ -18,6 +18,7 @@ const cache: Cache = {
python: useStorage("code_python", sources["python"]),
c: useStorage("code_c", sources["c"]),
cpp: useStorage("code_cpp", sources["cpp"]),
turtle: useStorage("code_turtle", sources["turtle"]),
},
}
@@ -29,6 +30,7 @@ export const input = ref("")
export const output = ref("")
export const status = ref(Status.NotStarted)
export const loading = ref(false)
export const turtleRunId = ref(0)
export const size = ref(0)
export const debug = ref(false)
@@ -100,15 +102,22 @@ export function reset() {
export async function run() {
loading.value = true
const cleanCode = code.value.trim()
if (!cleanCode) return
output.value = ""
status.value = Status.NotStarted
const result = await submit(
{ value: cleanCode, language: code.language },
input.value.trim(),
)
output.value = result.output || ""
status.value = result.status
if (!cleanCode) {
loading.value = false
return
}
if (code.language === "turtle") {
turtleRunId.value++
} else {
output.value = ""
status.value = Status.NotStarted
const result = await submit(
{ value: cleanCode, language: code.language },
input.value.trim(),
)
output.value = result.output || ""
status.value = result.status
}
loading.value = false
}

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import copyTextToClipboard from "copy-text-to-clipboard"
import { useMessage } from "naive-ui"
import { computed } from "vue"
import { computed, watch, useTemplateRef } from "vue"
// @ts-ignore
import * as Sk from "skulpt"
import CodeEditor from "../components/CodeEditor.vue"
import { analyse, analyzeError, showAnalyse } from "../composables/analyse"
import {
@@ -13,6 +15,7 @@ import {
reset,
size,
status,
turtleRunId,
} from "../composables/code"
import { Status } from "../types"
@@ -26,6 +29,42 @@ function copy() {
function handleDebug() {
debug.value = true
}
const turtleCanvas = useTemplateRef("turtle")
function builtinRead(x: any) {
if (
Sk.builtinFiles === undefined ||
Sk.builtinFiles["files"][x] === undefined
)
throw "文件没有找到:'" + x + "'"
return Sk.builtinFiles["files"][x]
}
function runSkulptTurtle() {
const canvas = turtleCanvas.value
if (!canvas) return
canvas.innerHTML = ""
Sk.configure({
output: console.log,
read: builtinRead,
inputfun: function () {
return input.value
},
__future__: Sk.python3,
})
Sk.TurtleGraphics = {
target: canvas,
}
Sk.misceval
.asyncToPromise(function () {
return Sk.importMainWithBody("<stdin>", false, code.value, true)
})
.catch((err: any) => {
output.value += String(err)
})
}
watch(turtleRunId, () => runSkulptTurtle())
</script>
<template>
@@ -82,6 +121,7 @@ function handleDebug() {
</template>
<template #2>
<CodeEditor
v-if="code.language !== 'turtle'"
icon="streamline-emojis:hibiscus"
label="输出框"
v-model="output"
@@ -115,6 +155,7 @@ function handleDebug() {
</n-popover>
</template>
</CodeEditor>
<div v-else ref="turtle" class="canvas"></div>
</template>
</n-split>
</template>
@@ -126,4 +167,9 @@ function handleDebug() {
.container {
height: calc(100vh - 60px);
}
.canvas {
width: 100%;
height: 100%;
}
</style>

View File

@@ -21,7 +21,7 @@
import qs from "query-string"
import { onMounted, ref, useTemplateRef } from "vue"
import { code, debug } from "../composables/code"
import { useDark } from "@vueuse/core";
import { useDark } from "@vueuse/core"
const src = ref("")
const loading = ref(true)
@@ -29,7 +29,6 @@ const main = useTemplateRef("main")
const isDark = useDark()
onMounted(() => {
// const url = "http://localhost:8000"
const url = import.meta.env.PUBLIC_PYVIZ_URL
const base = url + "/iframe-embed.html"

View File

@@ -6,6 +6,17 @@ const pythonSource = ""
const javaSource =
"public class Main {\r\n public static void main(String[] args) {\r\n \r\n }\r\n}"
const turtleSource = `import turtle
t = turtle.Turtle()
t.speed(1)
for i in range(4):
t.forward(100)
t.left(90)
turtle.done()`
export const languageToId = {
c: 50,
cpp: 54,
@@ -18,4 +29,5 @@ export const sources = {
cpp: cppSource,
java: javaSource,
python: pythonSource,
turtle: turtleSource,
}

View File

@@ -1,6 +1,6 @@
import { RemovableRef } from "@vueuse/core"
export type LANGUAGE = "c" | "python" | "cpp"
export type LANGUAGE = "c" | "python" | "cpp" | "turtle"
export interface Code {
value: string