Просмотр исходного кода

feat: 代码生成/路由权限/接口调试

From-wh 2 лет назад
Родитель
Сommit
69b6b9cb7d
29 измененных файлов с 3017 добавлено и 87 удалено
  1. 108 0
      template/admin/src/api/systemBackendRouting.js
  2. 0 1
      template/admin/src/assets/iconfont/iconfont.js
  3. 0 7
      template/admin/src/components/goodsList/index.vue
  4. 20 18
      template/admin/src/components/systemStore/index.vue
  5. 0 2
      template/admin/src/layout/component/aside.vue
  6. 0 9
      template/admin/src/layout/component/columnsAside.vue
  7. 0 2
      template/admin/src/layout/index.vue
  8. 0 8
      template/admin/src/layout/navBars/breadcrumb/breadcrumb.vue
  9. 0 1
      template/admin/src/layout/navBars/breadcrumb/index.vue
  10. 0 11
      template/admin/src/layout/navBars/breadcrumb/setings.vue
  11. 0 9
      template/admin/src/layout/navBars/tagsView/tagsView.vue
  12. 0 1
      template/admin/src/layout/navMenu/vertical.vue
  13. 0 1
      template/admin/src/layout/routerView/parent.vue
  14. 0 2
      template/admin/src/pages/account/login/index.vue
  15. 10 4
      template/admin/src/pages/cms/articleCategory/index.vue
  16. 75 0
      template/admin/src/pages/setting/systemOutInterface/components/MonacoEditor.vue
  17. 465 0
      template/admin/src/pages/setting/systemOutInterface/debugging.vue
  18. 14 9
      template/admin/src/pages/setting/systemOutInterface/index.vue
  19. 121 0
      template/admin/src/pages/setting/systemOutInterface/request.js
  20. 75 0
      template/admin/src/pages/system/backendRouting/components/MonacoEditor.vue
  21. 467 0
      template/admin/src/pages/system/backendRouting/debugging.vue
  22. 1102 0
      template/admin/src/pages/system/backendRouting/index.vue
  23. 121 0
      template/admin/src/pages/system/backendRouting/request.js
  24. 119 0
      template/admin/src/pages/system/codeGeneration/components/Field.vue
  25. 123 0
      template/admin/src/pages/system/codeGeneration/components/FormItem.vue
  26. 56 0
      template/admin/src/pages/system/codeGeneration/components/FoundationForm.vue
  27. 45 0
      template/admin/src/pages/system/codeGeneration/components/StorageLoc.vue
  28. 76 0
      template/admin/src/pages/system/codeGeneration/index.vue
  29. 20 2
      template/admin/src/router/modules/system.js

+ 108 - 0
template/admin/src/api/systemBackendRouting.js

@@ -0,0 +1,108 @@
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+
+import request from '@/libs/request';
+
+/**
+ * 同步路由权限
+ */
+export function syncRoute(appName) {
+  return request({
+    url: `system/route/sync_route/${appName}`,
+    method: 'get',
+  });
+}
+/**
+ * 新增路由分类
+ */
+export function routeCate(appName) {
+  return request({
+    url: `system/route_cate/create?app_name=${appName}`,
+    method: 'get',
+  });
+}
+/**
+ * 路由树
+ */
+export function routeList() {
+  return request({
+    url: `system/route/tree`,
+    method: 'get',
+  });
+}
+
+/**
+ * 添加/编辑接口
+ * @param {*} data
+ * @returns
+ */
+export function routeSave(data) {
+  return request({
+    url: `system/route/${data.id}`,
+    method: 'post',
+    data,
+  });
+}
+
+/**
+ * 接口信息详情
+ * @param {*} data
+ * @returns
+ */
+export function routeDet(id) {
+  return request({
+    url: `system/route/${id}`,
+    method: 'get',
+  });
+}
+
+/**
+ * @description 修改名称
+ * @param {Object} data data {Object} 传值
+ */
+export function interfaceEditName(data) {
+  return request({
+    url: `setting/system_out_interface/edit_name`,
+    method: 'PUT',
+    data,
+  });
+}
+
+/**
+ * @description 删除
+ */
+export function routeDel(id) {
+  return request({
+    url: 'system/route/' + id,
+    method: 'delete',
+  });
+}
+/**
+ * @description 删除
+ */
+export function routeCateDel(id) {
+  return request({
+    url: 'system/route_cate/' + id,
+    method: 'delete',
+  });
+}
+
+/**
+ * 接口信息详情
+ * @param {*} data
+ * @returns
+ */
+export function textOutUrl(data) {
+  return request({
+    url: `setting/system_out_account/text_out_url`,
+    method: 'post',
+    data,
+  });
+}

+ 0 - 1
template/admin/src/assets/iconfont/iconfont.js

