ConverScript.vue 6.28 KB
<template>
  <div>
    <a-form
      ref="formRef"
      :model="scriptForm"
      name="basic"
      :label-col="{ span: 4 }"
      :wrapper-col="{ span: 16 }"
      autocomplete="off"
    >
      <a-form-item
        :label="ifAdd ? '名称' : '输入参数(params)'"
        :name="ifAdd ? 'name' : 'params'"
        :rules="[{ required: true, message: ifAdd ? '请输入脚本名称' : '请输入参数' }]"
      >
        <a-input v-if="ifAdd" v-model:value="scriptForm.name" placeholder="请输入脚本名称" />
        <a-input v-else v-model:value="scriptForm.params" placeholder="请输入参数" />
      </a-form-item>
      <a-form-item
        label="上报数据类型"
        name="dataType"
        :rules="[{ required: true, message: '请选择上报数据类型' }]"
      >
        <a-space direction="vertical">
          <a-radio-group v-model:value="scriptForm.dataType" :options="typeOptions" />
        </a-space>
      </a-form-item>
      <a-form-item label="脚本内容" :name="ifAdd ? 'convertJs' : 'script'">
        <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }">
          <template #extra>
            <a-button @click="handleFormat" size="small">格式化</a-button>
            <Tooltip :title="defaultTitle" class="ml-2">
              <QuestionCircleOutlined style="font-size: 1rem" />
            </Tooltip>
          </template>
          <div ref="aceRef" class="overflow-hidden"></div>
        </Card>
        <Button @click="handleCopy" class="mt-4">
          <template #icon>
            <CopyOutlined />
          </template>
          copy
        </Button>
      </a-form-item>
      <a-form-item
        :label="ifAdd ? '备注' : '输出参数(output)'"
        :name="ifAdd ? 'description' : 'output'"
      >
        <a-textarea
          :rows="3"
          v-if="ifAdd"
          v-model:value="scriptForm.description"
          placeholder="请输入备注"
        />
        <a-textarea
          :rows="3"
          v-else
          v-model:value="scriptForm.output"
          placeholder="输出参数为服务端返回的内容"
        />
      </a-form-item>
    </a-form>
  </div>
</template>
<script setup lang="ts">
  import { ref, unref, reactive, onMounted, toRefs } from 'vue';
  import ace from 'ace-builds';
  import { Card, Button, Tooltip } from 'ant-design-vue';
  import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
  import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式
  import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js';
  import { CopyOutlined } from '@ant-design/icons-vue';
  import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { findDictItemByCode } from '/@/api/system/dict';
  import { QuestionCircleOutlined } from '@ant-design/icons-vue';
  import { defaultTitle, defaultScriptContent } from './config.data';

  defineEmits(['register']);
  const props = defineProps({
    ifAdd: { type: Boolean, default: true },
  });
  const scriptForm = reactive({
    name: '',
    description: '',
    convertJs: '',
    script: '',
    params: '',
    output: '',
    dataType: 'HEX',
  });
  const reportTypeOptions = reactive({
    typeOptions: [],
  });
  const { typeOptions } = toRefs(reportTypeOptions);
  const { createMessage } = useMessage();
  const { clipboardRef, copiedRef } = useCopyToClipboard();
  const aceEditor = ref();
  const aceRef = ref();
  onMounted(async () => {
    const res: any = await findDictItemByCode({
      dictCode: 'report_data_type',
    });
    reportTypeOptions.typeOptions = res.map((m) => {
      return { label: m.itemText, value: m.itemValue };
    });
    scriptForm.dataType = 'HEX';
  });
  // 初始化编辑器
  const initEditor = (jsScript?: string) => {
    aceEditor.value = ace.edit(aceRef.value, {
      maxLines: 12, // 最大行数,超过会自动出现滚动条
      minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
      fontSize: 14, // 编辑器内字体大小
      theme: 'ace/theme/chrome', // 默认设置的主题
      mode: 'ace/mode/javascript', // 默认设置的语言模式
      tabSize: 2, // 制表符设置为 4 个空格大小
    });

    aceEditor.value.setOptions({
      enableBasicAutocompletion: true,
      enableLiveAutocompletion: true,
    });
    aceEditor.value.setValue(jsScript ?? defaultScriptContent);
    beautify(aceEditor.value.session);
    scriptForm.convertJs = aceEditor.value.getValue();
  };
  const handleCopy = () => {
    const valueRef = aceEditor.value.getValue();
    const value = unref(valueRef);
    if (!value) {
      createMessage.warning('请输入要拷贝的内容!');
      return;
    }
    clipboardRef.value = value;
    if (unref(copiedRef)) {
      createMessage.success('复制成功!');
    }
  };
  const formRef = ref();
  const getFormData = async () => {
    const value = await formRef.value.validateFields();
    if (props.ifAdd) {
      scriptForm.convertJs = aceEditor.value.getValue();
      if (scriptForm.convertJs == '') {
        createMessage.error('请编写脚本内容');
        throw '请编写脚本内容';
      }
    } else {
      scriptForm.script = aceEditor.value.getValue();
      if (scriptForm.script == '') {
        createMessage.error('请编写脚本内容');
        throw '请编写脚本内容';
      }
    }
    if (!value) return;
    return {
      ...value,
      ...{ convertJs: props.ifAdd ? scriptForm.convertJs : null },
      ...{ script: !props.ifAdd ? scriptForm.script : null },
    };
  };
  const setFormData = (v) => {
    for (let i in scriptForm) {
      Reflect.set(scriptForm, i, v[i]);
    }
    aceEditor.value.setValue(v.convertJs);
    handleFormat();
  };
  const setScriptContentData = (v) => {
    aceEditor.value.setValue(v);
    handleFormat();
  };
  const resetFormData = () => {
    for (let i in scriptForm) {
      Reflect.set(scriptForm, i, '');
    }
  };
  const setScriptOutputData = (v) => {
    scriptForm.output = v;
  };
  const handleFormat = () => beautify(aceEditor.value.session);

  defineExpose({
    initEditor,
    getFormData,
    resetFormData,
    setFormData,
    setScriptContentData,
    setScriptOutputData,
  });
</script>
<style lang="less" scoped>
  @import url('./ConverScriptModal.less');
</style>