Browse Source

interface组件查看/编辑/复制/新增和rule组件查看/编辑/复制/新增

qinzhipeng_v 6 years ago
parent
commit
9b7d5fbc40

+ 1 - 1
package.json

@@ -50,7 +50,7 @@
     "script-loader": "0.7.2",
     "serve-static": "^1.13.2",
     "svg-sprite-loader": "4.1.3",
-    " o": "1.2.2",
+    "svgo": "1.2.2",
     "vue-template-compiler": "2.6.10"
   },
   "engines": {

+ 59 - 0
src/api/httpmock.js

@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+// ================================== Interface ======================================
+
+export function fetchEnvInfo(envChannel) {
+  return request({
+    url: '/api/mock/envConfig/getAllEnvConfigByChannel',
+    method: 'get',
+    params: { channelId: envChannel }
+  })
+}
+
+export function fetchServiceById(data) {
+  return request({
+    url: '/api/mock/methodConfig/query',
+    method: 'post',
+    data
+  })
+}
+
+export function fetchServiceList(data) {
+  return request({
+    url: '/api/mock/methodConfig/query',
+    method: 'post',
+    data
+  })
+}
+
+export function fetchConsumerList() {
+  return request({
+    url: '/api/mock/dubboConsumer/getAll',
+    method: 'get',
+    params: {}
+  })
+}
+
+export function createService(data) {
+  return request({
+    url: '/api/mock/methodConfig/add',
+    method: 'post',
+    data
+  })
+}
+
+export function updateService(data) {
+  return request({
+    url: '/api/mock/methodConfig/update',
+    method: 'post',
+    data
+  })
+}
+
+export function changeStatus(data) {
+  return request({
+    url: '/api/mock/methodConfig/changeStatus',
+    method: 'post',
+    data
+  })
+}

+ 43 - 0
src/api/httprule.js

@@ -0,0 +1,43 @@
+import request from '@/utils/request'
+
+// ================================== Rule ======================================
+
+export function fetchRuleById(data) {
+  return request({
+    url: '/api/mock/mockRule/query',
+    method: 'post',
+    data
+  })
+}
+
+export function fetchRuleList(data) {
+  return request({
+    url: '/api/mock/mockRule/query',
+    method: 'post',
+    data
+  })
+}
+
+export function createRule(data) {
+  return request({
+    url: '/api/mock/mockRule/add',
+    method: 'post',
+    data
+  })
+}
+
+export function updateRule(data) {
+  return request({
+    url: '/api/mock/mockRule/update',
+    method: 'post',
+    data
+  })
+}
+
+export function changeStatus(data) {
+  return request({
+    url: '/api/mock/mockRule/changeStatus',
+    method: 'post',
+    data
+  })
+}

+ 16 - 2
src/router/index.js

@@ -75,13 +75,27 @@ export const constantRoutes = [
         path: 'interface',
         name: 'Interface',
         component: () => import('@/views/mock/interface'),
-        meta: { title: '接口', icon: 'interface' }
+        meta: { title: 'dubbo mock', icon: 'interface' }
       },
       {
         path: 'interface/:rule',
         name: 'Rule',
+        hidden: true,
         component: () => import('@/views/mock/rule'),
-        meta: { title: '规则', icon: 'rule' }
+        meta: { title: '规则' }
+      },
+      {
+        path: 'httpmock',
+        name: 'httpmock',
+        component: () => import('@/views/mock/httpmock'),
+        meta: { title: 'http mock', icon: 'rule' }
+      },
+      {
+        path: 'httpmock/:httprule',
+        name: 'Httprule',
+        hidden: true,
+        component: () => import('@/views/mock/httprule'),
+        meta: { title: '规则' }
       }
     ]
   },

+ 2 - 1
src/styles/sidebar.scss