@@ -17,7 +17,6 @@
         '<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>',
       );
     } catch (a) {
-      console && console.log(a);
     }
   }
   function t() {

+ 0 - 7
template/admin/src/components/goodsList/index.vue

@@ -272,7 +272,6 @@ export default {
     } else {
       this.getList();
     }
-    console.log(this.diy);
   },
   methods: {
     productList() {
@@ -338,15 +337,12 @@ export default {
         }
         changeListApi(this.formValidate)
           .then(async (res) => {
-            console.log(this.selectIds);
-
             let data = res.data;
             if (this.selectIds.length) {
               let arr = [];
               this.selectIds.map((item) => {
                 data.list.map((i) => {
                   if (i.id == item) {
-                    console.log(i);
                     i._checked = true;
                     arr.push(i);
                   }
@@ -376,13 +372,10 @@ export default {
             data.list.forEach((el) => {
               el.image = el.cover_img;
             });
-
-            console.log(this.selectIds);
             if (this.selectIds.length) {
               this.selectIds.map((item) => {
                 data.list.map((i) => {
                   if (i.id == item) {
-                    console.log(i);
                     i._checked = true;
                   }
                 });

+ 20 - 18
template/admin/src/components/systemStore/index.vue

@@ -178,8 +178,8 @@
 <script>
 import { storeApi, keyApi, storeAddApi, storeGetInfoApi } from '@/api/setting';
 import { mapState } from 'vuex';
-import city from '@/utils/city';
 import uploadPictures from '@/components/uploadPictures';
+import { cityList } from '@/api/app';
 export default {
   name: 'systemStore',
   components: { uploadPictures },
@@ -297,23 +297,7 @@ export default {
     };
   },
   created() {
-    let that = this;
-    city.map((item) => {
-      item.value = item.label;
-      if (item.children && item.children.length) {
-        item.children.map((j) => {
-          j.value = j.label;
-          if (j.children && j.children.length) {
-            j.children.map((o) => {
-              o.value = o.label;
-            });
-          }
-        });
-      }
-    });
-    setTimeout(function () {
-      that.addresData = city;
-    }, 10);
+    this.getCityList();
   },
   computed: {},
   mounted: function () {
@@ -332,6 +316,24 @@ export default {
     window.selectAdderss = this.selectAdderss;
   },
   methods: {
+    getCityList() {
+      cityList().then((res) => {
+        res.data.map((item) => {
+          item.value = item.label;
+          if (item.children && item.children.length) {
+            item.children.map((j) => {
+              j.value = j.label;
+              if (j.children && j.children.length) {
+                j.children.map((o) => {
+                  o.value = o.label;
+                });
+              }
+            });
+          }
+        });
+        this.addresData = res.data;
+      });
+    },
     cancel() {
       this.$refs['formItem'].resetFields();
       this.clearFrom();

+ 0 - 2
template/admin/src/layout/component/aside.vue

@@ -74,11 +74,9 @@ export default {
     },
   },
   created() {
-    console.log(this.$store.state.menus, 'this.$store.state.menus');
     this.initMenuFixed(document.body.clientWidth);
     this.setFilterRoutes();
     this.bus.$on('setSendColumnsChildren', (res) => {
-      console.log('收到了', res);
       this.menuList = res || [];
       this.menuList.length > 0
         ? (this.$store.state.themeConfig.themeConfig.isCollapse = false)

+ 0 - 9
template/admin/src/layout/component/columnsAside.vue

@@ -63,11 +63,9 @@ export default {
     },
     // 设置分栏布局风格
     setColumnsAsidelayout() {
-      console.log(this.$store.state.themeConfig.themeConfig.columnsAsideLayout, '122311');
       return this.$store.state.themeConfig.themeConfig.columnsAsideLayout;
     },
     Layout() {
-      console.log(this.$store.state.themeConfig.themeConfig.Layout, '122311444');
       return this.$store.state.themeConfig.themeConfig.Layout;
     },
   },
@@ -77,7 +75,6 @@ export default {
   methods: {
     // 设置菜单高亮位置移动
     setColumnsAsideMove(k) {
-      console.log(k);
       if (k === undefined) return false;
       const els = this.$refs.columnsAsideOffsetTopRefs;
       this.liIndex = k;
@@ -85,7 +82,6 @@ export default {
     },
     // 菜单高亮点击事件
     onColumnsAsideMenuClick(v) {
-      //   console.log(v, 'vvvv');
       let { path, redirect } = v;
       if (path) this.$router.push(path);
       else this.$router.push(path);
@@ -151,9 +147,7 @@ export default {
       // this.routeSplit = path.split('/');
       // this.routeSplit.shift();
       // const routeFirst = `/${this.routeSplit[0]}`;
-      console.log(path, this.columnsAsideList);
       const currentSplitRoute = this.columnsAsideList.find((v) => v.path === path);
-      console.log(currentSplitRoute, 'currentSplitRoute');
       if (!currentSplitRoute) {
         // this.onColumnsAsideDown(0);
         return false;
@@ -168,7 +162,6 @@ export default {
     // 监听 vuex 数据变化
     '$store.state': {
       handler(val) {
-        console.log('变了变了');
         val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound'
           ? (this.difference = 3)
           : (this.difference = 0);
@@ -182,8 +175,6 @@ export default {
         this.setColumnsMenuHighlight(to.path);
         // this.setColumnsAsideMove();
         let HeadName = getHeaderName(to, this.columnsAsideList);
-        console.log(to, '1231');
-
         let asideList = getMenuSider(this.columnsAsideList, HeadName)[0]?.children;
         const resData = this.setSendChildren(HeadName);
         if (resData.length <= 0) return false;

+ 0 - 2
template/admin/src/layout/index.vue

@@ -34,7 +34,6 @@ export default {
   },
   watch: {
     $route(newRoute) {
-      console.log(newRoute, '出发了。。。');
       this.headMenuNoShow = this.$route.meta.fullScreen;
       const { name, query, params, meta, path } = newRoute;
       this.addTag({
@@ -46,7 +45,6 @@ export default {
     },
   },
   created() {
-    console.log(this.$route, 'this.$route.this.$route.');
     this.headMenuNoShow = this.$route.meta.fullScreen;
     this.onLayoutResize();
     window.addEventListener('resize', this.onLayoutResize);

+ 0 - 8
template/admin/src/layout/navBars/breadcrumb/breadcrumb.vue

@@ -118,7 +118,6 @@ export default {
     },
     // 递归设置 breadcrumb
     getBreadcrumbList(arr) {
-      console.log(this.routeSplit, 'routeSplit');
       arr.map((item) => {
         this.routeSplit.map((v, k, arrs) => {
           if (this.routeSplitFirst === item.path) {
@@ -129,7 +128,6 @@ export default {
           }
         });
       });
-      console.log(arr, 'arrarrarr');
     },
     // 当前路由分割处理
     initRouteSplit(path) {
@@ -143,12 +141,9 @@ export default {
         },
       ];
       //   this.routeSplit = path.split('/');
-      console.log(path.split('/'), 'path');
-
       //   this.routeSplit.shift();
       this.routeSplitFirst = path;
       this.routeSplitIndex = 1;
-      console.log(',,,,,');
       this.getBreadcrumbList(this.$store.state.routesList.routesList);
     },
   },
@@ -156,11 +151,9 @@ export default {
   watch: {
     $route: {
       handler(newVal) {
-        console.log(newVal, '123321`', this.$store.state.menus.menusName);
         // this.initRouteSplit(newVal.path);
         let menuList = this.$store.state.menus.menusName;
         let openMenus = getMenuopen(newVal, menuList);
-        console.log('11', openMenus);
         let allMenuList = R(menuList, []);
         let selectMenu = [];
         if (allMenuList.length > 0) {
@@ -172,7 +165,6 @@ export default {
             });
           });
         }
-        console.log(openMenus, 'selectMenu');
       },
       deep: true,
     },

+ 0 - 1
template/admin/src/layout/navBars/breadcrumb/index.vue

@@ -24,7 +24,6 @@ export default {
     // 设置 logo 是否显示
     setIsShowLogo() {
       let { isShowLogo, layout } = this.$store.state.themeConfig.themeConfig;
-      console.log(this.$store.state.themeConfig.themeConfig, layout, 'isShowLogo, layout');
       return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse');
     },
     // 设置是否显示横向菜单

+ 0 - 11
template/admin/src/layout/navBars/breadcrumb/setings.vue

@@ -356,7 +356,6 @@ export default {
     },
     setLocalTheme(val) {
       let themeSelect = themeList[val];
-      console.log(this.getThemeConfig.layout);
       if (['theme-1', 'theme-3', 'theme-5', 'theme-7'].includes(val)) {
         // 这几个为黑色背景主题
         if (['classic', 'transverse'].includes(this.getThemeConfig.layout)) {
@@ -422,16 +421,8 @@ export default {
             themeSelect['--prev-MenuActiveColor'] = '#fff';
           }
         }
-      } else {
-        if (this.getThemeConfig.layout === 'columns') {
-          if (val == 'theme-4') {
-            // themeSelect['--prev-bg-menu-hover-ba-color'] = '#ecf8f3';
-            // themeSelect['--prev-color-primary'] = '#41b584';
-          }
-        }
       }
       for (let key in themeSelect) {
-        console.log(key, themeSelect[key]);
         document.documentElement.style.setProperty(key, themeSelect[key]);
       }
     },
@@ -475,7 +466,6 @@ export default {
     },
     // 布局配置弹窗打开
     openDrawer() {
-      console.log('触发了');
       this.$store.state.themeConfig.themeConfig.isDrawer = true;
     },
     // 关闭弹窗时,初始化变量
@@ -511,7 +501,6 @@ export default {
     },
     // 设置布局切换,重置主题样式
     initSetLayoutChange() {
-      console.log(this.$store.state.themeConfig.themeConfig.layout);
 
       // if (this.$store.state.themeConfig.themeConfig.layout === 'classic') {
       //   this.onBgColorPickerChange('menuBar', '#282c34');

+ 0 - 9
template/admin/src/layout/navBars/tagsView/tagsView.vue

@@ -74,7 +74,6 @@ export default {
     this.bus.$on('onCurrentContextmenuClick', (data) => {
       this.onCurrentContextmenuClick(data);
     });
-    console.log(this.$store.state.app.tagNavList);
     this.tagsViewRoutesList = this.$store.state.app.tagNavList;
   },
   mounted() {
@@ -91,7 +90,6 @@ export default {
     onTagsClick(v, k) {
       this.tagsRoutePath = v.path;
       this.tagsRefsIndex = k;
-      console.log(v, k, '11111');
       this.$router.push(v);
     },
     // 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动
@@ -189,7 +187,6 @@ export default {
       this.tagsViewList = [];
       if (!this.$store.state.themeConfig.themeConfig.isCacheTagsView) Session.remove('tagsViewList');
       this.tagsViewRoutesList = this.$store.state.tagsViewRoutes.tagsViewRoutes;
-      console.log(this.tagsViewRoutesList, 'tagsViewRoutesList');
       this.initTagsViewList();
     },
     // 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录
@@ -198,11 +195,9 @@ export default {
     },
     // 初始化设置了 tagsView 数据
     initTagsViewList() {
-      console.log(Session.get('tagsViewList'), 'Session.get');
       if (Session.get('tagsViewList') && this.$store.state.themeConfig.themeConfig.isCacheTagsView) {
         this.tagsViewList = Session.get('tagsViewList');
       } else {
-        console.log(this.tagsViewRoutesList, 'this.tagsViewRoutesList');
         this.tagsViewRoutesList.map((v) => {
           if (v.isAffix && !v.isHide) this.tagsViewList.push({ ...v });
         });
@@ -224,14 +219,12 @@ export default {
     },
     // 右键菜单点击时显示菜单列表
     onContextmenu(v, e) {
-      console.log(v, e);
       let { clientX, clientY } = e;
       this.tagsDropdown.x = clientX;
       this.tagsDropdown.y = clientY;
       this.$refs.tagsContextmenu.openContextmenu(v);
     },
     onContextmenuIcon(e) {
-      console.log(e);
     },
     // 当前项右键菜单点击
     onCurrentContextmenuClick(data) {
@@ -256,7 +249,6 @@ export default {
     },
     // 1、刷新当前 tagsView:
     refreshCurrentTagsView(path) {
-      console.log(path);
       this.bus.$emit('onTagsViewRefreshRouterView', path);
     },
     // 2、关闭当前 tagsView:当前项 `tags-view` icon 关闭时点击,如果是设置了固定的(isAffix),不可以关闭
@@ -284,7 +276,6 @@ export default {
       this.tagsViewRoutesList.map((v) => {
         if (v.meta.isAffix && !v.meta.isHide) tagsViewList.push({ ...v });
         if ((v.path = path)) tagsViewList.push({ ...v });
-        console.log(tagsViewList);
       });
       this.addBrowserSetSession(tagsViewList);
       // this.addTagsView(path);

+ 0 - 1
template/admin/src/layout/navMenu/vertical.vue

@@ -80,7 +80,6 @@ export default {
     },
   },
   created() {
-    console.log(this.menuList, 'menuListmenuList');
   },
 };
 </script>

+ 0 - 1
template/admin/src/layout/routerView/parent.vue

@@ -22,7 +22,6 @@ export default {
   created() {
     this.keepAliveNameList = this.getKeepAliveNames();
     this.bus.$on('onTagsViewRefreshRouterView', (path) => {
-      console.log(path);
       if (this.$route.path !== path) return false;
       this.keepAliveNameList = this.getKeepAliveNames().filter((name) => this.$route.name !== name);
       this.refreshRouterViewKey = this.$route.path;

+ 0 - 2
template/admin/src/pages/account/login/index.vue

@@ -258,7 +258,6 @@ export default {
     },
     formatTwoStageRoutes(arr) {
       if (arr.length <= 0) return false;
-      console.log(arr, 'arr');
       const newArr = [];
       const cacheList = [];
       arr.forEach((v) => {
@@ -268,7 +267,6 @@ export default {
           this.$store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);
         }
       });
-      console.log(newArr, 'newArr');
       return newArr;
     },
     // 多级嵌套数组处理成一维数组

+ 10 - 4
template/admin/src/pages/cms/articleCategory/index.vue

@@ -79,10 +79,16 @@
           </template>
         </vxe-table-column>
       </vxe-table>
-      <!--            <div class="acea-row row-right page">-->
-      <!--                <Page :total="total" :current="formValidate.page" show-elevator show-total @on-change="pageChange"-->
-      <!--                      :page-size="formValidate.limit"/>-->
-      <!--            </div>-->
+      <div class="acea-row row-right page">
+        <Page
+          :total="total"
+          :current="formValidate.page"
+          show-elevator
+          show-total
+          @on-change="pageChange"
+          :page-size="formValidate.limit"
+        />
+      </div>
     </Card>
   </div>
 </template>

+ 75 - 0
template/admin/src/pages/setting/systemOutInterface/components/MonacoEditor.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="monaco-container">
+    <div ref="container" class="monaco-editor"></div>
+  </div>
+</template>
+
+<script>
+import * as monaco from 'monaco-editor';
+export default {
+  name: '',
+  props: {
+    // 编辑器中呈现的内容
+    codes: {
+      type: String,
+      default: function () {
+        return '';
+      },
+    },
+    readOnly: {
+      type: Boolean,
+      default: function () {
+        return false;
+      },
+    },
+    // 主要配置
+    editorOptions: {
+      type: Object,
+      default: function () {
+        return {
+          selectOnLineNumbers: true,
+          roundedSelection: false,
+          readOnly: this.readOnly, // 只读
+          cursorStyle: 'line', // 光标样式
+          automaticLayout: false, // 自动布局
+          glyphMargin: true, // 字形边缘
+          useTabStops: false,
+          fontSize: 28, // 字体大小
+          autoIndent: true, // 自动布局
+        };
+      },
+    },
+  },
+
+  data() {
+    return {};
+  },
+  created() {},
+  mounted() {
+    this.monacoEditor = monaco.editor.create(this.$refs.container, {
+      value: this.codes, // 见props
+      language: 'json',
+      theme: 'vs', // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网
+      automaticLayout: true, //自动布局
+      //   foldingStrategy: 'indentation', // 代码可分小段折叠
+      scrollbar: {
+        // 滚动条设置
+        verticalScrollbarSize: 4, // 竖滚动条
+        horizontalScrollbarSize: 10, // 横滚动条
+      },
+      lineNumbersMinChars: 5,
+      editorOptions: this.editorOptions, // 同codes
+    });
+    setTimeout(() => {
+      this.monacoEditor.trigger('anyString', 'editor.action.formatDocument');
+      this.monacoEditor.setValue(this.monacoEditor.getValue());
+    }, 100);
+  },
+  methods: {},
+};
+</script>
+<style lang="stylus" scoped>
+.monaco-editor{
+    min-height: 300px
+}
+</style>

+ 465 - 0
template/admin/src/pages/setting/systemOutInterface/debugging.vue

@@ -0,0 +1,465 @@
+<template>
+  <div class="content" v-if="interfaceData">
+    <div class="head">
+      <Input v-model="interfaceData.url">
+        <template #prepend>
+          <Select v-model="interfaceData.method" style="width: 120px">
+            <Option v-for="(item, index) in requestTypeList" :key="index" :value="item.value">{{ item.label }}</Option>
+          </Select>
+        </template>
+      </Input>
+      <Button class="ml20" type="primary" @click="requestData">请求</Button>
+    </div>
+    <div class="params">
+      <Tabs class="mt10" v-model="paramsType" @on-click="changeTab">
+        <TabPane label="Params" name="Params"> </TabPane>
+        <TabPane label="Body" name="Body"> </TabPane>
+        <TabPane label="Header" name="Header"> </TabPane>
+      </Tabs>
+      <div v-show="paramsType === 'Params'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="xTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.request_params"
+        >
+          <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="120" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column field="must" title="必填" width="50" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.must == '1' ? '是' : '否' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" width="150" title="说明" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.trip" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="120">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'xTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'xTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('xTable')">添加参数</Button>
+      </div>
+      <div v-show="paramsType === 'Body'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="yTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.request_body"
+        >
+          <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="120" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column field="must" title="必填" width="50" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.must == '1' ? '是' : '否' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" title="说明" width="150" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.trip" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="120">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'yTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'yTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('yTable')">添加参数</Button>
+      </div>
+      <div v-show="paramsType === 'Header'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="zTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.headerData"
+        >
+          <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="200" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="100">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'zTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'zTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('zTable')">添加参数</Button>
+        <h4 class="mt10 title">全局Header参数</h4>
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="zaTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.allHeaderData"
+        >
+          <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.attribute || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.value || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="200" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.type || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" title="说明" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.trip || '' }}</span>
+            </template>
+          </vxe-column>
+        </vxe-table>
+      </div>
+    </div>
+    <div class="res mt10 mb10" v-if="codes">
+      <div class="copy-btn"><Button class="mt10 copy-btn" type="primary" @click="insertCopy()">复制</Button></div>
+      <MonacoEditor :codes="codes" :readOnly="true" />
+    </div>
+  </div>
+</template>
+
+<script>
+import request from './request';
+import MonacoEditor from './components/MonacoEditor.vue';
+function requestMethod(url, method, params, data, headerItem) {
+  return request({
+    url,
+    method,
+    params,
+    data,
+    headerItem,
+  });
+}
+export default {
+  components: { MonacoEditor },
+  props: {
+    formValidate: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+    requestTypeList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    typeList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      interfaceData: undefined,
+      paramsType: 'Params',
+      editor: '', //当前编辑器对象
+      codes: '',
+    };
+  },
+  created() {
+    this.interfaceData = this.formValidate;
+    this.interfaceData.request_body = JSON.parse(JSON.stringify(this.interfaceData.request_params));
+    console.log(this.interfaceData);
+  },
+  mounted() {},
+  methods: {
+    insertCopy() {
+      this.$copyText(this.codes)
+        .then((message) => {
+          this.$Message.success('复制成功');
+        })
+        .catch((err) => {
+          this.$Message.error('复制失败');
+        });
+    },
+    async requestData() {
+      console.log(this.$refs.xTable.getTableData().tableData);
+      console.log(this.filtersData((await this.$refs.xTable.getTableData().tableData) || []));
+      let url, method, params, body, headers;
+      url = this.interfaceData.url;
+      method = this.interfaceData.method;
+      params = this.filtersData((await this.$refs.xTable.getTableData().tableData) || []);
+      body = this.filtersData((await this.$refs.yTable.getTableData().tableData) || []);
+      let h = this.filtersData((await this.$refs.zTable.getTableData().tableData) || []);
+      let h1 = this.filtersData((await this.$refs.zaTable.getTableData().tableData) || []);
+      console.log(this.interfaceData, h, h1);
+      headers = {
+        ...h,
+        ...h1,
+      };
+      console.log(url, method, params, body, headers);
+      requestMethod(url, method, params, body, headers)
+        .then((res) => {
+          this.codes = res + '';
+        })
+        .catch((err) => {
+          this.codes = JSON.stringify(err);
+        });
+    },
+    filtersData(arr) {
+      console.log(arr);
+      try {
+        let x = {};
+        arr.map((e) => {
+          if (!e.parentId) {
+            for (let i in e) {
+              if (i == 'attribute') {
+                console.log(e);
+                if (e.type !== 'array') {
+                  x[e[i]] = e.value || '';
+                } else {
+                  let arr = [];
+                  e.children.map((item, index) => {
+                    arr[index] = this.filtersObj(item);
+                  });
+                  x[e[i]] = arr;
+                }
+              }
+            }
+          }
+        });
+        return x;
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    filtersObj(obj) {
+      let x = {};
+      for (let i in obj) {
+        if (i == 'attribute') {
+          if (obj.type !== 'array') {
+            x[obj[i]] = obj.value || '';
+          } else {
+            let arr = [];
+            obj.children.map((item, index) => {
+              arr[index] = this.filtersObj(item);
+            });
+            x[obj[i]] = arr;
+          }
+        }
+      }
+      return x;
+    },
+    changeTab(name) {
+      if (name === 'Header') {
+        console.log(this.interfaceData.headerData);
+        if (!this.interfaceData.headerData) {
+          this.insertEvent('zTable', {
+            attribute: 'Content-Type',
+            value: 'application/x-www-form-urlencoded',
+          });
+          this.insertEvent('zaTable');
+        }
+      }
+      console.log(this.interfaceData);
+    },
+    async insertEvent(type, d) {
+      const $table = this.$refs[type];
+      let newRow;
+      if (type == 'xTable') {
+        newRow = {
+          attribute: '',
+          type: 'string',
+          must: 0,
+          value: '',
+          trip: '',
+        };
+      } else if (type == 'yTable') {
+        newRow = {
+          attribute: '',
+          type: 'string',
+          value: '',
+          must: 0,
+          trip: '',
+        };
+      } else if (type == 'zTable') {
+        newRow = {
+          attribute: '',
+          type: '',
+          value: '',
+          trip: '',
+        };
+        newRow = { ...newRow, ...d };
+      } else if (type == 'zaTable') {
+        newRow = {
+          attribute: 'token',
+          type: 'string',
+          value: '',
+          must: 0,
+          trip: '',
+        };
+      } else {
+        newRow = {
+          code: '',
+          value: '',
+          solution: '',
+        };
+      }
+      const { row: data } = await $table.insertAt(newRow, -1);
+      await $table.setActiveCell(data, 'name');
+    },
+    async insertRow(currRow, type) {
+      const $table = this.$refs[type];
+      // 如果 null 则插入到目标节点顶部
+      // 如果 -1 则插入到目标节点底部
+      // 如果 row 则有插入到效的目标节点该行的位置
+      let record;
+      if (type == 'xTable') {
+        record = {
+          attribute: '',
+          type: 'string',
+          must: 0,
+          value: '',
+          trip: '',
+          id: Date.now(),
+          parentId: currRow.id, // 需要指定父节点,自动插入该节点中
+        };
+      } else {
+        record = {
+          code: '',
+          value: '',
+          solution: '',
+          id: Date.now(),
+          parentId: currRow.id, // 需要指定父节点,自动插入该节点中
+        };
+      }
+      const { row: newRow } = await $table.insertAt(record, -1);
+      await $table.setTreeExpand(currRow, true); // 将父节点展开
+      await $table.setActiveRow(newRow); // 插入子节点
+    },
+    async removeRow(row, type) {
+      const $table = this.$refs[type];
+      await $table.remove(row);
+    },
+  },
+};
+</script>
+<style>
+.vxe-select--panel.is--transfer {
+  z-index: 99999 !important;
+}
+</style>
+<style lang="scss" scoped>
+.content {
+  padding: 12px;
+  .head {
+    display: flex;
+    align-items: center;
+    .item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 12px;
+      font-size: 14px;
+      .title {
+        margin-right: 14px;
+      }
+    }
+  }
+}
+.copy-btn{
+  display: flex;
+  justify-content: right;
+}
+</style>

+ 14 - 9
template/admin/src/pages/setting/systemOutInterface/index.vue

@@ -67,7 +67,7 @@
             <span class="icon" slot="delNodeIcon">
               <!-- <Icon type="ios-cut" /> -->
             </span>
-            <template v-slot:treeNodeIcon="slotProps" class="req-method">
+            <template v-slot:treeNodeIcon="slotProps">
               <span
                 v-if="slotProps.model.method"
                 class="req-method"
@@ -90,6 +90,7 @@
               {{ formValidate.name }}
             </div>
             <div>
+              <Button type="primary" class="submission mr20" @click="debugging()">调试</Button>
               <Button v-if="formValidate.id" type="primary" class="submission mr20" @click="isEdit = !isEdit">{{
                 isEdit ? '返回' : '编辑'
               }}</Button>
@@ -387,23 +388,29 @@
       <label>分组名称:</label>
       <Input v-model="value" placeholder="请输入分组名称" style="width: 85%" />
     </Modal>
+    <Modal v-model="debuggingModal" :title="formValidate.name" width="70%" footer-hide :loading="loading">
+      <debugging v-if="debuggingModal" :formValidate="formValidate" :typeList="typeList" :requestTypeList="requestTypeList" />
+    </Modal>
   </div>
 </template>
 
 <script>
 import { interfaceList, interfaceDet, interfaceSave, interfaceEditName, interfaceDel } from '@/api/systemOutAccount';
 import { VueTreeList, Tree, TreeNode } from 'vue-tree-list';
+import debugging from './debugging.vue';
 import { mapState } from 'vuex';
 export default {
   name: 'systemOutInterface',
   components: {
     VueTreeList,
+    debugging,
   },
   data() {
     return {
       value: '',
       isEdit: false,
       nameModal: false,
+      debuggingModal: false,
       formValidate: {},
       grid: {
         xl: 7,
@@ -504,8 +511,10 @@ export default {
     this.getInterfaceList('one');
   },
   methods: {
-    onClicksss(e) {
+    debugging() {
+      this.debuggingModal = true;
     },
+    onClicksss(e) {},
     methodsColor(newVal) {
       let method = newVal.toUpperCase();
       if (method == 'GET') {
@@ -518,12 +527,9 @@ export default {
         return '#f93e3e';
       }
     },
-    insertBefore(params) {
-    },
-    insertAfter(params) {
-    },
-    moveInto(params) {
-    },
+    insertBefore(params) {},
+    insertAfter(params) {},
+    moveInto(params) {},
     async addTableData() {
       const { row: data } = await $table.insertAt(newRow, -1);
       await $table.setActiveCell(data, 'name');
@@ -600,7 +606,6 @@ export default {
           solution: '',
         };
       }
-      console.log();
       // $table.insert(newRow).then(({ row }) => $table.setEditRow(row, -1));
       const { row: data } = await $table.insertAt(newRow, -1);
       await $table.setActiveCell(data, 'name');

+ 121 - 0
template/admin/src/pages/setting/systemOutInterface/request.js

@@ -0,0 +1,121 @@
+import axios from 'axios';
+import Setting from '@/setting';
+import { getCookies, removeCookies } from '@/libs/util';
+
+const service = axios.create({
+  baseURL: Setting.apiBaseURL,
+  timeout: 10000, // 请求超时时间
+});
+axios.defaults.withCredentials = true; // 携带cookie
+
+// 请求拦截器
+service.interceptors.request.use(
+  (config) => {
+    if (config.kefu) {
+      let baseUrl = Setting.apiBaseURL.replace(/adminapi/, 'kefuapi');
+      config.baseURL = baseUrl;
+    } else {
+      config.baseURL = 'https://v5.wuht.net/outapi' || Setting.apiBaseURL;
+    }
+    if (config.file) {
+      config.headers['Content-Type'] = 'multipart/form-data';
+    }
+    try {
+      if (config.headerItem) {
+        for (let i in config.headerItem) {
+          config.headers[i] = config.headerItem[i];
+        }
+      }
+    } catch (error) {
+      console.log(error);
+    }
+
+    const token = getCookies('token');
+    const kefuToken = getCookies('kefu_token');
+    if (token || kefuToken) {
+      config.headers['Authori-zation'] = config.kefu ? 'Bearer ' + kefuToken : 'Bearer ' + token;
+    }
+    console.log('请求了', config);
+
+    return config;
+  },
+  (error) => {
+    // do something with request error
+    return Promise.reject(error);
+  },
+);
+service.interceptors.response.use(
+  (response) => {
+    let obj = {};
+    if (!!response.data) {
+      if (typeof response.data == 'string') {
+        obj = JSON.parse(response.data);
+      } else {
+        obj = response.data;
+      }
+    }
+    let status = response.data ? obj.status : 0;
+    // let status = response.data ? response.data.status : 0;
+    const code = status;
+    switch (code) {
+      case 200:
+        return obj;
+      default:
+        return Promise.reject(obj || { msg: '未知错误' });
+    }
+  },
+  (error) => {
+    return Promise.reject(error);
+  },
+);
+export default service;
+
+// function sendRequest(url, method, params, header) {
+//   const instance = axios.create({
+//     baseURL: Setting.apiBaseURL, // 请求的根域名
+//     timeout: 1000, // 请求超时时间
+//     headers: {
+//       'X-Custom-Header': header, // 自定义头信息
+//     },
+//   });
+
+//   if (method === 'GET') {
+//     instance
+//       .get(url, { params: params })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'POST') {
+//     instance
+//       .post(url, params, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'PUT') {
+//     instance
+//       .put(url, params, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'DELETE') {
+//     instance
+//       .delete(url, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   }
+
+//   return instance;
+// }

+ 75 - 0
template/admin/src/pages/system/backendRouting/components/MonacoEditor.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="monaco-container">
+    <div ref="container" class="monaco-editor"></div>
+  </div>
+</template>
+
+<script>
+import * as monaco from 'monaco-editor';
+export default {
+  name: '',
+  props: {
+    // 编辑器中呈现的内容
+    codes: {
+      type: String,
+      default: function () {
+        return '';
+      },
+    },
+    readOnly: {
+      type: Boolean,
+      default: function () {
+        return false;
+      },
+    },
+    // 主要配置
+    editorOptions: {
+      type: Object,
+      default: function () {
+        return {
+          selectOnLineNumbers: true,
+          roundedSelection: false,
+          readOnly: this.readOnly, // 只读
+          cursorStyle: 'line', // 光标样式
+          automaticLayout: false, // 自动布局
+          glyphMargin: true, // 字形边缘
+          useTabStops: false,
+          fontSize: 28, // 字体大小
+          autoIndent: true, // 自动布局
+        };
+      },
+    },
+  },
+
+  data() {
+    return {};
+  },
+  created() {},
+  mounted() {
+    this.monacoEditor = monaco.editor.create(this.$refs.container, {
+      value: this.codes, // 见props
+      language: 'json',
+      theme: 'vs', // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网
+      automaticLayout: true, //自动布局
+      //   foldingStrategy: 'indentation', // 代码可分小段折叠
+      scrollbar: {
+        // 滚动条设置
+        verticalScrollbarSize: 4, // 竖滚动条
+        horizontalScrollbarSize: 10, // 横滚动条
+      },
+      lineNumbersMinChars: 5,
+      editorOptions: this.editorOptions, // 同codes
+    });
+    setTimeout(() => {
+      this.monacoEditor.trigger('anyString', 'editor.action.formatDocument');
+      this.monacoEditor.setValue(this.monacoEditor.getValue());
+    }, 100);
+  },
+  methods: {},
+};
+</script>
+<style lang="stylus" scoped>
+.monaco-editor{
+    min-height: 300px
+}
+</style>

+ 467 - 0
template/admin/src/pages/system/backendRouting/debugging.vue

@@ -0,0 +1,467 @@
+<template>
+  <div class="content" v-if="interfaceData">
+    <div class="head">
+      <Input v-model="interfaceData.path">
+        <template #prepend>
+          <Select v-model="interfaceData.method" style="width: 120px">
+            <Option v-for="(item, index) in requestTypeList" :key="index" :value="item.value">{{ item.label }}</Option>
+          </Select>
+        </template>
+      </Input>
+      <Button class="ml20" type="primary" @click="requestData">请求</Button>
+    </div>
+    <div class="params">
+      <Tabs class="mt10" v-model="paramsType" @on-click="changeTab">
+        <TabPane label="Params" name="Params"> </TabPane>
+        <TabPane label="Body" name="Body"> </TabPane>
+        <TabPane label="Header" name="Header"> </TabPane>
+      </Tabs>
+      <div v-show="paramsType === 'Params'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="xTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.request"
+        >
+          <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="120" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column field="must" title="必填" width="50" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.must == '1' ? '是' : '否' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" width="150" title="说明" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.trip" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="120">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'xTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'xTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('xTable')">添加参数</Button>
+      </div>
+      <div v-show="paramsType === 'Body'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="yTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.request_body"
+        >
+          <vxe-column field="attribute" width="150" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="120" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column field="must" title="必填" width="50" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.must == '1' ? '是' : '否' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" title="说明" width="150" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.trip" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="120">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'yTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'yTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('yTable')">添加参数</Button>
+      </div>
+      <div v-show="paramsType === 'Header'">
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="zTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.headerData"
+        >
+          <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.attribute" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-input v-model="row.value" type="text"></vxe-input>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="200" :edit-render="{}">
+            <template #default="{ row }">
+              <vxe-select v-model="row.type" transfer>
+                <vxe-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :value="item.value"
+                  :label="item.label"
+                ></vxe-option>
+              </vxe-select>
+            </template>
+          </vxe-column>
+          <vxe-column title="操作" width="100">
+            <template #default="{ row }">
+              <vxe-button type="text" v-if="row.type === 'array'" status="primary" @click="insertRow(row, 'zTable')"
+                >插入</vxe-button
+              >
+              <vxe-button type="text" status="primary" @click="removeRow(row, 'zTable')">删除</vxe-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <Button class="mt10" type="primary" @click="insertEvent('zTable')">添加参数</Button>
+        <h4 class="mt10 title">全局Header参数</h4>
+        <vxe-table
+          class="mt10"
+          resizable
+          show-overflow
+          keep-source
+          ref="zaTable"
+          row-id="id"
+          :print-config="{}"
+          :export-config="{}"
+          :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
+          :data="interfaceData.allHeaderData"
+        >
+          <vxe-column field="attribute" width="300" title="属性" tree-node :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.attribute || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="value" title="参数值" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.value || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="type" title="类型" width="200" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.type || '' }}</span>
+            </template>
+          </vxe-column>
+          <vxe-column field="trip" title="说明" :edit-render="{}">
+            <template #default="{ row }">
+              <span>{{ row.trip || '' }}</span>
+            </template>
+          </vxe-column>
+        </vxe-table>
+      </div>
+    </div>
+    <div class="res mt10 mb10" v-if="codes">
+      <div class="copy-btn"><Button class="mt10 copy-btn" type="primary" @click="insertCopy()">复制</Button></div>
+      <MonacoEditor :codes="codes" :readOnly="true" />
+    </div>
+  </div>
+</template>
+
+<script>
+import request from './request';
+import MonacoEditor from './components/MonacoEditor.vue';
+import vuedraggable from 'vuedraggable';
+
+function requestMethod(url, method, params, data, headerItem) {
+  return request({
+    url,
+    method,
+    params,
+    data,
+    headerItem,
+  });
+}
+export default {
+  components: { MonacoEditor },
+  props: {
+    formValidate: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+    requestTypeList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    typeList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      interfaceData: undefined,
+      paramsType: 'Params',
+      editor: '', //当前编辑器对象
+      codes: '',
+    };
+  },
+  created() {
+    this.interfaceData = this.formValidate;
+    this.interfaceData.request_body = JSON.parse(JSON.stringify(this.interfaceData.request));
+    console.log(this.interfaceData);
+  },
+  mounted() {},
+  methods: {
+    insertCopy() {
+      this.$copyText(this.codes)
+        .then((message) => {
+          this.$Message.success('复制成功');
+        })
+        .catch((err) => {
+          this.$Message.error('复制失败');
+        });
+    },
+    async requestData() {
+      console.log(this.$refs.xTable.getTableData().tableData);
+      console.log(this.filtersData((await this.$refs.xTable.getTableData().tableData) || []));
+      let url, method, params, body, headers;
+      url = this.interfaceData.url;
+      method = this.interfaceData.method;
+      params = this.filtersData((await this.$refs.xTable.getTableData().tableData) || []);
+      body = this.filtersData((await this.$refs.yTable.getTableData().tableData) || []);
+      let h = this.filtersData((await this.$refs.zTable.getTableData().tableData) || []);
+      let h1 = this.filtersData((await this.$refs.zaTable.getTableData().tableData) || []);
+      console.log(this.interfaceData, h, h1);
+      headers = {
+        ...h,
+        ...h1,
+      };
+      console.log(url, method, params, body, headers);
+      requestMethod(url, method, params, body, headers)
+        .then((res) => {
+          this.codes = res + '';
+        })
+        .catch((err) => {
+          this.codes = JSON.stringify(err);
+        });
+    },
+    filtersData(arr) {
+      console.log(arr);
+      try {
+        let x = {};
+        arr.map((e) => {
+          if (!e.parentId) {
+            for (let i in e) {
+              if (i == 'attribute') {
+                console.log(e);
+                if (e.type !== 'array') {
+                  x[e[i]] = e.value || '';
+                } else {
+                  let arr = [];
+                  e.children.map((item, index) => {
+                    arr[index] = this.filtersObj(item);
+                  });
+                  x[e[i]] = arr;
+                }
+              }
+            }
+          }
+        });
+        return x;
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    filtersObj(obj) {
+      let x = {};
+      for (let i in obj) {
+        if (i == 'attribute') {
+          if (obj.type !== 'array') {
+            x[obj[i]] = obj.value || '';
+          } else {
+            let arr = [];
+            obj.children.map((item, index) => {
+              arr[index] = this.filtersObj(item);
+            });
+            x[obj[i]] = arr;
+          }
+        }
+      }
+      return x;
+    },
+    changeTab(name) {
+      if (name === 'Header') {
+        console.log(this.interfaceData.headerData);
+        if (!this.interfaceData.headerData) {
+          this.insertEvent('zTable', {
+            attribute: 'Content-Type',
+            value: 'application/x-www-form-urlencoded',
+          });
+          this.insertEvent('zaTable');
+        }
+      }
+      console.log(this.interfaceData);
+    },
+    async insertEvent(type, d) {
+      const $table = this.$refs[type];
+      let newRow;
+      if (type == 'xTable') {
+        newRow = {
+          attribute: '',
+          type: 'string',
+          must: 0,
+          value: '',
+          trip: '',
+        };
+      } else if (type == 'yTable') {
+        newRow = {
+          attribute: '',
+          type: 'string',
+          value: '',
+          must: 0,
+          trip: '',
+        };
+      } else if (type == 'zTable') {
+        newRow = {
+          attribute: '',
+          type: '',
+          value: '',
+          trip: '',
+        };
+        newRow = { ...newRow, ...d };
+      } else if (type == 'zaTable') {
+        newRow = {
+          attribute: 'token',
+          type: 'string',
+          value: '',
+          must: 0,
+          trip: '',
+        };
+      } else {
+        newRow = {
+          code: '',
+          value: '',
+          solution: '',
+        };
+      }
+      const { row: data } = await $table.insertAt(newRow, -1);
+      await $table.setActiveCell(data, 'name');
+    },
+    async insertRow(currRow, type) {
+      const $table = this.$refs[type];
+      // 如果 null 则插入到目标节点顶部
+      // 如果 -1 则插入到目标节点底部
+      // 如果 row 则有插入到效的目标节点该行的位置
+      let record;
+      if (type == 'xTable') {
+        record = {
+          attribute: '',
+          type: 'string',
+          must: 0,
+          value: '',
+          trip: '',
+          id: Date.now(),
+          parentId: currRow.id, // 需要指定父节点,自动插入该节点中
+        };
+      } else {
+        record = {
+          code: '',
+          value: '',
+          solution: '',
+          id: Date.now(),
+          parentId: currRow.id, // 需要指定父节点,自动插入该节点中
+        };
+      }
+      const { row: newRow } = await $table.insertAt(record, -1);
+      await $table.setTreeExpand(currRow, true); // 将父节点展开
+      await $table.setActiveRow(newRow); // 插入子节点
+    },
+    async removeRow(row, type) {
+      const $table = this.$refs[type];
+      await $table.remove(row);
+    },
+  },
+};
+</script>
+<style>
+.vxe-select--panel.is--transfer {
+  z-index: 99999 !important;
+}
+</style>
+<style lang="scss" scoped>
+.content {
+  padding: 12px;
+  .head {
+    display: flex;
+    align-items: center;
+    .item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 12px;
+      font-size: 14px;
+      .title {
+        margin-right: 14px;
+      }
+    }
+  }
+}
+.copy-btn {
+  display: flex;
+  justify-content: right;
+}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 1102 - 0
template/admin/src/pages/system/backendRouting/index.vue


+ 121 - 0
template/admin/src/pages/system/backendRouting/request.js

@@ -0,0 +1,121 @@
+import axios from 'axios';
+import Setting from '@/setting';
+import { getCookies, removeCookies } from '@/libs/util';
+
+const service = axios.create({
+  baseURL: Setting.apiBaseURL,
+  timeout: 10000, // 请求超时时间
+});
+axios.defaults.withCredentials = true; // 携带cookie
+
+// 请求拦截器
+service.interceptors.request.use(
+  (config) => {
+    if (config.kefu) {
+      let baseUrl = Setting.apiBaseURL.replace(/adminapi/, 'kefuapi');
+      config.baseURL = baseUrl;
+    } else {
+      config.baseURL = 'https://v5.wuht.net/outapi' || Setting.apiBaseURL;
+    }
+    if (config.file) {
+      config.headers['Content-Type'] = 'multipart/form-data';
+    }
+    try {
+      if (config.headerItem) {
+        for (let i in config.headerItem) {
+          config.headers[i] = config.headerItem[i];
+        }
+      }
+    } catch (error) {
+      console.log(error);
+    }
+
+    const token = getCookies('token');
+    const kefuToken = getCookies('kefu_token');
+    if (token || kefuToken) {
+      config.headers['Authori-zation'] = config.kefu ? 'Bearer ' + kefuToken : 'Bearer ' + token;
+    }
+    console.log('请求了', config);
+
+    return config;
+  },
+  (error) => {
+    // do something with request error
+    return Promise.reject(error);
+  },
+);
+service.interceptors.response.use(
+  (response) => {
+    let obj = {};
+    if (!!response.data) {
+      if (typeof response.data == 'string') {
+        obj = JSON.parse(response.data);
+      } else {
+        obj = response.data;
+      }
+    }
+    let status = response.data ? obj.status : 0;
+    // let status = response.data ? response.data.status : 0;
+    const code = status;
+    switch (code) {
+      case 200:
+        return obj;
+      default:
+        return Promise.reject(obj || { msg: '未知错误' });
+    }
+  },
+  (error) => {
+    return Promise.reject(error);
+  },
+);
+export default service;
+
+// function sendRequest(url, method, params, header) {
+//   const instance = axios.create({
+//     baseURL: Setting.apiBaseURL, // 请求的根域名
+//     timeout: 1000, // 请求超时时间
+//     headers: {
+//       'X-Custom-Header': header, // 自定义头信息
+//     },
+//   });
+
+//   if (method === 'GET') {
+//     instance
+//       .get(url, { params: params })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'POST') {
+//     instance
+//       .post(url, params, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'PUT') {
+//     instance
+//       .put(url, params, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   } else if (method === 'DELETE') {
+//     instance
+//       .delete(url, { headers: header })
+//       .then((response) => {
+//         // 处理响应数据
+//       })
+//       .catch((error) => {
+//         // 处理错误
+//       });
+//   }
+
+//   return instance;
+// }

+ 119 - 0
template/admin/src/pages/system/codeGeneration/components/Field.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="main">
+    <div class="mb20">
+      <Button class="mr10" type="primary" @click="addRow">添加列</Button>
+      <Button>添加</Button>
+    </div>
+    <Table border :columns="columns" :data="dataList">
+      <!-- <template slot-scope="{ row }" slot="id">
+        <Input v-model="row.id" class="priceBox"></Input>
+      </template>
+      <template slot-scope="{ row }" slot="field">
+        <Input v-model="row.field" class="priceBox"></Input>
+      </template> -->
+    </Table>
+    <Modal v-model="modal" width="360" title="新增列">
+      <div>
+        <Select v-model="rowName">
+          <Option v-for="item in rowList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+        </Select>
+      </div>
+      <template #footer>
+        <Button type="primary" size="large" long @click="add">添加</Button>
+      </template>
+    </Modal>
+  </div>
+</template>
+
+<script>
+export default {
+  name: '',
+  props: {
+    field: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modal: false,
+      rowName: '',
+      rowList: [
+        {
+          value: 'New York',
+          label: 'New York',
+        },
+        {
+          value: 'London',
+          label: 'London',
+        },
+        {
+          value: 'Sydney',
+          label: 'Sydney',
+        },
+        {
+          value: 'Ottawa',
+          label: 'Ottawa',
+        },
+        {
+          value: 'Paris',
+          label: 'Paris',
+        },
+        {
+          value: 'Canberra',
+          label: 'Canberra',
+        },
+      ],
+      columns: [
+        {
+          title: 'id',
+          key: 'id',
+          align: 'center',
+          width: 110,
+        },
+        {
+          title: 'field',
+          key: 'field',
+          align: 'center',
+          minWidth: 110,
+        },
+      ],
+      dataList: [
+        {
+          id: '字段id',
+          field: '字段field',
+        },
+      ],
+    };
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    addRow() {
+      this.modal = true;
+    },
+    add() {
+      this.dataList[0][this.rowName] = '字段';
+      this.$nextTick((e) => {
+        this.columns.push({
+          title: this.rowName,
+          key: this.rowName,
+          align: 'center',
+          minWidth: 110,
+        });
+      });
+    },
+  },
+};
+</script>
+<style lang="stylus" scoped>
+.ivu-table-wrapper {
+  border-top: 1px solid #dcdee2;;
+  border-left: 1px solid #dcdee2;;
+}
+.form-width {
+  width: 500px;
+}
+</style>

+ 123 - 0
template/admin/src/pages/system/codeGeneration/components/FormItem.vue

@@ -0,0 +1,123 @@
+<template>
+  <div class="main">
+    <div class="mb20">
+      <Button class="mr10" type="primary" @click="addRow">添加行</Button>
+      <Button>添加</Button>
+    </div>
+    <div>
+      <div class="item" v-for="(item, index) in dataList" :key="index">
+        <div class="row">
+          <Select v-model="item.rowName" transfer>
+            <Option v-for="item in rowList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+          </Select>
+        </div>
+        <div class="row">
+          <Input v-model="item.field" class="priceBox"></Input>
+        </div>
+        <div class="row">
+          <Select v-model="item.method" transfer>
+            <Option v-for="item in reqMetList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+          </Select>
+        </div>
+        <div class="row">
+          <Select v-model="item.required" transfer>
+            <Option v-for="item in requiredList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+          </Select>
+        </div>
+        <div class="row" v-if="item.method == 2">
+          <Input v-model="item.textarea" class="priceBox"></Input>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: '',
+  props: {
+    formItem: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      requiredList: [
+        {
+          value: 0,
+          label: '否',
+        },
+        {
+          value: 1,
+          label: '是',
+        },
+      ],
+      rowList: [],
+      reqMetList: [
+        {
+          value: 0,
+          label: 'input',
+        },
+        {
+          value: 1,
+          label: 'textarea',
+        },
+        {
+          value: 2,
+          label: 'select',
+        },
+        {
+          value: 3,
+          label: 'radio',
+        },
+        {
+          value: 4,
+          label: 'number',
+        },
+      ],
+      dataList: [
+        {
+          rowName: 0,
+          method: 0,
+          field: '',
+          required: 0,
+          textarea: '',
+        },
+      ],
+    };
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    addRow() {
+      this.dataList.push({
+        rowName: 0,
+        method: 0,
+        field: '',
+        required: 0,
+        textarea: '',
+      });
+    },
+  },
+};
+</script>
+<style lang="stylus" scoped>
+.ivu-table-wrapper {
+  border-top: 1px solid #dcdee2;;
+  border-left: 1px solid #dcdee2;;
+}
+.form-width {
+  width: 500px;
+}
+.item{
+  display flex
+  margin-bottom 10px
+  .row{
+    width 140px
+    margin-right 10px
+  }
+}
+</style>

+ 56 - 0
template/admin/src/pages/system/codeGeneration/components/FoundationForm.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="main">
+    <Form ref="foundation" :model="foundation" :rules="foundation" :label-width="100">
+      <FormItem label="菜单">
+        <Select class="form-width" v-model="foundation.pid">
+          <Option value="beijing">New York</Option>
+          <Option value="shanghai">London</Option>
+          <Option value="shenzhen">Sydney</Option>
+        </Select>
+      </FormItem>
+      <FormItem label="表名">
+        <Input class="form-width" v-model="foundation.tableName" placeholder="请输入表名"></Input>
+      </FormItem>
+      <FormItem label="是否存在">
+        <RadioGroup v-model="foundation.required">
+          <Radio :label="1">是</Radio>
+          <Radio :label="0">否</Radio>
+        </RadioGroup>
+      </FormItem>
+      <FormItem label="表SQL">
+        <Input
+          class="form-width"
+          v-model="foundation.sql"
+          type="textarea"
+          :autosize="{ minRows: 4, maxRows: 8 }"
+          placeholder="请输入表SQL"
+        ></Input>
+      </FormItem>
+    </Form>
+  </div>
+</template>
+
+<script>
+export default {
+  name: '',
+  props: {
+    foundation: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {};
+  },
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="stylus" scoped>
+.form-width {
+  width: 500px;
+}
+</style>

+ 45 - 0
template/admin/src/pages/system/codeGeneration/components/StorageLoc.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="main">
+    <Form ref="foundation" :model="storage" :rules="storageRules" :label-width="130">
+      <FormItem label="生成controller位置">
+        <Input class="form-width" v-model="storage.input" placeholder="请输入"></Input>
+      </FormItem>
+      <FormItem label="生成service位置">
+        <Input class="form-width" v-model="storage.input" placeholder="请输入"></Input>
+      </FormItem>
+      <FormItem label="生成dao位置">
+        <Input class="form-width" v-model="storage.input" placeholder="请输入"></Input>
+      </FormItem>
+      <FormItem label="生成model位置">
+        <Input class="form-width" v-model="storage.input" placeholder="请输入"></Input>
+      </FormItem>
+    </Form>
+  </div>
+</template>
+
+<script>
+export default {
+  name: '',
+  props: {
+    storage: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      storageRules: {},
+    };
+  },
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="stylus" scoped>
+.form-width {
+  width: 500px;
+}
+</style>

+ 76 - 0
template/admin/src/pages/system/codeGeneration/index.vue

@@ -0,0 +1,76 @@
+<template>
+  <div>
+    <div class="message">
+      <Card :bordered="false" dis-hover class="">
+        <Tabs v-model="currentTab" @on-click="changeTab">
+          <TabPane :label="item.label" :name="item.value.toString()" v-for="(item, index) in headerList" :key="index" />
+        </Tabs>
+      </Card>
+    </div>
+    <div class="pt10" v-show="currentTab == 'foundation'">
+      <Card :bordered="false" dis-hover class="ivu-mt">
+        <FoundationForm :foundation="formItem.foundation" />
+      </Card>
+    </div>
+    <div class="pt10" v-show="currentTab == 'storage'">
+      <Card :bordered="false" dis-hover class="ivu-mt">
+        <StorageLoc :storage="formItem.storage" />
+      </Card>
+    </div>
+    <div class="pt10" v-show="currentTab == 'field'">
+      <Card :bordered="false" dis-hover class="ivu-mt">
+        <Field :field="formItem.field" />
+      </Card>
+    </div>
+    <div class="pt10" v-show="currentTab == 'formItem'">
+      <Card :bordered="false" dis-hover class="ivu-mt">
+        <FormItem :formItem="formItem.formItem" />
+      </Card>
+    </div>
+  </div>
+</template>
+
+<script>
+import { codeCurd } from '@/api/setting';
+import FoundationForm from './components/FoundationForm.vue';
+import StorageLoc from './components/StorageLoc.vue';
+import Field from './components/Field.vue';
+import FormItem from './components/FormItem.vue';
+export default {
+  name: 'system_code_generation',
+  components: { FoundationForm, StorageLoc, Field, FormItem },
+  data() {
+    return {
+      currentTab: 'formItem',
+      headerList: [
+        { label: '基础信息', value: 'foundation' },
+        { label: '存放位置', value: 'storage' },
+        { label: '表格字段', value: 'field' },
+        { label: '表单项', value: 'formItem' },
+      ],
+      formItem: {
+        foundation: {
+          pid: '',
+          tableName: '',
+          required: 0,
+          sql: '',
+        },
+        storage: {},
+        field: {},
+        formItem: {},
+      },
+      ruleValidate: {
+        foundation: {},
+      },
+    };
+  },
+  created() {},
+  mounted: function () {},
+  methods: {
+    changeTab(data) {
+      this.currentTab = data;
+    },
+  },
+};
+</script>
+<style scoped></style>

+ 20 - 2
template/admin/src/router/modules/system.js

@@ -9,13 +9,13 @@
 // +---------------------------------------------------------------------
 
 import LayoutMain from '@/layout';
-import setting  from '@/setting'
+import setting from '@/setting';
 let routePre = setting.routePre;
 
 const pre = 'system_';
 
 export default {
-  path: routePre+'/system',
+  path: routePre + '/system',
   name: 'system',
   header: 'system',
   redirect: {
@@ -26,6 +26,24 @@ export default {
   },
   component: LayoutMain,
   children: [
+    {
+      path: 'code_generation',
+      name: `${pre}code_generation`,
+      meta: {
+        auth: ['system-config-code-generation'],
+        title: '代码生成',
+      },
+      component: () => import('@/pages/system/codeGeneration/index'),
+    },
+    {
+      path: 'backend_routing',
+      name: `${pre}backend_routing`,
+      meta: {
+        auth: ['system-config-backend-routing'],
+        title: '路由权限',
+      },
+      component: () => import('@/pages/system/backendRouting/index'),
+    },
     {
       path: 'file',
       name: `${pre}file`,