CzRger 5 months ago
parent
commit
7260f81bd9

+ 32 - 0
src/api/modules/manage/service.ts

@@ -0,0 +1,32 @@
+import { handle } from '../../index'
+
+const suffix = 'api'
+
+// 归属插件
+export const sysPluginGetAllPlugins = () => handle({
+  url: `/${suffix}/sysPlugin/getAllPlugins`,
+  method: 'get',
+})
+// 解析插件
+export const sysPluginGetAllParsePlugins = () => handle({
+  url: `/${suffix}/sysPlugin/getAllParsePlugins`,
+  method: 'get',
+})
+// 新增|编辑
+export const outsideServiceSaveOrUpdate = (params: any) => handle({
+  url: `/${suffix}/api/outsideService/saveOrUpdate`,
+  method: 'post',
+  params
+})
+// 分页查询
+export const outsideServiceFindByPage = (params: any) => handle({
+  url: `/${suffix}/api/outsideService/findByPage`,
+  method: 'get',
+  params
+})
+// 启用|停用
+export const outsideServiceStatusUpdate = (params: any) => handle({
+  url: `/${suffix}/api/outsideService/statusUpdate`,
+  method: 'post',
+  params
+})

+ 2 - 2
src/stores/dictionary-define.ts

@@ -23,8 +23,8 @@ export const dictionaryDefine = {
 	request_type: ['requestTypeList', 'requestTypeMap'], //  请求类型
 	request_params: ['requestParamsList', 'requestParamsMap'], //  Request_Params
 	fz_cs: ['fzCsList', 'fzCsMap'], //  复杂参数规则
-	request_body: ['RequestBodyList', 'RequestBodyMap'], //  Request_Body
-	response_body: ['Response_BodyList', 'Response_BodyMap'], //  Response_Body
+	request_body: ['requestBodyList', 'requestBodyMap'], //  Request_Body
+	response_body: ['responseBodyList', 'responseBodyMap'], //  Response_Body
 	qz_type: ['qzTypeList', 'qzTypeMap'], //  取值类型
 	format_type: ['formatTypeList', 'formatTypeMap'], //  格式类型
 	service_type: ['serviceTypeList', 'serviceTypeMap'], //  服务类型

+ 2 - 0
src/stores/dictionary-other-define.ts

@@ -2,6 +2,8 @@ export const dictionaryOtherDefine = {
 	//非字典接口的数据项,针对各业务功能内频繁需要调用的,尽量避免多余参数来回传递
 	itemType: ['itemTypeList', 'itemTypeMap', 'itemTypeObjMap'],	// 事项类型
 	jgType: ['jgTypeList', 'jgTypeMap', 'jgTypeObjMap'],	// 结果类型
+	gsPlug: ['gsPlugList', 'gsPlugMap', 'gsPlugObjMap'],	// 归属插件
+	jxPlug: ['jxPlugList', 'jxPlugMap', 'jxPlugObjMap'],  // 解析插件
 }
 
 const stateMap = {}

+ 482 - 59
src/views/manage/service/detail.vue

@@ -15,32 +15,32 @@
           required
           label="数据服务名称"
           label-width="120px"
-          v-model:param="state.form.themeName"
+          v-model:param="state.form.serviceName"
         />
         <CusFormColumn
           :span="8"
           required
           label="归属插件"
-          v-model:param="state.form.themeType"
+          v-model:param="state.form.affiliationPlugin"
           link="select"
-          :options="DictionaryStore.themeTypeList"
+          :options="DictionaryStore.gsPlugList"
+          @change="onChangeGsPlug"
         />
         <CusFormColumn
           :span="8"
           required
           label="插件类型"
-          v-model:param="state.form.themeState"
-          link="select"
-          :options="DictionaryStore.themeStatusList"
+          v-model:param="state.form.pluginType"
           :disabled="true"
         />
         <CusFormColumn
+          v-if="state.form.pluginType === 'http'"
           :span="24"
           required
-          v-model:param="state.form.themeName"
+          v-model:param="state.form.requestUrl"
         >
           <template #prepend>
-            <el-select v-model="state.form.xx" placeholder="Select" style="width: 115px">
+            <el-select v-model="state.form.requestType" placeholder="请求类型" style="width: 115px">
               <template v-for="item in DictionaryStore.requestTypeList">
                 <el-option :label="item.dictLabel" :value="item.dictValue" />
               </template>
@@ -48,7 +48,15 @@
           </template>
         </CusFormColumn>
       </CusForm>
-      <CusTab :tabs="state.params.options" type="type1" v-model:param="state.params.tab"/>
+      <CusTab :tabs="state.form.pluginType === 'http' ? [
+        {name: 'Request Params', value: 1},
+        {name: 'Request Headers', value: 2},
+        {name: 'Request Body', value: 3},
+        {name: 'Response Body', value: 4},
+      ] : [
+        {name: 'Request Params', value: 1},
+        {name: 'Response Body', value: 4},
+      ]" type="type1" v-model:param="state.params.tab"/>
       <div class="params-content">
         <template v-if="state.params.tab == 1">
           <div class="request-params">
