httprule.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. <template>
  2. <div class="app-container">
  3. <el-header style="height:auto;!improtant">
  4. <div class="filter-container" style="padding-bottom: 20px;!improtant">
  5. <el-input v-model="listQuery.whenScript" disabled placeholder="any" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
  6. <el-input v-model="listQuery.execSort" placeholder="优先级" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
  7. <!-- <el-input-number v-model="listQuery.execSort" label="优先级" :min="1" :max="100" /> -->
  8. <el-select v-model="listQuery.status" class="filter-item" filterable clearable placeholder="状态">
  9. <el-option v-for="item in ruleStatus" :key="item.key" :label="item.display_name" :value="item.key" />
  10. </el-select>
  11. <!-- <el-input v-model="listQuery.interfaceName" placeholder="接口类" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> -->
  12. <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
  13. 搜索
  14. </el-button>
  15. <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
  16. 新增
  17. </el-button>
  18. <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
  19. 显示返回值
  20. </el-checkbox>
  21. <el-button style="float: right;" type="primary" @click="prev">
  22. 返回
  23. </el-button>
  24. </div>
  25. </el-header>
  26. <el-table
  27. :key="tableKey"
  28. v-loading="listLoading"
  29. :data="list"
  30. fit
  31. highlight-current-row
  32. style="width: 100%;"
  33. :header-cell-style="styleObj"
  34. @sort-change="sortChange"
  35. >
  36. <el-table-column label="ID" prop="id" sortable="custom" align="center" min-width="80px">
  37. <template slot-scope="scope">
  38. <span>{{ scope.row.id }}</span>
  39. </template>
  40. </el-table-column>
  41. <el-table-column label="方法名" min-width="150px" align="center">
  42. <!-- <template slot-scope="scope"> -->
  43. <span>{{ this.$route.query.methodName }}</span>
  44. <!-- </template> -->
  45. </el-table-column>
  46. <el-table-column label="方法ID" min-width="220px" align="center">
  47. <!-- <template slot-scope="scope"> -->
  48. <span>{{ this.$route.path.split('/')[3] }}</span>
  49. <!-- </template> -->
  50. </el-table-column>
  51. <el-table-column label="规则" min-min-width="60px">
  52. <template slot-scope="{row}">
  53. <span>{{ row.whenScript }}</span>
  54. <!-- <el-tag>{{ row.type | typeFilter }}</el-tag> -->
  55. </template>
  56. </el-table-column>
  57. <el-table-column label="优先级" min-width="110px" align="center">
  58. <template slot-scope="scope">
  59. <span>{{ scope.row.execSort }}</span>
  60. </template>
  61. </el-table-column>
  62. <el-table-column label="状态" class-name="status-col" min-width="100">
  63. <template slot-scope="{row}">
  64. <el-tag :type="row.status | statusFilter">
  65. {{ statusMappings.get(row.status) }}
  66. </el-tag>
  67. </template>
  68. </el-table-column>
  69. <el-table-column label="更新时间" min-width="170px" align="center">
  70. <template slot-scope="scope">
  71. <span>{{ scope.row.updateTimeStr }}</span>
  72. </template>
  73. </el-table-column>
  74. <el-table-column v-if="showReviewer" label="返回值" min-width="110px" align="center">
  75. <template slot-scope="scope">
  76. <span style="color:red;">{{ scope.row.returnMessage }}</span>
  77. </template>
  78. </el-table-column>
  79. <el-table-column label="操作" align="center" min-width="370" class-name="small-padding fixed-width" fixed="right">
  80. <template slot-scope="{row}">
  81. <el-button type="primary" size="mini" @click="handleCheck(row)">
  82. 查看
  83. </el-button>
  84. <el-button type="primary" size="mini" @click="handleUpdate(row)">
  85. 编辑
  86. </el-button>
  87. <el-button type="primary" size="mini" @click="handleCopy(row)">
  88. 复制
  89. </el-button>
  90. <el-button type="primary" size="mini">
  91. 测试
  92. </el-button>
  93. <el-button v-if="row.status!=1" size="mini" type="success" @click="handleModifyStatus(row, 1)">
  94. 开启
  95. </el-button>
  96. <el-button v-if="row.status!=0" size="mini" type="danger" @click="handleModifyStatus(row, 0)">
  97. 关闭
  98. </el-button>
  99. </template>
  100. </el-table-column>
  101. </el-table>
  102. <pagination v-show="total>0" :total="total" :page.sync="listQuery.curIndex" :limit.sync="listQuery.pageSize" @pagination="getList" />
  103. <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%">
  104. <el-form ref="ruleDataForm" :rules="roleDataRules" :model="ruleData" label-position="left" label-width="120px" style="width: 500px; margin-left:80px;">
  105. <el-form-item label="规则" prop="whenScript">
  106. <el-input v-model="ruleData.whenScript" placeholder="any" disabled />
  107. </el-form-item>
  108. <el-form-item label="优先级" prop="execSort">
  109. <el-input-number v-model="ruleData.execSort" label="优先级" :min="1" :max="100" title="值越大,优先级越高" />
  110. </el-form-item>
  111. <el-form-item label="返回值" prop="returnMessage">
  112. <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'}}" @blur="getFormatJsonStrFromStringRule(ruleData.returnMessage)" />
  113. </el-form-item>
  114. </el-form>
  115. <div slot="footer" class="dialog-footer">
  116. <el-button @click="dialogFormVisible = false">
  117. 取消
  118. </el-button>
  119. <el-button v-if="showSubmit" type="primary" @click="dialogStatus==='create'?createData():updateData()">
  120. 确定
  121. </el-button>
  122. </div>
  123. </el-dialog>
  124. <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
  125. <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
  126. <el-table-column prop="key" label="Channel" />
  127. <el-table-column prop="pv" label="Pv" />
  128. </el-table>
  129. <span slot="footer" class="dialog-footer">
  130. <el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
  131. </span>
  132. </el-dialog>
  133. </div>
  134. </template>
  135. <script>
  136. import { fetchEnvInfo, fetchRuleById, fetchRuleList, createRule, updateRule, changeStatus } from '@/api/httpmock'
  137. import waves from '@/directive/waves' // waves directive
  138. import { parseTime } from '@/utils'
  139. import Pagination from '@/components/Pagination' // secondary package based on el-pagination
  140. // const envTypeSelections = [
  141. // { key: 1, display_name: '自定义环境配置' },
  142. // { key: 2, display_name: '环境平台' }
  143. // ]
  144. // var envSelections = []
  145. const ruleStatus = [
  146. { key: 1, display_name: '已开启' },
  147. { key: 0, display_name: '未开启' },
  148. { key: '', display_name: '全部显示' }
  149. ]
  150. export default {
  151. name: 'Httpmock',
  152. components: { Pagination },
  153. directives: { waves },
  154. filters: {
  155. statusFilter(status) {
  156. const statusMap = {
  157. 1: 'success',
  158. draft: 'info',
  159. 0: 'danger'
  160. }
  161. return statusMap[status]
  162. }
  163. },
  164. data() {
  165. return {
  166. styleObj: {
  167. 'color': 'rgba(0, 0, 0, 0.726)'
  168. },
  169. tableKey: 0,
  170. list: null,
  171. total: 0,
  172. listLoading: true,
  173. statusMappings: new Map([[1, '已开启'], [0, '未开启']]),
  174. ruleStatus,
  175. listQuery: {
  176. curIndex: 1,
  177. pageSize: 20,
  178. whenScript: 'any',
  179. methodId: 0,
  180. execSort: null,
  181. status: null,
  182. methodProtocol: ''
  183. },
  184. showSubmit: true,
  185. sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
  186. statusOptions: ['published', 'draft', 'deleted'],
  187. showReviewer: false,
  188. ruleData: {
  189. methodId: 0,
  190. creator: '',
  191. updator: '',
  192. execSort: 1,
  193. whenScript: '',
  194. returnMessage: '',
  195. curIndex: 1,
  196. pageSize: 20
  197. },
  198. dialogFormVisible: false,
  199. dialogStatus: '',
  200. textMap: {
  201. update: '编辑',
  202. create: '新增规则'
  203. },
  204. dialogPvVisible: false,
  205. pvData: [],
  206. roleDataRules: {
  207. whenScript: [{ required: true, message: '规则不能为空', trigger: 'change' }],
  208. execSort: [{ required: true, message: '优先级1-100', trigger: 'change' }],
  209. returnMessage: [{ required: true, message: '不能为空', trigger: 'change' }]
  210. // interfaceName: [{ required: true, message: '接口名称不能为空', trigger: 'change' }],
  211. // serviceVersion: [{ required: true, message: '服务版本不能为空', trigger: 'change' }],
  212. // protocol: [{ required: true, message: '请选择协议类型', trigger: 'change' }],
  213. // consumerIds: [{ required: false, message: '请选择消费者', trigger: 'change' }],
  214. // methodName: [{ required: true, message: '方法名称不能为空', trigger: 'change' }],
  215. // methodParamsTypes: [{ required: true, message: '入参类型不能为空', trigger: 'change' }],
  216. },
  217. downloadLoading: false
  218. }
  219. },
  220. created() {
  221. this.getList()
  222. },
  223. methods: {
  224. prev() {
  225. this.$router.go(-1)
  226. },
  227. getList() {
  228. this.listLoading = true
  229. this.listQuery.methodId = parseInt(this.$route.path.split('/')[3])
  230. fetchRuleList(this.listQuery).then(response => {
  231. this.list = response.data.mockRuleList
  232. this.total = response.data.total
  233. // Just to simulate the time of the request
  234. this.listLoading = false
  235. })
  236. },
  237. getFormatJsonStrFromStringRule: function(jsonStr) {
  238. console.log(jsonStr)
  239. var res = ''
  240. for (var i = 0, j = 0, k = 0, ii, ele; i < jsonStr.length; i++) { // k:缩进,j:""个数
  241. ele = jsonStr.charAt(i)
  242. if (j % 2 === 0 && ele === '}') {
  243. k--
  244. for (ii = 0; ii < k; ii++) ele = ' ' + ele
  245. ele = '\n' + ele
  246. } else if (j % 2 === 0 && ele === '{') {
  247. ele += '\n'
  248. k++
  249. for (ii = 0; ii < k; ii++) ele += ' '
  250. } else if (j % 2 === 0 && ele === ',') {
  251. ele += '\n'
  252. for (ii = 0; ii < k; ii++) ele += ' '
  253. } else if (ele === '"') j++
  254. res += ele
  255. }
  256. // eslint-disable-next-line no-return-assign
  257. return this.ruleData.returnMessage = res
  258. },
  259. updateEnvChannel(v) {
  260. console.log(v)
  261. this.ruleData.envChannel = v
  262. this.envSelections = []
  263. fetchEnvInfo(v).then(response => {
  264. for (var sel of response.data) {
  265. var envSel = {}
  266. envSel.key = sel.envId
  267. envSel.display_name = sel.envName
  268. this.envSelections.push(envSel)
  269. }
  270. })
  271. },
  272. handleFilter() {
  273. // this.listQuery.page = 1
  274. this.listQuery.methodStatus = this.listQuery.value
  275. this.getList()
  276. },
  277. sortChange(data) {
  278. const { prop, order } = data
  279. if (prop === 'id') {
  280. this.sortByID(order)
  281. }
  282. },
  283. sortByID(order) {
  284. if (order === 'ascending') {
  285. this.listQuery.sort = '+id'
  286. } else {
  287. this.listQuery.sort = '-id'
  288. }
  289. this.handleFilter()
  290. },
  291. resetServiceData() {
  292. this.ruleData = {
  293. methodId: 0,
  294. creator: '',
  295. updator: '',
  296. execSort: 1,
  297. whenScript: '',
  298. returnMessage: '',
  299. curIndex: 1,
  300. pageSize: 20
  301. }
  302. },
  303. handleCreate() {
  304. this.resetServiceData()
  305. this.dialogStatus = 'create'
  306. this.dialogFormVisible = true
  307. this.showSubmit = true
  308. this.$nextTick(() => {
  309. this.$refs['ruleDataForm'].clearValidate()
  310. })
  311. },
  312. createData() {
  313. const shouldJson = this.ruleData.returnMessage
  314. if (this.ruleData.whenScript === '') { this.ruleData.whenScript = 'any' }
  315. if (typeof shouldJson === 'string') {
  316. this.$refs['ruleDataForm'].validate((valid) => {
  317. if (valid) {
  318. delete this.ruleData.id
  319. this.ruleData.methodId = parseInt(this.$route.path.split('/')[3])
  320. createRule(this.ruleData).then(response => {
  321. // this.list.unshift(this.serviceData)
  322. if (response.code === 200) {
  323. this.dialogFormVisible = false
  324. this.getList()
  325. this.$notify({
  326. title: 'Success',
  327. message: 'Created Successfully',
  328. type: 'success',
  329. duration: 2000
  330. })
  331. } else {
  332. this.$notify({
  333. title: 'Failed',
  334. message: 'Created Failed',
  335. type: 'error',
  336. duration: 2000
  337. })
  338. }
  339. })
  340. }
  341. })
  342. }
  343. },
  344. handleUpdate(row) {
  345. var queryData = { id: row.id }
  346. fetchRuleById(queryData).then(response => {
  347. console.log(response)
  348. var row_data = response.data.mockRuleList
  349. // this.ruleData.timestamp = new Date(this.temp.timestamp)
  350. // console.log(this.ruleData)
  351. // console.log(row_data)
  352. this.ruleData = Object.assign({}, row_data[0])
  353. // console.log(this.ruleData)
  354. this.ruleData.timestamp = new Date(this.ruleData.timestamp)
  355. this.dialogStatus = 'update'
  356. this.dialogFormVisible = true
  357. this.showSubmit = true
  358. this.$nextTick(() => {
  359. this.$refs['ruleDataForm'].clearValidate()
  360. })
  361. })
  362. },
  363. handleModifyStatus(row, status) {
  364. var statusData = {
  365. id: row.id,
  366. status: status
  367. }
  368. // console.log(statusData)
  369. changeStatus(statusData).then(response => {
  370. // console.log(response)
  371. if (response.code === 200) {
  372. row.status = status
  373. this.$message({
  374. message: row.id.toString() + ' 操作成功!',
  375. type: 'success'
  376. })
  377. } else {
  378. this.$message({
  379. message: row.id.toString() + ' 操作失败!',
  380. type: 'danger'
  381. })
  382. }
  383. })
  384. },
  385. handleCopy(row) {
  386. this.ruleData = Object.assign({}, row) // copy obj
  387. this.ruleData.timestamp = new Date(this.ruleData.timestamp)
  388. this.dialogStatus = 'create'
  389. this.dialogFormVisible = true
  390. this.showSubmit = true
  391. this.$nextTick(() => {
  392. this.$refs['ruleDataForm'].clearValidate()
  393. })
  394. },
  395. updateData() {
  396. this.$refs['ruleDataForm'].validate((valid) => {
  397. if (valid) {
  398. // const tempData = Object.assign({}, this.ruleData)
  399. const tempData = {
  400. id: this.ruleData.id,
  401. methodId: parseInt(this.$route.path.split('/')[3]),
  402. creator: '',
  403. updator: '',
  404. execSort: this.ruleData.execSort,
  405. whenScript: this.ruleData.whenScript,
  406. returnMessage: this.ruleData.returnMessage,
  407. mehtodName: this.$route.query.methodName
  408. }
  409. updateRule(tempData).then(() => {
  410. this.getList()
  411. // for (const v of this.list) {
  412. // if (v.id === this.ruleData.id) {
  413. // const index = this.list.indexOf(v)
  414. // this.list.splice(index, 1, this.ruleData)
  415. // break
  416. // }
  417. // }
  418. this.dialogFormVisible = false
  419. this.$notify({
  420. title: 'Success',
  421. message: 'Update Successfully',
  422. type: 'success',
  423. duration: 2000
  424. })
  425. })
  426. }
  427. })
  428. },
  429. formatJson(filterVal, jsonData) {
  430. return jsonData.map(v => filterVal.map(j => {
  431. if (j === 'timestamp') {
  432. return parseTime(v[j])
  433. } else {
  434. return v[j]
  435. }
  436. }))
  437. },
  438. handleCheck(row) {
  439. var queryData = { id: row.id }
  440. fetchRuleById(queryData).then(response => {
  441. console.log(response)
  442. var row_data = response.data.mockRuleList
  443. // this.ruleData.timestamp = new Date(this.temp.timestamp)
  444. // console.log(this.ruleData)
  445. // console.log(row_data)
  446. this.ruleData = Object.assign({}, row_data[0])
  447. // console.log(this.ruleData)
  448. this.ruleData.timestamp = new Date(this.ruleData.timestamp)
  449. this.dialogStatus = 'update'
  450. this.dialogFormVisible = true
  451. this.showSubmit = false
  452. this.$nextTick(() => {
  453. this.$refs['ruleDataForm'].clearValidate()
  454. })
  455. })
  456. }
  457. }
  458. }
  459. </script>
  460. <style>
  461. .el-notification.right{
  462. position: fixed;
  463. right: 38.5%;
  464. }
  465. </style>