vue elementUI Plus实现拖拽流程图,不引入插件,纯手写实现。

news2025/1/4 20:21:10

vue elementUI Plus实现拖拽流程图,不引入插件,纯手写实现。

    • 1.设计思路:
    • 2.设计细节
    • 3.详细代码实现

1.设计思路:

左侧button列表是要拖拽的组件。中间是拖拽后的流程图。右侧是拖拽后的数据列表。

我们拖动左侧组件放入中间的流程图中,并把button携带的数据信息带过来。

在这里插入图片描述

2.设计细节

左侧button组件列表可拖动并携带信息,当拖动到中间流程图上方时,流程图网格变色。当鼠标释放后,数据传递,流程图变化。

拖拽事件流程和参数
‌dragstart‌:当元素开始被拖拽时触发。
‌drag‌:元素正在被拖拽时持续触发(某些浏览器支持)。
‌dragend‌:当拖拽结束时触发。
‌dragenter‌:当拖拽的元素进入目标元素时触发。
‌dragover‌:当拖拽的元素在目标元素上移动时持续触发。
‌dragleave‌:当拖拽的元素离开目标元素时触发。
‌drop‌:当拖拽的元素在目标元素上释放时触发。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.详细代码实现

<template>
  <div class="scriptDraweAdd">
    <drawer-Box
      :drawerVisible="drawer.visible"
      :drawerFooter="drawer.drawerFooter"
      :direction="drawer.direction"
      :drawerSize="drawer.drawerSize"
      :drawerTitle="drawer.drawerTitle"
      @handleDrawerOpened="handleDrawerOpened"
      @handleDrawerClose="handleDrawerClose"
      @handleDrawerSubmit="handleDrawerSubmit"
    >
      <div class="main h100">
        <el-form ref="addFormRef" :model="editFrom" size="small" status-icon class="h100" label-width="auto">
          <el-row :gutter="0">
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20 setting-title"><span>General settings</span></el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="projectName" :rules="rules.projectName">
                    <template v-slot:label
                      ><span>Project Name </span>
                      <el-tooltip effect="dark" content="Project Name" placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>

                    <el-input v-model="editFrom.projectName" placeholder="Project Name" clearable></el-input>
                  </el-form-item>
                </el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="version" :rules="rules.version">
                    <template v-slot:label
                      ><span>Version </span>
                      <el-tooltip effect="dark" content="Software Version" placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input v-model="editFrom.version" placeholder="Software Version" clearable></el-input>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20"><span></span></el-col>
                <!-- <el-col :span="10" class="mb20">
                  <el-form-item prop="softwareName" :rules="rules.softwareName">
                    <template v-slot:label
                      ><span>Software Name </span>
                      <el-tooltip effect="dark" content="Software Name" placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input v-model="editFrom.softwareName" placeholder="Software Name" clearable></el-input>
                  </el-form-item>
                </el-col> -->
                <el-col :span="10" class="mb20">
                  <el-form-item prop="function" :rules="rules.function">
                    <template v-slot:label
                      ><span>Function </span>
                      <el-tooltip effect="dark" content="Function of the script" placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-select v-model="editFrom.function" placeholder="Function">
                      <el-option v-for="item in functionOptions" :key="item.value" :label="item.label" :value="item.value" />
                    </el-select>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20 setting-title"><span>Advanced settings</span></el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item label="" prop="maxRunTime" :rules="rules.maxRunTime">
                    <template v-slot:label
                      ><span>Max Run Time </span>
                      <el-tooltip effect="dark" content="The max run time of the script" placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input-number type="number" v-model="editFrom.maxRunTime" :min="0" :max="1000" placeholder="Max Run Time" style="width: 100%" />
                  </el-form-item>
                </el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="startStopService" :rules="rules.startStopService">
                    <template v-slot:label
                      ><span>Start Stop Service </span>
                      <el-tooltip effect="dark" content="Service(s) needed to be pause during software installation, separate with commas." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input v-model="editFrom.startStopService" placeholder="Start Stop Service" clearable></el-input>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20"><span></span></el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="debugEnable" :rules="rules.debugEnable">
                    <template v-slot:label
                      ><span>Debug Enable </span>
                      <el-tooltip effect="dark" content="Used to enable logging." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-switch v-model="editFrom.debugEnable" :active-value="true" :inactive-value="false" />
                  </el-form-item>
                </el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="defaultMsicLine" :rules="rules.defaultMsicLine">
                    <template v-slot:label
                      ><span>Default MSIC Line </span>
                      <el-tooltip effect="dark" content="Default MSI commands, used for each MSI installer." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input v-model="editFrom.defaultMsicLine" placeholder="Default MSIC Line" clearable></el-input>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20"><span></span></el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item prop="uDriveMap" :rules="rules.uDriveMap">
                    <template v-slot:label
                      ><span>U-Drive Map </span>
                      <el-tooltip effect="dark" content="If the software stored on U-Drive." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-switch v-model="editFrom.uDriveMap" :active-value="true" :inactive-value="false" />
                  </el-form-item>
                </el-col>
                <el-col :span="10" class="mb20">
                  <el-form-item label="IFS Script" prop="ifsScript" :rules="rules.ifsScript">
                    <template v-slot:label
                      ><span>IFS Script </span>
                      <el-tooltip effect="dark" content="If you need to run the script on your local computer." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-switch v-model="editFrom.ifsScript" :active-value="true" :inactive-value="false" />
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>
            <el-col>
              <el-row :gutter="10">
                <el-col :span="4" class="mb20"><span></span></el-col>
                <!-- <el-col :span="10" class="mb20">
                  <el-form-item prop="patchCommands">
                    <template v-slot:label
                      ><span>Patch Commands </span>
                      <el-tooltip effect="dark" content="Used if need to install software to alternate folder." placement="top">
                        <i>
                          <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />
                        </i>
                      </el-tooltip>
                    </template>
                    <el-input v-model="editFrom.patchCommands" placeholder="Patch Commands" disabled></el-input>
                  </el-form-item>
                </el-col> -->
                <el-col :span="10" class="mb20">
                  <el-form-item label="Remarks" prop="remarks" :rules="rules.remarks">
                    <el-input v-model="editFrom.remarks" clearable placeholder="Remarks" :rows="2" type="textarea" />
                  </el-form-item>
                </el-col>
              </el-row>
            </el-col>

            <el-col>
              <el-row :gutter="10" class="custom-row-height">
                <el-col :span="8" class="mb20">
                  <div class="searchdiv">
                    <div style="display: flex">
                      <el-input style="margin-right: 10px" v-model="searchScriptName" placeholder="Script Name" @keyup.enter="getScriptList()" clearable></el-input>
                      <el-button @click="getScriptList()" type="primary">
                        <i> <svg-icon icon-class="icon_screen" class-name="iconfont font14" /> </i
                      ></el-button>
                    </div>
                    <div class="paramslabel">
                      <el-tooltip v-for="(item, index) in scriptList" :key="index" placement="top" raw-content :content="remarkHTML(item.remarks)">
                        <el-button draggable="true" @dragstart="dragstart($event, item)" @dragend="dragend($event, item)" class="buttondiv" :title="item.scriptName" type="primary">{{
                          item.scriptName
                        }}</el-button>
                      </el-tooltip>
                    </div>
                  </div>
                </el-col>
                <el-col :span="9" class="mb20">
                  <div class="flowdiv">
                    <div class="flowlabel">
                      <div>
                        <el-button class="buttondiv" type="primary">Start</el-button>
                        <div :class="['add-contain-div', overFlag.over0 ? 'add-contain-div-active' : '']" @dragover="dragOver($event, 'over0')" @drop="drop($event, 0)">
                          <svg-icon icon-class="downward_vertical_line" class="addline" />
                          <svg-icon icon-class="icon_add" class="addicon" />
                        </div>
                      </div>

                      <div v-for="(item, index) in editFrom.scriptList" :key="index" style="padding-left: 60px">
                        <!-- <el-button v-show="true" class="buttondiv2" type="primary">{{ item.gClientScriptId }}</el-button> -->
                        <el-input style="width: 180px" v-show="false" v-model="item.gClientScriptId" placeholder="gClientScriptId" readonly></el-input>

                        <el-tooltip placement="top" raw-content :content="remarkHTML(item.remarks)">
                        <el-button class="buttondiv" type="primary">{{ item.scriptName }}</el-button>
                        </el-tooltip>
                        <el-button type="text" @click="deleteMethod(index)" class="deletebutton">
                          <svg-icon icon-class="icon_delete2" class="deleteline" />
                        </el-button>

                        <div style="padding-right: 60px" @dragover="dragOver($event, 'over' + (index + 1))" @drop="drop($event, index + 1)">
                          <div :class="['add-contain-div', overFlag['over' + (index + 1)] ? 'add-contain-div-active' : '']">
                            <svg-icon icon-class="downward_vertical_line" class="addline" />
                            <svg-icon icon-class="icon_add" class="addicon" />
                          </div>
                        </div>
                      </div>

                      <el-button class="buttondiv" type="primary">End</el-button>
                    </div>
                  </div>
                </el-col>

                <el-col :span="7" class="mb20" style="min-width:350px">
                  <div v-for="(item2, index2) in editFrom.scriptList" :key="index2 + 'params'">
                    <div class="paramsdiv">
                      <div class="params-title-parent">
                        <el-form-item
                          ><span style="margin-left: 10px; font-weight: bold">{{ item2.scriptName }}</span></el-form-item
                        >
                      </div>
                      <div class="paramsdiv-content">
                        <el-form-item label-width="auto" label="Order No."> <el-input style="width: 100%" v-model="item2.orderNum" placeholder="Order No." readonly></el-input></el-form-item>
                        <el-form-item label="CmdRCOpt" label-width="auto" :prop="`scriptList[${index2}].cmdRcopt`" :rules="[{ required: true, message: `Please input  CmdRCOpt`, trigger: 'change' }]">
                          <el-select v-model="item2.cmdRcopt" placeholder="CmdRCOpt" disabled style="width: 100%">
                            <el-option v-for="item3 in cmdRCOptOptions" :key="item3.value" :label="item3.label" :value="item3.value" />
                          </el-select>
                        </el-form-item>
                        <div v-for="(item, index) in item2.paramslist" :key="index2 + '_' + index">
                          <el-form-item v-show="false" label="Order No." label-width="140px">
                            <el-input style="width: 100%" v-model="item.index" placeholder="Order No." readonly></el-input>
                          </el-form-item>
                          <div v-if="item.dataType === 'String'" class="paramsdiv-params">
                            <el-form-item
                              :prop="`scriptList[${index2}].paramslist[${index}].value`"
                              :rules="[{ required: true, message: `Please input  ${item.name}`, trigger: 'blur' }]"
                              label-width="auto"
                            >
                              <template v-slot:label
                                ><span>{{ item.name }}</span>
                                <el-tooltip effect="dark" :content="item.remarks" placement="top">
                                  <i> <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />&nbsp;&nbsp; </i>
                                </el-tooltip>
                                <el-tag style="margin-right: 0px !important; margin-top: 3px !important" type="primary" class="mr12" effect="light" round>{{ item.dataType }}</el-tag>
                              </template>

                              <el-input style="width: 100%" v-model="item.value" :placeholder="item.name"></el-input>
                            </el-form-item>
                          </div>

                          <div v-if="item.dataType === 'Int'" class="paramsdiv-params">
                            <el-form-item
                              :prop="`scriptList[${index2}].paramslist[${index}].value`"
                              :rules="[{ required: true, message: `Please input  ${item.name}`, trigger: 'change' }]"
                              label-width="auto"
                            >
                              <template v-slot:label
                                ><span>{{ item.name }}</span>
                                <el-tooltip effect="dark" :content="item.remarks" placement="top">
                                  <i> <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />&nbsp;&nbsp; </i>
                                </el-tooltip>
                                <el-tag style="margin-right: 0px !important; margin-top: 3px !important" type="primary" class="mr12" effect="light" round>{{ item.dataType }}</el-tag>
                              </template>

                              <!-- <el-input style="width: 100%" v-model="item.value" :placeholder="item.name"></el-input> -->
                              <el-input-number type="number" v-model="item.value" :placeholder="item.name" style="width: 100%" />
                            </el-form-item>
                          </div>

                          <div v-if="item.dataType === 'Boolean'" class="paramsdiv-params">
                            <el-form-item
                              :prop="`scriptList[${index2}].paramslist[${index}].value`"
                              :rules="[{ required: true, message: `Please input  ${item.name}`, trigger: 'change' }]"
                              label-width="auto"
                            >
                              <template v-slot:label
                                ><span>{{ item.name }}</span>
                                <el-tooltip effect="dark" :content="item.remarks" placement="top">
                                  <i> <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />&nbsp;&nbsp; </i>
                                </el-tooltip>
                                <el-tag style="margin-right: 0px !important; margin-top: 3px !important" type="primary" class="mr12" effect="light" round>{{ item.dataType }}</el-tag>
                              </template>

                              <el-switch v-model="item.value" :active-value="true" :inactive-value="false" :value="false" :disabled="index === 0" />
                            </el-form-item>
                          </div>
                          <div v-if="item.dataType === 'File'" class="paramsdiv-params">
                            <el-form-item
                              :label="item.name"
                              :placeholder="item.name"
                              :prop="`scriptList[${index2}].paramslist[${index}].fileList`"
                              :rules="[{ required: true, message: `Please upload file`, validator: validator, trigger: 'change' }]"
                              label-width="auto"
                            >
                              <template v-slot:label
                                ><span>{{ item.name }}</span>
                                <el-tooltip effect="dark" :content="item.remarks" placement="top">
                                  <i> <svg-icon icon-class="icon_ notes_info" class-name="iconfont font14" />&nbsp;&nbsp; </i>
                                </el-tooltip>
                                <el-tag style="margin-right: 0px !important; margin-top: 3px !important" type="primary" class="mr12" effect="light" round>{{ item.dataType }}</el-tag>
                              </template>

                              <el-upload
                                :disabled="item.isOriginalFile === 1"
                                :action="upload.action"
                                :headers="upload.headers"
                                :limit="upload.limit"
                                multiple
                                v-model:file-list="item.fileList"
                                :on-success="(res) => handleUploadSuccess(res, item, index)"
                                :on-remove="(uploadFile, uploadFiles) => handleRemove(uploadFile, uploadFiles, item, index)"
                                :before-upload="(file) => beforeAvatarUpload(file, item, index)"
                                :on-exceed="(uploadFile, uploadFiles) => handleExceed(uploadFile, uploadFiles, item, index)"
                                :on-preview="(uploadFile) => handlePreview(uploadFile, item, index)"
                              >
                                <el-button :disabled="item.fileList && item.fileList.length > 0" type="primary">Click to upload</el-button>
                                <template #tip>
                                  <div class="el-upload__tip">.ps1, .txt files with a size less than 2M</div>
                                </template>
                              </el-upload>
                            </el-form-item>
                            <el-form-item v-show="false" label="File Name" label-width="140px">
                              <el-input style="width: 80%" v-model="item.fileName" placeholder="File Name" readonly></el-input>
                            </el-form-item>
                            <el-form-item :prop="`scriptList[${index2}].paramslist[${index}].fileContent`" label-width="140px" style="margin-top: -20px">
                              <el-input
                                v-show="false"
                                type="textarea"
                                readonly
                                style="width: 100%"
                                v-model="item.fileContent"
                                placeholder="File Content"
                                :autosize="{ minRows: 3, maxRows: 10000 }"
                              ></el-input>
                            </el-form-item>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
              </el-row>
            </el-col>
          </el-row>
        </el-form>
      </div>
    </drawer-Box>
  </div>