@@ -93,7 +101,7 @@
                 />
               </template>
               <template #do-column-value="{scope}">
-                <CusButton v-if="state.params.requestParams.data.length > 1" type="table-del" @click="state.params.requestParams.data.splice(scope.$index, 1)"/>
+                <CusButton type="table-del" @click="state.params.requestParams.data.splice(scope.$index, 1)"/>
               </template>
             </CusTable>
           </div>
@@ -141,7 +149,7 @@
                 />
               </template>
               <template #do-column-value="{scope}">
-                <CusButton v-if="state.params.requestHeaders.data.length > 1" type="table-del" @click="state.params.requestHeaders.data.splice(scope.$index, 1)"/>
+                <CusButton type="table-del" @click="state.params.requestHeaders.data.splice(scope.$index, 1)"/>
               </template>
             </CusTable>
           </div>
@@ -153,7 +161,7 @@
                 :span="24"
                 v-model:param="state.params.requestBody.type"
                 link="radio"
-                :options="DictionaryStore.RequestBodyList"
+                :options="DictionaryStore.requestBodyList"
                 @change="onChangeRequestBodyType"
               />
               <CusFormColumn
@@ -182,6 +190,9 @@
               <div style="margin-bottom: 10px; display: flex">
                 <CusButton type="main" title="新增" style="margin-right: auto;" @click="state.params.requestBody.data.push({key: '', type: '1', value: '', valueTable: []})"/>
                 <template v-if="['RAW_JSON', 'RAW_TEXT', 'RAW_XML', 'RAW_HTML'].includes(state.params.requestBody.type)">
+                  <div class="tips" style="margin: 0 10px">
+                    为了保证数据结构准确,提交时将默认触发“<span style="color: var(--cus-main-color)">逆向生成JSON结构</span>”
+                  </div>
                   <CusButton type="main" title="正向解析JSON结构" style="margin-left: auto" @click="jsonToTable"/>
                   <CusButton type="main" title="逆向生成JSON结构" @click="tableToJson"/>
                 </template>
@@ -232,12 +243,282 @@
             </template>
           </div>
         </template>
