debugging.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. <template>
  2. <div class="content" v-if="interfaceData">
  3. <div class="head">
  4. <Input v-model="interfaceData.path">
  5. <template #prepend>
  6. <Select v-model="interfaceData.method" style="width: 120px">
  7. <Option v-for="(item, index) in requestTypeList" :key="index" :value="item.value">{{ item.label }}</Option>
  8. </Select>
  9. </template>
  10. </Input>
  11. <Button class="ml20" type="primary" @click="requestData">请求</Button>
  12. <Button v-if="codes" class="ml10 copy-btn" type="success" @click="insertCopy()">复制结果</Button>
  13. </div>
  14. <div class="params">
  15. <Tabs class="mt10" v-model="paramsType" @on-click="changeTab">
  16. <TabPane label="Params" name="Params"> </TabPane>
  17. <TabPane label="Body" name="Body"> </TabPane>
  18. <TabPane label="Header" name="Header"> </TabPane>
  19. </Tabs>
  20. <div v-show="paramsType === 'Params'">
  21. <vxe-table
  22. class="mt10"
  23. resizable
  24. show-overflow
  25. keep-source
  26. ref="xTable"
  27. row-id="id"
  28. :print-config="{}"
  29. :export-config="{}"
  30. :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
  31. :data="interfaceData.request"
  32. >
  33. <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
  34. <template #default="{ row }">
  35. <vxe-input v-model="row.attribute" type="text"></vxe-input>
  36. </template>
  37. </vxe-column>
  38. <vxe-column field="value" title="参数值" :edit-render="{}">
  39. <template #default="{ row }">
  40. <vxe-input v-model="row.value" type="text"></vxe-input>
  41. </template>
  42. </vxe-column>
  43. <vxe-column field="type" title="类型" width="120" :edit-render="{}">
  44. <template #default="{ row }">
  45. <vxe-select
  46. v-model="row.type"
  47. transfer
  48. @change="
  49. (val) => {
  50. handleChange(val, row, 'xTable');
  51. }
  52. "
  53. >
  54. <vxe-option
  55. v-for="item in typeList"
  56. :key="item.value"
  57. :value="item.value"
  58. :label="item.label"
  59. ></vxe-option>
  60. </vxe-select>
  61. </template>
  62. </vxe-column>
  63. <!-- <vxe-column field="must" title="必填" width="50" :edit-render="{}">
  64. <template #default="{ row }">
  65. <span>{{ row.must == '1' ? '是' : '否' }}</span>
  66. </template>
  67. </vxe-column>
  68. <vxe-column field="trip" width="150" title="说明" :edit-render="{}">
  69. <template #default="{ row }">
  70. <vxe-input v-model="row.trip" type="text"></vxe-input>
  71. </template>
  72. </vxe-column> -->
  73. <vxe-column title="操作" width="120">
  74. <template #default="{ row }">
  75. <vxe-button
  76. type="text"
  77. v-if="['array', 'object'].includes(row.type)"
  78. status="primary"
  79. @click="insertRow(row, 'xTable')"
  80. >插入</vxe-button
  81. >
  82. <vxe-button type="text" status="primary" @click="removeRow(row, 'xTable')">删除</vxe-button>
  83. </template>
  84. </vxe-column>
  85. </vxe-table>
  86. <Button class="mt10" type="primary" @click="insertEvent('xTable')">添加参数</Button>
  87. </div>
  88. <div v-show="paramsType === 'Body'">
  89. <RadioGroup v-model="bodyType" class="mt10">
  90. <Radio label="form-data"></Radio>
  91. <Radio label="json"></Radio>
  92. </RadioGroup>
  93. <vxe-table
  94. v-if="bodyType == 'form-data'"
  95. class="mt10"
  96. resizable
  97. show-overflow
  98. keep-source
  99. ref="yTable"
  100. row-id="id"
  101. :print-config="{}"
  102. :export-config="{}"
  103. :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
  104. :data="interfaceData.request_body"
  105. >
  106. <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
  107. <template #default="{ row }">
  108. <vxe-input v-model="row.attribute" type="text"></vxe-input>
  109. </template>
  110. </vxe-column>
  111. <vxe-column field="value" title="参数值" :edit-render="{}">
  112. <template #default="{ row }">
  113. <vxe-input v-model="row.value" type="text"></vxe-input>
  114. </template>
  115. </vxe-column>
  116. <vxe-column field="type" title="类型" width="120" :edit-render="{}">
  117. <template #default="{ row }">
  118. <vxe-select
  119. v-model="row.type"
  120. transfer
  121. @change="
  122. (val) => {
  123. handleChange(val, row, 'yTable');
  124. }
  125. "
  126. >
  127. <vxe-option
  128. v-for="item in typeList"
  129. :key="item.value"
  130. :value="item.value"
  131. :label="item.label"
  132. ></vxe-option>
  133. </vxe-select>
  134. </template>
  135. </vxe-column>
  136. <!-- <vxe-column field="must" title="必填" width="50" :edit-render="{}">
  137. <template #default="{ row }">
  138. <span>{{ row.must == '1' ? '是' : '否' }}</span>
  139. </template>
  140. </vxe-column>
  141. <vxe-column field="trip" title="说明" width="150" :edit-render="{}">
  142. <template #default="{ row }">
  143. <vxe-input v-model="row.trip" type="text"></vxe-input>
  144. </template>
  145. </vxe-column> -->
  146. <vxe-column title="操作" width="120">
  147. <template #default="{ row }">
  148. <vxe-button
  149. type="text"
  150. v-if="['array', 'object'].includes(row.type)"
  151. status="primary"
  152. @click="insertRow(row, 'yTable')"
  153. >插入</vxe-button
  154. >
  155. <vxe-button type="text" status="primary" @click="removeRow(row, 'yTable')">删除</vxe-button>
  156. </template>
  157. </vxe-column>
  158. </vxe-table>
  159. <div v-else>
  160. <Input v-model="jsonBody" type="textarea" :rows="8" placeholder="请求数据" />
  161. </div>
  162. <Button v-if="bodyType == 'form-data'" class="mt10" type="primary" @click="insertEvent('yTable')"
  163. >添加参数</Button
  164. >
  165. </div>
  166. <div v-show="paramsType === 'Header'">
  167. <vxe-table
  168. class="mt10"
  169. resizable
  170. show-overflow
  171. keep-source
  172. ref="zTable"
  173. row-id="id"
  174. :print-config="{}"
  175. :export-config="{}"
  176. :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
  177. :data="interfaceData.headerData"
  178. >
  179. <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
  180. <template #default="{ row }">
  181. <vxe-input v-model="row.attribute" type="text"></vxe-input>
  182. </template>
  183. </vxe-column>
  184. <vxe-column field="value" title="参数值" :edit-render="{}">
  185. <template #default="{ row }">
  186. <vxe-input v-model="row.value" type="text"></vxe-input>
  187. </template>
  188. </vxe-column>
  189. <vxe-column title="操作" width="100">
  190. <template #default="{ row }">
  191. <vxe-button
  192. type="text"
  193. v-if="['array', 'object'].includes(row.type)"
  194. status="primary"
  195. @click="insertRow(row, 'zTable')"
  196. >插入</vxe-button
  197. >
  198. <vxe-button type="text" status="primary" @click="removeRow(row, 'zTable')">删除</vxe-button>
  199. </template>
  200. </vxe-column>
  201. </vxe-table>
  202. <Button class="mt10" type="primary" @click="insertEvent('zTable')">添加参数</Button>
  203. <!-- <h4 class="mt10 title">全局Header参数</h4>
  204. <vxe-table
  205. class="mt10"
  206. resizable
  207. show-overflow
  208. keep-source
  209. ref="zaTable"
  210. row-id="id"
  211. :print-config="{}"
  212. :export-config="{}"
  213. :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
  214. :data="interfaceData.allHeaderData"
  215. >
  216. <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
  217. <template #default="{ row }">
  218. <span>{{ row.attribute || '' }}</span>
  219. </template>
  220. </vxe-column>
  221. <vxe-column field="value" title="参数值" :edit-render="{}">
  222. <template #default="{ row }">
  223. <span>{{ row.value || '' }}</span>
  224. </template>
  225. </vxe-column>
  226. <vxe-column field="type" title="类型" width="200" :edit-render="{}">
  227. <template #default="{ row }">
  228. <span>{{ row.type || '' }}</span>
  229. </template>
  230. </vxe-column>
  231. <vxe-column field="trip" title="说明" :edit-render="{}">
  232. <template #default="{ row }">
  233. <span>{{ row.trip || '' }}</span>
  234. </template>
  235. </vxe-column>
  236. </vxe-table> -->
  237. </div>
  238. </div>
  239. <div class="res mt10 mb10" v-if="codes">
  240. <MonacoEditor :codes="codes" :readOnly="true" />
  241. </div>
  242. </div>
  243. </template>
  244. <script>
  245. import request from './request';
  246. import MonacoEditor from './components/MonacoEditor.vue';
  247. import vuedraggable from 'vuedraggable';
  248. function requestMethod(url, method, params, data, headerItem) {
  249. return request({
  250. url,
  251. method,
  252. params,
  253. data,
  254. headerItem,
  255. });
  256. }
  257. export default {
  258. components: { MonacoEditor },
  259. props: {
  260. formValidate: {
  261. type: Object,
  262. default: () => {
  263. return {};
  264. },
  265. },
  266. requestTypeList: {
  267. type: Array,
  268. default: () => {
  269. return [];
  270. },
  271. },
  272. typeList: {
  273. type: Array,
  274. default: () => {
  275. return [];
  276. },
  277. },
  278. },
  279. data() {
  280. return {
  281. bodyType: 'form-data',
  282. interfaceData: undefined,
  283. paramsType: 'Params',
  284. editor: '', //当前编辑器对象
  285. codes: '',
  286. jsonBody: '',
  287. };
  288. },
  289. created() {
  290. this.interfaceData = this.formValidate;
  291. this.interfaceData.request_body = JSON.parse(JSON.stringify(this.interfaceData.request));
  292. console.log(this.interfaceData);
  293. },
  294. mounted() {},
  295. methods: {
  296. async handleChange(e, row, type) {
  297. console.log(type, row);
  298. if (e.value !== 'array' && e.value !== 'object') {
  299. if (row.children.length) {
  300. let arr = this.$refs[type].getTableData().tableData;
  301. let id = row.children[0].parentId;
  302. const $table = this.$refs[type];
  303. for (let i = 0; i < arr.length; i++) {
  304. if (arr[i].parentId == id) {
  305. await $table.remove(arr[i]);
  306. }
  307. }
  308. }
  309. }
  310. },
  311. insertCopy() {
  312. this.$copyText(this.codes)
  313. .then((message) => {
  314. this.$Message.success('复制成功');
  315. })
  316. .catch((err) => {
  317. this.$Message.error('复制失败');
  318. });
  319. },
  320. async requestData() {
  321. let url, method, params, body, headers;
  322. url = this.interfaceData.app_name + '/' + this.interfaceData.path;
  323. method = this.interfaceData.method;
  324. params = this.filtersData((await this.$refs.xTable.getTableData().tableData) || []);
  325. body =
  326. this.bodyType === 'json'
  327. ? this.jsonBody
  328. : this.filtersData((await this.$refs.yTable.getTableData().tableData) || []);
  329. let h = this.filtersData((await this.$refs.zTable.getTableData().tableData) || []);
  330. let h1 = this.filtersData((await this.$refs.zaTable.getTableData().tableData) || []);
  331. headers = {
  332. ...h,
  333. ...h1,
  334. };
  335. console.log(url, method, params, body, headers);
  336. this.codes = '';
  337. requestMethod(url, method, params, body, headers)
  338. .then((res) => {
  339. console.log(res, 'res');
  340. if (!res) return this.$Message.error('接口异常');
  341. this.codes = JSON.stringify(res);
  342. })
  343. .catch((err) => {
  344. console.log(err, 'err');
  345. if (!err) return this.$Message.error('接口异常');
  346. this.codes = JSON.stringify(err);
  347. });
  348. },
  349. filtersData(arr) {
  350. console.log(arr);
  351. try {
  352. let x = {};
  353. arr.map((e) => {
  354. if (!e.parentId) {
  355. for (let i in e) {
  356. if (i == 'attribute') {
  357. console.log(e.type);
  358. if (e.type === 'object') {
  359. let obj = {};
  360. e.children.map((item, index) => {
  361. obj = this.filtersObj(item, 1);
  362. });
  363. console.log(obj, 'objobjobj');
  364. x[e[i]] = obj;
  365. } else if (e.type !== 'array') {
  366. x[e[i]] = e.value || '';
  367. } else {
  368. let arr = [];
  369. e.children.map((item, index) => {
  370. arr[index] = this.filtersObj(item);
  371. });
  372. x[e[i]] = arr;
  373. }
  374. }
  375. }
  376. }
  377. });
  378. return x;
  379. } catch (error) {
  380. console.log(error);
  381. }
  382. },
  383. // type 1 为obj属性
  384. filtersObj(obj, type) {
  385. let x = {};
  386. for (let i in obj) {
  387. if (i == 'attribute') {
  388. console.log(obj, 'obj111');
  389. if (obj.type === 'object') {
  390. let oj = {};
  391. obj.children.map((item, index) => {
  392. oj[obj.attribute] = this.filtersObj(item);
  393. });
  394. console.log(oj, 'oj');
  395. x = oj;
  396. } else if (obj.type !== 'array') {
  397. if (type) {
  398. x[obj.attribute] = obj.value || '';
  399. } else {
  400. x[obj[i]] = obj.value || '';
  401. }
  402. } else {
  403. let arr = [];
  404. obj.children.map((item, index) => {
  405. arr[index] = this.filtersObj(item);
  406. });
  407. x[obj[i]] = arr;
  408. }
  409. }
  410. }
  411. return x;
  412. },
  413. changeTab(name) {
  414. if (name === 'Header') {
  415. // if (!this.$refs.zTable.getTableData().tableData.length) {
  416. // this.insertEvent('zTable', {
  417. // attribute: 'Content-Type',
  418. // value: 'application/x-www-form-urlencoded',
  419. // });
  420. // this.insertEvent('zaTable');
  421. // }
  422. }
  423. console.log(this.interfaceData);
  424. },
  425. async insertEvent(type, d) {
  426. const $table = this.$refs[type];
  427. let newRow;
  428. if (type == 'xTable') {
  429. newRow = {
  430. attribute: '',
  431. type: 'string',
  432. must: 0,
  433. value: '',
  434. trip: '',
  435. };
  436. } else if (type == 'yTable') {
  437. newRow = {
  438. attribute: '',
  439. type: 'string',
  440. value: '',
  441. must: 0,
  442. trip: '',
  443. };
  444. } else if (type == 'zTable') {
  445. newRow = {
  446. attribute: '',
  447. type: '',
  448. value: '',
  449. trip: '',
  450. };
  451. newRow = { ...newRow, ...d };
  452. } else if (type == 'zaTable') {
  453. newRow = {
  454. attribute: 'token',
  455. type: 'string',
  456. value: '',
  457. must: 0,
  458. trip: '',
  459. };
  460. } else {
  461. newRow = {
  462. code: '',
  463. value: '',
  464. solution: '',
  465. };
  466. }
  467. const { row: data } = await $table.insertAt(newRow, -1);
  468. await $table.setActiveCell(data, 'name');
  469. },
  470. async insertRow(currRow, type) {
  471. const $table = this.$refs[type];
  472. // 如果 null 则插入到目标节点顶部
  473. // 如果 -1 则插入到目标节点底部
  474. // 如果 row 则有插入到效的目标节点该行的位置
  475. let record;
  476. if (type == 'xTable') {
  477. record = {
  478. attribute: '',
  479. type: 'string',
  480. must: 0,
  481. value: '',
  482. trip: '',
  483. id: Date.now(),
  484. parentId: currRow.id, // 需要指定父节点,自动插入该节点中
  485. };
  486. } else {
  487. record = {
  488. code: '',
  489. value: '',
  490. solution: '',
  491. id: Date.now(),
  492. parentId: currRow.id, // 需要指定父节点,自动插入该节点中
  493. };
  494. }
  495. const { row: newRow } = await $table.insertAt(record, -1);
  496. await $table.setTreeExpand(currRow, true); // 将父节点展开
  497. await $table.setActiveRow(newRow); // 插入子节点
  498. },
  499. async removeRow(row, type) {
  500. const $table = this.$refs[type];
  501. await $table.remove(row);
  502. },
  503. },
  504. };
  505. </script>
  506. <style>
  507. .vxe-select--panel.is--transfer {
  508. z-index: 99999 !important;
  509. }
  510. </style>
  511. <style lang="scss" scoped>
  512. .content {
  513. padding: 12px;
  514. .head {
  515. display: flex;
  516. align-items: center;
  517. .item {
  518. display: flex;
  519. align-items: center;
  520. margin-bottom: 12px;
  521. font-size: 14px;
  522. .title {
  523. margin-right: 14px;
  524. }
  525. }
  526. }
  527. }
  528. .copy-btn {
  529. display: flex;
  530. justify-content: right;
  531. }
  532. </style>