From a0bdf517c15d51c9a4c4e56ce539359d0de894b3 Mon Sep 17 00:00:00 2001
From: "liu.shiyi" <liu.shiyi@ustcinfo.com>
Date: Wed, 26 Jul 2023 09:28:20 +0800
Subject: [PATCH 1/4] =?UTF-8?q?fix:=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0htt?=
 =?UTF-8?q?p=E6=95=B0=E6=8D=AE=E9=9B=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../DataSetManagement/src/HttpEditForm.vue    | 1114 +++++++++++++++++
 .../packages/js/utils/httpParamsFormatting.js |   54 +
 2 files changed, 1168 insertions(+)
 create mode 100644 data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
 create mode 100644 data-room-ui/packages/js/utils/httpParamsFormatting.js

diff --git a/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
new file mode 100644
index 00000000..244d7955
--- /dev/null
+++ b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
@@ -0,0 +1,1114 @@
+<template>
+  <div
+    class="inner-container"
+    :element-loading-text="saveText"
+  >
+    <el-scrollbar class="data-set-scrollbar">
+      <div class="header">
+        <el-page-header class="bs-el-page-header">
+          <template slot="content">
+            <div class="page-header">
+              <div class="page-header-left">
+                {{ !isEdit ? 'HTTP数据集详情' : dataForm.id ? 'HTTP数据集编辑' : 'HTTP数据集新增' }}
+              </div>
+              <div class="page-header-right">
+                <el-button
+                  class="bs-el-button-default"
+                  @click="openNewWindow('https://www.yuque.com/chuinixiongkou/bigscreen/groovy_dataset')"
+                >
+                  帮助
+                </el-button>
+                <el-button
+                  v-if="isEdit"
+                  type="primary"
+                  @click="save('form')"
+                >
+                  保存
+                </el-button>
+                <el-button
+                  class="bs-el-button-default"
+                  @click="goBack"
+                >
+                  返回
+                </el-button>
+              </div>
+            </div>
+          </template>
+        </el-page-header>
+      </div>
+      <el-row style="margin: 16px 16px 0;">
+        <el-col :span="isEdit ? 16 : 24">
+          <el-form
+            ref="form"
+            :model="dataForm"
+            :rules="rules"
+            label-width="120px"
+            style="padding: 16px 16px 0;"
+            class="bs-el-form"
+          >
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item
+                  label="名称"
+                  prop="name"
+                >
+                  <el-input
+                    v-model="dataForm.name"
+                    class="bs-el-input"
+                    clearable
+                    :disabled="!isEdit"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item
+                  label="分组"
+                  prop="typeId"
+                >
+                  <el-select
+                    ref="selectParentName"
+                    v-model="dataForm.typeId"
+                    class="bs-el-select"
+                    popper-class="bs-el-select"
+                    placeholder="请选择分组"
+                    clearable
+                    :disabled="!isEdit"
+                    @clear="clearType"
+                    @visible-change="setCurrentNode"
+                  >
+                    <el-option
+                      style="height: auto;padding: 0;"
+                      :label="typeName"
+                      :value="dataForm.typeId"
+                    >
+                      <div class="tree-box">
+                        <el-tree
+                          ref="categorySelectTree"
+                          :data="categoryData"
+                          node-key="id"
+                          :indent="0"
+                          :props="{ label: 'name', children: 'children' }"
+                          :default-expand-all="true"
+                          :highlight-current="true"
+                          :expand-on-click-node="false"
+                          class="bs-el-tree"
+                          @node-click="selectParentCategory"
+                        >
+                          <span
+                            slot-scope="{ data }"
+                            class="custom-tree-node"
+                          >
+                            <span>
+                              <i
+                                :class="data.children && data.children.length ? 'el-icon el-icon-folder' : 'el-icon el-icon-document'"
+                              />
+                              {{ data.name }}
+                            </span>
+                          </span>
+                        </el-tree>
+                      </div>
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item
+                  label="描述"
+                  prop="remark"
+                >
+                  <el-input
+                    v-model="dataForm.remark"
+                    class="bs-el-input"
+                    :disabled="!isEdit"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item
+                  label="调用方式"
+                  prop="labelIds"
+                >
+                  <el-select
+                    v-model="dataForm.config.requestType"
+                    class="bs-el-select"
+                    popper-class="bs-el-select"
+                  >
+                    <el-option
+                      label="前台代理"
+                      value="front"
+                    />
+                    <el-option
+                      label="后台代理"
+                      value="back"
+                    />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item
+                  label="标签"
+                  prop="labelIds"
+                >
+                  <LabelSelect
+                    :dataset-id="datasetId"
+                    :id-list="dataForm.labelIds"
+                    @commit="(ids) =>{dataForm.labelIds = ids}"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-form-item
+              label="请求类型"
+              prop="config.method"
+            >
+              <el-radio-group
+                v-model="dataForm.config.method"
+                class="bs-radio-wrap"
+              >
+                <el-radio-button label="get">
+                  GET
+                </el-radio-button>
+                <el-radio-button label="post">
+                  POST
+                </el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item
+              label="请求地址"
+              prop="config.url"
+            >
+              <el-input
+                v-model="dataForm.config.url"
+                autocomplete="off"
+                class="bs-el-input"
+                placeholder="请输入静态请求地址或动态请求地址,动态请求地址必须以${baseUrl}开头"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item
+              label="请求头"
+              prop="config.headers"
+            >
+              <el-button
+                type="primary"
+                @click="addHeader"
+              >
+                增加
+              </el-button>
+              <el-row
+                v-for="(item,index) in dataForm.config.headers"
+                :key="index"
+                :gutter="10"
+                :span="21"
+              >
+                <el-col :span="5">
+                  <el-form-item
+                    label="键"
+                    :prop="'headers.'+index+'.key'"
+                    label-width="50px"
+                    :rules="rules.key"
+                  >
+                    <el-input
+                      v-model="dataForm.config.headers[index].key"
+                      placeholder="请输入键"
+                      clearable
+                      @blur="dataForm.config.headers[index].key = inputChange($event)"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="5">
+                  <el-form-item
+                    label="类型"
+                    :prop="'headers.'+index+'.type'"
+                    label-width="60px"
+                    :rules="rules.type"
+                  >
+                    <el-select
+                      v-model="dataForm.config.headers[index].type"
+                      filterable
+                      clearable
+                      allow-create
+                      default-first-option
+                      placeholder="请选择类型"
+                    >
+                      <el-option
+                        v-for="item in options"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                      />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="5">
+                  <el-form-item
+                    label="值"
+                    :prop="dataForm.config.headers[index].value"
+                    label-width="50px"
+                  >
+                    <el-input
+                      v-model="dataForm.config.headers[index].value"
+                      placeholder="请输入值"
+                      clearable
+                      @blur="dataForm.config.headers[index].value = inputChange($event)"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col
+                  :span="2"
+                  style="text-align: center"
+                >
+                  <el-button
+                    type="primary"
+                    @click="delHeader(index)"
+                  >
+                    移除
+                  </el-button>
+                </el-col>
+              </el-row>
+            </el-form-item>
+            <el-form-item
+              label="请求参数"
+              prop="config.params"
+              :rules="dataForm.config.method==='get'?rules.params:[{ required: false}]"
+            >
+              <el-button
+                type="primary"
+                @click="addParam"
+              >
+                增加
+              </el-button>
+              <el-row
+                v-for="(item,index) in dataForm.config.params"
+                :key="index"
+                :gutter="10"
+                :span="21"
+              >
+                <el-col :span="7">
+                  <el-form-item
+                    label="键"
+                    :prop="'params.'+index+'.key'"
+                    label-width="50px"
+                    :rules="rules.key"
+                  >
+                    <el-input
+                      v-model="dataForm.config.params[index].key"
+                      placeholder="请输入键"
+                      clearable
+                      @blur="dataForm.config.params[index].key = inputChange($event)"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="7">
+                  <el-form-item
+                    label="值"
+                    :prop="dataForm.config.params[index].value"
+                    label-width="50px"
+                  >
+                    <el-input
+                      v-model="dataForm.config.params[index].value"
+                      placeholder="请输入值"
+                      clearable
+                      @blur="dataForm.config.params[index].value = inputChange($event)"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col
+                  :span="2"
+                  style="text-align: center"
+                >
+                  <el-button
+                    type="primary"
+                    @click="delParam(index)"
+                  >
+                    移除
+                  </el-button>
+                </el-col>
+              </el-row>
+            </el-form-item>
+            <el-form-item
+              label="请求脚本"
+              prop="requestScript"
+            >
+              <codemirror
+                v-model.trim="dataForm.config.requestScript"
+                :options="codemirrorOption"
+                class="code"
+              />
+            </el-form-item>
+            <el-form-item
+              v-if="dataForm.config.method === 'post'"
+              label="请求体"
+              prop="requestScript"
+            >
+              <el-input
+                v-model="dataForm.config.body"
+                class="bs-el-input"
+                type="textarea"
+                :autosize="{ minRows: 10, maxRows: 10}"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item
+              label="响应脚本"
+              prop="responseScript"
+            >
+              <codemirror
+                v-model.trim="dataForm.config.responseScript"
+                :options="codemirrorOption"
+                class="code"
+              />
+            </el-form-item>
+          </el-form>
+          <div
+            v-if="isEdit"
+            class="sql-config"
+          >
+            <div style="text-align: center; padding: 16px 0;">
+              <el-button
+                type="primary"
+                @click="scriptExecute()"
+              >
+                解析并执行
+              </el-button>
+            </div>
+          </div>
+        </el-col>
+        <el-col
+          v-if="isEdit"
+          :span="8"
+        >
+          <div class="right-setting">
+            <div class="paramConfig">
+              <div class="title-style bs-title-style">
+                动态参数
+                <el-button
+                  type="text"
+                  style="float: right;border: none;margin-top: -4px;"
+                  @click="$refs.paramsSettingDialog.open()"
+                >
+                  配置
+                </el-button>
+              </div>
+              <div class="field-wrap bs-field-wrap bs-scrollbar">
+                <div
+                  v-for="param in dataForm.config.paramsList"
+                  :key="param.name"
+                  class="field-item"
+                  @click="$refs.paramsSettingDialog.open()"
+                >
+                  <span>{{ param.name }}</span>&nbsp;<span
+                    v-show="param.remark"
+                    style="color: #909399;"
+                  >
+                    ({{ param.remark }})
+                  </span>
+                  <el-button
+                    class="edit_field"
+                    type="text"
+                    style="float: right;border: none;margin-top: 2px;"
+                    @click="$refs.paramsSettingDialog.open()"
+                  >
+                    配置
+                  </el-button>
+                </div>
+              </div>
+            </div>
+            <div class="structure">
+              <div class="title-style bs-title-style">
+                输出字段
+                <el-button
+                  type="text"
+                  style="float: right;border: none;margin-top: -4px;"
+                  @click="$refs.outputFieldDialog.open()"
+                >
+                  配置
+                </el-button>
+              </div>
+              <div class="field-wrap bs-field-wrap bs-scrollbar">
+                <div
+                  v-for="(field, key) in outputFieldList"
+                  :key="key"
+                  class="field-item"
+                  @click="$refs.outputFieldDialog.open()"
+                >
+                  <span>{{ field.fieldName }}</span>&nbsp;
+                  <span
+                    v-show="field.fieldDesc"
+                    style="color: #909399;"
+                  >
+                    ({{ field.fieldDesc }})</span>
+                  <el-button
+                    class="edit_field"
+                    type="text"
+                    style="float: right;border: none;margin-top: 2px;"
+                    @click="$refs.outputFieldDialog.open()"
+                  >
+                    配置
+                  </el-button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+      <div
+        v-if="isEdit"
+        class="dataPreView"
+        style="margin-top: 12px;"
+      >
+        <div class="result-view">
+          数据预览
+        </div>
+        <div
+          v-loading="tableLoading"
+          class="bs-table-box is-Edit bs-scrollbar"
+        >
+          <el-table
+            align="center"
+            :data="dataPreviewList"
+            max-height="400"
+            :border="true"
+            class="bs-el-table bs-scrollbar"
+          >
+            <el-table-column
+              v-for="(value, key) in dataPreviewList[0]"
+              :key="key"
+              :label="key"
+              align="center"
+              show-overflow-tooltip
+              :render-header="renderHeader"
+            >
+              <template slot-scope="scope">
+                <span>{{ scope.row[key] }}</span>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div
+        v-if="!isEdit"
+        class="dataPreView"
+      >
+        <el-tabs v-model="activeName">
+          <el-tab-pane
+            v-loading="tableLoading"
+            label="数据预览"
+            name="data"
+          >
+            <div class="bs-table-box">
+              <el-table
+                align="center"
+                :data="dataPreviewList"
+                max-height="400"
+                :border="true"
+                class="bs-el-table"
+              >
+                <el-table-column
+                  v-for="(value, key) in dataPreviewList[0]"
+                  :key="key"
+                  :label="key"
+                  align="center"
+                  show-overflow-tooltip
+                  :render-header="renderHeader"
+                >
+                  <template slot-scope="scope">
+                    <span>{{ scope.row[key] }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+          <el-tab-pane
+            v-loading="tableLoading"
+            label="数据集结构"
+            name="structure"
+          >
+            <div class="bs-table-box">
+              <el-table
+                max-height="400"
+                :data="outputFieldList"
+                :border="true"
+                align="center"
+              >
+                <el-table-column
+                  align="center"
+                  show-overflow-tooltip
+                  prop="fieldName"
+                  label="字段值"
+                />
+                <el-table-column
+                  align="center"
+                  prop="fieldDesc"
+                  label="字段描述"
+                >
+                  <template slot-scope="scope">
+                    <el-input
+                      v-if="isEdit"
+                      v-model="scope.row.fieldDesc"
+                      size="small"
+                      class="labeldsc bs-el-input"
+                    />
+                    <span v-else>{{ scope.row.fieldDesc }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+      <ParamsSettingDialog
+        ref="paramsSettingDialog"
+        :params-list="dataForm.config.paramsList"
+        @saveParams="saveParams"
+      />
+      <OutputFieldDialog
+        ref="outputFieldDialog"
+        :output-field-list="outputFieldList"
+        @setFieldList="(list) => { outputFieldList = list }"
+      />
+    </el-scrollbar>
+    <FieldFillDialog
+      ref="fieldFillDialog"
+      @fieldDescFill="fieldDescFill"
+      @fieldDescEdit="fieldDescEdit"
+      @toSave="toSave"
+    />
+  </div>
+</template>
+
+<script>
+import LabelSelect from 'data-room-ui/DataSetLabelManagement/src/LabelSelect.vue'
+import ParamsSettingDialog from './JsComponents/ParamsSettingDialog.vue'
+import OutputFieldDialog from './JsComponents/OutputFieldDialog.vue'
+import FieldFillDialog from './JsComponents/FieldFillDialog.vue'
+import { nameCheckRepeat, datasetAdd, datasetUpdate, getDataset, getCategoryTree, datasetExecuteTest } from 'data-room-ui/js/utils/datasetConfigService'
+import { codemirror } from 'vue-codemirror'
+import 'codemirror/mode/javascript/javascript'
+import 'codemirror/lib/codemirror.css'
+import 'codemirror/theme/nord.css'
+import axiosFormatting from '../../js/utils/httpParamsFormatting'
+import _ from 'lodash'
+export default {
+  name: 'HttpEditForm',
+  components: {
+    codemirror,
+    FieldFillDialog,
+    ParamsSettingDialog,
+    OutputFieldDialog,
+    LabelSelect
+  },
+  props: {
+    config: {
+      type: Object,
+      default: () => { }
+    },
+    isEdit: {
+      type: Boolean,
+      default: false
+    },
+    datasetId: {
+      type: String,
+      default: null
+    },
+    typeId: {
+      type: String,
+      default: ''
+    },
+    appCode: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    const validateName = (rule, value, callback) => {
+      nameCheckRepeat({
+        id: this.datasetId,
+        name: value,
+        moduleCode: this.appCode
+      }).then((r) => {
+        if (r) {
+          callback(new Error('数据集名称已存在'))
+        } else {
+          callback()
+        }
+      })
+    }
+    const validateUrl = (rule, value, callback) => {
+      // eslint-disable-next-line no-template-curly-in-string
+      if (value.startsWith('${baseUrl}/')) {
+        callback()
+      }
+      const reg = /(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
+      if (!reg.test(value)) {
+        // eslint-disable-next-line no-template-curly-in-string
+        callback(new Error('请输入正确的静态请求地址或动态请求地址,动态请求地址必须以${baseUrl}/开头'))
+      } else {
+        callback()
+      }
+    }
+    return {
+      options: [{
+        value: 'string',
+        label: '字符串'
+      }, {
+        value: 'boolean',
+        label: '布尔值'
+      }, {
+        value: 'int',
+        label: '数字'
+      }, {
+        value: 'date',
+        label: '日期'
+      }],
+      dataForm: {
+        id: '',
+        name: '',
+        typeId: '',
+        remark: '',
+        labelIds: [],
+        config: {
+          className: 'com.gccloud.dataset.entity.config.HttpDataSetConfig',
+          requestType: '',
+          method: 'get',
+          url: '',
+          headers: [],
+          params: [],
+          body: null,
+          requestScript: null,
+          responseScript: null
+        }
+      },
+      rules: {
+        name: [
+          { required: true, message: '请输入数据集名称', trigger: 'blur' },
+          { validator: validateName, trigger: 'blur' }
+        ],
+        typeId: [
+          { required: true, message: '请选择分组', trigger: 'blur' }
+        ],
+        key: [{ required: true, message: '键不能为空', trigger: 'blur' }],
+        type: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
+        'config.method': [{ required: true, message: '请求类型不能为空', trigger: 'blur' }],
+        'config.url': [
+          { required: true, message: '请求地址不能为空', trigger: 'blur' },
+          { validator: validateUrl, trigger: 'blur' }
+        ]
+      },
+      codemirrorOption: {
+        mode: 'text/javascript',
+        lineNumbers: true,
+        lineWrapping: true,
+        theme: 'nord',
+        extraKey: { Ctrl: 'autocomplete' },
+        hintOptions: {
+          completeSingle: true
+        }
+      },
+      activeName: 'data',
+      dataPreviewList: [],
+      outputFieldList: [],
+      structurePreviewListCopy: [],
+      typeName: '',
+      categoryData: [],
+      // fieldDescVisible: false,
+      fieldsetVisible: false,
+      paramsVisible: false,
+      tableLoading: false,
+      saveloading: false,
+      saveText: '',
+      // paramsListCopy: [],
+      isSet: false, // 参数是否配置状态
+      passTest: false,
+      fieldDesc: null // 字段描述
+    }
+  },
+  watch: {
+    'dataForm.config.script' (val) {
+      if (!val) {
+        this.passTest = false
+      }
+    }
+  },
+  mounted () {
+    this.init()
+  },
+  methods: {
+    async init () {
+      this.categoryData = await getCategoryTree({ tableName: 'dataset', moduleCode: this.appCode })
+      if (this.typeId) {
+        this.dataForm.typeId = this.typeId
+        this.$nextTick(() => {
+          try {
+            this.typeName = this.$refs.categorySelectTree.getNode(this.dataForm.typeId).data.name
+          } catch (error) {
+            console.error(error)
+          }
+        })
+      }
+      if (this.datasetId) {
+        getDataset(this.datasetId).then(res => {
+          const { id, name, typeId, remark, datasetType, moduleCode, editable, sourceId, config } = res
+          const { script, paramsList, fieldDesc, fieldList } = config
+          this.dataForm = { id, name, typeId, remark, datasetType, moduleCode, editable, sourceId, config: { script, paramsList } }
+          this.fieldDesc = fieldDesc
+          this.outputFieldList = fieldList
+          this.scriptExecute(true)
+        })
+      }
+    },
+    // 保存数据集
+    save (formName, nochecktosave = false) {
+      // if (this.passTest === false) {
+      //   this.$message.error('请确保脚本不为空且执行通过')
+      //   return
+      // }
+      // if (!this.outputFieldList.length) {
+      //   this.$message.warning('该执行脚本未生成输出字段,请重新检查')
+      //   return
+      // }
+      // if (!nochecktosave) {
+      //   const temp = this.outputFieldList.some(item => {
+      //     return item.fieldDesc === '' || !item.hasOwnProperty('fieldDesc')
+      //   }) // true-存在为空
+      //   if (temp) {
+      //     this.$refs.fieldFillDialog.open()
+      //     // this.fieldDescVisible = true
+      //     return
+      //   }
+      // }
+      requestType: '',
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.saveloading = true
+          this.saveText = '正在保存...'
+          const { datasetId, dataForm, appCode, fieldDesc, outputFieldList } = this
+          const form = {
+            id: datasetId,
+            name: dataForm.name,
+            typeId: dataForm.typeId,
+            remark: dataForm.remark,
+            datasetType: 'http',
+            moduleCode: appCode,
+            editable: appCode ? 1 : 0,
+            labelIds: dataForm.labelIds,
+            config: {
+              className: 'com.gccloud.dataset.entity.config.HttpDataSetConfig',
+              method: dataForm.config.headers,
+              url: dataForm.config.url,
+              headers: dataForm.config.headers,
+              params: dataForm.config.params,
+              body: dataForm.config.body,
+              requestScript: dataForm.config.requestScript,
+              responseScript: dataForm.config.responseScript,
+              fieldDesc,
+              paramsList: dataForm.config.paramsList,
+              fieldList: outputFieldList
+            }
+          }
+          const datasetSave = this.dataForm.id === '' ? datasetAdd : datasetUpdate
+          datasetSave(form).then(() => {
+            this.$message.success('操作成功')
+            this.$parent.init(false)
+            this.$parent.setType = null
+            this.saveloading = false
+            this.saveText = ''
+            this.goBack()
+          }).catch(() => {
+            this.saveloading = false
+            this.saveText = ''
+          })
+        }
+      })
+    },
+    // 增加header
+    addHeader () {
+      const header = { key: '', type: 'string', value: '', remark: '' }
+      console.log(this.dataForm)
+      this.dataForm.config.headers.push(_.cloneDeep(header))
+    },
+    // 移除header
+    delHeader (index) {
+      this.dataForm.config.headers.splice(index, 1)
+    },
+    // 增加请求参数
+    addParam () {
+      const param = { key: '', value: '', remark: '' }
+      this.dataForm.config.params.push(_.cloneDeep(param))
+    },
+    // 移除请求参数
+    delParam (index) {
+      this.dataForm.config.params.splice(index, 1)
+    },
+    saveParams (val) {
+      this.dataForm.config.paramsList = val
+    },
+    // 取消操作
+    // cancelField () {
+    //   this.structurePreviewListCopy = cloneDeep(this.outputFieldList)
+    //   this.fieldsetVisible = false
+    // },
+    // 设置输出字段
+    setField () {
+      // this.outputFieldList = cloneDeep(this.structurePreviewListCopy)
+      // if (this.outputFieldList.length) {
+      //   this.fieldDesc = {}
+      //   this.outputFieldList.forEach(key => {
+      //     this.fieldDesc[key.fieldName] = key.fieldDesc
+      //   })
+      // } else {
+      //   this.fieldDesc = null
+      // }
+      // this.fieldsetVisible = false
+    },
+    // 字段值填充
+    fieldDescFill () {
+      this.fieldDesc = {}
+      this.outputFieldList.forEach(field => {
+        if (field.fieldDesc === '' || !field.hasOwnProperty('fieldDesc')) {
+          field.fieldDesc = field.fieldName
+          this.fieldDesc[field.fieldName] = field.fieldName
+        } else {
+          this.fieldDesc[field.fieldName] = field.fieldDesc
+        }
+      })
+      this.save('form')
+      this.$refs.fieldFillDialog.close()
+      // this.fieldDescVisible = false
+    },
+    // 进入编辑
+    fieldDescEdit () {
+      this.$refs.fieldFillDialog.close()
+      // this.fieldDescVisible = false
+      this.fieldsetVisible = true
+    },
+    // 继续保存
+    toSave () {
+      this.fieldDesc = {}
+      this.outputFieldList.forEach(field => {
+        this.fieldDesc[field.fieldName] = field.fieldDesc
+      })
+      this.save('form', true)
+      this.$refs.fieldFillDialog.close()
+      // this.fieldDescVisible = false
+    },
+    // 字段描述构建及同步
+    buildFieldDesc () {
+      const fieldDesc = {}
+      this.outputFieldList.forEach(field => {
+        if (this.fieldDesc.hasOwnProperty(field.fieldName)) {
+          field.fieldDesc = this.fieldDesc[field.fieldName]
+        }
+        fieldDesc[field.fieldName] = field.fieldDesc
+      })
+      this.fieldDesc = fieldDesc
+    },
+    // 执行配置好的接口
+    scriptExecute (isInit = false) {
+      // 如果是前端代理,则自行组装接口及参数并调接口
+      if (this.dataForm.config.requestType === 'front') {
+        axiosFormatting({ ...this.dataForm.config }).then((res) => {
+          console.log(res)
+        })
+      } else {
+        // 如果是后端代理,则将配置传到后端
+        const script = JSON.stringify(this.dataForm.config)
+        const executeParams = {
+          script,
+          params: this.dataForm.paramsList,
+          dataSetType: 'http'
+        }
+        datasetExecuteTest(executeParams).then(res => {
+
+        }).catch((e) => {
+
+        })
+      }
+    },
+    // 清空分类
+    clearType () {
+      this.typeName = ''
+      this.dataForm.typeId = ''
+    },
+    // 分类展开高亮
+    setCurrentNode ($event) {
+      if ($event) {
+        const key = this.dataForm.typeId || null
+        this.$refs.categorySelectTree.setCurrentKey(key)
+      }
+    },
+    // 分类选择
+    selectParentCategory (value) {
+      this.dataForm.typeId = value.id
+      this.typeName = value.name
+      this.$refs.selectParentName.blur()
+    },
+    goBack () {
+      this.$emit('back')
+    },
+    renderHeader (h, { column, index }) {
+      const labelLong = column.label.length // 表头label长度
+      const size = 14 // 根据需要定义标尺,直接使用字体大小确定就行,也可以根据需要定义
+      column.minWidth = labelLong * size < 120 ? 120 : labelLong * size // 根据label长度计算该表头最终宽度
+      return h('span', { class: 'cell-content', style: { width: '100%' } }, [column.label])
+    },
+    openNewWindow (url) {
+      window.open(url, '_blank')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../assets/style/bsTheme.scss';
+
+.data-set-scrollbar {
+  height: 100%;
+  overflow-y: auto;
+  overflow-x: none;
+
+  .el-scrollbar__view {
+    height: 100%;
+  }
+}
+
+::v-deep .el-input__inner {
+  width: 100% !important;
+}
+
+.page-header {
+  display: flex;
+  position: relative;
+
+  .page-header-right {
+    position: absolute;
+    right: 16px;
+  }
+}
+
+.sql-config {
+  padding: 0 16px;
+}
+
+.operation {
+  ::v-deep .el-select {
+    width: 200px !important;
+    margin-right: 16px;
+  }
+
+  display: flex;
+}
+
+::v-deep .CodeMirror {
+  height: 180px !important;
+  font-family: Helvetica, Tahoma;
+}
+
+.no-border {
+  border: 0;
+}
+
+::v-deep .fieldDescCheck {
+  .el-dialog__body {
+    height: fit-content !important;
+    min-height: unset !important;
+  }
+}
+
+.title-style {
+  padding: 8px 12px;
+  background-color: #f6f7fb;
+  border-left: 5px solid var(--bs-el-color-primary);
+  margin: 16px 16px 0 0;
+}
+
+.field-wrap {
+  // max-height: 110px;
+  overflow: auto;
+  margin-right: 16px;
+  cursor: pointer;
+
+  .field-item {
+    line-height: 32px;
+    padding: 0 12px 0 16px;
+
+    .edit_field {
+      display: none;
+    }
+
+    &:hover {
+      background-color: #f2f7fe;
+
+      .edit_field {
+        display: block;
+      }
+    }
+  }
+}
+
+.right-setting {
+  height: 358px;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+
+  .paramConfig {
+    max-height: 179px;
+
+    .field-wrap {
+      max-height: 127px;
+    }
+  }
+
+  .structure {
+    flex: 1;
+    overflow: hidden;
+
+    .field-wrap {
+      height: calc(100% - 40px);
+    }
+  }
+}
+
+.result-view {
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--bs-el-text);
+  position: relative;
+  padding: 16px 0;
+  padding-left: 12px;
+  border-bottom: 1px solid var(--bs-background-1);
+
+  &::before {
+    content: "";
+    height: 14px;
+    position: absolute;
+    left: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    border-left: 4px solid var(--bs-el-color-primary);
+  }
+}
+
+::v-deep .bs-table-box.is-Edit .el-table {
+  max-height: unset !important;
+
+  .el-table__body-wrapper {
+    max-height: unset !important;
+  }
+}
+
+.bs-table-box {
+  padding: 0;
+  height: 100% !important;
+  margin-bottom: 0 !important;
+}
+
+.tree-box {
+  padding: 0;
+}
+</style>
diff --git a/data-room-ui/packages/js/utils/httpParamsFormatting.js b/data-room-ui/packages/js/utils/httpParamsFormatting.js
new file mode 100644
index 00000000..1fe11579
--- /dev/null
+++ b/data-room-ui/packages/js/utils/httpParamsFormatting.js
@@ -0,0 +1,54 @@
+import axios from 'axios'
+import { Loading, Message } from 'element-ui'
+export default function axiosFormatting (customConfig) {
+  const httpConfig = {
+    timeout: 1000 * 30,
+    baseURL: '',
+    headers: {
+      ...customConfig.headers
+    }
+  }
+  // let loadingInstance = null // 加载全局的loading
+  const instance = axios.create(httpConfig)
+  /** 添加请求拦截器 **/
+  instance.interceptors.request.use(config => {
+    /**
+     * 在这里:可以根据业务需求可以在发送请求之前做些什么。
+     * config.headers['token'] = sessionStorage.getItem('token') || ''
+     */
+    // 执行请求脚本
+    eval(customConfig.requestScript)
+    return config
+  }, error => {
+    // 对请求错误做些什么
+    return Promise.reject(error)
+  })
+
+  /** 添加响应拦截器  **/
+  instance.interceptors.response.use(response => {
+    if (response.data.code === 200) {
+      // 执行响应脚本
+      const data = response.data.data
+      eval(customConfig.responseScript)
+      return Promise.resolve(data)
+    } else {
+      Message({
+        message: response.data.message,
+        type: 'error'
+      })
+      return Promise.reject(response.data.message)
+    }
+  })
+  return new Promise((resolve, reject) => {
+    instance({
+      method: customConfig.method,
+      url: customConfig.url,
+      params: customConfig.params,
+      data: customConfig.method === 'post' ? customConfig.body : undefined
+    }).then(response => {
+      resolve(response)
+    }).catch(error => {
+      reject(error)
+    })
+  })
+}

From 29984eeee3e41202886e4bced1a998973758ba90 Mon Sep 17 00:00:00 2001
From: "liu.shiyi" <liu.shiyi@ustcinfo.com>
Date: Wed, 26 Jul 2023 09:38:52 +0800
Subject: [PATCH 2/4] =?UTF-8?q?fix:=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0htt?=
 =?UTF-8?q?p=E6=95=B0=E6=8D=AE=E9=9B=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 data-room-ui/example/main.js                              | 6 +++++-
 .../packages/DataSetManagement/src/HttpEditForm.vue       | 8 ++++----
 data-room-ui/packages/DataSetManagement/src/index.vue     | 7 +++++--
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/data-room-ui/example/main.js b/data-room-ui/example/main.js
index c566d664..a85f2555 100644
--- a/data-room-ui/example/main.js
+++ b/data-room-ui/example/main.js
@@ -13,6 +13,7 @@ import * as $dataRoomAxios from 'data-room-ui/js/utils/http.js'
 import { registerConfig } from '@gcpaas/data-room-ui'
 import remoteComponents from '@/remoteComponents/exports.js'
 import customDatasetComponents from '@/customDatasetComponents/exports.js'
+import customPlots from '@/customPlots/exports'
 Vue.use(ElementUI, { size: 'mini' })
 registerConfig(
   {
@@ -65,7 +66,10 @@ promise.polyfill()
 Vue.use(ElementUI, { size: 'mini' })
 Vue.prototype.$dataRoomAxios = $dataRoomAxios
 Vue.config.productionTip = false
-
+// 兼容ie下双向绑定事件
+Vue.prototype.inputChange = function (e) {
+  return e.target.value
+}
 /* eslint-disable no-new */
 new Vue({
   el: '#app',
diff --git a/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
index 244d7955..28eb0f64 100644
--- a/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
+++ b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
@@ -678,9 +678,9 @@ export default {
           url: '',
           headers: [],
           params: [],
-          body: null,
-          requestScript: null,
-          responseScript: null
+          body: '',
+          requestScript: '',
+          responseScript: ''
         }
       },
       rules: {
@@ -798,7 +798,7 @@ export default {
             labelIds: dataForm.labelIds,
             config: {
               className: 'com.gccloud.dataset.entity.config.HttpDataSetConfig',
-              method: dataForm.config.headers,
+              method: dataForm.config.method,
               url: dataForm.config.url,
               headers: dataForm.config.headers,
               params: dataForm.config.params,
diff --git a/data-room-ui/packages/DataSetManagement/src/index.vue b/data-room-ui/packages/DataSetManagement/src/index.vue
index 458d8ffc..240a6bad 100644
--- a/data-room-ui/packages/DataSetManagement/src/index.vue
+++ b/data-room-ui/packages/DataSetManagement/src/index.vue
@@ -262,6 +262,7 @@ import checkDatasource from 'data-room-ui/DataSourceManagement/src/checkDatasour
 import CustomEditForm from './CustomEditForm.vue'
 import { pageMixins } from 'data-room-ui/js/mixins/page'
 import OriginalEditForm from './OriginalEditForm.vue'
+import HttpEditForm from './HttpEditForm.vue'
 import DatasetTypeDialog from './DatasetTypeDialog.vue'
 import StoredProcedureEditForm from './StoredProcedureEditForm.vue'
 import { datasetPage, datasetRemove, datasetCheck } from 'data-room-ui/js/utils/datasetConfigService'
@@ -280,7 +281,8 @@ export default {
     StoredProcedureEditForm,
     ScriptEditForm,
     JsEditForm,
-    checkDatasource
+    checkDatasource,
+    HttpEditForm
   },
   mixins: [pageMixins],
   props: {
@@ -529,7 +531,8 @@ export default {
         { name: '存储过程数据集', datasetType: 'storedProcedure', componentName: 'StoredProcedureEditForm' },
         { name: 'JSON数据集', datasetType: 'json', componentName: 'JsonEditForm' },
         { name: '脚本数据集', datasetType: 'script', componentName: 'ScriptEditForm' },
-        { name: 'JS数据集', datasetType: 'js', componentName: 'JsEditForm' }
+        { name: 'JS数据集', datasetType: 'js', componentName: 'JsEditForm' },
+        { name: 'HTTP数据集', datasetType: 'http', componentName: 'HttpEditForm' }
       ]
       if (window.BS_CONFIG?.datasetTypeList&&window.BS_CONFIG?.datasetTypeList?.length!=0) {
         this.datasetTypeList = [{ name: '全部', datasetType: '' }, ...list.filter(item => window.BS_CONFIG?.datasetTypeList.findIndex(x => x === item.datasetType) !== -1)]

From 93926f50b07f013e18dea0b704ae6130d2ded2d1 Mon Sep 17 00:00:00 2001
From: "wu.jian2" <distantmtn@gmail.com>
Date: Wed, 26 Jul 2023 09:51:50 +0800
Subject: [PATCH 3/4] =?UTF-8?q?style:=20=E4=BF=AE=E6=94=B9=E6=97=B6?=
 =?UTF-8?q?=E9=97=B4=E9=80=89=E6=8B=A9=E5=99=A8=E6=A0=B7=E5=BC=8F=EF=BC=8C?=
 =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=B7=B1=E8=89=B2=E4=B8=BB=E9=A2=98=E9=80=82?=
 =?UTF-8?q?=E9=85=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../packages/assets/style/bsTheme.scss        | 91 ++++++++++++++-----
 1 file changed, 69 insertions(+), 22 deletions(-)

diff --git a/data-room-ui/packages/assets/style/bsTheme.scss b/data-room-ui/packages/assets/style/bsTheme.scss
index 3d7c7e4c..8a7a9b65 100644
--- a/data-room-ui/packages/assets/style/bsTheme.scss
+++ b/data-room-ui/packages/assets/style/bsTheme.scss
@@ -67,7 +67,7 @@
   border-color: var(--bs-el-border) !important;
   background: var(--bs-background-2) !important;
   background-color: var(--bs-background-2) !important;
-  th.el-table__cell.is-leaf{
+  th.el-table__cell.is-leaf {
     border-color: var(--bs-el-border) !important;
   }
 
@@ -543,15 +543,15 @@
   background: var(--bs-background-2) !important;
   border-color: var(--bs-background-1) !important;
   background-color: var(--bs-background-2) !important;
-  .el-button--default{
+  .el-button--default {
     color: var(--bs-el-text) !important;
     border-color: var(--bs-background-1) !important;
     background-color: var(--bs-background-2) !important;
   }
-  .el-color-picker__trigger{
-    border-color:   var(--bs-background-1) !important;
+  .el-color-picker__trigger {
+    border-color: var(--bs-background-1) !important;
   }
-  .el-color-picker__panel{
+  .el-color-picker__panel {
     border-color: var(--bs-background-1) !important;
   }
   .el-input__inner {
@@ -602,32 +602,79 @@
 .bs-el-date-picker {
   left: -115px !important;
   background-color: var(--bs-background-1) !important;
-  .el-date-picker__time-header{
+  .el-date-picker__time-header {
     border-color: var(--bs-el-border) !important;
   }
-  .el-picker-panel{
-     .el-date-picker__header{
+
+  .popper__arrow::after {
+    border-bottom-color: var(--bs-background-1) !important;
+    border-top-color: var(--bs-background-1) !important;
+  }
+  .el-date-picker__header {
+    background: var(--bs-el-background-1) !important;
+    background-color: var(--bs-el-background-1) !important;
+    .el-date-picker__header-label {
+      color: var(--bs-el-text) !important;
+    }
+    .el-picker-panel__icon-btn {
+      color: var(--bs-el-text) !important;
+    }
+  }
+  .el-date-table {
+    background: var(--bs-el-background-1) !important;
+    background-color: var(--bs-el-background-1) !important;
+    th {
+      color: var(--bs-el-text) !important;
+      border-color: var(--bs-el-border) !important;
+    }
+    .el-button--text {
       color: var(--bs-el-text) !important;
       background: var(--bs-background-2) !important;
       background-color: var(--bs-background-2) !important;
-     }
-     .el-date-table{
-      background: var(--bs-background-2) !important;
-      background-color: var(--bs-background-2) !important;
-      th{
-        border-color: var(--bs-el-border) !important;
+    }
+  }
+  .el-year-table {
+    background: var(--bs-el-background-1) !important;
+    background-color: var(--bs-el-background-1) !important;
+    .disabled {
+      .cell {
+        background-color: var(--bs-background-2) !important;
       }
-      .el-button--text{
+    }
+    td {
+      .cell {
         color: var(--bs-el-text) !important;
-        background: var(--bs-background-2) !important;
+      }
+    }
+  }
+  .el-month-table {
+    background: var(--bs-el-background-1) !important;
+    background-color: var(--bs-el-background-1) !important;
+    .disabled {
+      .cell {
         background-color: var(--bs-background-2) !important;
       }
-     }
+    }
+    td {
+      .cell {
+        color: var(--bs-el-text) !important;
+      }
+    }
+  }
+  .el-date-table {
+    .available {
+      color: var(--bs-el-text) !important;
+    }
   }
   .el-picker-panel__footer {
     background-color: var(--bs-background-1) !important;
     border-top: 1px solid var(--bs-el-border) !important;
   }
+  .el-picker-panel {
+    .el-button--text {
+      color: var(--bs-el-text) !important;
+    }
+  }
   .el-date-table td.disabled div {
     background-color: var(--bs-background-2) !important;
   }
@@ -676,15 +723,15 @@
   }
 }
 
-.bs-el-tabs{
-  .el-tabs__item{
+.bs-el-tabs {
+  .el-tabs__item {
     color: var(--bs-el-text) !important;
   }
-  .is-active{
+  .is-active {
     color: var(--bs-el-color-primary) !important;
   }
-  .el-tabs__nav-wrap{
-    &:after{
+  .el-tabs__nav-wrap {
+    &:after {
       background-color: var(--bs-background-1) !important;
     }
   }

From e7791d49c34830afd20c74a700142a204c4382a8 Mon Sep 17 00:00:00 2001
From: "liu.shiyi" <liu.shiyi@ustcinfo.com>
Date: Wed, 26 Jul 2023 09:52:25 +0800
Subject: [PATCH 4/4] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9http=E6=95=B0?=
 =?UTF-8?q?=E6=8D=AE=E9=9B=86=E6=95=B0=E6=8D=AE=E5=9B=9E=E6=98=BE=E9=97=AE?=
 =?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../packages/DataSetManagement/src/HttpEditForm.vue  | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
index 28eb0f64..6a402d6d 100644
--- a/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
+++ b/data-room-ui/packages/DataSetManagement/src/HttpEditForm.vue
@@ -63,7 +63,6 @@
               <el-col :span="12">
                 <el-form-item
                   label="分组"
-                  prop="typeId"
                 >
                   <el-select
                     ref="selectParentName"
@@ -128,7 +127,7 @@
               <el-col :span="12">
                 <el-form-item
                   label="调用方式"
-                  prop="labelIds"
+                  prop="config.requestType"
                 >
                   <el-select
                     v-model="dataForm.config.requestType"
@@ -673,7 +672,7 @@ export default {
         labelIds: [],
         config: {
           className: 'com.gccloud.dataset.entity.config.HttpDataSetConfig',
-          requestType: '',
+          requestType: 'back',
           method: 'get',
           url: '',
           headers: [],
@@ -688,8 +687,8 @@ export default {
           { required: true, message: '请输入数据集名称', trigger: 'blur' },
           { validator: validateName, trigger: 'blur' }
         ],
-        typeId: [
-          { required: true, message: '请选择分组', trigger: 'blur' }
+        'config.requestType': [
+          { required: true, message: '请选择调用方式', trigger: 'change' }
         ],
         key: [{ required: true, message: '键不能为空', trigger: 'blur' }],
         type: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
@@ -754,7 +753,7 @@ export default {
         getDataset(this.datasetId).then(res => {
           const { id, name, typeId, remark, datasetType, moduleCode, editable, sourceId, config } = res
           const { script, paramsList, fieldDesc, fieldList } = config
-          this.dataForm = { id, name, typeId, remark, datasetType, moduleCode, editable, sourceId, config: { script, paramsList } }
+          this.dataForm = { id, name, typeId, remark, datasetType, moduleCode, editable, sourceId, config: { ...config } }
           this.fieldDesc = fieldDesc
           this.outputFieldList = fieldList
           this.scriptExecute(true)
@@ -805,6 +804,7 @@ export default {
               body: dataForm.config.body,
               requestScript: dataForm.config.requestScript,
               responseScript: dataForm.config.responseScript,
+              requestType: dataForm.config.requestType,
               fieldDesc,
               paramsList: dataForm.config.paramsList,
               fieldList: outputFieldList