-        <template v-else-if="state.params.tab == 4"></template>
+        <template v-else-if="state.params.tab == 4">
+          <div class="response-body">
+            <CusForm label-width="80px">
+              <CusFormColumn
+                :span="24"
+                v-model:param="state.params.responseBody.type"
+                link="radio"
+                :options="DictionaryStore.responseBodyList"
+              />
+              <template v-if="state.params.responseBody.type == 1 || state.params.responseBody.type == 2">
+                <el-col :span="24">
+                  <div class="tips">
+                    @代表返回的数据,如下返回结果,匹配总数为"<span style="color: var(--cus-main-color)">@.data.total</span>"
+                    <br/>
+                    {code: 200,data: {pageNum: 1, pageSize: 10, data: [], total: 0},msg: ''}
+                  </div>
+                </el-col>
+              </template>
+              <template v-if="state.params.responseBody.type == 1">
+                <CusFormColumn
+                  :span="6"
+                  required
+                  v-model:param="state.params.responseBody.json.pathForm.pageNum"
+                  label="当前页"
+                />
+                <CusFormColumn
+                  :span="6"
+                  required
+                  v-model:param="state.params.responseBody.json.pathForm.pageSize"
+                  label="每页数"
+                />
+                <CusFormColumn
+                  :span="6"
+                  v-model:param="state.params.responseBody.json.pathForm.pageTotal"
+                  label="总页数"
+                />
+                <CusFormColumn
+                  :span="6"
+                  required
+                  v-model:param="state.params.responseBody.json.pathForm.total"
+                  label="总数"
+                />
+                <CusFormColumn
+                  :span="6"
+                  required
+                  v-model:param="state.params.responseBody.json.pathForm.data"
+                  label="结果集"
+                />
+              </template>
+            </CusForm>
+            <template v-if="state.params.responseBody.type == 1">
+              <div style="margin-bottom: 10px; display: flex">
+                <CusButton type="main" title="新增" style="margin-right: auto;" @click="state.params.responseBody.json.data.push({label: '', key: '', valueType: '1', value: '', formatType: '1', formatRule: ''})"/>
+                <div class="tips" style="margin-left: 10px">
+                  取值类型为JsonPath时,@代表返回的数据(逻辑同上),也可以直接写字段名进行匹配
+                </div>
+              </div>
+              <CusTable
+                :data="state.params.responseBody.json.data"
+                :table-head="state.params.responseBody.json.tableHead"
+                :no-page="true"
+              >
+                <template #label-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.label"
+                  />
+                </template>
+                <template #key-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.key"
+                  />
+                </template>
+                <template #valueType-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.valueType"
+                    link="select"
+                    :options="DictionaryStore.qzTypeList"
+                    :clearable="false"
+                  />
+                </template>
+                <template #value-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.value"
+                  />
+                </template>
+                <template #formatType-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.formatType"
+                    link="select"
+                    :options="DictionaryStore.formatTypeList"
+                    :clearable="false"
+                    @change="scope.row.formatRule = ''"
+                  />
+                </template>
+                <template #formatRule-column-value="{scope}">
+                  <template v-if="scope.row.formatType == 1">
+<!--                    <CusFormColumn-->
+<!--                      class="__cus-table-form-column"-->
+<!--                      :span="24"-->
+<!--                      v-model:param="scope.row.formatRule"-->
+<!--                    />-->
+                  </template>
+                  <template v-else-if="scope.row.formatType == 2">
+                    <CusFormColumn
+                      class="__cus-table-form-column"
+                      :span="24"
+                      v-model:param="scope.row.formatRule"
+                      link="select"
+                      static
+                      :options="[
+                        {dictLabel: 'yyyy', dictValue: 'yyyy'},
+                        {dictLabel: 'yyyy-MM', dictValue: 'yyyy-MM'},
+                        {dictLabel: 'yyyy-MM-dd', dictValue: 'yyyy-MM-dd'},
+                        {dictLabel: 'yyyy-MM-dd HH', dictValue: 'yyyy-MM-dd HH'},
+                        {dictLabel: 'yyyy-MM-dd HH:mm', dictValue: 'yyyy-MM-dd HH:mm'},
+                        {dictLabel: 'yyyy-MM-dd HH:mm:ss', dictValue: 'yyyy-MM-dd HH:mm:ss'},
+                      ]"
+                      :clearable="false"
+                    />
+                  </template>
+                  <template v-else-if="scope.row.formatType == 3">
+                    <CusFormColumn
+                      class="__cus-table-form-column"
+                      :span="24"
+                      v-model:param="scope.row.formatRule"
+                      :readonly="true"
+                      @click="onClickFormatRuleDictJson(scope.row, scope.$index)"
+                    />
+                  </template>
+                </template>
+                <template #do-column-value="{scope}">
+                  <CusButton  type="table-del" @click="state.params.responseBody.json.data.splice(scope.$index, 1)"/>
+                </template>
+              </CusTable>
+            </template>
+            <template v-if="state.params.responseBody.type == 2">
+              <CusTable
+                :data="state.params.responseBody.text.data"
+                :table-head="state.params.responseBody.text.tableHead"
+                :no-page="true"
+              >
+                <template #label-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.label"
+                  />
+                </template>
+                <template #key-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.key"
+                  />
+                </template>
+                <template #valueType-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.valueType"
+                    link="select"
+                    :options="DictionaryStore.qzTypeList"
+                    :clearable="false"
+                  />
+                </template>
+                <template #value-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.value"
+                  />
+                </template>
+                <template #formatType-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.formatType"
+                    link="select"
+                    :options="DictionaryStore.formatTypeList"
+                    :clearable="false"
+                    @change="scope.row.formatRule = ''"
+                  />
+                </template>
+                <template #formatRule-column-value="{scope}">
+                  <template v-if="scope.row.formatType == 1">
+                    <!--                    <CusFormColumn-->
+                    <!--                      class="__cus-table-form-column"-->
+                    <!--                      :span="24"-->
+                    <!--                      v-model:param="scope.row.formatRule"-->
+                    <!--                    />-->
+                  </template>
+                  <template v-else-if="scope.row.formatType == 2">
+                    <CusFormColumn
+                      class="__cus-table-form-column"
+                      :span="24"
+                      v-model:param="scope.row.formatRule"
+                      link="select"
+                      static
+                      :options="[
+                        {dictLabel: 'yyyy', dictValue: 'yyyy'},
+                        {dictLabel: 'yyyy-MM', dictValue: 'yyyy-MM'},
+                        {dictLabel: 'yyyy-MM-dd', dictValue: 'yyyy-MM-dd'},
+                        {dictLabel: 'yyyy-MM-dd HH', dictValue: 'yyyy-MM-dd HH'},
+                        {dictLabel: 'yyyy-MM-dd HH:mm', dictValue: 'yyyy-MM-dd HH:mm'},
+                        {dictLabel: 'yyyy-MM-dd HH:mm:ss', dictValue: 'yyyy-MM-dd HH:mm:ss'},
+                      ]"
+                      :clearable="false"
+                    />
+                  </template>
+                  <template v-else-if="scope.row.formatType == 3">
+                    <CusFormColumn
+                      class="__cus-table-form-column"
+                      :span="24"
+                      v-model:param="scope.row.formatRule"
+                      :readonly="true"
+                      @click="onClickFormatRuleDictText(scope.row, scope.$index)"
+                    />
+                  </template>
+                </template>
+              </CusTable>
+            </template>
+            <template v-if="state.params.responseBody.type == 3">
+              <div style="margin-bottom: 10px; display: flex">
+                <CusButton type="main" title="新增" style="margin-right: 10px;" @click="state.params.responseBody.other.data.push({label: '', key: ''})"/>
+                <CusFormColumn
+                  class="__cus-table-form-column"
+                  :span="6"
+                  v-model:param="state.params.responseBody.other.plug"
+                  link="select"
+                  :options="DictionaryStore.jxPlugList"
+                  :clearable="false"
+                />
+              </div>
+              <CusTable
+                :data="state.params.responseBody.other.data"
+                :table-head="state.params.responseBody.other.tableHead"
+                :no-page="true"
+              >
+                <template #label-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.label"
+                  />
+                </template>
+                <template #key-column-value="{scope}">
+                  <CusFormColumn
+                    class="__cus-table-form-column"
+                    :span="24"
+                    v-model:param="scope.row.key"
+                  />
+                </template>
+                <template #do-column-value="{scope}">
+                  <CusButton type="table-del" @click="state.params.requestBody.other.data.splice(scope.$index, 1)"/>
+                </template>
+              </CusTable>
+            </template>
+          </div>
+        </template>
       </div>
     </div>
     <complexRequestParams v-model:show="state.complexRequestParams.show" :transfer="state.complexRequestParams.transfer" @complex="getComplexRequestParams"/>
     <complexRequestParams v-model:show="state.complexRequestHeaders.show" :transfer="state.complexRequestHeaders.transfer" @complex="getComplexRequestHeaders"/>
     <complexRequestParams v-model:show="state.complexRequestBody.show" :transfer="state.complexRequestBody.transfer" @complex="getComplexRequestBody"/>