@@ -79,7 +79,7 @@
     & .el-submenu .el-menu-item {
       min-width: $sideBarWidth !important;
       background-color: $subMenuBg !important;
-
+      
       &:hover {
         background-color: $subMenuHover !important;
       }
@@ -182,6 +182,7 @@
 
   .nest-menu .el-submenu>.el-submenu__title,
   .el-menu-item {
+    
     &:hover {
       // you can use $subMenuHover
       background-color: $menuHover !important;

+ 647 - 0
src/views/mock/httpmock.vue

@@ -0,0 +1,647 @@
+<template style="height=0px;improtanent">
+  <div class="app-container">
+    <el-header style="height: auto;!improtant">
+      <div class="filter-container" style="padding-bottom: 20px;!improtant">
+        <el-input v-model="listQuery.id" placeholder="ID" style="width: 80px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-input v-model="listQuery.customName" placeholder="接口名称" style="width: 150px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-input v-model="listQuery.interfaceName" placeholder="url" style="width: 100px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <!-- <el-input v-model="listQuery.methodName" placeholder="方法名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-input v-model="listQuery.serviceVersion" placeholder="版本" style="width: 100px;" class="filter-item" @keyup.enter.native="handleFilter" /> -->
+        <el-select v-model="listQuery.importance" placeholder="method" clearable style="width: 90px" class="filter-item">
+          <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" />
+        </el-select>
+        <el-select v-model="listQuery.type" placeholder="data类型" clearable class="filter-item" style="width: 130px">
+          <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" />
+        </el-select>
+        <el-select v-model="listQuery.value" placeholder="状态" style="width: 100px;" class="filter-item" @change="handleFilter">
+          <el-option v-for="item in listQuery.options" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
+        <el-input v-model="listQuery.methodName" placeholder="真实服务URL" style="width: 100px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-input v-model="listQuery.serviceVersion" placeholder="创建人" style="width: 100px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
+          搜索
+        </el-button>
+        <el-button class="filter-item" style="margin-left: 1px;" type="primary" icon="el-icon-edit" @click="handleCreate">
+          新增
+        </el-button>
+        <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:1px;" @change="tableKey=tableKey+1">
+          备注
+        </el-checkbox>
+      </div>
+    </el-header>
+    <!-- <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> -->
+    <el-table
+      :key="tableKey"
+      v-loading="listLoading"
+      :data="list"
+      border
+      fit
+      highlight-current-row
+      style="width: 100%;"
+      @sort-change="sortChange"
+    >
+      <el-table-column label="接口ID" prop="id" sortable="custom" align="center" width="70px">
+        <template slot-scope="scope">
+          <span>{{ scope.row.id }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="接口名称" width="150px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.customName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="url" width="100px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.interfaceName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="method" min-width="120px">
+        <template slot-scope="{row}">
+          <span>{{ row.serviceVersion }}</span>
+          <!-- <el-tag>{{ row.type | typeFilter }}</el-tag> -->
+        </template>
+      </el-table-column>
+      <el-table-column label="data类型" width="110px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.methodName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" class-name="status-col" width="100">
+        <template slot-scope="{row}">
+          <el-tag :type="row.methodStatus | statusFilter">
+            {{ statusMappings.get(row.methodStatus) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="真实服务URL" width="110px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.methodName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建人" align="center" width="95">
+        <template slot-scope="{row}">
+          <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
+          <span v-else>0</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新时间" width="150px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.updateTimeStr }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column v-if="showReviewer" label="备注" width="110px" align="center">
+        <template slot-scope="scope">
+          <span style="color:red;">{{ scope.row.remark }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="370px" class-name="small-padding fixed-width">
+        <template slot-scope="{row}">
+          <el-button type="primary" size="mini" @click="handleCheck(row)">
+            查看
+          </el-button>
+          <el-button type="primary" size="mini" @click="handleUpdate(row)">
+            编辑
+          </el-button>
+          <el-button type="primary" size="mini" @click="handleCopy(row)">
+            复制
+          </el-button>
+          <el-button v-if="row.methodStatus!=1" size="mini" type="success" @click="handleModifyStatus(row, 1)">
+            开启
+          </el-button>
+          <el-button v-if="row.methodStatus!=0" size="mini" type="danger" @click="handleModifyStatus(row, 0)">
+            关闭
+          </el-button>
+          <el-button type="primary" size="mini" @click="redirectTo(row.id, row.methodName)">
+            规则 >>
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.curIndex" :limit.sync="listQuery.pageSize" @pagination="getList" />
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%" @open="dialogOpenInit()">
+      <el-form ref="serviceDataForm" :rules="serviceDataRules" :model="serviceData" label-position="left" label-width="120px" style="width: 500px; margin-left:80px;">
+        <el-form-item label="名称" prop="customName">
+          <el-input v-model="serviceData.customName" placeholder="dj_order_圈司机" />
+        </el-form-item>
+        <div style="display:flex; margin-left:0px;">
+          <el-form-item label="环境配置" prop="envChannel" style="flex:1;">
+            <el-select v-model="serviceData.envChannel" class="filter-item" style="width: 190px;" filterable placeholder="环境配置" @change="updateEnvChannel(serviceData.envChannel)">
+              <el-option v-for="item in envTypeSelections" :key="item.key" :label="item.display_name" :value="item.key" />
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="envId" style="flex:1; margin-left:-120px;">
+            <el-select v-model="serviceData.envId" class="filter-item" style="width: 190px;" filterable placeholder="环境" @change="showZkAddress">
+              <el-option v-for="item in envSelections" :key="item.key" :label="item.display_name" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </div>
+        <el-form-item label="接口类名" prop="interfaceName">
+          <el-input v-model="serviceData.interfaceName" placeholder="com.didi.prado.config.api.CampaignRemoteServce" />
+        </el-form-item>
+        <el-form-item label="方法名" prop="methodName">
+          <el-input v-model="serviceData.methodName" placeholder="addCampaign" />
+        </el-form-item>
+        <el-form-item label="服务版本" prop="serviceVersion">
+          <el-input v-model="serviceData.serviceVersion" placeholder="1.0.0_test" />
+        </el-form-item>
+        <el-form-item label="协议" prop="protocol">
+          <el-select v-model="serviceData.protocol" class="filter-item" filterable clearable placeholder="协议">
+            <el-option v-for="item in protocols" :key="item.key" :label="item.display_name" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="消费者" prop="consumerIds">
+          <el-select v-model="serviceData.consumerIds" class="filter-item" multiple placeholder="消费者">
+            <el-option v-for="item in consumerSelections" :key="item.key" :label="item.display_name" :value="item.key" />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="Date" prop="timestamp">
+          <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" />
+        </el-form-item>
+        <el-form-item label="Status">
+          <el-select v-model="temp.status" class="filter-item" placeholder="Please select">
+            <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="Imp">
+          <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" />
+        </el-form-item> -->
+        <el-form-item label="入参类型" prop="methodParamsTypes">
+          <el-input v-model="serviceData.methodParamsTypes" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" placeholder="[java.lang.Integer, com.didi.prado.config.api.param.CampaignRequest]" />
+        </el-form-item>
+        <el-form-item label="返回值类型" prop="returnDataStructure">
+          <el-input v-model="serviceData.returnDataStructure" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" placeholder="{'data':'com.didi.order.api.response.BaserOrderInfoResult','data.feeInfo':'com.didi.order.api.response.FeeInfoResult'}" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">
+          取消
+        </el-button>
+        <el-button v-if="showSubmitBtn" type="primary" @click="dialogStatus==='create'?createData():updateData()">
+          确定
+        </el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
+      <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
+        <el-table-column prop="key" label="Channel" />
+        <el-table-column prop="pv" label="Pv" />
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<style scoped>
+</style>
+
+<script>
+import { fetchEnvInfo, fetchServiceById, fetchServiceList, fetchConsumerList, createService, updateService, changeStatus } from '@/api/httpmock'
+import waves from '@/directive/waves' // waves directive
+import { parseTime } from '@/utils'
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+
+const envTypeSelections = [
+  { key: 1, display_name: '自定义环境配置' },
+  { key: 2, display_name: '环境平台' }
+]
+
+var envSelections = []
+var consumerSelections = []
+
+const protocols = [
+  { key: 'dubbo', display_name: 'dubbo' }
+  // { key: 'http', display_name: 'http' }
+]
+
+// var envTypeID = 1;
+// arr to obj, such as { CN : "China", US : "USA" }
+// const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
+//   acc[cur.key] = cur.display_name
+//   return acc
+// }, {})
+
+export default {
+  name: 'Httpmock',
+  components: { Pagination },
+  directives: { waves },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        1: 'success',
+        draft: 'info',
+        0: 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: null,
+      total: 0,
+      listLoading: true,
+      statusMappings: new Map([[1, '已开启'], [0, '未开启']]),
+      statusOperateMap: new Map([[1, '开启'], [0, '关闭']]),
+      listQuery: {
+        options: [{ value: '0', label: '未开启' }, { value: '1', label: '已开启' }],
+        value: '',
+        curIndex: 1,
+        pageSize: 20,
+        customName: '',
+        interfaceName: '',
+        // page: 1,
+        // limit: 20,
+        // importance: undefined,
+        // title: undefined,
+        // type: undefined,
+        sort: '+id',
+        id: null,
+        methodName: '',
+        serviceVersion: '',
+        methodStatus: null
+      },
+      importanceOptions: [1, 2, 3],
+      envTypeSelections,
+      envSelections,
+      consumerSelections,
+      protocols,
+      sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
+      statusOptions: ['published', 'draft', 'deleted'],
+      showReviewer: false,
+      showSubmitBtn: true,
+      temp: {
+        id: undefined,
+        importance: 1,
+        remark: '',
+        timestamp: new Date(),
+        title: '',
+        type: '',
+        status: 'published'
+      },
+      serviceData: {
+        // bizLine: 0,
+        // bizModuleId: 0,
+        customName: '',
+        interfaceName: '',
+        protocol: '',
+        serviceVersion: '',
+        envChannel: 1,
+        envId: 0,
+        methodName: '',
+        methodParamsTypes: '',
+        returnDataStructure: '',
+        methodStatus: 1,
+        consumerIds: [],
+        remark: '',
+        updator: ''
+      },
+      // ConsumerIdsStr: this.serviceData.consumerIds.replace('[', '').replace(']', '').split(',').map(Number),
+      serviceDataExt: {
+        id: 0,
+        bizLine: 0,
+        bizModuleId: 0
+      },
+      dialogFormVisible: false,
+      dialogStatus: '',
+      textMap: {
+        update: '编辑',
+        create: '新增服务'
+      },
+      dialogPvVisible: false,
+      pvData: [],
+      serviceDataRules: {
+        customName: [{ required: true, message: '名称不能为空', trigger: 'change' }],
+        envChannel: [{ required: true, message: '请选择环境配置', trigger: 'change' }],
+        envId: [{ required: true, message: '请选择环境', trigger: 'change' }],
+        interfaceName: [{ required: true, message: '接口名称不能为空', trigger: 'change' }],
+        serviceVersion: [{ required: true, message: '服务版本不能为空', trigger: 'change' }],
+        protocol: [{ required: true, message: '请选择协议类型', trigger: 'change' }],
+        consumerIds: [{ required: false, message: '请选择消费者', trigger: 'change' }],
+        methodName: [{ required: true, message: '方法名称不能为空', trigger: 'change' }]
+        // methodParamsTypes: [{ required: true, message: '入参类型不能为空', trigger: 'change' }],
+        // returnDataStructure: [{ required: true, message: '返回值类型不能为空', trigger: 'change' }]
+      },
+      downloadLoading: false
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      fetchServiceList(this.listQuery).then(response => {
+        console.log(this.listQuery)
+        this.list = response.data.mockMethodList
+        this.total = response.data.total
+        // Just to simulate the time of the request
+        this.listLoading = false
+        // setTimeout(() => {
+        //   this.listLoading = false
+        // }, 1.5 * 1000)
+      })
+    },
+    updateEnvChannel(v) {
+      // console.log(v)
+      this.serviceData.envChannel = v
+      this.envSelections = []
+      fetchEnvInfo(v).then(response => {
+        for (var sel of response.data) {
+          var envSel = {}
+          envSel.key = sel.envId
+          envSel.display_name = sel.envName
+          this.envSelections.push(envSel)
+        }
+      })
+    },
+    getConsumers() {
+      this.consumerSelections = []
+      fetchConsumerList().then(response => {
+        for (var sel of response.data) {
+          var consumerSel = {}
+          consumerSel.key = sel.dubboConsumerId
+          consumerSel.display_name = sel.customizeName
+          this.consumerSelections.push(consumerSel)
+        }
+        // console.log(this.serviceData.consumerIds)
+        // for (var op of this.consumerSelections) {
+        //   if (op.key in this.serviceData.consumerIds) {
+        //     this.consumerSelected.push(op)
+        //     // this.consumerSelected = op.display_name
+        //   }
+        // }
+        // console.log(this.consumerSelected)
+      })
+    },
+    dialogOpenInit() {
+      this.updateEnvChannel(this.serviceData.envChannel)
+      this.getConsumers()
+    },
+    handleFilter() {
+      // this.listQuery.page = 1
+      this.listQuery.methodStatus = this.listQuery.value
+      this.getList()
+    },
+    handleModifyStatus(row, status) {
+      var statusData = {
+        id: row.id,
+        methodStatus: status
+      }
+      // console.log(statusData)
+      changeStatus(statusData).then(response => {
+        // console.log(response)
+        if (response.code === 200) {
+          row.methodStatus = status
+          this.$message({
+            message: row.id.toString() + ' ' + this.statusOperateMap.get(status) + '成功!',
+            type: 'success'
+          })
+        } else {
+          this.$message({
+            message: row.id.toString() + ' ' + this.statusOperateMap.get(status) + '失败!',
+            type: 'danger'
+          })
+        }
+      })
+    },
+    sortChange(data) {
+      const { prop, order } = data
+      if (prop === 'id') {
+        this.sortByID(order)
+      }
+    },
+    sortByID(order) {
+      if (order === 'ascending') {
+        this.listQuery.sort = '+id'
+      } else {
+        this.listQuery.sort = '-id'
+      }
+      this.handleFilter()
+    },
+    resetServiceData() {
+      this.serviceData = {
+        // bizLine: 0,
+        // bizModuleId: 0,
+        customName: '',
+        interfaceName: '',
+        protocol: '',
+        serviceVersion: '',
+        envChannel: 1,
+        envId: 0,
+        methodName: '',
+        methodParamsTypes: '[]',
+        returnDataStructure: '',
+        methodStatus: 1,
+        consumerIds: [],
+        remark: '',
+        updator: ''
+      }
+    },
+    handleCreate() {
+      this.resetServiceData()
+      this.dialogStatus = 'create'
+      this.dialogFormVisible = true
+      this.showSubmitBtn = true
+      this.$nextTick(() => {
+        this.$refs['serviceDataForm'].clearValidate()
+      })
+    },
+    showZkAddress() {
+      alert(this.serviceData.zkAddress)
+    },
+    createData() {
+      this.$refs['serviceDataForm'].validate((valid) => {
+        if (valid) {
+          // this.serviceData.id = parseInt(Math.random() * 100) + 1024 // mock a id
+          // this.temp.author = 'vue-element-admin'
+          delete this.serviceData.id
+          delete this.serviceData.bizLine
+          delete this.serviceData.bizModuleId
+          delete this.serviceData.bizName
+          delete this.serviceData.consumerCustomizeName
+          delete this.serviceData.consumerNames
+          delete this.serviceData.createTime
+          delete this.serviceData.createTimeStr
+          delete this.serviceData.envName
+          delete this.serviceData.updateTime
+          delete this.serviceData.updateTimeStr
+          delete this.serviceData.zkAddress
+          if (typeof this.serviceData.consumerIds === 'object') {
+            this.serviceData.consumerIds = '[' + this.serviceData.consumerIds.toString() + ']'
+          }
+          // console.log('#######################')
+          // console.log(this.serviceData)
+          // console.log('#######################')
+          createService(this.serviceData).then(response => {
+            // this.list.unshift(this.serviceData)
+            // console.log(response)
+            if (response.code === 200) {
+              this.dialogFormVisible = false
+              this.getList()
+              this.$notify({
+                title: 'Success',
+                message: response.msg,
+                type: 'success',
+                duration: 10000
+              })
+            } else {
+              this.$notify({
+                title: 'Failed',
+                message: response.msg,
+                type: 'error',
+                duration: 10000
+              })
+            }
+          })
+        }
+      })
+    },
+    handleUpdate(row) {
+      var queryData = { id: row.id }
+      fetchServiceById(queryData).then(response => {
+        // console.log(response)
+        var rowData = response.data.mockMethodList
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.serviceData)
+        // console.log(row_data[0])
+        this.serviceData = Object.assign({}, rowData[0])
+        this.serviceDataExt.id = row.id
+        this.serviceDataExt.bizLine = row.bizLine
+        this.serviceDataExt.bizModuleId = row.bizModuleId
+        // console.log(this.serviceData.consumerIds.split('[')[1].split(']')[0].split(','))
+        if (this.serviceData.consumerIds === '[]') {
+          this.serviceData.consumerIds = []
+        } else {
+          this.serviceData.consumerIds = this.serviceData.consumerIds.split('[')[1].split(']')[0].split(',').map(value => { return parseInt(value) })
+        }
+        // console.log(this.serviceData)
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.showSubmitBtn = true
+        this.$nextTick(() => {
+          this.$refs['serviceDataForm'].clearValidate()
+        })
+      })
+    },
+    handleCheck(row) {
+      var queryData = { id: row.id }
+      fetchServiceById(queryData).then(response => {
+        // console.log(response)
+        var rowData = response.data.mockMethodList
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.serviceData)
+        // console.log(row_data[0])
+        this.serviceData = Object.assign({}, rowData[0])
+        this.serviceDataExt.id = row.id
+        this.serviceDataExt.bizLine = row.bizLine
+        this.serviceDataExt.bizModuleId = row.bizModuleId
+        // console.log(this.serviceData.consumerIds.split('[')[1].split(']')[0].split(','))
+        if (this.serviceData.consumerIds === '[]') {
+          this.serviceData.consumerIds = []
+        } else {
+          this.serviceData.consumerIds = this.serviceData.consumerIds.split('[')[1].split(']')[0].split(',').map(value => { return parseInt(value) })
+        }
+        // console.log(this.serviceData)
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.showSubmitBtn = false
+        this.$nextTick(() => {
+          this.$refs['serviceDataForm'].clearValidate()
+        })
+      })
+    },
+    handleCopy(row) {
+      var queryData = { id: row.id }
+      fetchServiceById(queryData).then(response => {
+        // console.log(response)
+        var rowData = response.data.mockMethodList
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.serviceData)
+        // console.log(row_data[0])
+        this.serviceData = Object.assign({}, rowData[0])
+        this.serviceDataExt.id = row.id
+        this.serviceDataExt.bizLine = row.bizLine
+        this.serviceDataExt.bizModuleId = row.bizModuleId
+        // console.log(this.serviceData.consumerIds.split('[')[1].split(']')[0].split(','))
+        if (this.serviceData.consumerIds === '[]') {
+          this.serviceData.consumerIds = []
+        } else {
+          this.serviceData.consumerIds = this.serviceData.consumerIds.split('[')[1].split(']')[0].split(',').map(value => { return parseInt(value) })
+        }
+        // console.log(this.serviceData)
+        // this.serviceData.timestamp = new Date(this.temp.timestamp)
+        this.dialogStatus = 'create'
+        this.dialogFormVisible = true
+        this.$nextTick(() => {
+          this.$refs['serviceDataForm'].clearValidate()
+        })
+      })
+    },
+    updateData() {
+      this.$refs['serviceDataForm'].validate((valid) => {
+        if (valid) {
+          const tempData = {
+            id: this.serviceDataExt.id,
+            bizLine: this.serviceDataExt.bizLine,
+            bizModuleId: this.serviceDataExt.bizModuleId,
+            customName: this.serviceData.customName,
+            interfaceName: this.serviceData.interfaceName,
+            protocol: this.serviceData.protocol,
+            serviceVersion: this.serviceData.serviceVersion,
+            envChannel: this.serviceData.envChannel,
+            envId: this.serviceData.envId,
+            methodName: this.serviceData.methodName,
+            methodParamsTypes: this.serviceData.methodParamsTypes,
+            returnDataStructure: this.serviceData.returnDataStructure,
+            methodStatus: this.serviceData.methodStatus,
+            consumerIds: '[' + this.serviceData.consumerIds.toString() + ']',
+            remark: this.serviceData.remark,
+            updator: ''
+          }
+          // console.log(tempData)
+          updateService(tempData).then(response => {
+            if (response.code === 200) {
+              this.dialogFormVisible = false
+              this.getList()
+              this.$notify({
+                title: 'Success',
+                message: response.msg,
+                type: 'success',
+                duration: 2000
+              })
+            } else {
+              this.$notify({
+                title: 'Failed',
+                message: response.msg,
+                type: 'error',
+                duration: 2000
+              })
+            }
+          })
+        }
+      })
+    },
+    formatJson(filterVal, jsonData) {
+      return jsonData.map(v => filterVal.map(j => {
+        if (j === 'timestamp') {
+          return parseTime(v[j])
+        } else {
+          return v[j]
+        }
+      }))
+    },
+    redirectTo(id, methodName) {
+      this.$router.push({
+        path: `/mock/httprule/${id}`,
+        query: {
+          methodName: methodName
+        }
+      })
+    }
+  }
+}
+</script>

+ 435 - 0
src/views/mock/httprule.vue

@@ -0,0 +1,435 @@
+<template>
+  <div class="app-container">
+    <el-header style="height:auto;!improtant">
+      <div class="filter-container" style="padding-bottom: 20px;!improtant">
+        <el-input v-model="listQuery.whenScript" placeholder="规则" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-input v-model="listQuery.execSort" placeholder="优先级" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <!-- <el-input-number v-model="listQuery.execSort" label="优先级" :min="1" :max="100" /> -->
+        <el-select v-model="listQuery.status" class="filter-item" filterable clearable placeholder="状态">
+          <el-option v-for="item in ruleStatus" :key="item.key" :label="item.display_name" :value="item.key" />
+        </el-select>
+        <!-- <el-input v-model="listQuery.interfaceName" placeholder="接口类" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> -->
+        <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
+          搜索
+        </el-button>
+        <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
+          新增
+        </el-button>
+        <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
+          显示返回值
+        </el-checkbox>
+        <el-button style="float: right;" type="primary" @click="prev">
+          返回
+        </el-button>
+      </div>
+    </el-header>
+    <el-table
+      :key="tableKey"
+      v-loading="listLoading"
+      :data="list"
+      border
+      fit
+      highlight-current-row
+      style="width: 100%;"
+      @sort-change="sortChange"
+    >
+      <el-table-column label="ID" prop="id" sortable="custom" align="center" width="80">
+        <template slot-scope="scope">
+          <span>{{ scope.row.id }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="方法名" width="150px" align="center">
+        <!-- <template slot-scope="scope"> -->
+        <span>{{ this.$route.query.methodName }}</span>
+        <!-- </template> -->
+      </el-table-column>
+      <el-table-column label="方法ID" width="220px" align="center">
+        <!-- <template slot-scope="scope"> -->
+        <span>{{ this.$route.path.split('/')[3] }}</span>
+        <!-- </template> -->
+      </el-table-column>
+      <el-table-column label="规则" min-width="60px">
+        <template slot-scope="{row}">
+          <span>{{ row.whenScript }}</span>
+          <!-- <el-tag>{{ row.type | typeFilter }}</el-tag> -->
+        </template>
+      </el-table-column>
+      <el-table-column label="优先级" width="110px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.execSort }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" class-name="status-col" width="100">
+        <template slot-scope="{row}">
+          <el-tag :type="row.status | statusFilter">
+            {{ statusMappings.get(row.status) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新时间" width="150px" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.updateTimeStr }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column v-if="showReviewer" label="返回值" width="110px" align="center">
+        <template slot-scope="scope">
+          <span style="color:red;">{{ scope.row.returnMessage }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="370" class-name="small-padding fixed-width">
+        <template slot-scope="{row}">
+          <el-button type="primary" size="mini" @click="handleCheck(row)">
+            查看
+          </el-button>
+          <el-button type="primary" size="mini" @click="handleUpdate(row)">
+            编辑
+          </el-button>
+          <el-button type="primary" size="mini" @click="handleCopy(row)">
+            复制
+          </el-button>
+          <el-button type="primary" size="mini">
+            测试
+          </el-button>
+          <el-button v-if="row.status!=1" size="mini" type="success" @click="handleModifyStatus(row, 1)">
+            开启
+          </el-button>
+          <el-button v-if="row.status!=0" size="mini" type="danger" @click="handleModifyStatus(row, 0)">
+            关闭
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.curIndex" :limit.sync="listQuery.pageSize" @pagination="getList" />
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%">
+      <el-form ref="ruleDataForm" :rules="roleDataRules" :model="ruleData" label-position="left" label-width="120px" style="width: 500px; margin-left:80px;">
+        <el-form-item label="规则" prop="whenScript">
+          <el-input v-model="ruleData.whenScript" placeholder="Any" />
+        </el-form-item>
+        <el-form-item label="优先级" prop="execSort">
+          <el-input-number v-model="ruleData.execSort" label="优先级" :min="1" :max="100" />
+        </el-form-item>
+        <el-form-item label="返回值" prop="returnMessage">
+          <el-input v-model="ruleData.returnMessage" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" placeholder="{ 'code': 200, 'data': { 'crowdComposition': 'U_866', 'campaignId': 789, 'id': 4606, 'class': 'com.didi.prado.config.api.dto.CampaignCrowdDTO'}}" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">
+          取消
+        </el-button>
+        <el-button v-if="showSubmit" type="primary" @click="dialogStatus==='create'?createData():updateData()">
+          确定
+        </el-button>
+      </div>
+    </el-dialog>
+    <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
+      <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
+        <el-table-column prop="key" label="Channel" />
+        <el-table-column prop="pv" label="Pv" />
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { fetchEnvInfo, fetchRuleById, fetchRuleList, createRule, updateRule, changeStatus } from '@/api/httprule'
+import waves from '@/directive/waves' // waves directive
+import { parseTime } from '@/utils'
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+
+// const envTypeSelections = [
+//   { key: 1, display_name: '自定义环境配置' },
+//   { key: 2, display_name: '环境平台' }
+// ]
+
+// var envSelections = []
+
+const ruleStatus = [
+  { key: 1, display_name: '已开启' },
+  { key: 0, display_name: '未开启' }
+]
+
+export default {
+  name: 'Httprule',
+  components: { Pagination },
+  directives: { waves },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        1: 'success',
+        draft: 'info',
+        0: 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: null,
+      total: 0,
+      listLoading: true,
+      statusMappings: new Map([[1, '已开启'], [0, '未开启']]),
+      ruleStatus,
+      listQuery: {
+        curIndex: 1,
+        pageSize: 20,
+        whenScript: '',
+        methodId: 0,
+        execSort: null,
+        status: null
+      },
+      showSubmit: true,
+      sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
+      statusOptions: ['published', 'draft', 'deleted'],
+      showReviewer: false,
+      ruleData: {
+        methodId: 0,
+        creator: '',
+        updator: '',
+        execSort: 1,
+        whenScript: '',
+        returnMessage: '',
+        curIndex: 1,
+        pageSize: 20
+      },
+      dialogFormVisible: false,
+      dialogStatus: '',
+      textMap: {
+        update: '编辑',
+        create: '新增规则'
+      },
+      dialogPvVisible: false,
+      pvData: [],
+      roleDataRules: {
+        whenScript: [{ required: true, message: '规则不能为空', trigger: 'change' }],
+        execSort: [{ required: true, message: '优先级1-100', trigger: 'change' }],
+        returnMessage: [{ required: true, message: '不能为空', trigger: 'change' }]
+        // interfaceName: [{ required: true, message: '接口名称不能为空', trigger: 'change' }],
+        // serviceVersion: [{ required: true, message: '服务版本不能为空', trigger: 'change' }],
+        // protocol: [{ required: true, message: '请选择协议类型', trigger: 'change' }],
+        // consumerIds: [{ required: false, message: '请选择消费者', trigger: 'change' }],
+        // methodName: [{ required: true, message: '方法名称不能为空', trigger: 'change' }],
+        // methodParamsTypes: [{ required: true, message: '入参类型不能为空', trigger: 'change' }],
+        // returnDataStructure: [{ required: true, message: '返回值类型不能为空', trigger: 'change' }]
+      },
+      downloadLoading: false
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    prev() {
+      this.$router.go(-1)
+    },
+    getList() {
+      this.listLoading = true
+      this.listQuery.methodId = parseInt(this.$route.path.split('/')[3])
+      fetchRuleList(this.listQuery).then(response => {
+        this.list = response.data.mockRuleList
+        this.total = response.data.total
+        // Just to simulate the time of the request
+        this.listLoading = false
+      })
+    },
+    updateEnvChannel(v) {
+      console.log(v)
+      this.ruleData.envChannel = v
+      this.envSelections = []
+      fetchEnvInfo(v).then(response => {
+        for (var sel of response.data) {
+          var envSel = {}
+          envSel.key = sel.envId
+          envSel.display_name = sel.envName
+          this.envSelections.push(envSel)
+        }
+      })
+    },
+    handleFilter() {
+      // this.listQuery.page = 1
+      this.getList()
+    },
+    sortChange(data) {
+      const { prop, order } = data
+      if (prop === 'id') {
+        this.sortByID(order)
+      }
+    },
+    sortByID(order) {
+      if (order === 'ascending') {
+        this.listQuery.sort = '+id'
+      } else {
+        this.listQuery.sort = '-id'
+      }
+      this.handleFilter()
+    },
+    resetServiceData() {
+      this.ruleData = {
+        methodId: 0,
+        creator: '',
+        updator: '',
+        execSort: 1,
+        whenScript: '',
+        returnMessage: '',
+        curIndex: 1,
+        pageSize: 20
+      }
+    },
+    handleCreate() {
+      this.resetServiceData()
+      this.dialogStatus = 'create'
+      this.dialogFormVisible = true
+      this.$nextTick(() => {
+        this.$refs['ruleDataForm'].clearValidate()
+      })
+    },
+    createData() {
+      this.$refs['ruleDataForm'].validate((valid) => {
+        if (valid) {
+          // this.ruleData.id = parseInt(Math.random() * 100) + 1024 // mock a id
+          // this.temp.author = 'vue-element-admin'
+          //   delete this.ruleData.id
+          delete this.ruleData.id
+          this.ruleData.methodId = parseInt(this.$route.path.split('/')[3])
+          createRule(this.ruleData).then(response => {
+            // this.list.unshift(this.serviceData)
+            if (response.code === 200) {
+              this.dialogFormVisible = false
+              this.getList()
+              this.$notify({
+                title: 'Success',
+                message: 'Created Successfully',
+                type: 'success',
+                duration: 2000
+              })
+            } else {
+              this.$notify({
+                title: 'Failed',
+                message: 'Created Failed',
+                type: 'error',
+                duration: 2000
+              })
+            }
+          })
+        }
+      })
+    },
+    handleUpdate(row) {
+      var queryData = { id: row.id }
+      fetchRuleById(queryData).then(response => {
+        console.log(response)
+        var row_data = response.data.mockRuleList
+        // this.ruleData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.ruleData)
+        // console.log(row_data)
+        this.ruleData = Object.assign({}, row_data[0])
+        // console.log(this.ruleData)
+        this.ruleData.timestamp = new Date(this.ruleData.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.showSubmit = true
+        this.$nextTick(() => {
+          this.$refs['ruleDataForm'].clearValidate()
+        })
+      })
+    },
+    handleModifyStatus(row, status) {
+      var statusData = {
+        id: row.id,
+        status: status
+      }
+      // console.log(statusData)
+      changeStatus(statusData).then(response => {
+        // console.log(response)
+        if (response.code === 200) {
+          row.status = status
+          this.$message({
+            message: row.id.toString() + ' 操作成功!',
+            type: 'success'
+          })
+        } else {
+          this.$message({
+            message: row.id.toString() + ' 操作失败!',
+            type: 'danger'
+          })
+        }
+      })
+    },
+    handleCopy(row) {
+      this.ruleData = Object.assign({}, row) // copy obj
+      this.ruleData.timestamp = new Date(this.ruleData.timestamp)
+      this.dialogStatus = 'create'
+      this.dialogFormVisible = true
+      this.showSubmit = true
+      this.$nextTick(() => {
+        this.$refs['ruleDataForm'].clearValidate()
+      })
+    },
+    updateData() {
+      this.$refs['ruleDataForm'].validate((valid) => {
+        if (valid) {
+        //   const tempData = Object.assign({}, this.ruleData)
+          const tempData = {
+            id: this.ruleData.id,
+            methodId: parseInt(this.$route.path.split('/')[3]),
+            creator: '',
+            updator: '',
+            execSort: this.ruleData.execSort,
+            whenScript: this.ruleData.whenScript,
+            returnMessage: this.ruleData.returnMessage,
+            mehtodName: this.$route.query.methodName
+          }
+          updateRule(tempData).then(() => {
+            this.getList()
+            // for (const v of this.list) {
+            //   if (v.id === this.ruleData.id) {
+            //     const index = this.list.indexOf(v)
+            //     this.list.splice(index, 1, this.ruleData)
+            //     break
+            //   }
+            // }
+            this.dialogFormVisible = false
+            this.$notify({
+              title: 'Success',
+              message: 'Update Successfully',
+              type: 'success',
+              duration: 2000
+            })
+          })
+        }
+      })
+    },
+    formatJson(filterVal, jsonData) {
+      return jsonData.map(v => filterVal.map(j => {
+        if (j === 'timestamp') {
+          return parseTime(v[j])
+        } else {
+          return v[j]
+        }
+      }))
+    },
+    handleCheck(row) {
+      var queryData = { id: row.id }
+      fetchRuleById(queryData).then(response => {
+        console.log(response)
+        var row_data = response.data.mockRuleList
+        // this.ruleData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.ruleData)
+        // console.log(row_data)
+        this.ruleData = Object.assign({}, row_data[0])
+        // console.log(this.ruleData)
+        this.ruleData.timestamp = new Date(this.ruleData.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.showSubmit = false
+        this.$nextTick(() => {
+          this.$refs['ruleDataForm'].clearValidate()
+        })
+      })
+    }
+  }
+}
+</script>

+ 44 - 42
src/views/mock/interface.vue

@@ -1,22 +1,15 @@
-<template>
+<template style="height=0px;improtanent">
   <div class="app-container">
-    <el-header>
-      <div class="filter-container">
+    <el-header style="height: auto;!improtant">
+      <div class="filter-container" style="padding-bottom: 20px;!improtant">
         <el-input v-model="listQuery.id" placeholder="ID" style="width: 80px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <el-input v-model="listQuery.customName" placeholder="服务名" style="width: 150px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <el-input v-model="listQuery.interfaceName" placeholder="接口类" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <el-input v-model="listQuery.methodName" placeholder="方法名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <el-input v-model="listQuery.serviceVersion" placeholder="版本" style="width: 100px;" class="filter-item" @keyup.enter.native="handleFilter" />
-        <el-input v-model="listQuery.methodStatus" placeholder="状态" style="width: 80px;" class="filter-item" @keyup.enter.native="handleFilter" />
-        <!-- <el-select v-model="listQuery.importance" placeholder="接口类" clearable style="width: 90px" class="filter-item">
-          <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" />
+        <el-select v-model="listQuery.value" placeholder="状态" style="width: 100px;" class="filter-item" @change="handleFilter">
+          <el-option v-for="item in listQuery.options" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
-        <el-select v-model="listQuery.type" placeholder="Type" clearable class="filter-item" style="width: 130px">
-          <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" />
-        </el-select>
-        <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter">
-          <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" />
-        </el-select> -->
         <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
           搜索
         </el-button>
@@ -119,38 +112,40 @@
     <pagination v-show="total>0" :total="total" :page.sync="listQuery.curIndex" :limit.sync="listQuery.pageSize" @pagination="getList" />
     <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%" @open="dialogOpenInit()">
       <el-form ref="serviceDataForm" :rules="serviceDataRules" :model="serviceData" label-position="left" label-width="120px" style="width: 500px; margin-left:80px;">
-        <el-form-item label="服务名称" prop="customName">
-          <el-input v-model="serviceData.customName" />
-        </el-form-item>
-        <el-form-item label="环境配置" prop="envChannel">
-          <el-select v-model="serviceData.envChannel" class="filter-item" filterable placeholder="环境配置" @change="updateEnvChannel(serviceData.envChannel)">
-            <el-option v-for="item in envTypeSelections" :key="item.key" :label="item.display_name" :value="item.key" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="环境" prop="envId">
-          <el-select v-model="serviceData.envId" class="filter-item" filterable placeholder="环境">
-            <el-option v-for="item in envSelections" :key="item.key" :label="item.display_name" :value="item.key" />
-          </el-select>
+        <el-form-item label="名称" prop="customName">
+          <el-input v-model="serviceData.customName" placeholder="dj_order_圈司机" title="自定义,供配置人员查看,建议”业务线_模块_功能" />
         </el-form-item>
+        <div style="display:flex; margin-left:0px;">
+          <el-form-item label="环境配置" prop="envChannel" style="flex:1;">
+            <el-select v-model="serviceData.envChannel" class="filter-item" style="width: 190px;" filterable placeholder="环境配置" @change="updateEnvChannel(serviceData.envChannel)">
+              <el-option v-for="item in envTypeSelections" :key="item.key" :label="item.display_name" :value="item.key" />
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="envId" style="flex:1; margin-left:-120px;">
+            <el-select v-model="serviceData.envId" class="filter-item" style="width: 190px;" filterable placeholder="环境" @change="showZkAddress">
+              <el-option v-for="item in envSelections" :key="item.key" :label="item.display_name" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </div>
         <el-form-item label="接口类名" prop="interfaceName">
-          <el-input v-model="serviceData.interfaceName" />
+          <el-input v-model="serviceData.interfaceName" placeholder="com.didi.prado.config.api.CampaignRemoteServce" title="包名.接口类名" />
+        </el-form-item>
+        <el-form-item label="方法名" prop="methodName">
+          <el-input v-model="serviceData.methodName" placeholder="addCampaign" />
         </el-form-item>
         <el-form-item label="服务版本" prop="serviceVersion">
-          <el-input v-model="serviceData.serviceVersion" />
+          <el-input v-model="serviceData.serviceVersion" placeholder="1.0.0_test" />
         </el-form-item>
-        <el-form-item label="协议选择" prop="protocol">
+        <el-form-item label="协议" prop="protocol">
           <el-select v-model="serviceData.protocol" class="filter-item" filterable clearable placeholder="协议">
             <el-option v-for="item in protocols" :key="item.key" :label="item.display_name" :value="item.key" />
           </el-select>
         </el-form-item>
-        <el-form-item label="消费者设置" prop="consumerIds">
+        <el-form-item label="消费者" prop="consumerIds">
           <el-select v-model="serviceData.consumerIds" class="filter-item" multiple placeholder="消费者">
             <el-option v-for="item in consumerSelections" :key="item.key" :label="item.display_name" :value="item.key" />
           </el-select>
         </el-form-item>
-        <el-form-item label="方法名" prop="methodName">
-          <el-input v-model="serviceData.methodName" />
-        </el-form-item>
         <!-- <el-form-item label="Date" prop="timestamp">
           <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" />
         </el-form-item>
@@ -162,11 +157,11 @@
         <el-form-item label="Imp">
           <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" />
         </el-form-item> -->
-        <el-form-item label="方法参数" prop="methodParamsTypes">
-          <el-input v-model="serviceData.methodParamsTypes" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" placeholder="方法参数" />
+        <el-form-item label="入参类型" prop="methodParamsTypes">
+          <el-input v-model="serviceData.methodParamsTypes" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" title="列表形式,参数有序,多个参数类型以英文”,“分隔" placeholder="[java.lang.Integer, com.didi.prado.config.api.param.CampaignRequest]" />
         </el-form-item>
-        <el-form-item label="方法返回值" prop="returnDataStructure">
-          <el-input v-model="serviceData.returnDataStructure" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" placeholder="方法返回值" />
+        <el-form-item label="返回值类型" prop="returnDataStructure">
+          <el-input v-model="serviceData.returnDataStructure" :autosize="{ minRows: 2, maxRows: 8}" type="textarea" title="key:每个自定义类型在返回结构中的节点树,以英文“.“分隔;value:自定义类型的全限定类名" placeholder="{'data':'com.didi.order.api.response.BaserOrderInfoResult','data.feeInfo':'com.didi.order.api.response.FeeInfoResult'}" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -208,8 +203,8 @@ var envSelections = []
 var consumerSelections = []
 
 const protocols = [
-  { key: 'dubbo', display_name: 'dubbo' },
-  { key: 'http', display_name: 'http' }
+  { key: 'dubbo', display_name: 'dubbo' }
+  // { key: 'http', display_name: 'http' }
 ]
 
 // var envTypeID = 1;
@@ -242,6 +237,8 @@ export default {
       statusMappings: new Map([[1, '已开启'], [0, '未开启']]),
       statusOperateMap: new Map([[1, '开启'], [0, '关闭']]),
       listQuery: {
+        options: [{ value: '0', label: '未开启' }, { value: '1', label: '已开启' }],
+        value: '',
         curIndex: 1,
         pageSize: 20,
         customName: '',
@@ -307,16 +304,16 @@ export default {
       dialogPvVisible: false,
       pvData: [],
       serviceDataRules: {
-        customName: [{ required: true, message: '服务名称不能为空', trigger: 'change' }],
+        customName: [{ required: true, message: '名称不能为空', trigger: 'change' }],
         envChannel: [{ required: true, message: '请选择环境配置', trigger: 'change' }],
         envId: [{ required: true, message: '请选择环境', trigger: 'change' }],
         interfaceName: [{ required: true, message: '接口名称不能为空', trigger: 'change' }],
         serviceVersion: [{ required: true, message: '服务版本不能为空', trigger: 'change' }],
         protocol: [{ required: true, message: '请选择协议类型', trigger: 'change' }],
-        consumerIds: [{ required: false, message: '请选择消费者设置', trigger: 'change' }],
+        consumerIds: [{ required: false, message: '请选择消费者', trigger: 'change' }],
         methodName: [{ required: true, message: '方法名称不能为空', trigger: 'change' }]
-        // methodParamsTypes: [{ required: true, message: '方法参数不能为空', trigger: 'change' }],
-        // returnDataStructure: [{ required: true, message: '方法返回值不能为空', trigger: 'change' }]
+        // methodParamsTypes: [{ required: true, message: '入参类型不能为空', trigger: 'change' }],
+        // returnDataStructure: [{ required: true, message: '返回值类型不能为空', trigger: 'change' }]
       },
       downloadLoading: false
     }
@@ -328,7 +325,7 @@ export default {
     getList() {
       this.listLoading = true
       fetchServiceList(this.listQuery).then(response => {
-        // console.log(this.listQuery)
+        console.log(this.listQuery)
         this.list = response.data.mockMethodList
         this.total = response.data.total
         // Just to simulate the time of the request
@@ -376,6 +373,7 @@ export default {
     },
     handleFilter() {
       // this.listQuery.page = 1
+      this.listQuery.methodStatus = this.listQuery.value
       this.getList()
     },
     handleModifyStatus(row, status) {
@@ -442,6 +440,9 @@ export default {
         this.$refs['serviceDataForm'].clearValidate()
       })
     },
+    showZkAddress() {
+      alert(this.serviceData.zkAddress)
+    },
     createData() {
       this.$refs['serviceDataForm'].validate((valid) => {
         if (valid) {
@@ -626,6 +627,7 @@ export default {
       }))
     },
     redirectTo(id, methodName) {
+      // console.log(id,methodName)
       this.$router.push({
         path: `/mock/interface/${id}`,
         query: {

+ 74 - 38
src/views/mock/rule.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="app-container">
-    <el-header>
-      <div class="filter-container">
+    <el-header style="height:auto;!improtant">
+      <div class="filter-container" style="padding-bottom: 20px;!improtant">
         <el-input v-model="listQuery.whenScript" placeholder="规则" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <el-input v-model="listQuery.execSort" placeholder="优先级" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
         <!-- <el-input-number v-model="listQuery.execSort" label="优先级" :min="1" :max="100" /> -->
@@ -18,6 +18,9 @@
         <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
           显示返回值
         </el-checkbox>
+        <el-button style="float: right;" type="primary" @click="prev">
+          返回
+        </el-button>
       </div>
     </el-header>
     <el-table
@@ -73,11 +76,17 @@
           <span style="color:red;">{{ scope.row.returnMessage }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" width="230" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" width="370" class-name="small-padding fixed-width">
         <template slot-scope="{row}">
+          <el-button type="primary" size="mini" @click="handleCheck(row)">
+            查看
+          </el-button>
           <el-button type="primary" size="mini" @click="handleUpdate(row)">
             编辑
           </el-button>
+          <el-button type="primary" size="mini" @click="handleCopy(row)">
+            复制
+          </el-button>
           <el-button type="primary" size="mini">
             测试
           </el-button>
@@ -94,20 +103,20 @@
     <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%">
       <el-form ref="ruleDataForm" :rules="roleDataRules" :model="ruleData" label-position="left" label-width="120px" style="width: 500px; margin-left:80px;">
         <el-form-item label="规则" prop="whenScript">
-          <el-input v-model="ruleData.whenScript" />
+          <el-input v-model="ruleData.whenScript" placeholder="Any" />
         </el-form-item>
         <el-form-item label="优先级" prop="execSort">
           <el-input-number v-model="ruleData.execSort" label="优先级" :min="1" :max="100" />
         </el-form-item>
         <el-form-item label="返回值" prop="returnMessage">
-          <el-input v-model="ruleData.returnMessage" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" placeholder="返回值" />
+          <el-input v-model="ruleData.returnMessage" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" placeholder="{ 'code': 200, 'data': { 'crowdComposition': 'U_866', 'campaignId': 789, 'id': 4606, 'class': 'com.didi.prado.config.api.dto.CampaignCrowdDTO'}}" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button @click="dialogFormVisible = false">
           取消
         </el-button>
-        <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
+        <el-button v-if="showSubmit" type="primary" @click="dialogStatus==='create'?createData():updateData()">
           确定
         </el-button>
       </div>
@@ -172,6 +181,7 @@ export default {
         execSort: null,
         status: null
       },
+      showSubmit: true,
       sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
       statusOptions: ['published', 'draft', 'deleted'],
       showReviewer: false,
@@ -200,10 +210,10 @@ export default {
         // interfaceName: [{ required: true, message: '接口名称不能为空', trigger: 'change' }],
         // serviceVersion: [{ required: true, message: '服务版本不能为空', trigger: 'change' }],
         // protocol: [{ required: true, message: '请选择协议类型', trigger: 'change' }],
-        // consumerIds: [{ required: false, message: '请选择消费者设置', trigger: 'change' }],
+        // consumerIds: [{ required: false, message: '请选择消费者', trigger: 'change' }],
         // methodName: [{ required: true, message: '方法名称不能为空', trigger: 'change' }],
-        // methodParamsTypes: [{ required: true, message: '方法参数不能为空', trigger: 'change' }],
-        // returnDataStructure: [{ required: true, message: '方法返回值不能为空', trigger: 'change' }]
+        // methodParamsTypes: [{ required: true, message: '入参类型不能为空', trigger: 'change' }],
+        // returnDataStructure: [{ required: true, message: '返回值类型不能为空', trigger: 'change' }]
       },
       downloadLoading: false
     }
@@ -212,6 +222,9 @@ export default {
     this.getList()
   },
   methods: {
+    prev() {
+      this.$router.go(-1)
+    },
     getList() {
       this.listLoading = true
       this.listQuery.methodId = parseInt(this.$route.path.split('/')[3])
@@ -269,40 +282,42 @@ export default {
       this.resetServiceData()
       this.dialogStatus = 'create'
       this.dialogFormVisible = true
+      this.showSubmit = true
       this.$nextTick(() => {
         this.$refs['ruleDataForm'].clearValidate()
       })
     },
     createData() {
-      this.$refs['ruleDataForm'].validate((valid) => {
-        if (valid) {
-          // this.ruleData.id = parseInt(Math.random() * 100) + 1024 // mock a id
-          // this.temp.author = 'vue-element-admin'
-          //   delete this.ruleData.id
-          delete this.ruleData.id
-          this.ruleData.methodId = parseInt(this.$route.path.split('/')[3])
-          createRule(this.ruleData).then(response => {
-            // this.list.unshift(this.serviceData)
-            if (response.code === 200) {
-              this.dialogFormVisible = false
-              this.getList()
-              this.$notify({
-                title: 'Success',
-                message: 'Created Successfully',
-                type: 'success',
-                duration: 2000
-              })
-            } else {
-              this.$notify({
-                title: 'Failed',
-                message: 'Created Failed',
-                type: 'error',
-                duration: 2000
-              })
-            }
-          })
-        }
-      })
+      const shouldJson = this.ruleData.returnMessage
+      if (this.ruleData.whenScript === '') { this.ruleData.whenScript = 'Any' }
+      if (typeof shouldJson === 'string') {
+        this.$refs['ruleDataForm'].validate((valid) => {
+          if (valid) {
+            delete this.ruleData.id
+            this.ruleData.methodId = parseInt(this.$route.path.split('/')[3])
+            createRule(this.ruleData).then(response => {
+              // this.list.unshift(this.serviceData)
+              if (response.code === 200) {
+                this.dialogFormVisible = false
+                this.getList()
+                this.$notify({
+                  title: 'Success',
+                  message: 'Created Successfully',
+                  type: 'success',
+                  duration: 2000
+                })
+              } else {
+                this.$notify({
+                  title: 'Failed',
+                  message: 'Created Failed',
+                  type: 'error',
+                  duration: 2000
+                })
+              }
+            })
+          }
+        })
+      }
     },
     handleUpdate(row) {
       var queryData = { id: row.id }
@@ -317,6 +332,7 @@ export default {
         this.ruleData.timestamp = new Date(this.ruleData.timestamp)
         this.dialogStatus = 'update'
         this.dialogFormVisible = true
+        this.showSubmit = true
         this.$nextTick(() => {
           this.$refs['ruleDataForm'].clearValidate()
         })
@@ -349,6 +365,7 @@ export default {
       this.ruleData.timestamp = new Date(this.ruleData.timestamp)
       this.dialogStatus = 'create'
       this.dialogFormVisible = true
+      this.showSubmit = true
       this.$nextTick(() => {
         this.$refs['ruleDataForm'].clearValidate()
       })
@@ -395,6 +412,25 @@ export default {
           return v[j]
         }
       }))
+    },
+    handleCheck(row) {
+      var queryData = { id: row.id }
+      fetchRuleById(queryData).then(response => {
+        console.log(response)
+        var row_data = response.data.mockRuleList
+        // this.ruleData.timestamp = new Date(this.temp.timestamp)
+        // console.log(this.ruleData)
+        // console.log(row_data)
+        this.ruleData = Object.assign({}, row_data[0])
+        // console.log(this.ruleData)
+        this.ruleData.timestamp = new Date(this.ruleData.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.showSubmit = false
+        this.$nextTick(() => {
+          this.$refs['ruleDataForm'].clearValidate()
+        })
+      })
     }
   }
 }