123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- <template>
- <div class="data-parse-wrapper" style="position: relative" ref="wrapperRef">
- <div class="full-screen-btn">
- <!-- fullScreen -->
- <el-icon v-if="!isFullScreen" @click="toggleFullScreen" :title="$t('message.device.fullScreen')"><FullScreen /></el-icon>
- <!-- exitFullScreen -->
- <el-icon v-else @click="toggleFullScreen" :title="$t('message.device.exitFullScreen')"><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="script || emptyFunction"></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="$t('message.device.tip1')"
- ></el-input>
- <!-- 此处显示执行结果 -->
- <el-input class="input" v-model="outputData" type="textarea" readonly :placeholder="$t('message.device.tip2')"></el-input>
- </div>
- </div>
- <!-- 保存脚本 -->
- <el-button type="primary" style="margin-top: 20px" v-auth="'save'" @click="saveCode">{{ $t('message.device.tip3') }}</el-button>
- <!-- 调试 -->
- <el-button type="primary" style="margin-top: 20px" v-auth="'debug'" :loading="runing" @click="mock">{{ $t('message.device.tip4') }}</el-button>
- </div>
- </template>
- <script lang="ts" setup>
- import { onMounted, ref, onUnmounted, computed } 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 { FullScreen, Close } from '@element-plus/icons-vue'
- import { useI18n } from 'vue-i18n'
- const { t } = useI18n()
- // tip5: "下面是预制的空的方法,请不要修改函数名称,直接在内部编写函数即可",
- // tip6: "此处是设备功能调用应答数据解析",
- // tip7: "此处编写对数据的处理",
- // tip8: "此处是设备功能调用发送数据解析",
- // tip9: "此处编写对数据的处理",
- // tip10: "请先输入可执行脚本",
- const emptyFunction = computed(() =>
- `
- // ${t('message.device.tip5')}
- // ${t('message.device.tip6')}
- function parse (data) {
- // ${t('message.device.tip7')}
- return data
- }
- // ${t('message.device.tip8')}
- function send (data) {
- // ${t('message.device.tip9')}
- return data
- }
- `
- );
- const route = useRoute()
- const emit = defineEmits(['updateScript'])
- defineProps({
- script: String,
- })
- const inputData = ref('')
- const outputData = ref('')
- const functionName = ref('parse')
- const runing = ref(false)
- const mirrorRef = ref()
- const isFullScreen = ref(false)
- const wrapperRef = ref()
- onMounted(() => {
- // 添加全屏变化事件监听
- 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()
- if (funStr === '') {
- return toSave(funStr)
- }
- await validate()
- toSave(funStr)
- }
- function toSave(data: string) {
- api.product
- .script({
- key: route.params.id,
- scriptInfo: data,
- })
- .then(() => {
- ElMessage.success(t('message.tableI18nConfirm.saveSuccess'))
- emit('updateScript', data)
- })
- }
- function validate() {
- return new Promise((resolve, reject) => {
- const funStr = mirrorRef.value.getValue()
- const worker = new Worker('/worker.js')
- // 向 Worker 发送消息
- worker.postMessage({ type: 'validateFunctionString', functionString: funStr })
- // 监听 Worker 返回的消息
- worker.addEventListener('message', ({ data }) => {
- worker.terminate()
- if (data.isOk) return resolve(true)
- ElMessage.error(data.message)
- reject()
- })
- })
- }
- async function mock() {
- outputData.value = ''
- await validate()
- // 请输入参数
- if (!inputData.value) return ElMessage.error(t('message.device.formI18nPlaceholder.inputParameter'))
- const funStr = mirrorRef.value.getValue()
- if (funStr === '') {
- // 请先输入可执行脚本
- return ElMessage.error(t('message.device.tip10'))
- }
- // 远程调试
- 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
- })
- // 本地调试
- // const worker = new Worker('./worker.js');
- // // 向 Worker 发送消息
- // worker.postMessage({ type: 'runFunction', functionString: funStr, functionName: functionName.value, params: inputData.value });
- // // 监听 Worker 返回的消息
- // worker.addEventListener('message', ({ data }) => {
- // worker.terminate()
- // if (data.isOk) {
- // return outputData.value = typeof data.data === 'object' ? JSON.stringify(data.data, null, 2) : data.data
- // }
- // ElMessage.error(data.message)
- // });
- }
- </script>
- <style scoped lang="scss">
- .flex {
- display: flex;
- }
- .flex1 {
- flex: 1;
- }
- .mock {
- .input {
- margin-top: 20px;
- height: calc(50vh - 200px);
- }
- &.hidden {
- display: none;
- }
- }
- .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;
- }
- .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>
|