</template>
<script>
import { toRefs, reactive, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import DrawerBox from '../drawer/index'
import gClientApi from '@/api/gClientApi'
import gClientManagementApi from '@/api/gClientManagementApi'
import { removeProperty } from '@/utils/validate'
import { Session } from '@/utils/storage'
export default {
  name: 'GclientScriptMenagement',
  emits: ['handleSearch', 'handleClose', 'downScriptFile'],
  components: {
    DrawerBox
    // vxeTable
  },
  props: {
    drawer: {
      type: Object,
      default: () => {
        return {}
      }
    },
    GclientScriptMenagement: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  setup(props, ctx) {
    // 列表数组 接口返回的数据
    const vxeData = reactive({
      tableList: []
    })

    const addFormRef = ref(null)
    // 复选框数组
    const vxeList = reactive({
      checkList: []
    })
    const useTableHeader = reactive({})
    const state = reactive({
      upload: {
        action: process.env.VUE_APP_API_URL + '/portal/v1/GClientScript/scriptUpload',
        headers: {
          Authorization: Session.get('token')
        },
        accept: '.ps1, .txt',
        fileSize: 2,
        limit: 1
      },
      functionOptions: [
        { lable: 'Install', value: 'Install' },
        { lable: 'Uninstall', value: 'Uninstall' }
      ],
      typeOptions: [
        { label: 'String', value: 'String' },
        { label: 'Int', value: 'Int' },
        { label: 'Boolean', value: 'Boolean' },
        { label: 'File', value: 'File' }
      ],
      cmdRCOptOptions: [
        { label: 'Continue running', value: 0 },
        { label: 'Command failed,stop running', value: 1 },
        { label: 'Command failed,continue running', value: 2 }
      ],

      editFrom: {
        softwareName: '',
        version: '',
        projectName: '',
        // applicationName: '',
        patchCommands: '',
        maxRunTime: 90,
        startStopService: '',
        debugEnable: true,
        defaultMsicLine: '',
        uDriveMap: false,
        function: 'Install',
        ifsScript: false,
        remarks: '',
        scriptList: []
      },

      editFrom2: {
        softwareName: '',
        version: '',
        projectName: '',
        // applicationName: '',
        patchCommands: '',
        maxRunTime: 90,
        startStopService: '',
        debugEnable: true,
        defaultMsicLine: '',
        uDriveMap: false,
        function: 'Install',
        ifsScript: false,
        remarks: '',
        scriptList: []
      },
      scriptList: [],
      rules: {
        softwareName: [{ required: true, message: 'Please input Software Name', trigger: 'blur' }],
        version: [{ required: true, message: 'Please input Version', trigger: 'blur' }],
        projectName: [{ required: true, message: 'Please input Project Name', trigger: 'blur' }],
        // applicationName: [{ required: true, message: 'Please input Application Name', trigger: 'blur' }],
        patchCommands: [{ required: true, message: 'Please input Patch Commands', trigger: 'blur' }],
        maxRunTime: [{ required: true, message: 'Please input Max Run Time', trigger: 'blur' }],
        startStopService: [{ required: true, message: 'Please input Start Stop Service', trigger: 'blur' }],
        debugEnable: [{ required: true, message: 'Please input Debug Enable', trigger: 'blur' }],
        defaultMsicLine: [{ required: true, message: 'Please input Default MSIC Line', trigger: 'blur' }],
        uDriveMap: [{ required: true, message: 'Please input U-Drive Map', trigger: 'blur' }],
        function: [{ required: true, message: 'Please input Function', trigger: 'blur' }],
        ifsScript: [{ required: true, message: 'Please input IFS Script', trigger: 'blur' }]
      },
      paramsIndex: 1,
      searchScriptName: '',
      overFlag: {}
    })

    const getParamsName = (index) => {
      return `Param Name ${index + 1}`
    }

    const getParamsRules = (name) => {
      let msg = `Please input  ${name}`
      let tips = [{ required: true, message: msg, trigger: 'blur' }]
      return tips
    }

    const validator = (rule, value, callback) => {
      if (value && value.length > 0) {
        callback() // 表示验证通过
      } else {
        callback(new Error('length>0'))
      }
    }

    const deleteMethod = (index) => {
      const newArray = state.editFrom.scriptList.filter((element, index2) => index2 !== index)
      state.editFrom.scriptList = newArray
      state.editFrom.scriptList.forEach((val, index) => {
        val.orderNum = index + 1
      })
    }

    const SubmitList = (checkData) => {
      vxeList.checkList = checkData
    }
    // 数据提交
    const handleDrawerSubmit = async () => {
      addFormRef.value.validate(async (valid) => {
        if (valid) {
          const data = { ...state.editFrom }
          console.log(data)
          const res = await gClientManagementApi.add(data)
          if (res.code === 200) {
            resetForm(addFormRef.value)
            handleDrawerClose()
            ctx.emit('handleSearch')

            ElMessage({
              showClose: true,
              message: res.message,
              type: 'success'
            })
          } else {
            ElMessage({
              showClose: true,
              message: res.message,
              type: 'error'
            })
          }
        } else {
          console.log('error submit!')
          return false
        }
      })
    }

    // Drawer 打开时触发
    const handleDrawerOpened = () => {
      getScriptList()
    }

    // Drawer 关闭
    const handleDrawerClose = () => {
      state.editFrom = JSON.parse(JSON.stringify(state.editFrom2))
      ctx.emit('handleClose', 'Add')
    }
    const dragstart = (event, item) => {
      // console.log(event, item)
      // 使用 dataTransfer 对象传递JSON数据作为文本
      event.dataTransfer.setData('text/plain', JSON.stringify(item))
    }

    const dragend = (event, item) => {
      state.overFlag = {}
    }

    const dragOver = (event, name) => {
      // 阻止浏览器默认操作,允许drop事件发生
      event.preventDefault()
      state.overFlag = {}
      state.overFlag[name] = true
      // console.log(state.overFlag)
    }

    const drop = (event, index) => {
      // 阻止浏览器默认操作
      event.preventDefault()

      // 获取传递的JSON数据
      const jsonData = event.dataTransfer.getData('text/plain')
      // 解析JSON数据
      const data = JSON.parse(jsonData)

      state.overFlag = {}
      state.editFrom.scriptList.splice(index, 0, data)

      state.editFrom.scriptList = JSON.parse(JSON.stringify(state.editFrom.scriptList))
      state.editFrom.scriptList.forEach((val, index) => {
        val.orderNum = index + 1
      })
      console.log('get', state.editFrom.scriptList)
    }
    // 表单 Reset
    const resetForm = (formEl) => {
      if (!formEl) return
      formEl.resetFields()
      state.editFrom = JSON.parse(JSON.stringify(state.editFrom2))
    }

    const handleBlur = () => {
      // console.log('1111', state.editFrom.scriptList)
    }

    const getScriptList = async () => {
      // console.log(columns.value)
      // console.log(exportColumns.value)
      // 条件检索
      const query = removeProperty(JSON.parse(JSON.stringify({ scriptName: state.searchScriptName })))
      console.log(query)
      const res = await gClientApi.getDownLoadData({ ...query })
      if (res.code === 200) {
        const _arr = res.data.map((item) => {
          let paramslist = []
          if (item.paramsNameList && item.paramsNameList.length > 0) {
            item.paramsNameList.map((element) => {
              if (null !== element.value && undefined !== element.value && '' !== element.value) {
                paramslist.push({ ...element })
              } else {
                paramslist.push({ ...element, value: '', fileList: [], fileName: '', fileContent: '' })
              }
            })
          }
          item.paramslist = paramslist
          item.gClientScriptId = item.id
          let _item = { ...item }
          return _item
        })
        state.scriptList = JSON.parse(JSON.stringify(_arr))
        // ElMessage({
        //   message: res.message,
        //   type: 'success'
        // })
      } else {
        ElMessage({
          message: res.message,
          type: 'error'
        })
      }
    }

    // 上传图片验证
    const beforeAvatarUpload = (file, item, index) => {
      // 校检文件类型
      if (state.upload.accept) {
        // 文件后缀名
        let fileExtension = ''
        if (file.name.lastIndexOf('.') > -1) {
          fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
        }
        const isTypeOk = state.upload.accept.indexOf(fileExtension) > -1
        if (!isTypeOk) {
          ElMessage({
            showClose: true,
            message: `The file format is incorrect. Please upload the file in ${state.upload.accept} format!`,
            type: 'error'
          })
          return false
        }
      }
      // 校检文件大小
      if (state.upload.fileSize) {
        const isLt = file.size / 1024 / 1024 < state.upload.fileSize
        if (!isLt) {
          ElMessage({
            showClose: true,
            message: `The uploaded file size cannot exceed ${state.upload.fileSize} MB!`,
            type: 'error'
          })
          return false
        }
      }
      return true
    }

    // 文件个数超出
    const handleExceed = (files, uploadFiles, item, index) => {
      ElMessage({
        showClose: true,
        message: `The number of uploaded files cannot exceed ${state.upload.limit} !`,
        type: 'error'
      })
    }

    // 文件上传成功时的钩子
    const handleUploadSuccess = (res, item, index) => {
      switch (res.code) {
        case 200:
          item.fileContent = res.data.fileContent
          item.fileName = res.data.fileName
          item.value = res.data.fileName
          // ruleForm.systemScreenshot = res.data.filePath
          ElMessage({
            showClose: true,
            message: res.message,
            type: 'success'
          })
          break

        case 401:
          Session.clear()
          window.location.reload()
          break

        case 403:
          Session.clear()
          window.location.reload()
          break

        default:
          ElMessage({
            showClose: true,
            message: res.message,
            type: 'error'
          })
      }
    }

    // 文件列表移除文件时的钩子
    const handleRemove = (uploadFile, uploadFiles, item, index) => {
      item.fileList = []
      item.fileContent = ''
      item.fileName = ''
      item.value = ''
    }
    // 点击文件列表中已上传的文件时的钩子
    const handlePreview = (uploadFile, item, index) => {
      // ctx.emit('downScriptFile', item)
    }
    const handleChange = (value, item) => {
      console.log(value, item)
    }

    const fileChange = (name, item) => {
      addFormRef.value.validateField(name, (val) => {
        if (!val) {
          return true
        } else {
          return false
        }
      })
    }

    const remarkHTML = (remark) => {
      // return remark.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
      if (remark) {
        return remark.replace(/\n|\r\n/g, '<br/>').replace(/ /g, '  ')
      }
      return ''
    }

    onMounted(() => {})
    return {
      ...toRefs(state),
      ...toRefs(vxeData),
      ...toRefs(vxeList),
      ...toRefs(useTableHeader),
      addFormRef,
      handleDrawerOpened,
      handleDrawerClose,
      handleDrawerSubmit,
      SubmitList,
      getParamsName,
      getParamsRules,
      deleteMethod,
      resetForm,
      getScriptList,
      dragstart,
      dragOver,
      drop,
      dragend,
      handleBlur,
      validator,
      beforeAvatarUpload,
      handleExceed,
      handleUploadSuccess,
      handleRemove,
      handleChange,
      handlePreview,
      fileChange,
      remarkHTML
    }
  }
}
</script>
<style lang="scss">
.scriptDraweAdd {
  // .setting-title {
  //   font-size: var(--el-form-label-font-size);
  //   color: var(--el-text-color-regular);
  //   height: 32px;
  //   line-height: 32px;
  //   padding: 0 12px 0 0;
  //   box-sizing: border-box;
  //   font-weight: bold;
  // }
  .drawer_title {
    font-weight: bold;
    margin-bottom: 16px;
  }

  .name-parent {
    display: flex;
    .title {
      font-weight: bold;
      width: 5px;
      height: 30px;
      margin-right: 5px;
      background-color: var(--color-primary) !important;
    }
    .blank {
      font-weight: bold;
      width: 5px;
      height: 30px;
      margin-right: 5px;
    }
    .label {
      flex: 1;
    }
  }

  .title {
    font-weight: bold;
    width: 5px;
    height: 30px;
    margin-right: 5px;
    background-color: var(--color-primary) !important;
  }

  .no-label .el-form-item__label {
    display: none;
  }

  .custom-row-height {
    /* 使用calc()函数从100vh中减去100px */
    // height: calc(100vh - 600px);
    min-height: 400px;
    .searchdiv {
      flex: 1;
      height: 100%;
      padding: 5px;
      border-radius: 4px;
      border: 1px solid #cccccc;
      box-sizing: border-box;
      .paramslabel {
        margin-top: 10px;
        display: flex; /* 启用Flexbox布局 */
        flex-direction: column; /* 子元素纵向排列 */
        justify-content: center; /* 子元素在父容器内水平居中(纵向上的居中) */
        align-items: center; /* 子元素在父容器内水平居中(横向上的居中) */
        .buttondiv {
          width: 60%;
          // min-width: 290px;
          max-width: 300px;
          height: 30px;
          margin: 7px;
          color: var(--color-primary) !important;
          background-color: #fff;
          border: 2px solid var(--color-primary);
        }
      }
    }
    .flowdiv {
      min-width: 500px;
      flex: 1;
      height: 100%;
      padding: 5px;
      border-radius: 4px;
      border: 1px solid #cccccc;
      box-sizing: border-box;
      .deletebutton {
        width: 48px;
        height: 32px;
        color: #606266 !important;
        .deleteline {
          width: 40px;
          height: 32px;
          color: #606266 !important;
        }
      }

      .flowlabel {
        margin-top: 10px;
        display: flex; /* 启用Flexbox布局 */
        flex-direction: column; /* 子元素纵向排列 */
        justify-content: center; /* 子元素在父容器内水平居中(纵向上的居中) */
        align-items: center; /* 子元素在父容器内水平居中(横向上的居中) */

        .add-contain-div {
          margin: -5px 5px -5px 5px;
          height: 60px;
          // background-color: var(--color-primary) !important;
          position: relative;
          .addline {
            position: absolute;
            width: 100%;
            height: 100%;
            color: #606266;
          }

          .addicon {
            position: absolute;
            width: 40%;
            height: 40%;
            color: #606266;
            margin-left: 130px;
            margin-top: 17px;
          }
        }

        .add-contain-div-active {
          border: 1px dashed var(--color-primary);
        }
        .buttondiv {
          width: 300px;
          height: 30px;
          margin: 5px;
          color: var(--color-primary) !important;
          background-color: #fff;
          border: 2px solid var(--color-primary);
        }

        .buttondiv2 {
          width: 250px;
          height: 30px;
          margin: 5px;
          color: var(--color-primary) !important;
          background-color: #fff;
          border: 2px solid var(--color-primary);

          &:hover {
            border: 2px solid var(--el-color-primary);
            background-color: var(--el-color-primary) !important;
            color: #fff !important;
          }
          &:active,
          &:focus {
            background-color: var(--color-primary) !important;
            color: #fff !important;
          }
        }
        // .deletediv{
        //   float:right;
        //   right:0px;
        //   width:auto;
        // }
      }
    }
  }

  .paramsdiv {
   min-width: 500px;
    flex: 1 1 0%;
    height: 100%;

    border-radius: 2px;
    border: 1px solid #cccccc;
    box-sizing: border-box;
    margin-left: 0px;
    padding-bottom: 25px;
    margin-bottom: 20px;
    margin-right: 0px;
    .paramsdiv-content {
      padding: 5px;
      .paramsdiv-params {
        margin-bottom: 30px;
      }
    }
    .params-title-parent {
      padding: 5px 5px 5px 5px;
      display: flex;
      justify-content: space-between;
      /* 如果需要,可以添加以下样式以确保父 div 占据整个宽度 */
      width: 100%;
      border-bottom: 1px solid rgb(230, 230, 230);

      background-color: #fbfbfb;
      margin-bottom: 20px;

      .child {
        /* 你可以根据需要添加子 div 的样式 */
      }

      .left {
        /* 你可以在这里添加左边子 div 的特定样式 */
      }

      .right {
        /* 你可以在这里添加右边子 div 的特定样式 */
      }
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2269592.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能与传统编程的主要区别是什么?

传统编程&#xff1a;开发者预先编写软件行为规则&#xff0c;代码基于程序员定义逻辑处理输入并产生确定输出&#xff0c;具有确定性、手动编写规则和结构化逻辑特点&#xff0c;如垃圾邮件分类程序基于预设关键词等规则。AI 编程&#xff1a;从数据中学习而非手动编写规则&am…

电脑tkbrep.dll缺失怎么修复?

电脑运行时常见问题解析&#xff1a;tkbrep.dll缺失的修复策略与系统维护建议 在软件开发和电脑使用的日常中&#xff0c;我们时常会遇到各种系统报错和文件缺失的问题&#xff0c;其中tkbrep.dll的缺失便是一个较为常见的例子。作为软件开发从业者&#xff0c;我深知这些问题…

Nacos源码之服务注册

1. 准备工作 ​ 我们在使用Nacos作为SpringCloud中的注册中心组件时&#xff0c;最常用到的是它的三个功能&#xff1a;服务注册、服务发现和配置中心。 ​ 现在我们单机启动多个user-client&#xff0c;当我们成功运行UserClientApplication后可以在IDEA的service一栏中找到…

2025和数集团新年献词|和合与共,生生不息

2024年12月30日&#xff0c;“和数新春会”在上海环球港凯悦酒店举行&#xff0c;和数集团董事长兼总经理唐毅、集团高管和市场骨干欢聚一堂&#xff0c;共迎新春。 告别收获的2024&#xff0c;迎来腾飞的2025。 回望来时路&#xff0c;我们在挑战中砥砺前行&#xff0c;在困…

web 开发全局覆盖文件上传身份验证漏洞利用

全局覆盖 首先认识全局变量和局部变量 再一个就是知道全局变量是全局使用的并且有个特点就是可以覆盖 这个就是全局变量我们输出一下发现 z居然等于函数内的计算值 把我们原来定义的全局变量 $z给覆盖了 看一下局部变量 这个时候 z就不会被覆盖 <?php $x1; $y2; …

Day3 微服务 微服务保护(请求限流、线程隔离、服务熔断)、Sentinel微服务保护框架、分布式事务(XA模式、AT模式)、Seata分布式事务框架

目录 1.微服务保护 1.1.服务保护方案 1.1.1 请求限流 1.1.2 线程隔离 1.1.3 服务熔断 1.2 Sentinel 1.2.1.介绍和安装 1.2.2 微服务整合 1.2.2.1 引入sentinel依赖 1.2.2.2 配置控制台 1.2.2.3 访问cart-service的任意端点 1.3 请求限流 1.4 线程隔离 1.4.1 OpenFeign整合Senti…

使用 TensorFlow 打造企业智能数据分析平台

文章目录 摘要引言平台架构设计核心架构技术栈选型 数据采集与预处理代码详解 数据分析与预测代码详解 数据可视化ECharts 配置 总结未来展望参考资料 摘要 在大数据时代&#xff0c;企业决策正越来越依赖数据分析。然而&#xff0c;面对海量数据&#xff0c;传统分析工具常因…

计算机毕业设计Python动漫推荐系统 漫画推荐系统 动漫视频推荐系统 机器学习 bilibili动漫爬虫 数据可视化 数据分析 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

单北斗露天矿山人员车辆定位方案

你好&#xff0c;我是北京华星智控小智&#xff0c;我来给您介绍我公司的矿山人员定位系统。我们的露天矿山人员定位系统基于北斗技术&#xff0c;主要用于矿山人员和车辆的定位。 我们的矿山人员车辆定位设备主要有图上的3种&#xff0c;1是车辆定位的车载终端&#xff0c;他…

Gitlab17.7+Jenkins2.4.91实现Fastapi/Django项目持续发布版本详细操作(亲测可用)

一、gitlab设置&#xff1a; 1、进入gitlab选择主页在左侧菜单的下面点击管理员按钮。 2、选择左侧菜单的设置&#xff0c;选择网络&#xff0c;在右侧选择出站请求后选择允许来自webhooks和集成对本地网络的请求 3、webhook设置 进入你自己的项目选择左侧菜单的设置&#xff…

java项目之高校心理教育辅导系统的设计与实现(springboot+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的闲一品交易平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 高校心理教育辅导系统的设…

Cesium 实战 27 - 三维视频融合(视频投影)

Cesium 实战 27 - 三维视频融合(视频投影) 核心代码完整代码在线示例在 Cesium 中有几种展示视频的方式,比如墙体使用视频材质,还有地面多边形使用视频材质,都可以实现视频功能。 但是随着摄像头和无人机的流行,需要视频和场景深度融合,简单的实现方式则不能满足需求。…

MAC系统QT图标踩坑记录

MAC系统QT图标踩坑记录 1. 准备图标1.1 方法一&#xff1a;下载准备好的图标1.2 方法二&#xff1a;自己生成图标1.2.1 准备一个png文件1.2.2 用sips生成不同大小的图片1.2.3 用iconutil生成图标文件 2. 配置图标2.1. 把图标改命成自己想要的名字&#xff0c;如icon.icns&#…

ARM64 Windows 10 IoT工控主板运行x86程序效率测试

ARM上的 Windows 10 IoT 企业版支持仿真 x86 应用程序&#xff0c;而 ARM上的 Windows 11 IoT 企业版则支持仿真 x86 和 x64 应用程序。英创推出的名片尺寸ARM64工控主板ESM8400&#xff0c;可预装正版Windows 10 IoT企业版操作系统&#xff0c;x86程序可无需修改而直接在ESM84…

汽车损坏识别检测数据集,使用yolo,pasical voc xml,coco json格式标注,6696张图片,可识别11种损坏类型,识别率89.7%

汽车损坏识别检测数据集&#xff0c;使用yolo&#xff0c;pasical voc xml&#xff0c;coco json格式标注&#xff0c;6696张图片&#xff0c;可识别11种损坏类型损坏&#xff1a; 前挡风玻璃&#xff08;damage-front-windscreen &#xff09; 损坏的门 &#xff08;damaged-d…

西门子1200PLC和三菱FX3系列PLC接线方法

1、西门子1200PLC接线方法。* 2、从三菱官方手册查询得知&#xff0c;S/S公共端有两种接法&#xff0c;但是为了与西门子1200接法保持一致&#xff0c;所以也建议采用S/S公共点0V的接法。 **【总结】 三菱输入端采用公共点接0V接法建议提升至公司内部标准规范&#xff1a; …

一文理清JS中获取盒子宽高各方法的差异

前言 这段时间在研究一个反爬产品&#xff0c;环境检测用到了很多个盒子宽高取值方法&#xff0c;如window.outerWidth、window.screen.availWidth&#xff0c;各个方法取值结果不大相同&#xff0c;在此记录下遇到的方法。 各宽方法区别 这里就讲解下各宽度方法的区别&…

AWVS安装使用教程

一、AWVS工具介绍及下载 AWVS工具介绍 AWVS&#xff08;Acunetix Web Vulnerability Scanner&#xff09;是一款知名的网络漏洞扫描工具&#xff0c;它通过网络爬虫测试你的web站点&#xff0c;检测流行安全漏洞&#xff0c;可以检查SQL注入漏洞&#xff0c;也可以检查跨站脚…

用Python操作字节流中的Excel文档

Python能够轻松地从字节流中加载文件&#xff0c;在不依赖于外部存储的情况下直接对其进行读取、修改等复杂操作&#xff0c;并最终将更改后的文档保存回字节串中。这种能力不仅极大地提高了数据处理的灵活性&#xff0c;还确保了数据的安全性和完整性&#xff0c;尤其是在网络…

【LeetCode】928、尽量减少恶意软件的传播 II

【LeetCode】928、尽量减少恶意软件的传播 II 文章目录 一、并查集1.1 并查集 二、多语言解法 一、并查集 1.1 并查集 先把普通点, build 并查集遍历每个源头点, 找源头点附近的点所在的集合, 传染该集合拯救节点 3.1 若该节点 所在集合, 从未被感染过, 则开始感染 3.2 若该节…