+    <formatRuleDict v-model:show="state.formatRuleDictJson.show" :transfer="state.formatRuleDictJson.transfer" @dict="getDictJson"/>
+    <formatRuleDict v-model:show="state.formatRuleDictText.show" :transfer="state.formatRuleDictText.transfer" @dict="getDictText"/>
   </CusDialog>
 </template>
 
@@ -246,6 +527,8 @@ import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from "vue"
 import {useDictionaryStore} from "@/stores";
 import {ElMessage, ElMessageBox} from "element-plus";
 import complexRequestParams from './complex-params.vue'
+import formatRuleDict from './format-rule-dict.vue'
+import {outsideServiceSaveOrUpdate} from "@/api/modules/manage/service";
 
 const emit = defineEmits(['update:show', 'refresh'])
 const {proxy} = getCurrentInstance()
@@ -255,16 +538,12 @@ const props = defineProps({
   transfer: {}
  })
 const state: any = reactive({
-  form: {},
+  form: {
+    requestType: 'GET'
+  },
   loading: false,
   params: {
     tab: 1,
-    options: [
-      {name: 'Request Params', value: 1},
-      {name: 'Request Headers', value: 2},
-      {name: 'Request Body', value: 3},
-      {name: 'Response Body', value: 4},
-    ],
     requestParams: {
       tableHead: [
         {value: "key", label: "键名"},
@@ -296,6 +575,40 @@ const state: any = reactive({
         {value: "do", label: "操作", width: 120, fixed: 'right'},
       ],
       data: []
+    },
+    responseBody: {
+      type: '1',
+      json: {
+        pathForm: {},
+        tableHead: [
+          {value: "label", label: "列名"},
+          {value: "key", label: "键名"},
+          {value: "valueType", label: "取值类型", width: 160},
+          {value: "value", label: "取值规则"},
+          {value: "formatType", label: "格式类型", width: 160},
+          {value: "formatRule", label: "格式转换规则"},
+          {value: "do", label: "操作", width: 120, fixed: 'right'},
+        ],
+        data: []
+      },
+      text: {
+        tableHead: [
+          {value: "label", label: "列名"},
+          {value: "key", label: "键名"},
+          {value: "formatType", label: "格式类型", width: 160},
+          {value: "formatRule", label: "格式转换规则"},
+        ],
+        data: [{label: '', key: '', formatType: '1', formatRule: ''}]
+      },
+      other: {
+        plug: '',
+        tableHead: [
+          {value: "label", label: "列名"},
+          {value: "key", label: "键名"},
+          {value: "do", label: "操作", width: 120, fixed: 'right'},
+        ],
+        data: []
+      }
     }
   },
   complexRequestParams: {
@@ -312,6 +625,16 @@ const state: any = reactive({
     show: false,
     transfer: {},
     index: 0
+  },
+  formatRuleDictJson: {
+    show: false,
+    transfer: {},
+    index: 0
+  },
+  formatRuleDictText: {
+    show: false,
+    transfer: {},
+    index: 0
   }
 })
 const ref_form = ref()
@@ -326,46 +649,99 @@ const titleCpt = computed(() => {
   return t
 })
 const onSubmit = () => {
-  if (!state.params.requestParams.data.every(v => proxy.$util.isValue(v.key) && proxy.$util.isValue(v.value))) {
-    ElMessage.error('请完善Request Params参数信息!')
-    state.params.tab = 1
-    return
-  }
-  if (!state.params.requestHeaders.data.every(v => proxy.$util.isValue(v.key) && proxy.$util.isValue(v.value))) {
-    ElMessage.error('请完善Request Headers参数信息!')
-    state.params.tab = 2
-    return
-  }
   ref_form.value.submit().then(() => {
+    const params = {...state.form}
+    // requestParams
+    if (!state.params.requestParams.data.every(v => proxy.$util.isValue(v.key) && proxy.$util.isValue(v.value))) {
+      ElMessage.error('请完善Request Params参数信息!')
+      state.params.tab = 1
+      return
+    }
+    params.requestParams = state.params.requestParams.data.length > 0 ? JSON.stringify(state.params.requestParams.data) : null
+    if (state.form.pluginType === 'http') {
+      // requestHeaders
+      if (!state.params.requestHeaders.data.every(v => proxy.$util.isValue(v.key) && proxy.$util.isValue(v.value))) {
+        ElMessage.error('请完善Request Headers参数信息!')
+        state.params.tab = 2
+        return
+      }
+      params.requestHeaders = state.params.requestHeaders.data.length > 0 ? JSON.stringify(state.params.requestHeaders.data) : null
+      // requestBody
+      if (!state.params.requestBody.data.every(v => proxy.$util.isValue(v.key) && proxy.$util.isValue(v.value) && proxy.$util.isValue(v.type) && (v.type != 3 || v.type == 3 && v.valueTable.length > 0))) {
+        ElMessage.error('请完善Request Body参数信息!')
+        state.params.tab = 3
+        return
+      }
+      if (['RAW_JSON', 'RAW_TEXT', 'RAW_XML', 'RAW_HTML'].includes(state.params.requestBody.type) && state.params.requestBody.data.length > 0) {
+        try {
+          tableToJson()
+        } catch (e) {
+
+        }
+      } else {
+        state.params.requestBody.str = ''
+      }
+      params.requestBody = JSON.stringify({
+        type: state.params.requestBody.type,
+        str: state.params.requestBody.str,
+        data: state.params.requestBody.data.length > 0 ? state.params.requestBody.data : null
+      })
+    }
+    // responseBody
+    if (state.params.responseBody.type == '1') {
+      if (
+        !proxy.$util.isValue(state.params.responseBody.json.pathForm.pageNum) ||
+        !proxy.$util.isValue(state.params.responseBody.json.pathForm.pageSize) ||
+        !proxy.$util.isValue(state.params.responseBody.json.pathForm.total) ||
+        !proxy.$util.isValue(state.params.responseBody.json.pathForm.data) ||
+        !state.params.responseBody.json.data.every(v => proxy.$util.isValue(v.label) && proxy.$util.isValue(v.key) && proxy.$util.isValue(v.valueType) && proxy.$util.isValue(v.value) && proxy.$util.isValue(v.formatType) && (v.formatType == 1 || v.formatType != 1 && proxy.$util.isValue(v.formatRule)))
+      ) {
+        ElMessage.error('请完善Response Body参数信息!')
+        state.params.tab = 4
+        return
+      }
+    } else if (state.params.responseBody.type == '2') {
+      if (!state.params.responseBody.text.data.every(v => proxy.$util.isValue(v.label) && proxy.$util.isValue(v.key) && proxy.$util.isValue(v.valueType) && proxy.$util.isValue(v.value) && proxy.$util.isValue(v.formatType) && (v.formatType != 1 && proxy.$util.isValue(v.formatRule)))) {
+        ElMessage.error('请完善Response Body参数信息!')
+        state.params.tab = 4
+        return
+      }
+    } else if (state.params.responseBody.type == '3') {
+      if (!state.params.responseBody.other.plug || !state.params.responseBody.other.data.every(v => proxy.$util.isValue(v.label) && proxy.$util.isValue(v.key))) {
+        ElMessage.error('请完善Response Body参数信息!')
+        state.params.tab = 4
+        return
+      }
+    }
+    params.responseBody = JSON.stringify({
+      type: state.params.responseBody.type,
+      json: {
+        pathForm: state.params.responseBody.json.pathForm,
+        data: state.params.responseBody.json.data.length > 0 ? state.params.responseBody.json.data : null
+      },
+      text: {
+        data: state.params.responseBody.text.data.length > 0 ? state.params.responseBody.text.data : null
+      },
+      other: {
+        plug: state.params.responseBody.other.plug,
+        data: state.params.responseBody.other.data.length > 0 ? state.params.responseBody.other.data : null
+      }
+    })
+    console.log(params)
     ElMessageBox.confirm("是否提交?", "提示", {
       confirmButtonText: "确定",
       cancelButtonText: "取消",
       type: "warning",
     } as any).then(() => {
       state.loading = true
-      // const params = JSON.parse(JSON.stringify(state.form))
-      // if (params.themeType == '2') {
-      //   params.themeParam = params.themeParam.join(',')
-      // }
-      // if (props.transfer.mode === 'add') {
-      //   sysThemeAdd(params).then(res => {
-      //     ElMessage.success('新增成功!')
-      //     emit('update:show', false)
-      //     emit('refresh')
-      //     state.loading = false
-      //   }).catch(() => {
-      //     state.loading = false
-      //   })
-      // } else if (props.transfer.mode === 'edit') {
-      //   sysThemeUpdate(params).then(res => {
-      //     ElMessage.success('编辑成功!')
-      //     emit('update:show', false)
-      //     emit('refresh')
-      //     state.loading = false
-      //   }).catch(() => {
-      //     state.loading = false
-      //   })
-      // }
+      outsideServiceSaveOrUpdate(params).then(res => {
+        ElMessage.success(props.transfer.mode === 'add' ? '新增成功!' : '编辑成功!')
+        emit('update:show', false)
+        emit('refresh')
+        state.loading = false
+      }).catch(() => {
+        state.loading = false
+      })
     }).catch(() => {})
   }).catch((e) => {
     ElMessage({
@@ -385,6 +761,9 @@ const initDetail = () => {
   //   state.loading = false
   // })
 }
+const onChangeGsPlug = (val) => {
+  state.form.pluginType = DictionaryStore.gsPlugObjMap.get(val)?.type
+}
 const onClickComplexRequestParams = (row, index) => {
   if (row.type == 3) {
     state.complexRequestParams.transfer = {
@@ -456,15 +835,49 @@ const onChangeRequestBodyType = (val) => {
     })
   }
 }
+const onClickFormatRuleDictJson = (row, index) => {
+  state.formatRuleDictJson.transfer = {
+    formatRule: row.formatRule,
+    index: index
+  }
+  state.formatRuleDictJson.show = true
+}
+const getDictJson = (dict) => {
+  state.params.responseBody.json.data[state.formatRuleDictJson.transfer.index].formatRule = [...dict]
+}
+const onClickFormatRuleDictText = (row, index) => {
+  state.formatRuleDictText.transfer = {
+    formatRule: row.formatRule,
+    index: index
+  }
+  state.formatRuleDictText.show = true
+}
+const getDictText = (dict) => {
+  state.params.responseBody.text.data[state.formatRuleDictText.transfer.index].formatRule = [...dict]
+}
 watch(() => props.show, (n) => {
   if (n) {
     state.loading = false
     initDictionary()
-    // if (props.transfer.mode === 'add') {
-    //   state.form = {}
-    // } else {
-    //   initDetail()
-    // }
+    if (props.transfer.mode === 'add') {
+      state.form = {
+        requestType: 'GET'
+      }
+      state.params.tab = 1
+      state.params.requestParams.data = []
+      state.params.requestHeaders.data = []
+      state.params.requestBody.type = 'NONE'
+      state.params.requestBody.str = 'NONE'
+      state.params.requestBody.data = []
+      state.params.responseBody.type = '1'
+      state.params.responseBody.json.pathForm = {}
+      state.params.responseBody.json.data = []
+      state.params.responseBody.text.data = [{label: '', key: '', formatType: '1', formatRule: ''}]
+      state.params.responseBody.other.plug = ''
+      state.params.responseBody.other.data = []
+    } else {
+      initDetail()
+    }
     nextTick(() => {
       ref_form.value.reset()
     })
@@ -474,6 +887,9 @@ const initDictionary = () => {
   DictionaryStore.initDict('request_type')
   DictionaryStore.initDict('request_params')
   DictionaryStore.initDict('request_body')
+  DictionaryStore.initDict('response_body')
+  DictionaryStore.initDict('qz_type')
+  DictionaryStore.initDict('format_type')
 }
 </script>
 
@@ -487,11 +903,18 @@ const initDictionary = () => {
   flex: 1;
   margin-top: 20px;
   overflow: hidden;
-  .request-params, .request-headers, .request-body {
+  .request-params, .request-headers, .request-body, .response-body {
     width: 100%;
     height: 100%;
     display: flex;
     flex-direction: column;
   }
 }
+.tips {
+  background-color: rgba(var(--cus-main-color-rgb), 0.1);
+  border-radius: 6px;
+  padding: 7px;
+  margin-bottom: 10px;
+  width: 100%;
+}
 </style>

+ 113 - 0
src/views/manage/service/format-rule-dict.vue

@@ -0,0 +1,113 @@
+<template>
+  <CusDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    width="80%"
+    height="80%"
+    @onSubmit="onSubmit"
+    :loading="state.loading"
+  >
+    <div class="__cus-dialog-form">
+      <div style="margin-bottom: 10px; display: flex">
+        <CusButton type="main" title="新增" @click="state.data.push({key: '', value: ''})"/>
+      </div>
+      <CusForm ref="ref_form" label-width="100px">
+        <CusTable
+          :data="state.data"
+          :table-head="state.tableHead"
+          :no-page="true"
+        >
+          <template #key-column-value="{scope}">
+            <CusFormColumn
+              class="__cus-table-form-column"
+              required
+              :span="24"
+              v-model:param="scope.row.key"
+            />
+          </template>
+          <template #value-column-value="{scope}">
+            <CusFormColumn
+              class="__cus-table-form-column"
+              required
+              :span="24"
+              v-model:param="scope.row.value"
+            />
+          </template>
+          <template #do-column-value="{scope}">
+            <CusButton type="table-del" @click="state.data.splice(scope.$index, 1)"/>
+          </template>
+        </CusTable>
+      </CusForm>
+    </div>
+  </CusDialog>
+</template>
+
+<script setup lang="ts">
+import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from "vue";
+import {useDictionaryStore} from "@/stores";
+import {ElMessage, ElMessageBox} from "element-plus";
+
+const emit = defineEmits(['update:show', 'dict'])
+const {proxy} = getCurrentInstance()
+const DictionaryStore = useDictionaryStore()
+const props = defineProps({
+  show: {default: false},
+  transfer: {}
+ })
+const state: any = reactive({
+  tableHead: [
+    {value: "key", label: "字典键值"},
+    {value: "value", label: "字典名称"},
+    {value: "do", label: "操作", width: 120, fixed: 'right'},
+  ],
+  data: []
+})
+const ref_form = ref()
+const titleCpt = computed(() => {
+  let t = '转换规则-字典值'
+  return t
+})
+const onSubmit = () => {
+  ref_form.value.submit().then(() => {
+    const map = new Map()
+    state.data.forEach(v => {
+      map.set(v.key, v.value)
+    })
+    if (map.size < state.data.length) {
+      ElMessage.error('字典键值不可重复!')
+      return
+    }
+    ElMessageBox.confirm("是否提交?", "提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      type: "warning",
+    } as any).then(() => {
+      emit('update:show', false)
+      emit('dict', state.data)
+    }).catch(() => {})
+  }).catch((e) => {
+    ElMessage({
+      message: e[0].message,
+      grouping: true,
+      type: 'warning',
+    })
+  })
+}
+watch(() => props.show, (n) => {
+  if (n) {
+    state.data = typeof props.transfer.formatRule === 'object' ? [...props.transfer.formatRule] : []
+    nextTick(() => {
+      ref_form.value.reset()
+    })
+  }
+})
+</script>
+
+<style lang="scss" scoped>
+.__cus-dialog-form {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 54 - 20
src/views/manage/service/index.vue

@@ -5,22 +5,22 @@
       <CusForm labelWidth="100px" @handleEnter="onSearch">
         <CusFormColumn
           :span="8"
-          v-model:param="state.query.form.xx"
+          v-model:param="state.query.form.serviceName"
           placeholder="服务名称"
         />
         <CusFormColumn
           :span="4"
-          label="属插件"
-          v-model:param="state.query.form.xx"
+          label="属插件"
+          v-model:param="state.query.form.affiliationPlugin"
           link="select"
-          :options="DictionaryStore.trueFalseList"
+          :options="DictionaryStore.gsPlugList"
         />
         <CusFormColumn
           :span="4"
           label="状态"
-          v-model:param="state.query.form.xx"
+          v-model:param="state.query.form.status"
           link="select"
-          :options="DictionaryStore.trueFalseList"
+          :options="DictionaryStore.roleStatusList"
         />
         <CusButton type="main" title="搜索" @click="onSearch"/>
         <CusButton type="main" title="重置" @click="onReset"/>
@@ -36,13 +36,16 @@
         :table-head="state.query.tableHead"
         @handlePage="onPage"
       >
-        <template #shareMethod-column-value="{scope}">
-          {{DictionaryStore.gxMethodMap.get(scope.row.shareMethod)}}
+        <template #affiliationPlugin-column-value="{scope}">
+          {{DictionaryStore.gsPlugMap.get(scope.row.affiliationPlugin)}}
+        </template>
+        <template #status-column-value="{scope}">
+          {{DictionaryStore.roleStatusMap.get(scope.row.status)}}
         </template>
         <template #do-column-value="{scope}">
           <CusButton type="table-edit" @click="onEdit(scope.row)"/>
-          <CusButton v-if="scope.row.xx == 1" type="table-edit" title="启用" @click="onEdit(scope.row)"/>
-          <CusButton v-else type="table-edit" title="停用" @click="onEdit(scope.row)"/>
+          <CusButton v-if="scope.row.status == 2" type="table-edit" title="启用" @click="onStatus(scope.row, '1')"/>
+          <CusButton v-else type="table-edit" title="禁用" @click="onStatus(scope.row, '2')"/>
           <CusButton type="table-del" @click="onDel(scope.row)"/>
           <CusButton type="table" icon="relation" title="关联主题" @click="onTheme(scope.row)"/>
         </template>
@@ -59,16 +62,18 @@
 import {getCurrentInstance, onMounted, reactive} from "vue";
 import {ElMessage, ElMessageBox} from "element-plus";
 import {
-  sysIndexCreateEsIndex,
   sysIndexDeleteIndexById,
-  sysIndexExport,
-  sysIndexFindIndexByPage
 } from "@/api/modules/manage";
 import DetailCom from "./detail.vue";
 // import RelationCom from "./relation.vue";
 // import TextCom from "./text.vue";
 // import ThemeCom from "./theme.vue";
 import {useDictionaryStore} from "@/stores";
+import {
+  outsideServiceFindByPage,
+  outsideServiceStatusUpdate, sysPluginGetAllParsePlugins,
+  sysPluginGetAllPlugins
+} from "@/api/modules/manage/service";
 
 const {proxy} = getCurrentInstance()
 const DictionaryStore = useDictionaryStore()
@@ -80,14 +85,14 @@ const state: any = reactive({
       pageSize: 10
     },
     tableHead: [
-      {value: "x", label: "服务名称", fixed: 'left', width: 180},
-      {value: "x", label: "所属插件", width: 180},
-      {value: "x", label: "插件类型", width: 100},
-      {value: "x", label: "状态", width: 80},
+      {value: "serviceName", label: "服务名称", fixed: 'left', width: 180},
+      {value: "affiliationPlugin", label: "归属插件", width: 180},
+      {value: "pluginType", label: "插件类型", width: 100},
+      {value: "status", label: "状态", width: 80},
       {value: "createTime", label: "创建时间", width: 200},
-      {value: "createBy", label: "创建人"},
+      {value: "createUserStr", label: "创建人"},
       {value: "updateTime", label: "最后修改时间", width: 200},
-      {value: "updateBy", label: "最后修改人"},
+      {value: "updateUserStr", label: "最后修改人"},
       {value: "do", label: "操作", width: 400, fixed: 'right'},
     ],
     form: {},
@@ -130,7 +135,7 @@ const onPage = (pageNum, pageSize) => {
     }
   }
   state.query.loading = true
-  sysIndexFindIndexByPage(proxy.$util.formatGetParam(params)).then(res => {
+  outsideServiceFindByPage(proxy.$util.formatGetParam(params)).then(res => {
     state.query.result.total = res.data.totalElements
     state.query.result.data = res.data.content
     state.query.loading = false
@@ -187,8 +192,37 @@ const onDel = (row) => {
     })
   }).catch(() => {})
 }
+const onStatus = (row, status) => {
+  ElMessageBox.confirm(`请确认是否${status == 1 ? '启用' : '禁用'}${row.serviceName}?`, "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  } as any).then(() => {
+    state.query.loading = true
+    outsideServiceStatusUpdate({id: row.id, status}).then(res => {
+      ElMessage.success(status == 1 ? '启用成功!' : '禁用成功!')
+      state.query.loading = false
+      onSearch()
+    })
+  }).catch(() => {})
+}
 const initDictionary = () => {
   DictionaryStore.initDict('gx_method')
+  DictionaryStore.initDict('role_status')
+  sysPluginGetAllPlugins().then(res => {
+    DictionaryStore.initOtherDict('gsPlug', res.data.map(v => {
+      v.dictLabel = v.pluginValue
+      v.dictValue = v.pluginKey
+      return v
+    }))
+  })
+  sysPluginGetAllParsePlugins().then(res => {
+    DictionaryStore.initOtherDict('jxPlug', res.data.map(v => {
+      v.dictLabel = v.parseValue
+      v.dictValue = v.parseKey
+      return v
+    }))
+  })
 }
 onMounted(() => {
   initDictionary()