|
@@ -1,25 +1,37 @@
|
|
|
<template>
|
|
|
- <div class="flex" style="align-items: stretch;">
|
|
|
- <codeEditor class="params flex1" ref="mirrorRef" style="height: calc(100vh - 340px)" mode="javascript" :content="content"></codeEditor>
|
|
|
- <div class="mock" style="width: 300px;margin-left: 20px;">
|
|
|
- <el-radio-group v-model="functionName">
|
|
|
- <el-radio-button label="parse">parse</el-radio-button>
|
|
|
- <el-radio-button label="send">send</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- <el-input class="input" v-model="inputData" type="textarea" placeholder="请输入入参,以字符串的方式,如果是对象字符串会在执行时自动转换为对象再执行"></el-input>
|
|
|
- <el-input class="input" v-model="outputData" type="textarea" readonly placeholder="此处显示执行结果"></el-input>
|
|
|
+ <div class="data-parse-wrapper" style="position: relative" ref="wrapperRef">
|
|
|
+ <div class="full-screen-btn">
|
|
|
+ <el-icon v-if="!isFullScreen" @click="toggleFullScreen" title="全屏"><FullScreen /></el-icon>
|
|
|
+ <el-icon v-else @click="toggleFullScreen" title="退出全屏"><Close /></el-icon>
|
|
|
</div>
|
|
|
+ <div class="flex" style="align-items: stretch">
|
|
|
+ <codeEditor class="params flex1" ref="mirrorRef" style="height: calc(100vh - 310px)" mode="javascript" :content="content"></codeEditor>
|
|
|
+ <div class="mock" style="width: 300px; margin-left: 20px">
|
|
|
+ <el-radio-group v-model="functionName">
|
|
|
+ <el-radio-button label="parse">parse</el-radio-button>
|
|
|
+ <el-radio-button label="send">send</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ <el-input
|
|
|
+ class="input"
|
|
|
+ v-model="inputData"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="请输入入参,以字符串的方式,如果是对象字符串会在执行时自动转换为对象再执行"
|
|
|
+ ></el-input>
|
|
|
+ <el-input class="input" v-model="outputData" type="textarea" readonly placeholder="此处显示执行结果"></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button type="primary" style="margin-top: 20px" v-auth="'save'" @click="saveCode">保存脚本</el-button>
|
|
|
+ <el-button type="primary" style="margin-top: 20px" v-auth="'debug'" :loading="runing" @click="mock">调试</el-button>
|
|
|
</div>
|
|
|
- <el-button type="primary" style="margin-top:20px" v-auth="'save'" @click="saveCode">保存脚本</el-button>
|
|
|
- <el-button type="primary" style="margin-top:20px" v-auth="'debug'" :loading="runing" @click="mock">调试</el-button>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { onMounted, ref } from 'vue';
|
|
|
+import { onMounted, ref, onUnmounted } from 'vue'
|
|
|
import codeEditor from '/@/components/codeEditor/index.vue'
|
|
|
-import { ElMessage } from 'element-plus';
|
|
|
-import api from '/@/api/device';
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import api from '/@/api/device'
|
|
|
+import { useRoute } from 'vue-router'
|
|
|
+import { FullScreen, Close } from '@element-plus/icons-vue'
|
|
|
|
|
|
const emptyFunction = `
|
|
|
// 下面是预制的空的方法,请不要修改函数名称,直接在内部编写函数即可
|
|
@@ -42,12 +54,12 @@ function send (data) {
|
|
|
}
|
|
|
`
|
|
|
|
|
|
-const route = useRoute();
|
|
|
+const route = useRoute()
|
|
|
|
|
|
const emit = defineEmits(['updateScript'])
|
|
|
|
|
|
const props = defineProps({
|
|
|
- script: String
|
|
|
+ script: String,
|
|
|
})
|
|
|
|
|
|
const inputData = ref('')
|
|
@@ -56,11 +68,71 @@ const content = ref('')
|
|
|
const functionName = ref('parse')
|
|
|
const runing = ref(false)
|
|
|
const mirrorRef = ref()
|
|
|
+const isFullScreen = ref(false)
|
|
|
+const wrapperRef = ref(null)
|
|
|
|
|
|
onMounted(() => {
|
|
|
content.value = props.script! || emptyFunction
|
|
|
+
|
|
|
+ // 添加全屏变化事件监听
|
|
|
+ document.addEventListener('fullscreenchange', handleFullscreenChange)
|
|
|
+ document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
|
|
|
+ document.addEventListener('mozfullscreenchange', handleFullscreenChange)
|
|
|
+ document.addEventListener('MSFullscreenChange', handleFullscreenChange)
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ document.removeEventListener('fullscreenchange', handleFullscreenChange)
|
|
|
+ document.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
|
|
|
+ document.removeEventListener('mozfullscreenchange', handleFullscreenChange)
|
|
|
+ document.removeEventListener('MSFullscreenChange', handleFullscreenChange)
|
|
|
})
|
|
|
|
|
|
+// 切换全屏状态
|
|
|
+const toggleFullScreen = () => {
|
|
|
+ if (!isFullScreen.value) {
|
|
|
+ // 进入全屏
|
|
|
+ const element = wrapperRef.value as HTMLElement
|
|
|
+ if (element) {
|
|
|
+ if (element.requestFullscreen) {
|
|
|
+ element.requestFullscreen()
|
|
|
+ } else if ((element as any).webkitRequestFullscreen) {
|
|
|
+ // Safari
|
|
|
+ ;(element as any).webkitRequestFullscreen()
|
|
|
+ } else if ((element as any).msRequestFullscreen) {
|
|
|
+ // IE11
|
|
|
+ ;(element as any).msRequestFullscreen()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 退出全屏
|
|
|
+ if (document.exitFullscreen) {
|
|
|
+ document.exitFullscreen()
|
|
|
+ } else if ((document as any).webkitExitFullscreen) {
|
|
|
+ // Safari
|
|
|
+ ;(document as any).webkitExitFullscreen()
|
|
|
+ } else if ((document as any).msExitFullscreen) {
|
|
|
+ // IE11
|
|
|
+ ;(document as any).msExitFullscreen()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ isFullScreen.value = !isFullScreen.value
|
|
|
+}
|
|
|
+
|
|
|
+// 处理全屏状态变化
|
|
|
+const handleFullscreenChange = () => {
|
|
|
+ const isDocFullscreen =
|
|
|
+ document.fullscreenElement ||
|
|
|
+ (document as any).webkitFullscreenElement ||
|
|
|
+ (document as any).mozFullScreenElement ||
|
|
|
+ (document as any).msFullscreenElement
|
|
|
+
|
|
|
+ // 如果文档不在全屏状态,但我们的状态是全屏,则更新状态
|
|
|
+ if (!isDocFullscreen && isFullScreen.value) {
|
|
|
+ isFullScreen.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
async function saveCode() {
|
|
|
const funStr = mirrorRef.value.getValue()
|
|
|
|
|
@@ -74,23 +146,24 @@ async function saveCode() {
|
|
|
}
|
|
|
|
|
|
function toSave(data: string) {
|
|
|
- api.product.script({
|
|
|
- key: route.params.id,
|
|
|
- scriptInfo: data
|
|
|
- }).then(() => {
|
|
|
- ElMessage.success('保存成功')
|
|
|
- emit('updateScript', data)
|
|
|
- })
|
|
|
+ api.product
|
|
|
+ .script({
|
|
|
+ key: route.params.id,
|
|
|
+ scriptInfo: data,
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success('保存成功')
|
|
|
+ emit('updateScript', data)
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
function validate() {
|
|
|
-
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const funStr = mirrorRef.value.getValue()
|
|
|
- const worker = new Worker('/worker.js');
|
|
|
+ const worker = new Worker('/worker.js')
|
|
|
|
|
|
// 向 Worker 发送消息
|
|
|
- worker.postMessage({ type: 'validateFunctionString', functionString: funStr });
|
|
|
+ worker.postMessage({ type: 'validateFunctionString', functionString: funStr })
|
|
|
|
|
|
// 监听 Worker 返回的消息
|
|
|
worker.addEventListener('message', ({ data }) => {
|
|
@@ -98,7 +171,7 @@ function validate() {
|
|
|
if (data.isOk) return resolve(true)
|
|
|
ElMessage.error(data.message)
|
|
|
reject()
|
|
|
- });
|
|
|
+ })
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -117,16 +190,19 @@ async function mock() {
|
|
|
|
|
|
// 远程调试
|
|
|
runing.value = true
|
|
|
- api.product.scriptRun({
|
|
|
- functionName: functionName.value,
|
|
|
- scriptInfo: funStr,
|
|
|
- jsonData: inputData.value,
|
|
|
- }).then((res: any) => {
|
|
|
- // outputData.value = typeof res.data === 'object' ? JSON.stringify(res.data, null, 2) : res.data
|
|
|
- outputData.value = res.data
|
|
|
- }).finally(() => {
|
|
|
- runing.value = false
|
|
|
- })
|
|
|
+ api.product
|
|
|
+ .scriptRun({
|
|
|
+ functionName: functionName.value,
|
|
|
+ scriptInfo: funStr,
|
|
|
+ jsonData: inputData.value,
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ // outputData.value = typeof res.data === 'object' ? JSON.stringify(res.data, null, 2) : res.data
|
|
|
+ outputData.value = res.data
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ runing.value = false
|
|
|
+ })
|
|
|
|
|
|
// 本地调试
|
|
|
// const worker = new Worker('./worker.js');
|
|
@@ -143,17 +219,88 @@ async function mock() {
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
-:deep(.CodeMirror) {
|
|
|
- height: calc(100vh - 340px);
|
|
|
+<style scoped lang="scss">
|
|
|
+.flex {
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+.flex1 {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+.mock {
|
|
|
+ .input {
|
|
|
+ margin-top: 20px;
|
|
|
+ height: calc(50vh - 200px);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.hidden {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.input,
|
|
|
-.output {
|
|
|
- margin-top: 14px;
|
|
|
+.full-screen-btn {
|
|
|
+ position: absolute;
|
|
|
+ top: 2px;
|
|
|
+ right: 2px; /* 考虑到右侧 mock 区域的宽度 */
|
|
|
+ z-index: 100;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 4px;
|
|
|
+ background-color: rgba(255, 255, 255, 0.9);
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #f2f6fc;
|
|
|
+ }
|
|
|
|
|
|
- :deep(.el-textarea__inner) {
|
|
|
- height: calc(50vh - 200px);
|
|
|
+ .el-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #409eff;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+}
|
|
|
+.is-fullscreen {
|
|
|
+ position: fixed !important;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 9999;
|
|
|
+ height: 100vh !important;
|
|
|
+ width: 100vw;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+.data-parse-wrapper {
|
|
|
+ &:fullscreen {
|
|
|
+ padding: 20px;
|
|
|
+ background-color: white;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ .full-screen-btn {
|
|
|
+ right: 20px;
|
|
|
+ top: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mock {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-full-screen {
|
|
|
+ padding: 20px;
|
|
|
+ background-color: white;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ .full-screen-btn {
|
|
|
+ right: 20px;
|
|
|
+ top: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mock {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|