wangmengwei 2 kuukautta sitten
vanhempi
commit
f015575347
100 muutettua tiedostoa jossa 5584 lisäystä ja 55 poistoa
  1. 7 7
      ruoyi-ui-wuguan/src/App.vue
  2. 140 0
      ruoyi-ui-wuguan/src/api/flowable/definition.js
  3. 80 0
      ruoyi-ui-wuguan/src/api/flowable/finished.js
  4. 68 0
      ruoyi-ui-wuguan/src/api/flowable/form.js
  5. 106 0
      ruoyi-ui-wuguan/src/api/flowable/process.js
  6. 133 0
      ruoyi-ui-wuguan/src/api/flowable/todo.js
  7. 68 43
      ruoyi-ui-wuguan/src/api/login.js
  8. 1 1
      ruoyi-ui-wuguan/src/api/menu.js
  9. 54 0
      ruoyi-ui-wuguan/src/api/system/change.js
  10. 44 0
      ruoyi-ui-wuguan/src/api/system/class.js
  11. 77 0
      ruoyi-ui-wuguan/src/api/system/client.js
  12. 44 0
      ruoyi-ui-wuguan/src/api/system/expression.js
  13. 44 0
      ruoyi-ui-wuguan/src/api/system/listener.js
  14. 44 0
      ruoyi-ui-wuguan/src/api/system/parents.js
  15. 54 0
      ruoyi-ui-wuguan/src/api/system/school.js
  16. 27 0
      ruoyi-ui-wuguan/src/api/system/social/auth.js
  17. 44 0
      ruoyi-ui-wuguan/src/api/system/student.js
  18. 55 0
      ruoyi-ui-wuguan/src/api/system/table.js
  19. 44 0
      ruoyi-ui-wuguan/src/api/system/teacher.js
  20. 55 0
      ruoyi-ui-wuguan/src/api/system/time.js
  21. 106 0
      ruoyi-ui-wuguan/src/api/tool/build/CodeTypeDialog.vue
  22. 100 0
      ruoyi-ui-wuguan/src/api/tool/build/DraggableItem.vue
  23. 123 0
      ruoyi-ui-wuguan/src/api/tool/build/IconsDialog.vue
  24. 946 0
      ruoyi-ui-wuguan/src/api/tool/build/RightPanel.vue
  25. 149 0
      ruoyi-ui-wuguan/src/api/tool/build/TreeNodeDialog.vue
  26. 768 0
      ruoyi-ui-wuguan/src/api/tool/build/index.vue
  27. 4 4
      ruoyi-ui-wuguan/src/api/tool/gen.js
  28. 60 0
      ruoyi-ui-wuguan/src/api/tool/gen/basicInfoForm.vue
  29. 45 0
      ruoyi-ui-wuguan/src/api/tool/gen/createTable.vue
  30. 234 0
      ruoyi-ui-wuguan/src/api/tool/gen/editTable.vue
  31. 312 0
      ruoyi-ui-wuguan/src/api/tool/gen/genInfoForm.vue
  32. 120 0
      ruoyi-ui-wuguan/src/api/tool/gen/importTable.vue
  33. 354 0
      ruoyi-ui-wuguan/src/api/tool/gen/index.vue
  34. 15 0
      ruoyi-ui-wuguan/src/api/tool/swagger/index.vue
  35. 45 0
      ruoyi-ui-wuguan/src/api/zhihuixy/data.js
  36. 45 0
      ruoyi-ui-wuguan/src/api/zhihuixy/dingwei.js
  37. 45 0
      ruoyi-ui-wuguan/src/api/zhihuixy/gongzt.js
  38. 73 0
      ruoyi-ui-wuguan/src/api/zhihuixy/info.js
  39. 115 0
      ruoyi-ui-wuguan/src/api/zhihuixy/infos.js
  40. 0 0
      ruoyi-ui-wuguan/src/api/zhihuixy/kchb.js
  41. 109 0
      ruoyi-ui-wuguan/src/api/zhihuixy/notice.js
  42. 54 0
      ruoyi-ui-wuguan/src/api/zhihuixy/recipe.js
  43. 54 0
      ruoyi-ui-wuguan/src/api/zhihuixy/record.js
  44. 71 0
      ruoyi-ui-wuguan/src/api/zhihuixy/teacherdan.js
  45. 107 0
      ruoyi-ui-wuguan/src/api/zhihuixy/tenant.js
  46. 65 0
      ruoyi-ui-wuguan/src/api/zhihuixy/tenantPackage.js
  47. 61 0
      ruoyi-ui-wuguan/src/api/zhihuixy/tjxq.js
  48. 44 0
      ruoyi-ui-wuguan/src/api/zhihuixy/xiaoYuanInfo.js
  49. 45 0
      ruoyi-ui-wuguan/src/api/zhihuixy/yijianfk.js
  50. 52 0
      ruoyi-ui-wuguan/src/api/zhihuixy/yuyue.js
  51. 45 0
      ruoyi-ui-wuguan/src/api/zhihuixy/yuyuepzh.js
  52. 29 0
      ruoyi-ui-wuguan/src/assets/icons/svg/topiam.svg
  53. BIN
      ruoyi-ui-wuguan/src/assets/images/delei.png
  54. BIN
      ruoyi-ui-wuguan/src/assets/images/h-pic_dzh_tp2.png
  55. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_byfxsj.png
  56. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_jrfb.png
  57. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_jryc.png
  58. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_jrzs.png
  59. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_jzsh.png
  60. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_kcpz.png
  61. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_kcsj.png
  62. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_tkxx.png
  63. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_ht_fbxw.png
  64. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_ht_tksh.png
  65. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_ht_xwdt_add.png
  66. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_ht_zhsh.png
  67. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl__hbm.png
  68. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_hjs.png
  69. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_hzh.png
  70. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_myc_normal.png
  71. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_myc_selected.png
  72. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_mzc_normal.png
  73. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_mzc_selected.png
  74. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_smrs_normal.png
  75. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_smrs_selected.png
  76. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_wdyc_normal.png
  77. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_htgl_wdyc_selected.png
  78. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_cjtj.png
  79. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_dqlk.png
  80. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_dtaq.png
  81. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_kcb.png
  82. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_kjgn.png
  83. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_shlb.png
  84. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_hthp_tktz.png
  85. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_kjgn_jzsh.png
  86. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_kjgn_kcb.png
  87. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_kjgn_kcsj.png
  88. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_kjgn_tkxx.png
  89. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_qjlb_xxkc.png
  90. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_sjtj_js.png
  91. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_sjtj_zz.png
  92. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_swh_tq.png
  93. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_tc_add.png
  94. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_tc_del.png
  95. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_xyht_wsxx_add.png
  96. BIN
      ruoyi-ui-wuguan/src/assets/images/icon_xyht_wsxx_del.png
  97. BIN
      ruoyi-ui-wuguan/src/assets/images/logon.png
  98. BIN
      ruoyi-ui-wuguan/src/assets/images/ncbgc.png
  99. BIN
      ruoyi-ui-wuguan/src/assets/images/ncbgl.png
  100. BIN
      ruoyi-ui-wuguan/src/assets/images/opic_rylb_db.png

+ 7 - 7
ruoyi-ui-wuguan/src/App.vue

