debugging.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  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 field="type" title="类型" width="200" :edit-render="{}">
  190. <template #default="{ row }">
  191. <vxe-select
  192. v-model="row.type"
  193. transfer
  194. @change="
  195. (val) => {
  196. handleChange(val, row, 'zTable');
  197. }
  198. "
  199. >
  200. <vxe-option
  201. v-for="item in typeList"
  202. :key="item.value"
  203. :value="item.value"
  204. :label="item.label"
  205. ></vxe-option>
  206. </vxe-select>
  207. </template>
  208. </vxe-column>
  209. <vxe-column title="操作" width="100">
  210. <template #default="{ row }">
  211. <vxe-button
  212. type="text"
  213. v-if="['array', 'object'].includes(row.type)"
  214. status="primary"
  215. @click="insertRow(row, 'zTable')"
  216. >插入</vxe-button
  217. >
  218. <vxe-button type="text" status="primary" @click="removeRow(row, 'zTable')">删除</vxe-button>
  219. </template>
  220. </vxe-column>
  221. </vxe-table>
  222. <Button class="mt10" type="primary" @click="insertEvent('zTable')">添加参数</Button>
  223. <h4 class="mt10 title">全局Header参数</h4>
  224. <vxe-table
  225. class="mt10"
  226. resizable
  227. show-overflow
  228. keep-source
  229. ref="zaTable"
  230. row-id="id"
  231. :print-config="{}"
  232. :export-config="{}"
  233. :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
  234. :data="interfaceData.allHeaderData"
  235. >
  236. <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
  237. <template #default="{ row }">
  238. <span>{{ row.attribute || '' }}</span>
  239. </template>
  240. </vxe-column>
  241. <vxe-column field="value" title="参数值" :edit-render="{}">
  242. <template #default="{ row }">
  243. <span>{{ row.value || '' }}</span>
  244. </template>
  245. </vxe-column>
  246. <vxe-column field="type" title="类型" width="200" :edit-render="{}">
  247. <template #default="{ row }">
  248. <span>{{ row.type || '' }}</span>
  249. </template>
  250. </vxe-column>
  251. <vxe-column field="trip" title="说明" :edit-render="{}">
  252. <template #default="{ row }">
  253. <span>{{ row.trip || '' }}</span>
  254. </template>
  255. </vxe-column>
  256. </vxe-table>
  257. </div>
  258. </div>
  259. <div class="res mt10 mb10" v-if="codes">
  260. <MonacoEditor :codes="codes" :readOnly="true" />
  261. </div>
  262. </div>
  263. </template>
  264. <script>
  265. import request from './request';
  266. import MonacoEditor from './components/MonacoEditor.vue';
  267. import vuedraggable from 'vuedraggable';
  268. function requestMethod(url, method, params, data, headerItem) {
  269. return request({
  270. url,
  271. method,
  272. params,
  273. data,
  274. headerItem,
  275. });
  276. }
  277. export default {
  278. components: { MonacoEditor },
  279. props: {
  280. formValidate: {
  281. type: Object,
  282. default: () => {
  283. return {};
  284. },
  285. },
  286. requestTypeList: {
  287. type: Array,
  288. default: () => {
  289. return [];
  290. },
  291. },
  292. typeList: {
  293. type: Array,
  294. default: () => {
  295. return [];
  296. },
  297. },
  298. },
  299. data() {
  300. return {
  301. bodyType: 'form-data',
  302. interfaceData: undefined,
  303. paramsType: 'Params',
  304. editor: '', //当前编辑器对象
  305. codes: '',
  306. jsonBody: '',
  307. };
  308. },
  309. created() {
  310. this.interfaceData = this.formValidate;
  311. this.interfaceData.request_body = JSON.parse(JSON.stringify(this.interfaceData.request));
  312. console.log(this.interfaceData);
  313. },
  314. mounted() {},
  315. methods: {
  316. async handleChange(e, row, type) {
  317. console.log(type, row);
  318. if (e.value !== 'array' && e.value !== 'object') {
  319. if (row.children.length) {
  320. let arr = this.$refs[type].getTableData().tableData;
  321. let id = row.children[0].parentId;
  322. const $table = this.$refs[type];
  323. for (let i = 0; i < arr.length; i++) {
  324. if (arr[i].parentId == id) {
  325. await $table.remove(arr[i]);
  326. }
  327. }
  328. }
  329. }
  330. },
  331. insertCopy() {
  332. this.$copyText(this.codes)
  333. .then((message) => {
  334. this.$Message.success('复制成功');
  335. })
  336. .catch((err) => {
  337. this.$Message.error('复制失败');
  338. });
  339. },
  340. async requestData() {
  341. let url, method, params, body, headers;
  342. url = this.interfaceData.app_name + '/' + this.interfaceData.path;
  343. method = this.interfaceData.method;
  344. params = this.filtersData((await this.$refs.xTable.getTableData().tableData) || []);
  345. body =
  346. this.bodyType === 'json'
  347. ? this.jsonBody
  348. : this.filtersData((await this.$refs.yTable.getTableData().tableData) || []);
  349. let h = this.filtersData((await this.$refs.zTable.getTableData().tableData) || []);
  350. let h1 = this.filtersData((await this.$refs.zaTable.getTableData().tableData) || []);
  351. headers = {
  352. ...h,
  353. ...h1,
  354. };
  355. console.log(url, method, params, body, headers);
  356. this.codes = '';
  357. requestMethod(url, method, params, body, headers)
  358. .then((res) => {
  359. console.log(res, 'res');
  360. this.codes = JSON.stringify(res);
  361. })
  362. .catch((err) => {
  363. console.log(err, 'err');
  364. this.codes = JSON.stringify(err);
  365. });
  366. },
  367. filtersData(arr) {
  368. console.log(arr);
  369. try {
  370. let x = {};
  371. arr.map((e) => {
  372. if (!e.parentId) {
  373. for (let i in e) {
  374. if (i == 'attribute') {
  375. console.log(e.type);
  376. if (e.type === 'object') {
  377. let obj = {};
  378. e.children.map((item, index) => {
  379. obj = this.filtersObj(item, 1);
  380. });
  381. console.log(obj, 'objobjobj');
  382. x[e[i]] = obj;
  383. } else if (e.type !== 'array') {
  384. x[e[i]] = e.value || '';
  385. } else {
  386. let arr = [];
  387. e.children.map((item, index) => {
  388. arr[index] = this.filtersObj(item);
  389. });
  390. x[e[i]] = arr;
  391. }
  392. }
  393. }
  394. }
  395. });
  396. return x;
  397. } catch (error) {
  398. console.log(error);
  399. }
  400. },
  401. // type 1 为obj属性
  402. filtersObj(obj, type) {
  403. let x = {};
  404. for (let i in obj) {
  405. if (i == 'attribute') {
  406. console.log(obj, 'obj111');
  407. if (obj.type === 'object') {
  408. let oj = {};
  409. obj.children.map((item, index) => {
  410. oj[obj.attribute] = this.filtersObj(item);
  411. });
  412. console.log(oj, 'oj');
  413. x = oj;
  414. } else if (obj.type !== 'array') {
  415. if (type) {
  416. x[obj.attribute] = obj.value || '';
  417. } else {
  418. x[obj[i]] = obj.value || '';
  419. }
  420. } else {
  421. let arr = [];
  422. obj.children.map((item, index) => {
  423. arr[index] = this.filtersObj(item);
  424. });
  425. x[obj[i]] = arr;
  426. }
  427. }
  428. }
  429. return x;
  430. },
  431. changeTab(name) {
  432. if (name === 'Header') {
  433. // if (!this.$refs.zTable.getTableData().tableData.length) {
  434. // this.insertEvent('zTable', {
  435. // attribute: 'Content-Type',
  436. // value: 'application/x-www-form-urlencoded',
  437. // });
  438. // this.insertEvent('zaTable');
  439. // }
  440. }
  441. console.log(this.interfaceData);
  442. },
  443. async insertEvent(type, d) {
  444. const $table = this.$refs[type];
  445. let newRow;
  446. if (type == 'xTable') {
  447. newRow = {
  448. attribute: '',
  449. type: 'string',
  450. must: 0,
  451. value: '',
  452. trip: '',
  453. };
  454. } else if (type == 'yTable') {
  455. newRow = {
  456. attribute: '',
  457. type: 'string',
  458. value: '',
  459. must: 0,
  460. trip: '',
  461. };
  462. } else if (type == 'zTable') {
  463. newRow = {
  464. attribute: '',
  465. type: '',
  466. value: '',
  467. trip: '',
  468. };
  469. newRow = { ...newRow, ...d };
  470. } else if (type == 'zaTable') {
  471. newRow = {
  472. attribute: 'token',
  473. type: 'string',
  474. value: '',
  475. must: 0,
  476. trip: '',
  477. };
  478. } else {
  479. newRow = {
  480. code: '',
  481. value: '',
  482. solution: '',
  483. };
  484. }
  485. const { row: data } = await $table.insertAt(newRow, -1);
  486. await $table.setActiveCell(data, 'name');
  487. },
  488. async insertRow(currRow, type) {
  489. const $table = this.$refs[type];
  490. // 如果 null 则插入到目标节点顶部
  491. // 如果 -1 则插入到目标节点底部
  492. // 如果 row 则有插入到效的目标节点该行的位置
  493. let record;
  494. if (type == 'xTable') {
  495. record = {
  496. attribute: '',
  497. type: 'string',
  498. must: 0,
  499. value: '',
  500. trip: '',
  501. id: Date.now(),
  502. parentId: currRow.id, // 需要指定父节点,自动插入该节点中
  503. };
  504. } else {
  505. record = {
  506. code: '',
  507. value: '',
  508. solution: '',
  509. id: Date.now(),
  510. parentId: currRow.id, // 需要指定父节点,自动插入该节点中
  511. };
  512. }
  513. const { row: newRow } = await $table.insertAt(record, -1);
  514. await $table.setTreeExpand(currRow, true); // 将父节点展开
  515. await $table.setActiveRow(newRow); // 插入子节点
  516. },
  517. async removeRow(row, type) {
  518. const $table = this.$refs[type];
  519. await $table.remove(row);
  520. },
  521. },
  522. };
  523. </script>
  524. <style>
  525. .vxe-select--panel.is--transfer {
  526. z-index: 99999 !important;
  527. }
  528. </style>
  529. <style lang="scss" scoped>
  530. .content {
  531. padding: 12px;
  532. .head {
  533. display: flex;
  534. align-items: center;
  535. .item {
  536. display: flex;
  537. align-items: center;
  538. margin-bottom: 12px;
  539. font-size: 14px;
  540. .title {
  541. margin-right: 14px;
  542. }
  543. }
  544. }
  545. }
  546. .copy-btn {
  547. display: flex;
  548. justify-content: right;
  549. }
  550. </style>