@@ -11,14 +11,14 @@ import ThemePicker from "@/components/ThemePicker";
 export default {
   name: "App",
   components: { ThemePicker },
-  metaInfo() {
-    return {
-      title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
-      titleTemplate: title => {
-        return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
-      }
+    metaInfo() {
+        return {
+            title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
+            titleTemplate: title => {
+                return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
+            }
+        }
     }
-  }
 };
 </script>
 <style scoped>

+ 140 - 0
ruoyi-ui-wuguan/src/api/flowable/definition.js

@@ -0,0 +1,140 @@
+import request from '@/utils/request'
+
+// 查询流程定义列表
+export function listDefinition(query) {
+  return request({
+    url: '/flowable/definition/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 部署流程实例
+export function definitionStart(procDefId, data) {
+  return request({
+    url: '/flowable/definition/start/' + procDefId,
+    method: 'post',
+    data: data
+  })
+}
+
+// 获取流程变量
+export function getProcessVariables(taskId) {
+  return request({
+    url: '/flowable/task/processVariables/' + taskId,
+    method: 'get'
+  })
+}
+
+// 激活/挂起流程
+export function updateState(params) {
+  return request({
+    url: '/flowable/definition/updateState',
+    method: 'put',
+    params: params
+  })
+}
+
+// 指定流程办理人员列表
+export function userList(query) {
+  return request({
+    url: '/flowable/definition/userList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 指定流程办理组列表
+export function roleList(query) {
+  return request({
+    url: '/flowable/definition/roleList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 指定流程表达式
+export function expList(query) {
+  return request({
+    url: '/flowable/definition/expList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 读取xml文件
+export function readXml(deployId) {
+  return request({
+    url: '/flowable/definition/readXml/' + deployId,
+    method: 'get'
+  })
+}
+
+// 读取image文件
+export function readImage(deployId) {
+  return request({
+    url: '/flowable/definition/readImage/' + deployId,
+    method: 'get'
+  })
+}
+
+// 获取流程执行节点
+export function getFlowViewer(procInsId, executionId) {
+  return request({
+    url: '/flowable/task/flowViewer/' + procInsId + '/' + executionId,
+    method: 'get'
+  })
+}
+
+// 流程节点数据
+export function flowXmlAndNode(query) {
+  return request({
+    url: '/flowable/task/flowXmlAndNode',
+    method: 'get',
+    params: query
+  })
+}
+
+// 读取xml文件
+export function saveXml(data) {
+  return request({
+    url: '/flowable/definition/save',
+    method: 'post',
+    data: data
+  })
+}
+
+// 新增流程定义
+export function addDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程定义
+export function updateDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程定义
+export function delDeployment(deployId) {
+  return request({
+    url: '/flowable/definition/' + deployId,
+    method: 'delete',
+  })
+}
+
+// 导出流程定义
+export function exportDeployment(query) {
+  return request({
+    url: '/system/deployment/export',
+    method: 'get',
+    params: query
+  })
+}

+ 80 - 0
ruoyi-ui-wuguan/src/api/flowable/finished.js

@@ -0,0 +1,80 @@
+import request from '@/utils/request'
+import da from "element-ui/src/locale/lang/da";
+
+// 查询已办任务列表
+export function finishedList(query) {
+  return request({
+    url: '/flowable/task/finishedList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 任务流转记录
+export function flowRecord(query) {
+  return request({
+    url: '/flowable/task/flowRecord',
+    method: 'get',
+    params: query
+  })
+}
+
+// 撤回任务
+export function revokeProcess(data) {
+  return request({
+    url: '/flowable/task/revokeProcess',
+    method: 'post',
+    data: data
+  })
+}
+
+// 部署流程实例
+export function deployStart(deployId) {
+  return request({
+    url: '/flowable/process/startFlow/' + deployId,
+    method: 'get',
+  })
+}
+
+// 查询流程定义详细
+export function getDeployment(id) {
+  return request({
+    url: '/system/deployment/' + id,
+    method: 'get'
+  })
+}
+
+// 新增流程定义
+export function addDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程定义
+export function updateDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程定义
+export function delDeployment(id) {
+  return request({
+    url: '/flowable/instance/delete/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出流程定义
+export function exportDeployment(query) {
+  return request({
+    url: '/system/deployment/export',
+    method: 'get',
+    params: query
+  })
+}

+ 68 - 0
ruoyi-ui-wuguan/src/api/flowable/form.js

@@ -0,0 +1,68 @@
+import request from '@/utils/request'
+
+// 查询流程表单列表
+export function listForm(query) {
+  return request({
+    url: '/flowable/form/list',
+    method: 'get',
+    params: query
+  })
+}
+export function listAllForm(query) {
+  return request({
+    url: '/flowable/form/formList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询流程表单详细
+export function getForm(formId) {
+  return request({
+    url: '/flowable/form/' + formId,
+    method: 'get'
+  })
+}
+
+// 新增流程表单
+export function addForm(data) {
+  return request({
+    url: '/flowable/form',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程表单
+export function updateForm(data) {
+  return request({
+    url: '/flowable/form',
+    method: 'put',
+    data: data
+  })
+}
+// 挂载表单
+export function addDeployForm(data) {
+  return request({
+    url: '/flowable/form/addDeployForm',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除流程表单
+export function delForm(formId) {
+  return request({
+    url: '/flowable/form/' + formId,
+    method: 'delete'
+  })
+}
+
+// 导出流程表单
+export function exportForm(query) {
+  return request({
+    url: '/flowable/form/export',
+    method: 'get',
+    params: query
+  })
+}

+ 106 - 0
ruoyi-ui-wuguan/src/api/flowable/process.js

@@ -0,0 +1,106 @@
+import request from '@/utils/request'
+import da from "element-ui/src/locale/lang/da";
+
+// 我的发起的流程
+export function myProcessList(query) {
+  return request({
+    url: '/flowable/task/myProcess',
+    method: 'get',
+    params: query
+  })
+}
+
+export function flowFormData(query) {
+  return request({
+    url: '/flowable/task/flowFormData',
+    method: 'get',
+    params: query
+  })
+}
+
+// 完成任务
+export function complete(data) {
+  return request({
+    url: '/flowable/task/complete',
+    method: 'post',
+    data: data
+  })
+}
+
+// 取消申请
+export function stopProcess(data) {
+  return request({
+    url: '/flowable/task/stopProcess',
+    method: 'post',
+    data: data
+  })
+}
+
+// 驳回任务
+export function rejectTask(data) {
+  return request({
+    url: '/flowable/task/reject',
+    method: 'post',
+    data: data
+  })
+}
+
+// 可退回任务列表
+export function returnList(data) {
+  return request({
+    url: '/flowable/task/returnList',
+    method: 'post',
+    data: data
+  })
+}
+
+// 部署流程实例
+export function deployStart(deployId) {
+  return request({
+    url: '/flowable/process/startFlow/' + deployId,
+    method: 'get',
+  })
+}
+
+// 查询流程定义详细
+export function getDeployment(id) {
+  return request({
+    url: '/system/deployment/' + id,
+    method: 'get'
+  })
+}
+
+// 新增流程定义
+export function addDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程定义
+export function updateDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程定义
+export function delDeployment(id) {
+  return request({
+    url: '/system/deployment/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出流程定义
+export function exportDeployment(query) {
+  return request({
+    url: '/system/deployment/export',
+    method: 'get',
+    params: query
+  })
+}

+ 133 - 0
ruoyi-ui-wuguan/src/api/flowable/todo.js

@@ -0,0 +1,133 @@
+import request from '@/utils/request'
+import da from "element-ui/src/locale/lang/da";
+
+// 查询待办任务列表
+export function todoList(query) {
+  return request({
+    url: '/flowable/task/todoList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 完成任务
+export function complete(data) {
+  return request({
+    url: '/flowable/task/complete',
+    method: 'post',
+    data: data
+  })
+}
+
+// 委派任务
+export function delegate(data) {
+  return request({
+    url: '/flowable/task/delegate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 退回任务
+export function returnTask(data) {
+  return request({
+    url: '/flowable/task/return',
+    method: 'post',
+    data: data
+  })
+}
+
+// 驳回任务
+export function rejectTask(data) {
+  return request({
+    url: '/flowable/task/reject',
+    method: 'post',
+    data: data
+  })
+}
+
+// 可退回任务列表
+export function returnList(data) {
+  return request({
+    url: '/flowable/task/returnList',
+    method: 'post',
+    data: data
+  })
+}
+
+// 下一节点
+export function getNextFlowNode(data) {
+  return request({
+    url: '/flowable/task/nextFlowNode',
+    method: 'post',
+    data: data
+  })
+}
+
+// 下一节点
+export function getNextFlowNodeByStart(data) {
+  return request({
+    url: '/flowable/task/nextFlowNodeByStart',
+    method: 'post',
+    data: data
+  })
+}
+
+// 部署流程实例
+export function deployStart(deployId) {
+  return request({
+    url: '/flowable/process/startFlow/' + deployId,
+    method: 'get',
+  })
+}
+
+// 查询流程定义详细
+export function getDeployment(id) {
+  return request({
+    url: '/system/deployment/' + id,
+    method: 'get'
+  })
+}
+
+// 新增流程定义
+export function addDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程定义
+export function updateDeployment(data) {
+  return request({
+    url: '/system/deployment',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程定义
+export function delDeployment(id) {
+  return request({
+    url: '/system/deployment/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出流程定义
+export function exportDeployment(query) {
+  return request({
+    url: '/system/deployment/export',
+    method: 'get',
+    params: query
+  })
+}
+// 流程节点表单
+export function flowTaskForm(query) {
+  return request({
+    url: '/flowable/task/flowTaskForm',
+    method: 'get',
+    params: query
+  })
+}

+ 68 - 43
ruoyi-ui-wuguan/src/api/login.js

@@ -1,69 +1,70 @@
 import request from '@/utils/request'
 
-// 登录方法
-export function login(username, password, code, uuid) {
-  const data = {
-    username,
-    password,
-    code,
-    uuid
-  }
+// pc端固定客户端授权id
+// const clientId = 'e5cd7e4891bf95d1d19206ce24a7b32e';
+const clientId = process.env.VUE_APP_CLIENT_ID
+
+/**
+ * @param data {LoginData}
+ * @returns
+ */
+export function login(username, password, code, uuid,tenantId) {
+	const data = {
+	  username,
+	  password,
+	  code,
+	  uuid,
+	  tenantId
+	}
+  const params = {
+    ...data,
+    clientId: data.clientId || clientId,
+    grantType: data.grantType || 'password'
+  };
   return request({
-    url: '/login',
+    url: '/auth/login',
     headers: {
       isToken: false,
-      repeatSubmit: false
     },
     method: 'post',
-    data: data
-  })
+    data: params
+  });
 }
 
 // 注册方法
 export function register(data) {
   return request({
-    url: '/register',
+    url: '/auth/register',
     headers: {
-      isToken: false
+      isToken: false,
+      isEncrypt: true
     },
     method: 'post',
     data: data
-  })
-}
-
-// 获取用户详细信息
-export function getInfo() {
-  return request({
-    url: '/getInfo',
-    method: 'get'
-  })
+  });
 }
 
-// 退出方法
+/**
+ * 注销
+ */
 export function logout() {
   return request({
-    url: '/logout',
+    url: '/auth/logout',
     method: 'post'
-  })
+  });
 }
 
-// 获取验证码
-export function getCodeImg() {
+/**
+ * 获取验证码
+ */
+export function getCodeImg(){
   return request({
-    url: '/captchaImage',
+    url: '/auth/code',
     headers: {
       isToken: false
     },
     method: 'get',
     timeout: 20000
-  })
-}
-// 获取短信验证码
-
-export function getCaptcha(id) {
-  return request({
-    url: '/applet/appForgetPW/' + id,
-    method: 'get',
   });
 }
 
@@ -76,6 +77,19 @@ export function registerf(query) {
   });
 }
 
+// 获取短信验证码
+export function getCaptcha(data) {
+  return request({
+    url: '/wuYe/sendSms/sendLoginSms',
+    method: 'post',
+    data: data
+  });
+}
+
+
+
+
+
 /**
  * 第三方登录
  */
@@ -93,9 +107,20 @@ export function callback(data){
 }
 
 // 获取用户详细信息
-// export function getInfo() {
-//   return request({
-//     url: '/system/user/getInfo',
-//     method: 'get'
-//   });
-// }
+export function getInfo() {
+  return request({
+    url: '/system/user/getInfo',
+    method: 'get'
+  });
+}
+
+// 获取租户列表
+export function getTenantList(){
+  return request({
+    url: '/auth/tenant/list',
+    headers: {
+      isToken: false
+    },
+    method: 'get'
+  });
+}

+ 1 - 1
ruoyi-ui-wuguan/src/api/menu.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 获取路由
 export const getRouters = () => {
   return request({
-    url: '/getRouters',
+    url: '/system/menu/getRouters',
     method: 'get'
   })
 }

+ 54 - 0
ruoyi-ui-wuguan/src/api/system/change.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 查询调课列表
+export function listChange(query) {
+  return request({
+    url: '/course/change/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询调课详细
+export function getChange(id) {
+  return request({
+    url: '/course/change/' + id,
+    method: 'get'
+  })
+}
+
+// 新增调课
+export function addChange(data) {
+  return request({
+    url: '/course/change',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改调课
+export function updateChange(data) {
+  return request({
+    url: '/course/change/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除调课
+export function delChange(id) {
+  return request({
+    url: '/course/change/delete/' + id,
+    method: 'get'
+  })
+}
+
+export function setPass(query) {
+  return request({
+    url: '/course/change/reply',
+    method: 'get',
+    params: query
+  })
+}
+
+

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/class.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询老师-班级(学科)(审核通过之后数据)列表
+export function listClass(query) {
+  return request({
+    url: '/formal/class/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询老师-班级(学科)(审核通过之后数据)详细
+export function getClass(id) {
+  return request({
+    url: '/formal/class/' + id,
+    method: 'get'
+  })
+}
+
+// 新增老师-班级(学科)(审核通过之后数据)
+export function addClass(data) {
+  return request({
+    url: '/formal/class',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改老师-班级(学科)(审核通过之后数据)
+export function updateClass(data) {
+  return request({
+    url: '/formal/class/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除老师-班级(学科)(审核通过之后数据)
+export function delClass(id) {
+  return request({
+    url: '/formal/class/delete/' + id,
+    method: 'get'
+  })
+}

+ 77 - 0
ruoyi-ui-wuguan/src/api/system/client.js

@@ -0,0 +1,77 @@
+import request from '@/utils/request';
+/**
+ * 查询客户端管理列表
+ * @param query
+ * @returns {*}
+ */
+
+export function listClient(query) {
+  return request({
+    url: '/system/client/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询客户端管理详细
+ * @param id
+ */
+export function getClient(id){
+  return request({
+    url: '/system/client/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增客户端管理
+ * @param data
+ */
+export function addClient(data){
+  return request({
+    url: '/system/client',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改客户端管理
+ * @param data
+ */
+export function updateClient(data) {
+  return request({
+    url: '/system/client',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除客户端管理
+ * @param id
+ */
+export function delClient(id){
+  return request({
+    url: '/system/client/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 状态修改
+ * @param id ID
+ * @param status 状态
+ */
+export function changeStatus(id, status) {
+  const data = {
+    id,
+    status
+  };
+  return request({
+    url: '/system/client/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/expression.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询流程达式列表
+export function listExpression(query) {
+  return request({
+    url: '/system/expression/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询流程达式详细
+export function getExpression(id) {
+  return request({
+    url: '/system/expression/' + id,
+    method: 'get'
+  })
+}
+
+// 新增流程达式
+export function addExpression(data) {
+  return request({
+    url: '/system/expression',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程达式
+export function updateExpression(data) {
+  return request({
+    url: '/system/expression',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程达式
+export function delExpression(id) {
+  return request({
+    url: '/system/expression/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/listener.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询流程监听列表
+export function listListener(query) {
+  return request({
+    url: '/system/listener/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询流程监听详细
+export function getListener(id) {
+  return request({
+    url: '/system/listener/' + id,
+    method: 'get'
+  })
+}
+
+// 新增流程监听
+export function addListener(data) {
+  return request({
+    url: '/system/listener',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改流程监听
+export function updateListener(data) {
+  return request({
+    url: '/system/listener',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除流程监听
+export function delListener(id) {
+  return request({
+    url: '/system/listener/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/parents.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询注册-家长列表
+export function listParents(query) {
+  return request({
+    url: '/register/parents/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询注册-家长详细
+export function getParents(id) {
+  return request({
+    url: '/register/parents/' + id,
+    method: 'get'
+  })
+}
+
+// 新增注册-家长
+export function addParents(data) {
+  return request({
+    url: '/register/parents',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改注册-家长
+export function updateParents(data) {
+  return request({
+    url: '/register/parents',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除注册-家长
+export function delParents(id) {
+  return request({
+    url: '/register/parents/delete/' + id,
+    method: 'get'
+  })
+}

+ 54 - 0
ruoyi-ui-wuguan/src/api/system/school.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 查询注册-学校列表
+export function listSchool(query) {
+  return request({
+    url: '/register/school/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询注册-学校详细
+export function getSchool(id) {
+  return request({
+    url: '/register/school/' + id,
+    method: 'get'
+  })
+}
+
+// 新增注册-学校
+export function addSchool(data) {
+  return request({
+    url: '/register/school',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改注册-学校
+export function updateSchool(data) {
+  return request({
+    url: '/register/school',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除注册-学校
+export function delSchool(id) {
+  return request({
+    url: '/register/school/delete/' + id,
+    method: 'get'
+  })
+}
+
+
+export function setPass(data) {
+  return request({
+    url: '/audit/shyj',
+    method: 'post',
+    data: data
+  })
+}
+

+ 27 - 0
ruoyi-ui-wuguan/src/api/system/social/auth.js

@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+// 绑定账号
+export function authBinding(source, tenantId) {
+  return request({
+    url: '/auth/binding/' + source,
+    method: 'get',
+    params: {
+      tenantId: tenantId,
+      domain: window.location.host
+    }
+  });
+}
+
+// 解绑账号
+export function authUnlock(authId) {
+  return request({
+    url: '/auth/unlock/' + authId,
+    method: 'delete'
+  });
+}
+//获取授权列表
+export function getAuthList() {
+  return request({
+    url: '/system/social/list',
+    method: 'get'
+  });
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/student.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询注册-家长-学生列表
+export function listStudent(query) {
+  return request({
+    url: '/register/student/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询注册-家长-学生详细
+export function getStudent(id) {
+  return request({
+    url: '/register/student/' + id,
+    method: 'get'
+  })
+}
+
+// 新增注册-家长-学生
+export function addStudent(data) {
+  return request({
+    url: '/register/student',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改注册-家长-学生
+export function updateStudent(data) {
+  return request({
+    url: '/register/student',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除注册-家长-学生
+export function delStudent(id) {
+  return request({
+    url: '/register/student/delete/' + id,
+    method: 'get'
+  })
+}

+ 55 - 0
ruoyi-ui-wuguan/src/api/system/table.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+// 查询课程列表
+export function listTable(query) {
+  return request({
+    url: '/course/table/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 首页
+export function listTablexg(query) {
+  return request({
+    url: '/course/table/pc/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询课程详细
+export function getTable(id) {
+  return request({
+    url: '/course/table/' + id,
+    method: 'get'
+  })
+}
+
+// 新增课程
+export function addTable(data) {
+  return request({
+    url: '/course/table',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改课程
+export function updateTable(data) {
+  return request({
+    url: '/course/table/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除课程
+export function delTable(query) {
+  return request({
+    url: '/course/table/delete/classId',
+    method: 'get',
+    params: query
+  })
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/system/teacher.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询注册-老师列表
+export function listTeacher(query) {
+  return request({
+    url: '/register/teacher/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询注册-老师详细
+export function getTeacher(id) {
+  return request({
+    url: '/register/teacher/' + id,
+    method: 'get'
+  })
+}
+
+// 新增注册-老师
+export function addTeacher(data) {
+  return request({
+    url: '/register/teacher',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改注册-老师
+export function updateTeacher(data) {
+  return request({
+    url: '/register/teacher',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除注册-老师
+export function delTeacher(id) {
+  return request({
+    url: '/register/teacher/delete/' + id,
+    method: 'get'
+  })
+}

+ 55 - 0
ruoyi-ui-wuguan/src/api/system/time.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+// 查询课程-时间列表
+export function listTime(query) {
+  return request({
+    url: '/course/time/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listTimed(data) {
+  return request({
+    url: '/applet/pc/fangXue/statistics',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 查询课程-时间详细
+export function getTime(id) {
+  return request({
+    url: '/course/time/' + id,
+    method: 'get'
+  })
+}
+
+// 新增课程-时间
+export function addTime(data) {
+  return request({
+    url: '/course/time',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改课程-时间
+export function updateTime(data) {
+  return request({
+    url: '/course/time/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除课程-时间
+export function delTime(query) {
+  return request({
+    url: '/course/time/delete/schoolId',
+    method: 'get',
+     params: query
+  })
+}

+ 106 - 0
ruoyi-ui-wuguan/src/api/tool/build/CodeTypeDialog.vue

@@ -0,0 +1,106 @@
+<template>
+  <div>
+    <el-dialog
+      v-bind="$attrs"
+      width="500px"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <el-row :gutter="15">
+        <el-form
+          ref="elForm"
+          :model="formData"
+          :rules="rules"
+          size="medium"
+          label-width="100px"
+        >
+          <el-col :span="24">
+            <el-form-item label="生成类型" prop="type">
+              <el-radio-group v-model="formData.type">
+                <el-radio-button
+                  v-for="(item, index) in typeOptions"
+                  :key="index"
+                  :label="item.value"
+                  :disabled="item.disabled"
+                >
+                  {{ item.label }}
+                </el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item v-if="showFileName" label="文件名" prop="fileName">
+              <el-input v-model="formData.fileName" placeholder="请输入文件名" clearable />
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </el-row>
+
+      <div slot="footer">
+        <el-button @click="close">
+          取消
+        </el-button>
+        <el-button type="primary" @click="handleConfirm">
+          确定
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+export default {
+  inheritAttrs: false,
+  props: ['showFileName'],
+  data() {
+    return {
+      formData: {
+        fileName: undefined,
+        type: 'file'
+      },
+      rules: {
+        fileName: [{
+          required: true,
+          message: '请输入文件名',
+          trigger: 'blur'
+        }],
+        type: [{
+          required: true,
+          message: '生成类型不能为空',
+          trigger: 'change'
+        }]
+      },
+      typeOptions: [{
+        label: '页面',
+        value: 'file'
+      }, {
+        label: '弹窗',
+        value: 'dialog'
+      }]
+    }
+  },
+  computed: {
+  },
+  watch: {},
+  mounted() {},
+  methods: {
+    onOpen() {
+      if (this.showFileName) {
+        this.formData.fileName = `${+new Date()}.vue`
+      }
+    },
+    onClose() {
+    },
+    close(e) {
+      this.$emit('update:visible', false)
+    },
+    handleConfirm() {
+      this.$refs.elForm.validate(valid => {
+        if (!valid) return
+        this.$emit('confirm', { ...this.formData })
+        this.close()
+      })
+    }
+  }
+}
+</script>

+ 100 - 0
ruoyi-ui-wuguan/src/api/tool/build/DraggableItem.vue

@@ -0,0 +1,100 @@
+<script>
+import draggable from 'vuedraggable'
+import render from '@/utils/generator/render'
+
+const components = {
+  itemBtns(h, element, index, parent) {
+    const { copyItem, deleteItem } = this.$listeners
+    return [
+      <span class="drawing-item-copy" title="复制" onClick={event => {
+        copyItem(element, parent); event.stopPropagation()
+      }}>
+        <i class="el-icon-copy-document" />
+      </span>,
+      <span class="drawing-item-delete" title="删除" onClick={event => {
+        deleteItem(index, parent); event.stopPropagation()
+      }}>
+        <i class="el-icon-delete" />
+      </span>
+    ]
+  }
+}
+const layouts = {
+  colFormItem(h, element, index, parent) {
+    const { activeItem } = this.$listeners
+    let className = this.activeId === element.formId ? 'drawing-item active-from-item' : 'drawing-item'
+    if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
+    return (
+      <el-col span={element.span} class={className}
+        nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
+        <el-form-item label-width={element.labelWidth ? `${element.labelWidth}px` : null}
+          label={element.label} required={element.required}>
+          <render key={element.renderKey} conf={element} onInput={ event => {
+            this.$set(element, 'defaultValue', event)
+          }} />
+        </el-form-item>
+        {components.itemBtns.apply(this, arguments)}
+      </el-col>
+    )
+  },
+  rowFormItem(h, element, index, parent) {
+    const { activeItem } = this.$listeners
+    const className = this.activeId === element.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item'
+    let child = renderChildren.apply(this, arguments)
+    if (element.type === 'flex') {
+      child = <el-row type={element.type} justify={element.justify} align={element.align}>
+              {child}
+            </el-row>
+    }
+    return (
+      <el-col span={element.span}>
+        <el-row gutter={element.gutter} class={className}
+          nativeOnClick={event => { activeItem(element); event.stopPropagation() }}>
+          <span class="component-name">{element.componentName}</span>
+          <draggable list={element.children} animation={340} group="componentsGroup" class="drag-wrapper">
+            {child}
+          </draggable>
+          {components.itemBtns.apply(this, arguments)}
+        </el-row>
+      </el-col>
+    )
+  }
+}
+
+function renderChildren(h, element, index, parent) {
+  if (!Array.isArray(element.children)) return null
+  return element.children.map((el, i) => {
+    const layout = layouts[el.layout]
+    if (layout) {
+      return layout.call(this, h, el, i, element.children)
+    }
+    return layoutIsNotFound()
+  })
+}
+
+function layoutIsNotFound() {
+  throw new Error(`没有与${this.element.layout}匹配的layout`)
+}
+
+export default {
+  components: {
+    render,
+    draggable
+  },
+  props: [
+    'element',
+    'index',
+    'drawingList',
+    'activeId',
+    'formConf'
+  ],
+  render(h) {
+    const layout = layouts[this.element.layout]
+
+    if (layout) {
+      return layout.call(this, h, this.element, this.index, this.drawingList)
+    }
+    return layoutIsNotFound()
+  }
+}
+</script>

+ 123 - 0
ruoyi-ui-wuguan/src/api/tool/build/IconsDialog.vue

@@ -0,0 +1,123 @@
+<template>
+  <div class="icon-dialog">
+    <el-dialog
+      v-bind="$attrs"
+      width="980px"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <div slot="title">
+        选择图标
+        <el-input
+          v-model="key"
+          size="mini"
+          :style="{width: '260px'}"
+          placeholder="请输入图标名称"
+          prefix-icon="el-icon-search"
+          clearable
+        />
+      </div>
+      <ul class="icon-ul">
+        <li
+          v-for="icon in iconList"
+          :key="icon"
+          :class="active===icon?'active-item':''"
+          @click="onSelect(icon)"
+        >
+          <i :class="icon" />
+          <div>{{ icon }}</div>
+        </li>
+      </ul>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import iconList from '@/utils/generator/icon.json'
+
+const originList = iconList.map(name => `el-icon-${name}`)
+
+export default {
+  inheritAttrs: false,
+  props: ['current'],
+  data() {
+    return {
+      iconList: originList,
+      active: null,
+      key: ''
+    }
+  },
+  watch: {
+    key(val) {
+      if (val) {
+        this.iconList = originList.filter(name => name.indexOf(val) > -1)
+      } else {
+        this.iconList = originList
+      }
+    }
+  },
+  methods: {
+    onOpen() {
+      this.active = this.current
+      this.key = ''
+    },
+    onClose() {},
+    onSelect(icon) {
+      this.active = icon
+      this.$emit('select', icon)
+      this.$emit('update:visible', false)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.icon-ul {
+  margin: 0;
+  padding: 0;
+  font-size: 0;
+  li {
+    list-style-type: none;
+    text-align: center;
+    font-size: 14px;
+    display: inline-block;
+    width: 16.66%;
+    box-sizing: border-box;
+    height: 108px;
+    padding: 15px 6px 6px 6px;
+    cursor: pointer;
+    overflow: hidden;
+    &:hover {
+      background: #f2f2f2;
+    }
+    &.active-item{
+      background: #e1f3fb;
+      color: #7a6df0
+    }
+    > i {
+      font-size: 30px;
+      line-height: 50px;
+    }
+  }
+}
+.icon-dialog {
+  ::v-deep .el-dialog {
+    border-radius: 8px;
+    margin-bottom: 0;
+    margin-top: 4vh !important;
+    display: flex;
+    flex-direction: column;
+    max-height: 92vh;
+    overflow: hidden;
+    box-sizing: border-box;
+    .el-dialog__header {
+      padding-top: 14px;
+    }
+    .el-dialog__body {
+      margin: 0 20px 20px 20px;
+      padding: 0;
+      overflow: auto;
+    }
+  }
+}
+</style>

+ 946 - 0
ruoyi-ui-wuguan/src/api/tool/build/RightPanel.vue

@@ -0,0 +1,946 @@
+<template>
+  <div class="right-board">
+    <el-tabs v-model="currentTab" class="center-tabs">
+      <el-tab-pane label="组件属性" name="field" />
+      <el-tab-pane label="表单属性" name="form" />
+    </el-tabs>
+    <div class="field-box">
+      <a class="document-link" target="_blank" :href="documentLink" title="查看组件文档">
+        <i class="el-icon-link" />
+      </a>
+      <el-scrollbar class="right-scrollbar">
+        <!-- 组件属性 -->
+        <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px">
+          <el-form-item v-if="activeData.changeTag" label="组件类型">
+            <el-select
+              v-model="activeData.tagIcon"
+              placeholder="请选择组件类型"
+              :style="{width: '100%'}"
+              @change="tagChange"
+            >
+              <el-option-group v-for="group in tagList" :key="group.label" :label="group.label">
+                <el-option
+                  v-for="item in group.options"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.tagIcon"
+                >
+                  <svg-icon class="node-icon" :icon-class="item.tagIcon" />
+                  <span> {{ item.label }}</span>
+                </el-option>
+              </el-option-group>
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.vModel!==undefined" label="字段名">
+            <el-input v-model="activeData.vModel" placeholder="请输入字段名(v-model)" />
+          </el-form-item>
+          <el-form-item v-if="activeData.componentName!==undefined" label="组件名">
+            {{ activeData.componentName }}
+          </el-form-item>
+          <el-form-item v-if="activeData.label!==undefined" label="标题">
+            <el-input v-model="activeData.label" placeholder="请输入标题" />
+          </el-form-item>
+          <el-form-item v-if="activeData.placeholder!==undefined" label="占位提示">
+            <el-input v-model="activeData.placeholder" placeholder="请输入占位提示" />
+          </el-form-item>
+          <el-form-item v-if="activeData['start-placeholder']!==undefined" label="开始占位">
+            <el-input v-model="activeData['start-placeholder']" placeholder="请输入占位提示" />
+          </el-form-item>
+          <el-form-item v-if="activeData['end-placeholder']!==undefined" label="结束占位">
+            <el-input v-model="activeData['end-placeholder']" placeholder="请输入占位提示" />
+          </el-form-item>
+          <el-form-item v-if="activeData.span!==undefined" label="表单栅格">
+            <el-slider v-model="activeData.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData.layout==='rowFormItem'" label="栅格间隔">
+            <el-input-number v-model="activeData.gutter" :min="0" placeholder="栅格间隔" />
+          </el-form-item>
+          <el-form-item v-if="activeData.layout==='rowFormItem'" label="布局模式">
+            <el-radio-group v-model="activeData.type">
+              <el-radio-button label="default" />
+              <el-radio-button label="flex" />
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" label="水平排列">
+            <el-select v-model="activeData.justify" placeholder="请选择水平排列" :style="{width: '100%'}">
+              <el-option
+                v-for="(item, index) in justifyOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" label="垂直排列">
+            <el-radio-group v-model="activeData.align">
+              <el-radio-button label="top" />
+              <el-radio-button label="middle" />
+              <el-radio-button label="bottom" />
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.labelWidth!==undefined" label="标签宽度">
+            <el-input v-model.number="activeData.labelWidth" type="number" placeholder="请输入标签宽度" />
+          </el-form-item>
+          <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度">
+            <el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable />
+          </el-form-item>
+          <el-form-item v-if="activeData.vModel!==undefined" label="默认值">
+            <el-input
+              :value="setDefaultValue(activeData.defaultValue)"
+              placeholder="请输入默认值"
+              @input="onDefaultValueInput"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="至少应选">
+            <el-input-number
+              :value="activeData.min"
+              :min="0"
+              placeholder="至少应选"
+              @input="$set(activeData, 'min', $event?$event:undefined)"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="最多可选">
+            <el-input-number
+              :value="activeData.max"
+              :min="0"
+              placeholder="最多可选"
+              @input="$set(activeData, 'max', $event?$event:undefined)"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.prepend!==undefined" label="前缀">
+            <el-input v-model="activeData.prepend" placeholder="请输入前缀" />
+          </el-form-item>
+          <el-form-item v-if="activeData.append!==undefined" label="后缀">
+            <el-input v-model="activeData.append" placeholder="请输入后缀" />
+          </el-form-item>
+          <el-form-item v-if="activeData['prefix-icon']!==undefined" label="前图标">
+            <el-input v-model="activeData['prefix-icon']" placeholder="请输入前图标名称">
+              <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')">
+                选择
+              </el-button>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData['suffix-icon'] !== undefined" label="后图标">
+            <el-input v-model="activeData['suffix-icon']" placeholder="请输入后图标名称">
+              <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')">
+                选择
+              </el-button>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="选项分隔符">
+            <el-input v-model="activeData.separator" placeholder="请输入选项分隔符" />
+          </el-form-item>
+          <el-form-item v-if="activeData.autosize !== undefined" label="最小行数">
+            <el-input-number v-model="activeData.autosize.minRows" :min="1" placeholder="最小行数" />
+          </el-form-item>
+          <el-form-item v-if="activeData.autosize !== undefined" label="最大行数">
+            <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="最大行数" />
+          </el-form-item>
+          <el-form-item v-if="activeData.min !== undefined" label="最小值">
+            <el-input-number v-model="activeData.min" placeholder="最小值" />
+          </el-form-item>
+          <el-form-item v-if="activeData.max !== undefined" label="最大值">
+            <el-input-number v-model="activeData.max" placeholder="最大值" />
+          </el-form-item>
+          <el-form-item v-if="activeData.step !== undefined" label="步长">
+            <el-input-number v-model="activeData.step" placeholder="步数" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="精度">
+            <el-input-number v-model="activeData.precision" :min="0" placeholder="精度" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="按钮位置">
+            <el-radio-group v-model="activeData['controls-position']">
+              <el-radio-button label="">
+                默认
+              </el-radio-button>
+              <el-radio-button label="right">
+                右侧
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData.maxlength !== undefined" label="最多输入">
+            <el-input v-model="activeData.maxlength" placeholder="请输入字符长度">
+              <template slot="append">
+                个字符
+              </template>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData['active-text'] !== undefined" label="开启提示">
+            <el-input v-model="activeData['active-text']" placeholder="请输入开启提示" />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-text'] !== undefined" label="关闭提示">
+            <el-input v-model="activeData['inactive-text']" placeholder="请输入关闭提示" />
+          </el-form-item>
+          <el-form-item v-if="activeData['active-value'] !== undefined" label="开启值">
+            <el-input
+              :value="setDefaultValue(activeData['active-value'])"
+              placeholder="请输入开启值"
+              @input="onSwitchValueInput($event, 'active-value')"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-value'] !== undefined" label="关闭值">
+            <el-input
+              :value="setDefaultValue(activeData['inactive-value'])"
+              placeholder="请输入关闭值"
+              @input="onSwitchValueInput($event, 'inactive-value')"
+            />
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.type !== undefined && 'el-date-picker' === activeData.tag"
+            label="时间类型"
+          >
+            <el-select
+              v-model="activeData.type"
+              placeholder="请选择时间类型"
+              :style="{ width: '100%' }"
+              @change="dateTypeChange"
+            >
+              <el-option
+                v-for="(item, index) in dateOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.name !== undefined" label="文件字段名">
+            <el-input v-model="activeData.name" placeholder="请输入上传文件字段名" />
+          </el-form-item>
+          <el-form-item v-if="activeData.accept !== undefined" label="文件类型">
+            <el-select
+              v-model="activeData.accept"
+              placeholder="请选择文件类型"
+              :style="{ width: '100%' }"
+              clearable
+            >
+              <el-option label="图片" value="image/*" />
+              <el-option label="视频" value="video/*" />
+              <el-option label="音频" value="audio/*" />
+              <el-option label="excel" value=".xls,.xlsx" />
+              <el-option label="word" value=".doc,.docx" />
+              <el-option label="pdf" value=".pdf" />
+              <el-option label="txt" value=".txt" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="activeData.fileSize !== undefined" label="文件大小">
+            <el-input v-model.number="activeData.fileSize" placeholder="请输入文件大小">
+              <el-select slot="append" v-model="activeData.sizeUnit" :style="{ width: '66px' }">
+                <el-option label="KB" value="KB" />
+                <el-option label="MB" value="MB" />
+                <el-option label="GB" value="GB" />
+              </el-select>
+            </el-input>
+          </el-form-item>
+          <el-form-item v-if="activeData.action !== undefined" label="上传地址">
+            <el-input v-model="activeData.action" placeholder="请输入上传地址" clearable />
+          </el-form-item>
+          <el-form-item v-if="activeData['list-type'] !== undefined" label="列表类型">
+            <el-radio-group v-model="activeData['list-type']" size="small">
+              <el-radio-button label="text">
+                text
+              </el-radio-button>
+              <el-radio-button label="picture">
+                picture
+              </el-radio-button>
+              <el-radio-button label="picture-card">
+                picture-card
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.buttonText !== undefined"
+            v-show="'picture-card' !== activeData['list-type']"
+            label="按钮文字"
+          >
+            <el-input v-model="activeData.buttonText" placeholder="请输入按钮文字" />
+          </el-form-item>
+          <el-form-item v-if="activeData['range-separator'] !== undefined" label="分隔符">
+            <el-input v-model="activeData['range-separator']" placeholder="请输入分隔符" />
+          </el-form-item>
+          <el-form-item v-if="activeData['picker-options'] !== undefined" label="时间段">
+            <el-input
+              v-model="activeData['picker-options'].selectableRange"
+              placeholder="请输入时间段"
+            />
+          </el-form-item>
+          <el-form-item v-if="activeData.format !== undefined" label="时间格式">
+            <el-input
+              :value="activeData.format"
+              placeholder="请输入时间格式"
+              @input="setTimeValue($event)"
+            />
+          </el-form-item>
+          <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1">
+            <el-divider>选项</el-divider>
+            <draggable
+              :list="activeData.options"
+              :animation="340"
+              group="selectItem"
+              handle=".option-drag"
+            >
+              <div v-for="(item, index) in activeData.options" :key="index" class="select-item">
+                <div class="select-line-icon option-drag">
+                  <i class="el-icon-s-operation" />
+                </div>
+                <el-input v-model="item.label" placeholder="选项名" size="small" />
+                <el-input
+                  placeholder="选项值"
+                  size="small"
+                  :value="item.value"
+                  @input="setOptionValue(item, $event)"
+                />
+                <div class="close-btn select-line-icon" @click="activeData.options.splice(index, 1)">
+                  <i class="el-icon-remove-outline" />
+                </div>
+              </div>
+            </draggable>
+            <div style="margin-left: 20px;">
+              <el-button
+                style="padding-bottom: 0"
+                icon="el-icon-circle-plus-outline"
+                type="text"
+                @click="addSelectItem"
+              >
+                添加选项
+              </el-button>
+            </div>
+            <el-divider />
+          </template>
+
+          <template v-if="['el-cascader'].indexOf(activeData.tag) > -1">
+            <el-divider>选项</el-divider>
+            <el-form-item label="数据类型">
+              <el-radio-group v-model="activeData.dataType" size="small">
+                <el-radio-button label="dynamic">
+                  动态数据
+                </el-radio-button>
+                <el-radio-button label="static">
+                  静态数据
+                </el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+
+            <template v-if="activeData.dataType === 'dynamic'">
+              <el-form-item label="标签键名">
+                <el-input v-model="activeData.labelKey" placeholder="请输入标签键名" />
+              </el-form-item>
+              <el-form-item label="值键名">
+                <el-input v-model="activeData.valueKey" placeholder="请输入值键名" />
+              </el-form-item>
+              <el-form-item label="子级键名">
+                <el-input v-model="activeData.childrenKey" placeholder="请输入子级键名" />
+              </el-form-item>
+            </template>
+
+            <el-tree
+              v-if="activeData.dataType === 'static'"
+              draggable
+              :data="activeData.options"
+              node-key="id"
+              :expand-on-click-node="false"
+              :render-content="renderContent"
+            />
+            <div v-if="activeData.dataType === 'static'" style="margin-left: 20px">
+              <el-button
+                style="padding-bottom: 0"
+                icon="el-icon-circle-plus-outline"
+                type="text"
+                @click="addTreeItem"
+              >
+                添加父级
+              </el-button>
+            </div>
+            <el-divider />
+          </template>
+
+          <el-form-item v-if="activeData.optionType !== undefined" label="选项样式">
+            <el-radio-group v-model="activeData.optionType">
+              <el-radio-button label="default">
+                默认
+              </el-radio-button>
+              <el-radio-button label="button">
+                按钮
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData['active-color'] !== undefined" label="开启颜色">
+            <el-color-picker v-model="activeData['active-color']" />
+          </el-form-item>
+          <el-form-item v-if="activeData['inactive-color'] !== undefined" label="关闭颜色">
+            <el-color-picker v-model="activeData['inactive-color']" />
+          </el-form-item>
+
+          <el-form-item v-if="activeData['allow-half'] !== undefined" label="允许半选">
+            <el-switch v-model="activeData['allow-half']" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-text'] !== undefined" label="辅助文字">
+            <el-switch v-model="activeData['show-text']" @change="rateTextChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-score'] !== undefined" label="显示分数">
+            <el-switch v-model="activeData['show-score']" @change="rateScoreChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData['show-stops'] !== undefined" label="显示间断点">
+            <el-switch v-model="activeData['show-stops']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.range !== undefined" label="范围选择">
+            <el-switch v-model="activeData.range" @change="rangeChange" />
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.border !== undefined && activeData.optionType === 'default'"
+            label="是否带边框"
+          >
+            <el-switch v-model="activeData.border" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-color-picker'" label="颜色格式">
+            <el-select
+              v-model="activeData['color-format']"
+              placeholder="请选择颜色格式"
+              :style="{ width: '100%' }"
+              @change="colorFormatChange"
+            >
+              <el-option
+                v-for="(item, index) in colorFormatOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item
+            v-if="activeData.size !== undefined &&
+              (activeData.optionType === 'button' ||
+                activeData.border ||
+                activeData.tag === 'el-color-picker')"
+            label="选项尺寸"
+          >
+            <el-radio-group v-model="activeData.size">
+              <el-radio-button label="medium">
+                中等
+              </el-radio-button>
+              <el-radio-button label="small">
+                较小
+              </el-radio-button>
+              <el-radio-button label="mini">
+                迷你
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="输入统计">
+            <el-switch v-model="activeData['show-word-limit']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-input-number'" label="严格步数">
+            <el-switch v-model="activeData['step-strictly']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="是否多选">
+            <el-switch v-model="activeData.props.props.multiple" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="展示全路径">
+            <el-switch v-model="activeData['show-all-levels']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-cascader'" label="可否筛选">
+            <el-switch v-model="activeData.filterable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.clearable !== undefined" label="能否清空">
+            <el-switch v-model="activeData.clearable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.showTip !== undefined" label="显示提示">
+            <el-switch v-model="activeData.showTip" />
+          </el-form-item>
+          <el-form-item v-if="activeData.multiple !== undefined" label="多选文件">
+            <el-switch v-model="activeData.multiple" />
+          </el-form-item>
+          <el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传">
+            <el-switch v-model="activeData['auto-upload']" />
+          </el-form-item>
+          <el-form-item v-if="activeData.readonly !== undefined" label="是否只读">
+            <el-switch v-model="activeData.readonly" />
+          </el-form-item>
+          <el-form-item v-if="activeData.disabled !== undefined" label="是否禁用">
+            <el-switch v-model="activeData.disabled" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-select'" label="是否可搜索">
+            <el-switch v-model="activeData.filterable" />
+          </el-form-item>
+          <el-form-item v-if="activeData.tag === 'el-select'" label="是否多选">
+            <el-switch v-model="activeData.multiple" @change="multipleChange" />
+          </el-form-item>
+          <el-form-item v-if="activeData.required !== undefined" label="是否必填">
+            <el-switch v-model="activeData.required" />
+          </el-form-item>
+
+          <template v-if="activeData.layoutTree">
+            <el-divider>布局结构树</el-divider>
+            <el-tree
+              :data="[activeData]"
+              :props="layoutTreeProps"
+              node-key="renderKey"
+              default-expand-all
+              draggable
+            >
+              <span slot-scope="{ node, data }">
+                <span class="node-label">
+                  <svg-icon class="node-icon" :icon-class="data.tagIcon" />
+                  {{ node.label }}
+                </span>
+              </span>
+            </el-tree>
+          </template>
+
+          <template v-if="activeData.layout === 'colFormItem' && activeData.tag !== 'el-button'">
+            <el-divider>正则校验</el-divider>
+            <div
+              v-for="(item, index) in activeData.regList"
+              :key="index"
+              class="reg-item"
+            >
+              <span class="close-btn" @click="activeData.regList.splice(index, 1)">
+                <i class="el-icon-close" />
+              </span>
+              <el-form-item label="表达式">
+                <el-input v-model="item.pattern" placeholder="请输入正则" />
+              </el-form-item>
+              <el-form-item label="错误提示" style="margin-bottom:0">
+                <el-input v-model="item.message" placeholder="请输入错误提示" />
+              </el-form-item>
+            </div>
+            <div style="margin-left: 20px">
+              <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg">
+                添加规则
+              </el-button>
+            </div>
+          </template>
+        </el-form>
+        <!-- 表单属性 -->
+        <el-form v-show="currentTab === 'form'" size="small" label-width="90px">
+          <el-form-item label="表单名">
+            <el-input v-model="formConf.formRef" placeholder="请输入表单名(ref)" />
+          </el-form-item>
+          <el-form-item label="表单模型">
+            <el-input v-model="formConf.formModel" placeholder="请输入数据模型" />
+          </el-form-item>
+          <el-form-item label="校验模型">
+            <el-input v-model="formConf.formRules" placeholder="请输入校验模型" />
+          </el-form-item>
+          <el-form-item label="表单尺寸">
+            <el-radio-group v-model="formConf.size">
+              <el-radio-button label="medium">
+                中等
+              </el-radio-button>
+              <el-radio-button label="small">
+                较小
+              </el-radio-button>
+              <el-radio-button label="mini">
+                迷你
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="标签对齐">
+            <el-radio-group v-model="formConf.labelPosition">
+              <el-radio-button label="left">
+                左对齐
+              </el-radio-button>
+              <el-radio-button label="right">
+                右对齐
+              </el-radio-button>
+              <el-radio-button label="top">
+                顶部对齐
+              </el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="标签宽度">
+            <el-input-number v-model="formConf.labelWidth" placeholder="标签宽度" />
+          </el-form-item>
+          <el-form-item label="栅格间隔">
+            <el-input-number v-model="formConf.gutter" :min="0" placeholder="栅格间隔" />
+          </el-form-item>
+          <el-form-item label="禁用表单">
+            <el-switch v-model="formConf.disabled" />
+          </el-form-item>
+          <el-form-item label="表单按钮">
+            <el-switch v-model="formConf.formBtns" />
+          </el-form-item>
+          <el-form-item label="显示未选中组件边框">
+            <el-switch v-model="formConf.unFocusedComponentBorder" />
+          </el-form-item>
+        </el-form>
+      </el-scrollbar>
+    </div>
+
+    <treeNode-dialog :visible.sync="dialogVisible" title="添加选项" @commit="addNode" />
+    <icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" />
+  </div>
+</template>
+
+<script>
+import { isArray } from 'util'
+import draggable from 'vuedraggable'
+import TreeNodeDialog from './TreeNodeDialog'
+import { isNumberStr } from '@/utils/index'
+import IconsDialog from './IconsDialog'
+import {
+  inputComponents,
+  selectComponents,
+  layoutComponents
+} from '@/utils/generator/config'
+
+const dateTimeFormat = {
+  date: 'yyyy-MM-dd',
+  week: 'yyyy 第 WW 周',
+  month: 'yyyy-MM',
+  year: 'yyyy',
+  datetime: 'yyyy-MM-dd HH:mm:ss',
+  daterange: 'yyyy-MM-dd',
+  monthrange: 'yyyy-MM',
+  datetimerange: 'yyyy-MM-dd HH:mm:ss'
+}
+
+export default {
+  components: {
+    draggable,
+    TreeNodeDialog,
+    IconsDialog
+  },
+  props: ['showField', 'activeData', 'formConf'],
+  data() {
+    return {
+      currentTab: 'field',
+      currentNode: null,
+      dialogVisible: false,
+      iconsVisible: false,
+      currentIconModel: null,
+      dateTypeOptions: [
+        {
+          label: '日(date)',
+          value: 'date'
+        },
+        {
+          label: '周(week)',
+          value: 'week'
+        },
+        {
+          label: '月(month)',
+          value: 'month'
+        },
+        {
+          label: '年(year)',
+          value: 'year'
+        },
+        {
+          label: '日期时间(datetime)',
+          value: 'datetime'
+        }
+      ],
+      dateRangeTypeOptions: [
+        {
+          label: '日期范围(daterange)',
+          value: 'daterange'
+        },
+        {
+          label: '月范围(monthrange)',
+          value: 'monthrange'
+        },
+        {
+          label: '日期时间范围(datetimerange)',
+          value: 'datetimerange'
+        }
+      ],
+      colorFormatOptions: [
+        {
+          label: 'hex',
+          value: 'hex'
+        },
+        {
+          label: 'rgb',
+          value: 'rgb'
+        },
+        {
+          label: 'rgba',
+          value: 'rgba'
+        },
+        {
+          label: 'hsv',
+          value: 'hsv'
+        },
+        {
+          label: 'hsl',
+          value: 'hsl'
+        }
+      ],
+      justifyOptions: [
+        {
+          label: 'start',
+          value: 'start'
+        },
+        {
+          label: 'end',
+          value: 'end'
+        },
+        {
+          label: 'center',
+          value: 'center'
+        },
+        {
+          label: 'space-around',
+          value: 'space-around'
+        },
+        {
+          label: 'space-between',
+          value: 'space-between'
+        }
+      ],
+      layoutTreeProps: {
+        label(data, node) {
+          return data.componentName || `${data.label}: ${data.vModel}`
+        }
+      }
+    }
+  },
+  computed: {
+    documentLink() {
+      return (
+        this.activeData.document
+        || 'https://element.eleme.cn/#/zh-CN/component/installation'
+      )
+    },
+    dateOptions() {
+      if (
+        this.activeData.type !== undefined
+        && this.activeData.tag === 'el-date-picker'
+      ) {
+        if (this.activeData['start-placeholder'] === undefined) {
+          return this.dateTypeOptions
+        }
+        return this.dateRangeTypeOptions
+      }
+      return []
+    },
+    tagList() {
+      return [
+        {
+          label: '输入型组件',
+          options: inputComponents
+        },
+        {
+          label: '选择型组件',
+          options: selectComponents
+        }
+      ]
+    }
+  },
+  methods: {
+    addReg() {
+      this.activeData.regList.push({
+        pattern: '',
+        message: ''
+      })
+    },
+    addSelectItem() {
+      this.activeData.options.push({
+        label: '',
+        value: ''
+      })
+    },
+    addTreeItem() {
+      ++this.idGlobal
+      this.dialogVisible = true
+      this.currentNode = this.activeData.options
+    },
+    renderContent(h, { node, data, store }) {
+      return (
+        <div class="custom-tree-node">
+          <span>{node.label}</span>
+          <span class="node-operation">
+            <i on-click={() => this.append(data)}
+              class="el-icon-plus"
+              title="添加"
+            ></i>
+            <i on-click={() => this.remove(node, data)}
+              class="el-icon-delete"
+              title="删除"
+            ></i>
+          </span>
+        </div>
+      )
+    },
+    append(data) {
+      if (!data.children) {
+        this.$set(data, 'children', [])
+      }
+      this.dialogVisible = true
+      this.currentNode = data.children
+    },
+    remove(node, data) {
+      const { parent } = node
+      const children = parent.data.children || parent.data
+      const index = children.findIndex(d => d.id === data.id)
+      children.splice(index, 1)
+    },
+    addNode(data) {
+      this.currentNode.push(data)
+    },
+    setOptionValue(item, val) {
+      item.value = isNumberStr(val) ? +val : val
+    },
+    setDefaultValue(val) {
+      if (Array.isArray(val)) {
+        return val.join(',')
+      }
+      if (['string', 'number'].indexOf(val) > -1) {
+        return val
+      }
+      if (typeof val === 'boolean') {
+        return `${val}`
+      }
+      return val
+    },
+    onDefaultValueInput(str) {
+      if (isArray(this.activeData.defaultValue)) {
+        // 数组
+        this.$set(
+          this.activeData,
+          'defaultValue',
+          str.split(',').map(val => (isNumberStr(val) ? +val : val))
+        )
+      } else if (['true', 'false'].indexOf(str) > -1) {
+        // 布尔
+        this.$set(this.activeData, 'defaultValue', JSON.parse(str))
+      } else {
+        // 字符串和数字
+        this.$set(
+          this.activeData,
+          'defaultValue',
+          isNumberStr(str) ? +str : str
+        )
+      }
+    },
+    onSwitchValueInput(val, name) {
+      if (['true', 'false'].indexOf(val) > -1) {
+        this.$set(this.activeData, name, JSON.parse(val))
+      } else {
+        this.$set(this.activeData, name, isNumberStr(val) ? +val : val)
+      }
+    },
+    setTimeValue(val, type) {
+      const valueFormat = type === 'week' ? dateTimeFormat.date : val
+      this.$set(this.activeData, 'defaultValue', null)
+      this.$set(this.activeData, 'value-format', valueFormat)
+      this.$set(this.activeData, 'format', val)
+    },
+    spanChange(val) {
+      this.formConf.span = val
+    },
+    multipleChange(val) {
+      this.$set(this.activeData, 'defaultValue', val ? [] : '')
+    },
+    dateTypeChange(val) {
+      this.setTimeValue(dateTimeFormat[val], val)
+    },
+    rangeChange(val) {
+      this.$set(
+        this.activeData,
+        'defaultValue',
+        val ? [this.activeData.min, this.activeData.max] : this.activeData.min
+      )
+    },
+    rateTextChange(val) {
+      if (val) this.activeData['show-score'] = false
+    },
+    rateScoreChange(val) {
+      if (val) this.activeData['show-text'] = false
+    },
+    colorFormatChange(val) {
+      this.activeData.defaultValue = null
+      this.activeData['show-alpha'] = val.indexOf('a') > -1
+      this.activeData.renderKey = +new Date() // 更新renderKey,重新渲染该组件
+    },
+    openIconsDialog(model) {
+      this.iconsVisible = true
+      this.currentIconModel = model
+    },
+    setIcon(val) {
+      this.activeData[this.currentIconModel] = val
+    },
+    tagChange(tagIcon) {
+      let target = inputComponents.find(item => item.tagIcon === tagIcon)
+      if (!target) target = selectComponents.find(item => item.tagIcon === tagIcon)
+      this.$emit('tag-change', target)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.right-board {
+  width: 350px;
+  position: absolute;
+  right: 0;
+  top: 0;
+  padding-top: 3px;
+  .field-box {
+    position: relative;
+    height: calc(100vh - 42px);
+    box-sizing: border-box;
+    overflow: hidden;
+  }
+  .el-scrollbar {
+    height: 100%;
+  }
+}
+.select-item {
+  display: flex;
+  border: 1px dashed #fff;
+  box-sizing: border-box;
+  & .close-btn {
+    cursor: pointer;
+    color: #f56c6c;
+  }
+  & .el-input + .el-input {
+    margin-left: 4px;
+  }
+}
+.select-item + .select-item {
+  margin-top: 4px;
+}
+.select-item.sortable-chosen {
+  border: 1px dashed #409eff;
+}
+.select-line-icon {
+  line-height: 32px;
+  font-size: 22px;
+  padding: 0 4px;
+  color: #777;
+}
+.option-drag {
+  cursor: move;
+}
+.time-range {
+  .el-date-editor {
+    width: 227px;
+  }
+  ::v-deep .el-icon-time {
+    display: none;
+  }
+}
+.document-link {
+  position: absolute;
+  display: block;
+  width: 26px;
+  height: 26px;
+  top: 0;
+  left: 0;
+  cursor: pointer;
+  background: #409eff;
+  z-index: 1;
+  border-radius: 0 0 6px 0;
+  text-align: center;
+  line-height: 26px;
+  color: #fff;
+  font-size: 18px;
+}
+.node-label{
+  font-size: 14px;
+}
+.node-icon{
+  color: #bebfc3;
+}
+</style>

+ 149 - 0
ruoyi-ui-wuguan/src/api/tool/build/TreeNodeDialog.vue

@@ -0,0 +1,149 @@
+<template>
+  <div>
+    <el-dialog
+      v-bind="$attrs"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      v-on="$listeners"
+      @open="onOpen"
+      @close="onClose"
+    >
+      <el-row :gutter="0">
+        <el-form
+          ref="elForm"
+          :model="formData"
+          :rules="rules"
+          size="small"
+          label-width="100px"
+        >
+          <el-col :span="24">
+            <el-form-item
+              label="选项名"
+              prop="label"
+            >
+              <el-input
+                v-model="formData.label"
+                placeholder="请输入选项名"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item
+              label="选项值"
+              prop="value"
+            >
+              <el-input
+                v-model="formData.value"
+                placeholder="请输入选项值"
+                clearable
+              >
+                <el-select
+                  slot="append"
+                  v-model="dataType"
+                  :style="{width: '100px'}"
+                >
+                  <el-option
+                    v-for="(item, index) in dataTypeOptions"
+                    :key="index"
+                    :label="item.label"
+                    :value="item.value"
+                    :disabled="item.disabled"
+                  />
+                </el-select>
+              </el-input>
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </el-row>
+      <div slot="footer">
+        <el-button
+          type="primary"
+          @click="handleConfirm"
+        >
+          确定
+        </el-button>
+        <el-button @click="close">
+          取消
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { isNumberStr } from '@/utils/index'
+
+export default {
+  components: {},
+  inheritAttrs: false,
+  props: [],
+  data() {
+    return {
+      id: 100,
+      formData: {
+        label: undefined,
+        value: undefined
+      },
+      rules: {
+        label: [
+          {
+            required: true,
+            message: '请输入选项名',
+            trigger: 'blur'
+          }
+        ],
+        value: [
+          {
+            required: true,
+            message: '请输入选项值',
+            trigger: 'blur'
+          }
+        ]
+      },
+      dataType: 'string',
+      dataTypeOptions: [
+        {
+          label: '字符串',
+          value: 'string'
+        },
+        {
+          label: '数字',
+          value: 'number'
+        }
+      ]
+    }
+  },
+  computed: {},
+  watch: {
+    // eslint-disable-next-line func-names
+    'formData.value': function (val) {
+      this.dataType = isNumberStr(val) ? 'number' : 'string'
+    }
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    onOpen() {
+      this.formData = {
+        label: undefined,
+        value: undefined
+      }
+    },
+    onClose() {},
+    close() {
+      this.$emit('update:visible', false)
+    },
+    handleConfirm() {
+      this.$refs.elForm.validate(valid => {
+        if (!valid) return
+        if (this.dataType === 'number') {
+          this.formData.value = parseFloat(this.formData.value)
+        }
+        this.formData.id = this.id++
+        this.$emit('commit', this.formData)
+        this.close()
+      })
+    }
+  }
+}
+</script>

+ 768 - 0
ruoyi-ui-wuguan/src/api/tool/build/index.vue

@@ -0,0 +1,768 @@
+<template>
+  <div class="container">
+    <div class="left-board">
+      <div class="logo-wrapper">
+        <div class="logo">
+          <img :src="logo" alt="logo"> Form Generator
+        </div>
+      </div>
+      <el-scrollbar class="left-scrollbar">
+        <div class="components-list">
+          <div class="components-title">
+            <svg-icon icon-class="component" />输入型组件
+          </div>
+          <draggable
+            class="components-draggable"
+            :list="inputComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
+            :clone="cloneComponent"
+            draggable=".components-item"
+            :sort="false"
+            @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in inputComponents" :key="index" class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+          <div class="components-title">
+            <svg-icon icon-class="component" />选择型组件
+          </div>
+          <draggable
+            class="components-draggable"
+            :list="selectComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
+            :clone="cloneComponent"
+            draggable=".components-item"
+            :sort="false"
+            @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in selectComponents"
+              :key="index"
+              class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+          <div class="components-title">
+            <svg-icon icon-class="component" /> 布局型组件
+          </div>
+          <draggable
+            class="components-draggable" :list="layoutComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent"
+            draggable=".components-item" :sort="false" @end="onEnd"
+          >
+            <div
+              v-for="(element, index) in layoutComponents" :key="index" class="components-item"
+              @click="addComponent(element)"
+            >
+              <div class="components-body">
+                <svg-icon :icon-class="element.tagIcon" />
+                {{ element.label }}
+              </div>
+            </div>
+          </draggable>
+        </div>
+      </el-scrollbar>
+    </div>
+
+    <div class="center-board">
+      <div class="action-bar">
+        <el-button icon="el-icon-download" type="text" @click="download">
+          导出vue文件
+        </el-button>
+        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
+          复制代码
+        </el-button>
+        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
+          清空
+        </el-button>
+      </div>
+      <el-scrollbar class="center-scrollbar">
+        <el-row class="center-board-row" :gutter="formConf.gutter">
+          <el-form
+            :size="formConf.size"
+            :label-position="formConf.labelPosition"
+            :disabled="formConf.disabled"
+            :label-width="formConf.labelWidth + 'px'"
+          >
+            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
+              <draggable-item
+                v-for="(element, index) in drawingList"
+                :key="element.renderKey"
+                :drawing-list="drawingList"
+                :element="element"
+                :index="index"
+                :active-id="activeId"
+                :form-conf="formConf"
+                @activeItem="activeFormItem"
+                @copyItem="drawingItemCopy"
+                @deleteItem="drawingItemDelete"
+              />
+            </draggable>
+            <div v-show="!drawingList.length" class="empty-info">
+              从左侧拖入或点选组件进行表单设计
+            </div>
+          </el-form>
+        </el-row>
+      </el-scrollbar>
+    </div>
+
+    <right-panel
+      :active-data="activeData"
+      :form-conf="formConf"
+      :show-field="!!drawingList.length"
+      @tag-change="tagChange"
+    />
+
+    <code-type-dialog
+      :visible.sync="dialogVisible"
+      title="选择生成类型"
+      :show-file-name="showFileName"
+      @confirm="generate"
+    />
+    <input id="copyNode" type="hidden">
+  </div>
+</template>
+
+<script>
+import draggable from 'vuedraggable'
+import beautifier from 'js-beautify'
+import ClipboardJS from 'clipboard'
+import render from '@/utils/generator/render'
+import RightPanel from './RightPanel'
+import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config'
+import { beautifierConf, titleCase } from '@/utils/index'
+import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
+import { makeUpJs } from '@/utils/generator/js'
+import { makeUpCss } from '@/utils/generator/css'
+import drawingDefault from '@/utils/generator/drawingDefault'
+import logo from '@/assets/logo/logo.png'
+import CodeTypeDialog from './CodeTypeDialog'
+import DraggableItem from './DraggableItem'
+
+let oldActiveId
+let tempActiveData
+
+export default {
+  components: {
+    draggable,
+    render,
+    RightPanel,
+    CodeTypeDialog,
+    DraggableItem
+  },
+  data() {
+    return {
+      logo,
+      idGlobal: 100,
+      formConf,
+      inputComponents,
+      selectComponents,
+      layoutComponents,
+      labelWidth: 100,
+      drawingList: drawingDefault,
+      drawingData: {},
+      activeId: drawingDefault[0].formId,
+      drawerVisible: false,
+      formData: {},
+      dialogVisible: false,
+      generateConf: null,
+      showFileName: false,
+      activeData: drawingDefault[0]
+    }
+  },
+  created() {
+    // 防止 firefox 下 拖拽 会新打卡一个选项卡
+    document.body.ondrop = event => {
+      event.preventDefault()
+      event.stopPropagation()
+    }
+  },
+  watch: {
+    // eslint-disable-next-line func-names
+    'activeData.label': function (val, oldVal) {
+      if (
+        this.activeData.placeholder === undefined
+        || !this.activeData.tag
+        || oldActiveId !== this.activeId
+      ) {
+        return
+      }
+      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
+    },
+    activeId: {
+      handler(val) {
+        oldActiveId = val
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    const clipboard = new ClipboardJS('#copyNode', {
+      text: trigger => {
+        const codeStr = this.generateCode()
+        this.$notify({
+          title: '成功',
+          message: '代码已复制到剪切板,可粘贴。',
+          type: 'success'
+        })
+        return codeStr
+      }
+    })
+    clipboard.on('error', e => {
+      this.$message.error('代码复制失败')
+    })
+  },
+  methods: {
+    activeFormItem(element) {
+      this.activeData = element
+      this.activeId = element.formId
+    },
+    onEnd(obj, a) {
+      if (obj.from !== obj.to) {
+        this.activeData = tempActiveData
+        this.activeId = this.idGlobal
+      }
+    },
+    addComponent(item) {
+      const clone = this.cloneComponent(item)
+      this.drawingList.push(clone)
+      this.activeFormItem(clone)
+    },
+    cloneComponent(origin) {
+      const clone = JSON.parse(JSON.stringify(origin))
+      clone.formId = ++this.idGlobal
+      clone.span = formConf.span
+      clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件
+      if (!clone.layout) clone.layout = 'colFormItem'
+      if (clone.layout === 'colFormItem') {
+        clone.vModel = `field${this.idGlobal}`
+        clone.placeholder !== undefined && (clone.placeholder += clone.label)
+        tempActiveData = clone
+      } else if (clone.layout === 'rowFormItem') {
+        delete clone.label
+        clone.componentName = `row${this.idGlobal}`
+        clone.gutter = this.formConf.gutter
+        tempActiveData = clone
+      }
+      return tempActiveData
+    },
+    AssembleFormData() {
+      this.formData = {
+        fields: JSON.parse(JSON.stringify(this.drawingList)),
+        ...this.formConf
+      }
+    },
+    generate(data) {
+      const func = this[`exec${titleCase(this.operationType)}`]
+      this.generateConf = data
+      func && func(data)
+    },
+    execRun(data) {
+      this.AssembleFormData()
+      this.drawerVisible = true
+    },
+    execDownload(data) {
+      const codeStr = this.generateCode()
+      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
+      this.$download.saveAs(blob, data.fileName)
+    },
+    execCopy(data) {
+      document.getElementById('copyNode').click()
+    },
+    empty() {
+      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
+        () => {
+          this.drawingList = []
+        }
+      )
+    },
+    drawingItemCopy(item, parent) {
+      let clone = JSON.parse(JSON.stringify(item))
+      clone = this.createIdAndKey(clone)
+      parent.push(clone)
+      this.activeFormItem(clone)
+    },
+    createIdAndKey(item) {
+      item.formId = ++this.idGlobal
+      item.renderKey = +new Date()
+      if (item.layout === 'colFormItem') {
+        item.vModel = `field${this.idGlobal}`
+      } else if (item.layout === 'rowFormItem') {
+        item.componentName = `row${this.idGlobal}`
+      }
+      if (Array.isArray(item.children)) {
+        item.children = item.children.map(childItem => this.createIdAndKey(childItem))
+      }
+      return item
+    },
+    drawingItemDelete(index, parent) {
+      parent.splice(index, 1)
+      this.$nextTick(() => {
+        const len = this.drawingList.length
+        if (len) {
+          this.activeFormItem(this.drawingList[len - 1])
+        }
+      })
+    },
+    generateCode() {
+      const { type } = this.generateConf
+      this.AssembleFormData()
+      const script = vueScript(makeUpJs(this.formData, type))
+      const html = vueTemplate(makeUpHtml(this.formData, type))
+      const css = cssStyle(makeUpCss(this.formData))
+      return beautifier.html(html + script + css, beautifierConf.html)
+    },
+    download() {
+      this.dialogVisible = true
+      this.showFileName = true
+      this.operationType = 'download'
+    },
+    run() {
+      this.dialogVisible = true
+      this.showFileName = false
+      this.operationType = 'run'
+    },
+    copy() {
+      this.dialogVisible = true
+      this.showFileName = false
+      this.operationType = 'copy'
+    },
+    tagChange(newTag) {
+      newTag = this.cloneComponent(newTag)
+      newTag.vModel = this.activeData.vModel
+      newTag.formId = this.activeId
+      newTag.span = this.activeData.span
+      delete this.activeData.tag
+      delete this.activeData.tagIcon
+      delete this.activeData.document
+      Object.keys(newTag).forEach(key => {
+        if (this.activeData[key] !== undefined
+          && typeof this.activeData[key] === typeof newTag[key]) {
+          newTag[key] = this.activeData[key]
+        }
+      })
+      this.activeData = newTag
+      this.updateDrawingList(newTag, this.drawingList)
+    },
+    updateDrawingList(newTag, list) {
+      const index = list.findIndex(item => item.formId === this.activeId)
+      if (index > -1) {
+        list.splice(index, 1, newTag)
+      } else {
+        list.forEach(item => {
+          if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang='scss'>
+.editor-tabs{
+  background: #121315;
+  .el-tabs__header{
+    margin: 0;
+    border-bottom-color: #121315;
+    .el-tabs__nav{
+      border-color: #121315;
+    }
+  }
+  .el-tabs__item{
+    height: 32px;
+    line-height: 32px;
+    color: #888a8e;
+    border-left: 1px solid #121315 !important;
+    background: #363636;
+    margin-right: 5px;
+    user-select: none;
+  }
+  .el-tabs__item.is-active{
+    background: #1e1e1e;
+    border-bottom-color: #1e1e1e!important;
+    color: #fff;
+  }
+  .el-icon-edit{
+    color: #f1fa8c;
+  }
+  .el-icon-document{
+    color: #a95812;
+  }
+}
+
+// home
+.right-scrollbar {
+  .el-scrollbar__view {
+    padding: 12px 18px 15px 15px;
+  }
+}
+.left-scrollbar .el-scrollbar__wrap {
+  box-sizing: border-box;
+  overflow-x: hidden !important;
+  margin-bottom: 0 !important;
+}
+.center-tabs{
+  .el-tabs__header{
+    margin-bottom: 0!important;
+  }
+  .el-tabs__item{
+    width: 50%;
+    text-align: center;
+  }
+  .el-tabs__nav{
+    width: 100%;
+  }
+}
+.reg-item{
+  padding: 12px 6px;
+  background: #f8f8f8;
+  position: relative;
+  border-radius: 4px;
+  .close-btn{
+    position: absolute;
+    right: -6px;
+    top: -6px;
+    display: block;
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    background: rgba(0, 0, 0, 0.2);
+    border-radius: 50%;
+    color: #fff;
+    text-align: center;
+    z-index: 1;
+    cursor: pointer;
+    font-size: 12px;
+    &:hover{
+      background: rgba(210, 23, 23, 0.5)
+    }
+  }
+  & + .reg-item{
+    margin-top: 18px;
+  }
+}
+.action-bar{
+  & .el-button+.el-button {
+    margin-left: 15px;
+  }
+  & i {
+    font-size: 20px;
+    vertical-align: middle;
+    position: relative;
+    top: -1px;
+  }
+}
+
+.custom-tree-node{
+  width: 100%;
+  font-size: 14px;
+  .node-operation{
+    float: right;
+  }
+  i[class*="el-icon"] + i[class*="el-icon"]{
+    margin-left: 6px;
+  }
+  .el-icon-plus{
+    color: #409EFF;
+  }
+  .el-icon-delete{
+    color: #157a0c;
+  }
+}
+
+.left-scrollbar .el-scrollbar__view{
+  overflow-x: hidden;
+}
+
+.el-rate{
+  display: inline-block;
+  vertical-align: text-top;
+}
+.el-upload__tip{
+  line-height: 1.2;
+}
+
+$selectedColor: #f6f7ff;
+$lighterBlue: #409EFF;
+
+.container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.components-list {
+  padding: 8px;
+  box-sizing: border-box;
+  height: 100%;
+  .components-item {
+    display: inline-block;
+    width: 48%;
+    margin: 1%;
+    transition: transform 0ms !important;
+  }
+}
+.components-draggable{
+  padding-bottom: 20px;
+}
+.components-title{
+  font-size: 14px;
+  color: #222;
+  margin: 6px 2px;
+  .svg-icon{
+    color: #666;
+    font-size: 18px;
+  }
+}
+
+.components-body {
+  padding: 8px 10px;
+  background: $selectedColor;
+  font-size: 12px;
+  cursor: move;
+  border: 1px dashed $selectedColor;
+  border-radius: 3px;
+  .svg-icon{
+    color: #777;
+    font-size: 15px;
+  }
+  &:hover {
+    border: 1px dashed #787be8;
+    color: #787be8;
+    .svg-icon {
+      color: #787be8;
+    }
+  }
+}
+
+.left-board {
+  width: 260px;
+  position: absolute;
+  left: 0;
+  top: 0;
+  height: 100vh;
+}
+.left-scrollbar{
+  height: calc(100vh - 42px);
+  overflow: hidden;
+}
+.center-scrollbar {
+  height: calc(100vh - 42px);
+  overflow: hidden;
+  border-left: 1px solid #f1e8e8;
+  border-right: 1px solid #f1e8e8;
+  box-sizing: border-box;
+}
+.center-board {
+  height: 100vh;
+  width: auto;
+  margin: 0 350px 0 260px;
+  box-sizing: border-box;
+}
+.empty-info{
+  position: absolute;
+  top: 46%;
+  left: 0;
+  right: 0;
+  text-align: center;
+  font-size: 18px;
+  color: #ccb1ea;
+  letter-spacing: 4px;
+}
+.action-bar{
+  position: relative;
+  height: 42px;
+  text-align: right;
+  padding: 0 15px;
+  box-sizing: border-box;;
+  border: 1px solid #f1e8e8;
+  border-top: none;
+  border-left: none;
+  .delete-btn{
+    color: #F56C6C;
+  }
+}
+.logo-wrapper{
+  position: relative;
+  height: 42px;
+  background: #fff;
+  border-bottom: 1px solid #f1e8e8;
+  box-sizing: border-box;
+}
+.logo{
+  position: absolute;
+  left: 12px;
+  top: 6px;
+  line-height: 30px;
+  color: #00afff;
+  font-weight: 600;
+  font-size: 17px;
+  white-space: nowrap;
+  > img{
+    width: 30px;
+    height: 30px;
+    vertical-align: top;
+  }
+  .github{
+    display: inline-block;
+    vertical-align: sub;
+    margin-left: 15px;
+    > img{
+      height: 22px;
+    }
+  }
+}
+
+.center-board-row {
+  padding: 12px 12px 15px 12px;
+  box-sizing: border-box;
+  & > .el-form {
+    // 69 = 12+15+42
+    height: calc(100vh - 69px);
+  }
+}
+.drawing-board {
+  height: 100%;
+  position: relative;
+  .components-body {
+    padding: 0;
+    margin: 0;
+    font-size: 0;
+  }
+  .sortable-ghost {
+    position: relative;
+    display: block;
+    overflow: hidden;
+    &::before {
+      content: " ";
+      position: absolute;
+      left: 0;
+      right: 0;
+      top: 0;
+      height: 3px;
+      background: rgb(89, 89, 223);
+      z-index: 2;
+    }
+  }
+  .components-item.sortable-ghost {
+    width: 100%;
+    height: 60px;
+    background-color: $selectedColor;
+  }
+  .active-from-item {
+    & > .el-form-item{
+      background: $selectedColor;
+      border-radius: 6px;
+    }
+    & > .drawing-item-copy, & > .drawing-item-delete{
+      display: initial;
+    }
+    & > .component-name{
+      color: $lighterBlue;
+    }
+  }
+  .el-form-item{
+    margin-bottom: 15px;
+  }
+}
+.drawing-item{
+  position: relative;
+  cursor: move;
+  &.unfocus-bordered:not(.activeFromItem) > div:first-child  {
+    border: 1px dashed #ccc;
+  }
+  .el-form-item{
+    padding: 12px 10px;
+  }
+}
+.drawing-row-item{
+  position: relative;
+  cursor: move;
+  box-sizing: border-box;
+  border: 1px dashed #ccc;
+  border-radius: 3px;
+  padding: 0 2px;
+  margin-bottom: 15px;
+  .drawing-row-item {
+    margin-bottom: 2px;
+  }
+  .el-col{
+    margin-top: 22px;
+  }
+  .el-form-item{
+    margin-bottom: 0;
+  }
+  .drag-wrapper{
+    min-height: 80px;
+  }
+  &.active-from-item{
+    border: 1px dashed $lighterBlue;
+  }
+  .component-name{
+    position: absolute;
+    top: 0;
+    left: 0;
+    font-size: 12px;
+    color: #bbb;
+    display: inline-block;
+    padding: 0 6px;
+  }
+}
+.drawing-item, .drawing-row-item{
+  &:hover {
+    & > .el-form-item{
+      background: $selectedColor;
+      border-radius: 6px;
+    }
+    & > .drawing-item-copy, & > .drawing-item-delete{
+      display: initial;
+    }
+  }
+  & > .drawing-item-copy, & > .drawing-item-delete{
+    display: none;
+    position: absolute;
+    top: -10px;
+    width: 22px;
+    height: 22px;
+    line-height: 22px;
+    text-align: center;
+    border-radius: 50%;
+    font-size: 12px;
+    border: 1px solid;
+    cursor: pointer;
+    z-index: 1;
+  }
+  & > .drawing-item-copy{
+    right: 56px;
+    border-color: $lighterBlue;
+    color: $lighterBlue;
+    background: #fff;
+    &:hover{
+      background: $lighterBlue;
+      color: #fff;
+    }
+  }
+  & > .drawing-item-delete{
+    right: 24px;
+    border-color: #F56C6C;
+    color: #F56C6C;
+    background: #fff;
+    &:hover{
+      background: #F56C6C;
+      color: #fff;
+    }
+  }
+}
+</style>

+ 4 - 4
ruoyi-ui-wuguan/src/api/tool/gen.js

@@ -28,8 +28,8 @@ export function getGenTable(tableId) {
 // 修改代码生成信息
 export function updateGenTable(data) {
   return request({
-    url: '/tool/gen/put',
-    method: 'post',
+    url: '/tool/gen',
+    method: 'put',
     data: data
   })
 }
@@ -54,8 +54,8 @@ export function previewTable(tableId) {
 // 删除表数据
 export function delTable(tableId) {
   return request({
-    url: '/tool/gen/delete/' + tableId,
-    method: 'get'
+    url: '/tool/gen/' + tableId,
+    method: 'delete'
   })
 }
 

+ 60 - 0
ruoyi-ui-wuguan/src/api/tool/gen/basicInfoForm.vue

@@ -0,0 +1,60 @@
+<template>
+  <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item label="表名称" prop="tableName">
+          <el-input placeholder="请输入仓库名称" v-model="info.tableName" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="表描述" prop="tableComment">
+          <el-input placeholder="请输入" v-model="info.tableComment" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="实体类名称" prop="className">
+          <el-input placeholder="请输入" v-model="info.className" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="作者" prop="functionAuthor">
+          <el-input placeholder="请输入" v-model="info.functionAuthor" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="备注" prop="remark">
+          <el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+export default {
+  props: {
+    info: {
+      type: Object,
+      default: null
+    }
+  },
+  data() {
+    return {
+      rules: {
+        tableName: [
+          { required: true, message: "请输入表名称", trigger: "blur" }
+        ],
+        tableComment: [
+          { required: true, message: "请输入表描述", trigger: "blur" }
+        ],
+        className: [
+          { required: true, message: "请输入实体类名称", trigger: "blur" }
+        ],
+        functionAuthor: [
+          { required: true, message: "请输入作者", trigger: "blur" }
+        ]
+      }
+    };
+  }
+};
+</script>

+ 45 - 0
ruoyi-ui-wuguan/src/api/tool/gen/createTable.vue

@@ -0,0 +1,45 @@
+<template>
+  <!-- 创建表 -->
+  <el-dialog title="创建表" :visible.sync="visible" width="800px" top="5vh" append-to-body>
+    <span>创建表语句(支持多个建表语句):</span>
+    <el-input type="textarea" :rows="10" placeholder="请输入文本" v-model="content"></el-input>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="handleCreateTable">确 定</el-button>
+      <el-button @click="visible = false">取 消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { createTable } from "@/api/tool/gen";
+export default {
+  data() {
+    return {
+      // 遮罩层
+      visible: false,
+      // 文本内容
+      content: ""
+    };
+  },
+  methods: {
+    // 显示弹框
+    show() {
+      this.visible = true;
+    },
+    /** 创建按钮操作 */
+    handleCreateTable() {
+      if (this.content === "") {
+        this.$modal.msgError("请输入建表语句");
+        return;
+      }
+      createTable({ sql: this.content }).then(res => {
+        this.$modal.msgSuccess(res.msg);
+        if (res.code === 200) {
+          this.visible = false;
+          this.$emit("ok");
+        }
+      });
+    }
+  }
+};
+</script>

+ 234 - 0
ruoyi-ui-wuguan/src/api/tool/gen/editTable.vue

@@ -0,0 +1,234 @@
+<template>
+  <el-card>
+    <el-tabs v-model="activeName">
+      <el-tab-pane label="基本信息" name="basic">
+        <basic-info-form ref="basicInfo" :info="info" />
+      </el-tab-pane>
+      <el-tab-pane label="字段信息" name="columnInfo">
+        <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
+          <el-table-column label="序号" type="index" min-width="5%" class-name="allowDrag" />
+          <el-table-column
+            label="字段列名"
+            prop="columnName"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="字段描述" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.columnComment"></el-input>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="物理类型"
+            prop="columnType"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="Java类型" min-width="11%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.javaType">
+                <el-option label="Long" value="Long" />
+                <el-option label="String" value="String" />
+                <el-option label="Integer" value="Integer" />
+                <el-option label="Double" value="Double" />
+                <el-option label="BigDecimal" value="BigDecimal" />
+                <el-option label="Date" value="Date" />
+                <el-option label="Boolean" value="Boolean" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="java属性" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.javaField"></el-input>
+            </template>
+          </el-table-column>
+
+          <el-table-column label="插入" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isInsert"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="编辑" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isEdit"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="列表" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isList"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="查询" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isQuery"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="查询方式" min-width="10%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.queryType">
+                <el-option label="=" value="EQ" />
+                <el-option label="!=" value="NE" />
+                <el-option label=">" value="GT" />
+                <el-option label=">=" value="GTE" />
+                <el-option label="<" value="LT" />
+                <el-option label="<=" value="LTE" />
+                <el-option label="LIKE" value="LIKE" />
+                <el-option label="BETWEEN" value="BETWEEN" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="必填" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="1" false-label="0" v-model="scope.row.isRequired"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="显示类型" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.htmlType">
+                <el-option label="文本框" value="input" />
+                <el-option label="文本域" value="textarea" />
+                <el-option label="下拉框" value="select" />
+                <el-option label="单选框" value="radio" />
+                <el-option label="复选框" value="checkbox" />
+                <el-option label="日期控件" value="datetime" />
+                <el-option label="图片上传" value="imageUpload" />
+                <el-option label="文件上传" value="fileUpload" />
+                <el-option label="富文本控件" value="editor" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="字典类型" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
+                <el-option
+                  v-for="dict in dictOptions"
+                  :key="dict.dictType"
+                  :label="dict.dictName"
+                  :value="dict.dictType">
+                  <span style="float: left">{{ dict.dictName }}</span>
+                  <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
+              </el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-tab-pane>
+      <el-tab-pane label="生成信息" name="genInfo">
+        <gen-info-form ref="genInfo" :info="info" :tables="tables" :menus="menus"/>
+      </el-tab-pane>
+    </el-tabs>
+    <el-form label-width="100px">
+      <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;">
+        <el-button type="primary" @click="submitForm()">提交</el-button>
+        <el-button @click="close()">返回</el-button>
+      </el-form-item>
+    </el-form>
+  </el-card>
+</template>
+
+<script>
+import { getGenTable, updateGenTable } from "@/api/tool/gen";
+import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
+import { listMenu as getMenuTreeselect } from "@/api/system/menu";
+import basicInfoForm from "./basicInfoForm";
+import genInfoForm from "./genInfoForm";
+import Sortable from 'sortablejs'
+
+export default {
+  name: "GenEdit",
+  components: {
+    basicInfoForm,
+    genInfoForm
+  },
+  data() {
+    return {
+      // 选中选项卡的 name
+      activeName: "columnInfo",
+      // 表格的高度
+      tableHeight: document.documentElement.scrollHeight - 245 + "px",
+      // 表信息
+      tables: [],
+      // 表列信息
+      columns: [],
+      // 字典信息
+      dictOptions: [],
+      // 菜单信息
+      menus: [],
+      // 表详细信息
+      info: {}
+    };
+  },
+  created() {
+    const tableId = this.$route.params && this.$route.params.tableId;
+    if (tableId) {
+      // 获取表详细信息
+      getGenTable(tableId).then(res => {
+        this.columns = res.data.rows;
+        this.info = res.data.info;
+        this.tables = res.data.tables;
+      });
+      /** 查询字典下拉列表 */
+      getDictOptionselect().then(response => {
+        this.dictOptions = response.data;
+      });
+      /** 查询菜单下拉列表 */
+      getMenuTreeselect().then(response => {
+        this.menus = this.handleTree(response.data, "menuId");
+      });
+    }
+  },
+  methods: {
+    /** 提交按钮 */
+    submitForm() {
+      const basicForm = this.$refs.basicInfo.$refs.basicInfoForm;
+      const genForm = this.$refs.genInfo.$refs.genInfoForm;
+      Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => {
+        const validateResult = res.every(item => !!item);
+        if (validateResult) {
+          const genTable = Object.assign({}, basicForm.model, genForm.model);
+          genTable.columns = this.columns;
+          genTable.params = {
+            treeCode: genTable.treeCode,
+            treeName: genTable.treeName,
+            treeParentCode: genTable.treeParentCode,
+            parentMenuId: genTable.parentMenuId
+          };
+          updateGenTable(genTable).then(res => {
+            this.$modal.msgSuccess(res.msg);
+            if (res.code === 200) {
+              this.close();
+            }
+          });
+        } else {
+          this.$modal.msgError("表单校验未通过,请重新检查提交内容");
+        }
+      });
+    },
+    getFormPromise(form) {
+      return new Promise(resolve => {
+        form.validate(res => {
+          resolve(res);
+        });
+      });
+    },
+    /** 关闭按钮 */
+    close() {
+      const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: this.$route.query.pageNum } };
+      this.$tab.closeOpenPage(obj);
+    }
+  },
+  mounted() {
+    const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
+    const sortable = Sortable.create(el, {
+      handle: ".allowDrag",
+      onEnd: evt => {
+        const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
+        this.columns.splice(evt.newIndex, 0, targetRow);
+        for (let index in this.columns) {
+          this.columns[index].sort = parseInt(index) + 1;
+        }
+      }
+    });
+  }
+};
+</script>

+ 312 - 0
ruoyi-ui-wuguan/src/api/tool/gen/genInfoForm.vue

@@ -0,0 +1,312 @@
+<template>
+  <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item prop="tplCategory">
+          <span slot="label">生成模板</span>
+          <el-select v-model="info.tplCategory" @change="tplSelectChange">
+            <el-option label="单表(增删改查)" value="crud" />
+            <el-option label="树表(增删改查)" value="tree" />
+            <el-option label="主子表(增删改查)" value="sub" />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item prop="tplWebType">
+          <span slot="label">前端类型</span>
+          <el-select v-model="info.tplWebType">
+            <el-option label="Vue2 Element UI 模版" value="element-ui" />
+            <el-option label="Vue3 Element Plus 模版" value="element-plus" />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item prop="packageName">
+          <span slot="label">
+            生成包路径
+            <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.packageName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="moduleName">
+          <span slot="label">
+            生成模块名
+            <el-tooltip content="可理解为子系统名,例如 system" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.moduleName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="businessName">
+          <span slot="label">
+            生成业务名
+            <el-tooltip content="可理解为功能英文名,例如 user" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.businessName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="functionName">
+          <span slot="label">
+            生成功能名
+            <el-tooltip content="用作类描述,例如 用户" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.functionName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="genType">
+          <span slot="label">
+            生成代码方式
+            <el-tooltip content="默认为zip压缩包下载,也可以自定义生成路径" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-radio v-model="info.genType" label="0">zip压缩包</el-radio>
+          <el-radio v-model="info.genType" label="1">自定义路径</el-radio>
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            上级菜单
+            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <treeselect
+            :append-to-body="true"
+            v-model="info.parentMenuId"
+            :options="menus"
+            :normalizer="normalizer"
+            :show-count="true"
+            placeholder="请选择系统菜单"
+          />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="24" v-if="info.genType == '1'">
+        <el-form-item prop="genPath">
+          <span slot="label">
+            自定义路径
+            <el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.genPath">
+            <el-dropdown slot="append">
+              <el-button type="primary">
+                最近路径快速选择
+                <i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <el-row v-show="info.tplCategory == 'tree'">
+      <h4 class="form-header">其他信息</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树编码字段
+            <el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeCode" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树父编码字段
+            <el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeParentCode" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树名称字段
+            <el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeName" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+    <el-row v-show="info.tplCategory == 'sub'">
+      <h4 class="form-header">关联信息</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            关联子表的表名
+            <el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
+            <el-option
+              v-for="(table, index) in tables"
+              :key="index"
+              :label="table.tableName + ':' + table.tableComment"
+              :value="table.tableName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            子表关联的外键名
+            <el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableFkName" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in subColumns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  components: { Treeselect },
+  props: {
+    info: {
+      type: Object,
+      default: null
+    },
+    tables: {
+      type: Array,
+      default: null
+    },
+    menus: {
+      type: Array,
+      default: []
+    },
+  },
+  data() {
+    return {
+      subColumns: [],
+      rules: {
+        tplCategory: [
+          { required: true, message: "请选择生成模板", trigger: "blur" }
+        ],
+        packageName: [
+          { required: true, message: "请输入生成包路径", trigger: "blur" }
+        ],
+        moduleName: [
+          { required: true, message: "请输入生成模块名", trigger: "blur" }
+        ],
+        businessName: [
+          { required: true, message: "请输入生成业务名", trigger: "blur" }
+        ],
+        functionName: [
+          { required: true, message: "请输入生成功能名", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  watch: {
+    'info.subTableName': function(val) {
+      this.setSubTableColumns(val);
+    },
+    'info.tplWebType': function(val) {
+      if (val === '') {
+        this.info.tplWebType = "element-ui";
+      }
+    }
+  },
+  methods: {
+    /** 转换菜单数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.menuId,
+        label: node.menuName,
+        children: node.children
+      };
+    },
+    /** 选择子表名触发 */
+    subSelectChange(value) {
+      this.info.subTableFkName = '';
+    },
+    /** 选择生成模板触发 */
+    tplSelectChange(value) {
+      if(value !== 'sub') {
+        this.info.subTableName = '';
+        this.info.subTableFkName = '';
+      }
+    },
+    /** 设置关联外键 */
+    setSubTableColumns(value) {
+      for (var item in this.tables) {
+        const name = this.tables[item].tableName;
+        if (value === name) {
+          this.subColumns = this.tables[item].columns;
+          break;
+        }
+      }
+    }
+  }
+};
+</script>

+ 120 - 0
ruoyi-ui-wuguan/src/api/tool/gen/importTable.vue

@@ -0,0 +1,120 @@
+<template>
+  <!-- 导入表 -->
+  <el-dialog title="导入表" :visible.sync="visible" width="800px" top="5vh" append-to-body>
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+      <el-form-item label="表名称" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="请输入表名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="表描述" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="请输入表描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row>
+      <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="createTime" label="创建时间"></el-table-column>
+        <el-table-column prop="updateTime" label="更新时间"></el-table-column>
+      </el-table>
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="handleImportTable">确 定</el-button>
+      <el-button @click="visible = false">取 消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { listDbTable, importTable } from "@/api/tool/gen";
+export default {
+  data() {
+    return {
+      // 遮罩层
+      visible: false,
+      // 选中数组值
+      tables: [],
+      // 总条数
+      total: 0,
+      // 表数据
+      dbTableList: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tableName: undefined,
+        tableComment: undefined
+      }
+    };
+  },
+  methods: {
+    // 显示弹框
+    show() {
+      this.getList();
+      this.visible = true;
+    },
+    clickRow(row) {
+      this.$refs.table.toggleRowSelection(row);
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.tables = selection.map(item => item.tableName);
+    },
+    // 查询表数据
+    getList() {
+      listDbTable(this.queryParams).then(res => {
+        if (res.code === 200) {
+          this.dbTableList = res.rows;
+          this.total = res.total;
+        }
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 导入按钮操作 */
+    handleImportTable() {
+      const tableNames = this.tables.join(",");
+      if (tableNames == "") {
+        this.$modal.msgError("请选择要导入的表");
+        return;
+      }
+      importTable({ tables: tableNames }).then(res => {
+        this.$modal.msgSuccess(res.msg);
+        if (res.code === 200) {
+          this.visible = false;
+          this.$emit("ok");
+        }
+      });
+    }
+  }
+};
+</script>

+ 354 - 0
ruoyi-ui-wuguan/src/api/tool/gen/index.vue

@@ -0,0 +1,354 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="表名称" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="请输入表名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="表描述" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="请输入表描述"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker
+          v-model="dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :disabled="multiple"
+          @click="handleGenTable"
+          v-hasPermi="['tool:gen:code']"
+        >生成</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="openCreateTable"
+          v-hasRole="['admin']"
+        >创建</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-upload"
+          size="mini"
+          @click="openImportTable"
+          v-hasPermi="['tool:gen:import']"
+        >导入</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleEditTable"
+          v-hasPermi="['tool:gen:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['tool:gen:remove']"
+        >删除</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" align="center" width="55"></el-table-column>
+      <el-table-column label="序号" type="index" width="50" align="center">
+        <template slot-scope="scope">
+          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="表名称"
+        align="center"
+        prop="tableName"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column
+        label="表描述"
+        align="center"
+        prop="tableComment"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column
+        label="实体"
+        align="center"
+        prop="className"
+        :show-overflow-tooltip="true"
+        width="120"
+      />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="更新时间" align="center" prop="updateTime" width="160" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-view"
+            @click="handlePreview(scope.row)"
+            v-hasPermi="['tool:gen:preview']"
+          >预览</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-edit"
+            @click="handleEditTable(scope.row)"
+            v-hasPermi="['tool:gen:edit']"
+          >编辑</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['tool:gen:remove']"
+          >删除</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-refresh"
+            @click="handleSynchDb(scope.row)"
+            v-hasPermi="['tool:gen:edit']"
+          >同步</el-button>
+          <el-button
+            type="text"
+            size="small"
+            icon="el-icon-download"
+            @click="handleGenTable(scope.row)"
+            v-hasPermi="['tool:gen:code']"
+          >生成代码</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <!-- 预览界面 -->
+    <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body class="scrollbar">
+      <el-tabs v-model="preview.activeName">
+        <el-tab-pane
+          v-for="(value, key) in preview.data"
+          :label="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
+          :name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
+          :key="key"
+        >
+          <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="value" v-clipboard:success="clipboardSuccess" style="float:right">复制</el-link>
+          <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+    <import-table ref="import" @ok="handleQuery" />
+    <create-table ref="create" @ok="handleQuery" />
+  </div>
+</template>
+
+<script>
+import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/gen";
+import importTable from "./importTable";
+import createTable from "./createTable";
+import hljs from "highlight.js/lib/highlight";
+import "highlight.js/styles/github-gist.css";
+hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
+hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
+hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
+
+export default {
+  name: "Gen",
+  components: { importTable, createTable },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 唯一标识符
+      uniqueId: "",
+      // 选中数组
+      ids: [],
+      // 选中表数组
+      tableNames: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 表数据
+      tableList: [],
+      // 日期范围
+      dateRange: "",
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tableName: undefined,
+        tableComment: undefined
+      },
+      // 预览参数
+      preview: {
+        open: false,
+        title: "代码预览",
+        data: {},
+        activeName: "domain.java"
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  activated() {
+    const time = this.$route.query.t;
+    if (time != null && time != this.uniqueId) {
+      this.uniqueId = time;
+      this.queryParams.pageNum = Number(this.$route.query.pageNum);
+      this.getList();
+    }
+  },
+  methods: {
+    /** 查询表集合 */
+    getList() {
+      this.loading = true;
+      listTable(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+          this.tableList = response.rows;
+          this.total = response.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 生成代码操作 */
+    handleGenTable(row) {
+      const tableNames = row.tableName || this.tableNames;
+      if (tableNames == "") {
+        this.$modal.msgError("请选择要生成的数据");
+        return;
+      }
+      if(row.genType === "1") {
+        genCode(row.tableName).then(response => {
+          this.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath);
+        });
+      } else {
+        this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "ruoyi.zip");
+      }
+    },
+    /** 同步数据库操作 */
+    handleSynchDb(row) {
+      const tableName = row.tableName;
+      this.$modal.confirm('确认要强制同步"' + tableName + '"表结构吗?').then(function() {
+        return synchDb(tableName);
+      }).then(() => {
+        this.$modal.msgSuccess("同步成功");
+      }).catch(() => {});
+    },
+    /** 打开导入表弹窗 */
+    openImportTable() {
+      this.$refs.import.show();
+    },
+    /** 打开创建表弹窗 */
+    openCreateTable() {
+      this.$refs.create.show();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 预览按钮 */
+    handlePreview(row) {
+      previewTable(row.tableId).then(response => {
+        this.preview.data = response.data;
+        this.preview.open = true;
+        this.preview.activeName = "domain.java";
+      });
+    },
+    /** 高亮显示 */
+    highlightedCode(code, key) {
+      const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
+      var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
+      const result = hljs.highlight(language, code || "", true);
+      return result.value || '&nbsp;';
+    },
+    /** 复制代码成功 */
+    clipboardSuccess() {
+      this.$modal.msgSuccess("复制成功");
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.tableId);
+      this.tableNames = selection.map(item => item.tableName);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+    /** 修改按钮操作 */
+    handleEditTable(row) {
+      const tableId = row.tableId || this.ids[0];
+      const tableName = row.tableName || this.tableNames[0];
+      const params = { pageNum: this.queryParams.pageNum };
+      this.$tab.openPage("修改[" + tableName + "]生成配置", '/tool/gen-edit/index/' + tableId, params);
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const tableIds = row.tableId || this.ids;
+      this.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?').then(function() {
+        return delTable(tableIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    }
+  }
+};
+</script>

+ 15 - 0
ruoyi-ui-wuguan/src/api/tool/swagger/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <i-frame :src="url" />
+</template>
+<script>
+import iFrame from "@/components/iFrame/index";
+export default {
+  name: "Swagger",
+  components: { iFrame },
+  data() {
+    return {
+      url: process.env.VUE_APP_BASE_API + "/swagger-ui/index.html"
+    };
+  },
+};
+</script>

+ 45 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/data.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询成绩列表
+export function listData(query) {
+  return request({
+    url: '/score/data/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/score/data/query',
+    method: 'post',
+	data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/score/data/add',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/score/data/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/score/data/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 45 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/dingwei.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询定位信息
+export function listData(query) {
+  return request({
+    url: '/orientation/info/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/score/data/query',
+    method: 'post',
+	data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/system/info/list',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/score/data/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/score/data/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 45 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/gongzt.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询成绩列表
+export function listData(query) {
+  return request({
+    url: '/xiaoYuan/pay/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/xiaoYuan/pay/' + data,
+    method: 'get',
+	// data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/xiaoYuan/pay',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/xiaoYuan/pay/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/xiaoYuan/pay/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 73 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/info.js

@@ -0,0 +1,73 @@
+import request from '@/utils/request'
+
+// 查询学生档案信息列表
+export function listInfo(query) {
+  return request({
+    url: '/student/info/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listInfols(query) {
+  return request({
+    url: '/student/old/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listInfolss(query) {
+  return request({
+    url: '/student/old/echarts',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+export function listInfostu(query) {
+  return request({
+    url: '/system/student/noPage/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+// 查询学生档案信息详细
+export function getInfo(id) {
+  return request({
+    url: '/student/info/' + id,
+    method: 'get'
+  })
+}
+
+// 新增学生档案信息
+export function addInfo(data) {
+  return request({
+    url: '/student/info',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改学生档案信息
+export function updateInfo(data) {
+  return request({
+    url: '/student/info/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除学生档案信息
+export function delInfo(id) {
+  return request({
+    url: '/student/info/delete/' + id,
+    method: 'get'
+  })
+}

+ 115 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/infos.js

@@ -0,0 +1,115 @@
+import request from '@/utils/request'
+
+// 查询学生档案信息列表
+export function listInfo(query) {
+  return request({
+    url: '/student/info/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listInfolsxinl(query) {
+  return request({
+    url: '/mind/old/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listInfols(query) {
+  return request({
+    url: '/live/old/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listInfolss(query) {
+  return request({
+    url: '/student/old/echarts',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+export function listInfostu(query) {
+  return request({
+    url: '/system/student/noPage/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+// 查询学生档案信息详细
+export function getInfo(id) {
+  return request({
+    url: '/student/info/' + id,
+    method: 'get'
+  })
+}
+
+// 新增学生档案信息
+export function addInfo(data) {
+  return request({
+    url: '/student/info',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改学生档案信息
+export function updateInfo(data) {
+  return request({
+    url: '/mind/old',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateInfoxl(data) {
+  return request({
+    url: '/mind/old',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateInfoshg(data) {
+  return request({
+    url: '/live/old',
+    method: 'post',
+    data: data
+  })
+}
+
+
+
+
+
+// 删除学生档案信息
+export function delInfo(id) {
+  return request({
+    url: '/student/info/delete/' + id,
+    method: 'get'
+  })
+}
+
+// 删除学生档案信息
+export function delInfoxinl(id) {
+  return request({
+    url: '/mind/old/delete/' + id,
+    method: 'get'
+  })
+}
+export function delInfoshengao(id) {
+  return request({
+    url: '/live/old/delete/' + id,
+    method: 'get'
+  })
+}

+ 0 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/kchb.js


+ 109 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/notice.js

@@ -0,0 +1,109 @@
+import request from '@/utils/request'
+
+// 查询校园新闻列表
+export function listNotice(query) {
+  return request({
+    url: '/xiaoYuan/notice/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listNoticesc(query) {
+  return request({
+    url: '/xiaoYuan/notice/collect',
+    method: 'get',
+    params: query
+  })
+}
+
+
+export function listNoticef(query) {
+  return request({
+    url: '/xiaoYuan/notice/myList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listNoticefanq(query) {
+  return request({
+    url: '/system/xiaoYuanInfo/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+
+// export function listNoticef(query) {
+//   return request({
+//     url: '/xiaoYuan/notice/myList',
+//     method: 'get',
+//     params: query
+//   })
+// }
+
+
+
+// 查询校园新闻详细
+export function getNotice(noticeId) {
+  return request({
+    url: '/xiaoYuan/notice/' + noticeId,
+    method: 'get'
+  })
+}
+
+// 新增校园新闻
+export function addNotice(data) {
+  return request({
+    url: '/xiaoYuan/notice',
+    method: 'post',
+    data: data
+  })
+}
+
+export function addNotices(data) {
+  return request({
+    url: '/system/xiaoYuanInfo',
+    method: 'post',
+    data: data
+  })
+}
+
+
+
+// 修改校园新闻
+export function updateNotice(data) {
+  return request({
+    url: '/system/xiaoYuanInfo/put',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateNotices(data) {
+  return request({
+    url: '/xiaoYuan/notice/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除校园新闻
+export function delNotice(noticeId) {
+  return request({
+    url: '/xiaoYuan/notice/delete/' + noticeId,
+    method: 'get'
+  })
+}
+
+// 删除安全新闻
+export function delNoticeanq(noticeId) {
+  return request({
+    url: '/system/xiaoYuanInfo/delete/' + noticeId,
+    method: 'get'
+  })
+}

+ 54 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/recipe.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 查询请假记录信息列表
+export function listLeave(query) {
+  return request({
+    url: '/system/recipe/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询请假记录信息详细
+export function getLeave(id) {
+  return request({
+    url: '/system/recipe/' + id,
+    method: 'get'
+  })
+}
+
+// 新增请假记录信息
+export function addLeave(data) {
+  return request({
+    url: '/system/recipe',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改请假记录信息
+export function updateLeave(data) {
+  return request({
+    url: '/system/recipe/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除请假记录信息
+export function delLeave(id) {
+  return request({
+    url: '/system/recipe/delete/' + id,
+    method: 'get'
+  })
+}
+
+export function sh(data) {
+ return request({
+   url: '/system/recipe/sh',
+   method: 'post',
+   data: data
+ })
+}
+
+

+ 54 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/record.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 查询请假记录信息列表
+export function listLeave(query) {
+  return request({
+    url: '/ask/leave/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询请假记录信息详细
+export function getLeave(id) {
+  return request({
+    url: '/ask/leave/' + id,
+    method: 'get'
+  })
+}
+
+// 新增请假记录信息
+export function addLeave(data) {
+  return request({
+    url: '/ask/leave',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改请假记录信息
+export function updateLeave(data) {
+  return request({
+    url: '/ask/leave/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除请假记录信息
+export function delLeave(id) {
+  return request({
+    url: '/ask/leave/delete/' + id,
+    method: 'get'
+  })
+}
+
+export function sh(data) {
+ return request({
+   url: '/ask/leave/sh',
+   method: 'post',
+   data: data
+ })
+}
+
+

+ 71 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/teacherdan.js

@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+// 查询学生档案信息列表
+export function listInfo(query) {
+  return request({
+    url: '/teacher/info/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function jignwe(query) {
+  return request({
+    url: 'https://apis.map.qq.com/ws/geocoder/v1',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listInfostu(query) {
+  return request({
+    url: '/formal/class/noPage/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listInfostutwo(query) {
+  return request({
+    url: '/formal/class/noPage/list',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+
+// 查询学生档案信息详细
+export function getInfo(id) {
+  return request({
+    url: '/teacher/info/' + id,
+    method: 'get'
+  })
+}
+
+// 新增学生档案信息
+export function addInfo(data) {
+  return request({
+    url: '/teacher/info',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改学生档案信息
+export function updateInfo(data) {
+  return request({
+    url: '/teacher/info/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除学生档案信息
+export function delInfo(id) {
+  return request({
+    url: '/teacher/info/delete/' + id,
+    method: 'get'
+  })
+}

+ 107 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/tenant.js

@@ -0,0 +1,107 @@
+import request from '@/utils/request'
+
+// 查询租户列表
+export function listTenant(query) {
+  return request({
+    url: '/system/tenant/list',
+    method: 'get',
+    params: query
+  });
+}
+
+// 查询租户详细
+export function getTenant(id){
+  return request({
+    url: '/system/tenant/' + id,
+    method: 'get'
+  });
+}
+
+// 新增租户
+export function addTenant(data) {
+  return request({
+    url: '/system/tenant',
+    method: 'post',
+    headers: {
+      isEncrypt: true
+    },
+    data: data
+  });
+}
+
+// 修改租户
+export function updateTenant(data) {
+  return request({
+    url: '/system/tenant',
+    method: 'put',
+    data: data
+  });
+}
+
+// 租户状态修改
+export function changeTenantStatus(id, tenantId, status) {
+  const data = {
+    id,
+    tenantId,
+    status
+  };
+  return request({
+    url: '/system/tenant/changeStatus',
+    method: 'put',
+    data: data
+  });
+}
+
+// 删除租户
+export function delTenant(id) {
+  return request({
+    url: '/system/tenant/' + id,
+    method: 'delete'
+  });
+}
+
+// 动态切换租户
+export function dynamicTenant(tenantId) {
+  return request({
+    url: '/system/tenant/dynamic/' + tenantId,
+    method: 'get'
+  });
+}
+
+// 根据动态切换组合2
+export function dynamicTenantgw(data) {
+  return request({
+    url: '/system/tenant/dynamic/loginBody',
+    method: 'post',
+    data: data
+  });
+}
+
+// 清除动态租户
+export function dynamicClear() {
+  return request({
+    url: '/system/tenant/dynamic/clear',
+    method: 'get'
+  });
+}
+
+// 同步租户套餐
+export function syncTenantPackage(tenantId, packageId) {
+  const data = {
+    tenantId,
+    packageId
+  };
+  return request({
+    url: '/system/tenant/syncTenantPackage',
+    method: 'get',
+    params: data
+  });
+}
+// 根据username查询租户信息
+export function userNamet(query) {
+  return request({
+    url: '/system/tenant/userName/list',
+    method: 'get',
+    params: query
+  });
+}

+ 65 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/tenantPackage.js

@@ -0,0 +1,65 @@
+import request from '@/utils/request';
+
+// 查询租户套餐列表
+export function listTenantPackage(query){
+  return request({
+    url: '/system/tenant/package/list',
+    method: 'get',
+    params: query
+  });
+}
+
+// 查询租户套餐下拉选列表
+export function selectTenantPackage() {
+  return request({
+    url: '/system/tenant/package/selectList',
+    method: 'get'
+  });
+}
+
+// 查询租户套餐详细
+export function getTenantPackage(packageId) {
+  return request({
+    url: '/system/tenant/package/' + packageId,
+    method: 'get'
+  });
+}
+
+// 新增租户套餐
+export function addTenantPackage(data) {
+  return request({
+    url: '/system/tenant/package',
+    method: 'post',
+    data: data
+  });
+}
+
+// 修改租户套餐
+export function updateTenantPackage(data) {
+  return request({
+    url: '/system/tenant/package',
+    method: 'put',
+    data: data
+  });
+}
+
+// 租户套餐状态修改
+export function changePackageStatus(packageId, status) {
+  const data = {
+    packageId,
+    status
+  };
+  return request({
+    url: '/system/tenant/package/changeStatus',
+    method: 'put',
+    data: data
+  });
+}
+
+// 删除租户套餐
+export function delTenantPackage(packageId) {
+  return request({
+    url: '/system/tenant/package/' + packageId,
+    method: 'delete'
+  });
+}

+ 61 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/tjxq.js

@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+
+// 查询成绩列表
+export function xuekeRank(data) {
+  return request({
+    url: '/score/data/xuekeRank',
+    method: 'post',
+    data: data
+  })
+}
+
+// 查询成绩详细
+export function gradeRank(data) {
+  return request({
+    url: '/score/data/gradeRank',
+    method: 'post',
+	data: data
+  })
+}
+
+// 新增成绩
+export function classRank(data) {
+  return request({
+    url: '/score/data/classRank',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function avgRank(data) {
+  return request({
+    url: '/score/data/avgRankZheXian',
+    method: 'post',
+    data: data
+  })
+}
+
+export function bingTuRank(data) {
+  return request({
+    url: '/score/data/bingTuRank',
+    method: 'post',
+    data: data
+  })
+}
+
+export function indexList(data) {
+  return request({
+    url: '/score/data/indexList',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/score/data/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 44 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/xiaoYuanInfo.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询校园安全信息列表
+export function listXiaoYuanInfo(query) {
+  return request({
+    url: '/xiaoYuan/info/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询校园安全信息详细
+export function getXiaoYuanInfo(infoId) {
+  return request({
+    url: '/xiaoYuan/info/' + infoId,
+    method: 'get'
+  })
+}
+
+// 新增校园安全信息
+export function addXiaoYuanInfo(data) {
+  return request({
+    url: '/xiaoYuan/info',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改校园安全信息
+export function updateXiaoYuanInfo(data) {
+  return request({
+    url: '/xiaoYuan/info',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除校园安全信息
+export function delXiaoYuanInfo(infoId) {
+  return request({
+    url: '/xiaoYuan/info/delete/' + infoId,
+    method: 'get'
+  })
+}

+ 45 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/yijianfk.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询定位信息
+export function listData(query) {
+  return request({
+    url: '/system/opinion/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/score/data/query',
+    method: 'post',
+	data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/system/opinion',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/system/opinion/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/system/opinion/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 52 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/yuyue.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 查询成绩列表
+export function listData(query) {
+  return request({
+    url: '/system/reservat/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/system/reservat/' + data,
+    method: 'get',
+	// data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/system/reservat',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/system/reservat/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/system/reservat/delete/' + scoreId,
+    method: 'get'
+  })
+}
+export function setPass(data) {
+  return request({
+    url: '/system/reservat/sh',
+    method: 'post',
+    data: data
+  })
+}

+ 45 - 0
ruoyi-ui-wuguan/src/api/zhihuixy/yuyuepzh.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询成绩列表
+export function listData(query) {
+  return request({
+    url: '/system/reservatConfig/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询成绩详细
+export function getData(data) {
+  return request({
+    url: '/system/reservatConfig/' + data,
+    method: 'get',
+	// data: data
+  })
+}
+
+// 新增成绩
+export function addData(data) {
+  return request({
+    url: '/system/reservatConfig',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改成绩
+export function updateData(data) {
+  return request({
+    url: '/system/reservatConfig/put',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除成绩
+export function delData(scoreId) {
+  return request({
+    url: '/system/reservatConfig/delete/' + scoreId,
+    method: 'get'
+  })
+}

+ 29 - 0
ruoyi-ui-wuguan/src/assets/icons/svg/topiam.svg

@@ -0,0 +1,29 @@
+<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_446_540)">
+<path d="M113.069 160.072C103.717 170.743 93.0453 180.216 81.5345 188.609C61.5105 174.46 44.3642 156.595 30.9349 135.971C23.5009 124.46 17.2659 112.11 12.4697 99.0407C9.592 91.3668 7.19392 83.3332 5.27545 75.2996C2.03803 61.3907 0.359375 47.0022 0.359375 32.1341C0.359375 30.6953 0.359375 29.1365 0.359375 27.6977C6.35459 23.9806 12.7095 20.7432 19.0644 17.7456C20.7431 32.1341 24.1004 46.043 28.8966 59.3524C31.6544 66.9063 34.7719 74.3404 38.4889 81.4147C44.604 93.5251 52.0381 104.796 60.4314 115.228C75.1796 133.093 92.9254 148.321 113.069 160.072Z" fill="url(#paint0_linear_446_540)"/>
+<path d="M196.643 67.6256C195.084 76.3786 192.926 84.8918 190.168 93.1652C178.897 91.1269 167.266 90.0477 155.276 90.0477C154.197 90.0477 153.118 90.0477 152.039 90.0477C126.859 90.4074 102.878 95.6832 80.9352 105.036C72.302 94.8439 64.868 83.453 58.9927 71.3427C81.6546 61.8702 106.475 56.7144 132.614 56.7144C141.487 56.7144 150.24 57.3139 158.753 58.5129C171.823 60.1916 184.533 63.3091 196.643 67.6256Z" fill="url(#paint1_linear_446_540)"/>
+<path d="M199.64 34.0528C199.64 39.2087 199.401 44.3646 199.041 49.4005C186.691 44.1247 173.621 40.048 160.072 37.53C148.321 35.2518 136.211 34.0528 123.981 34.0528C97.7218 34.0528 72.6619 39.3286 49.88 48.9209C42.6858 51.9185 35.7313 55.3958 29.0167 59.2327C24.2205 46.0432 20.8632 32.0144 19.1846 17.6259C26.6186 14.1487 34.2925 11.271 42.2062 8.75301C60.3117 3.11751 79.4964 0 99.4005 0C119.904 0 139.568 3.23741 158.153 9.11272C172.782 13.789 186.691 20.2638 199.52 28.1775C199.64 30.2159 199.64 32.1343 199.64 34.0528Z" fill="url(#paint2_linear_446_540)"/>
+<path d="M190.168 93.2855C182.494 116.547 170.384 137.65 154.796 155.875C149.76 161.751 144.364 167.386 138.609 172.542C126.858 183.214 113.789 192.446 99.7601 200C93.4052 196.523 87.41 192.686 81.5347 188.609C93.0455 180.336 103.717 170.744 113.069 160.072C117.866 154.676 122.302 148.921 126.499 143.046C137.65 127.098 146.403 109.233 152.158 90.1679C153.237 90.1679 154.316 90.1679 155.396 90.1679C167.146 90.048 178.777 91.1272 190.168 93.2855Z" fill="url(#paint3_linear_446_540)"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_446_540" x1="15.8569" y1="27.5782" x2="86.4712" y2="182.06" gradientUnits="userSpaceOnUse">
+<stop stop-color="#57A4F7"/>
+<stop offset="1" stop-color="#2158F9"/>
+</linearGradient>
+<linearGradient id="paint1_linear_446_540" x1="58.9501" y1="80.8427" x2="196.648" y2="80.8427" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2158F9"/>
+<stop offset="1" stop-color="#33E1E5"/>
+</linearGradient>
+<linearGradient id="paint2_linear_446_540" x1="19.1564" y1="29.6353" x2="199.647" y2="29.6353" gradientUnits="userSpaceOnUse">
+<stop stop-color="#255DF9"/>
+<stop offset="1" stop-color="#7C35BA"/>
+</linearGradient>
+<linearGradient id="paint3_linear_446_540" x1="95.3808" y1="192.567" x2="174.674" y2="97.4815" gradientUnits="userSpaceOnUse">
+<stop stop-color="#54A0F7"/>
+<stop offset="1" stop-color="#2158F9"/>
+</linearGradient>
+<clipPath id="clip0_446_540">
+<rect width="200" height="200" fill="white"/>
+</clipPath>
+</defs>
+</svg>

BIN
ruoyi-ui-wuguan/src/assets/images/delei.png


BIN
ruoyi-ui-wuguan/src/assets/images/h-pic_dzh_tp2.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_byfxsj.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_jrfb.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_jryc.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_jrzs.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_jzsh.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_kcpz.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_kcsj.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hp_kj_tkxx.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_ht_fbxw.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_ht_tksh.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_ht_xwdt_add.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_ht_zhsh.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl__hbm.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_hjs.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_hzh.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_myc_normal.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_myc_selected.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_mzc_normal.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_mzc_selected.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_smrs_normal.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_smrs_selected.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_wdyc_normal.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_htgl_wdyc_selected.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_cjtj.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_dqlk.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_dtaq.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_kcb.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_kjgn.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_shlb.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_hthp_tktz.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_kjgn_jzsh.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_kjgn_kcb.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_kjgn_kcsj.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_kjgn_tkxx.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_qjlb_xxkc.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_sjtj_js.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_sjtj_zz.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_swh_tq.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_tc_add.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_tc_del.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_xyht_wsxx_add.png


BIN
ruoyi-ui-wuguan/src/assets/images/icon_xyht_wsxx_del.png


BIN
ruoyi-ui-wuguan/src/assets/images/logon.png


BIN
ruoyi-ui-wuguan/src/assets/images/ncbgc.png


BIN
ruoyi-ui-wuguan/src/assets/images/ncbgl.png


BIN
ruoyi-ui-wuguan/src/assets/images/opic_rylb_db.png


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä