From dc22358d8624d3f5a2c27ee6c27e0bdbfe705fe9 Mon Sep 17 00:00:00 2001
From: jiangping <jp@doumee.com>
Date: 星期一, 20 五月 2024 11:21:14 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 admin/src/views/business/reportRecord.vue                                                              |   85 +
 admin/src/assets/style/style.scss                                                                      |  161 +++
 admin/src/views/business/approvalConfiguration.vue                                                     |  844 +++++++++-------
 admin/package-lock.json                                                                                |  186 ++-
 admin/vue.config.js                                                                                    |   16 
 server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/MeetingApi.java                        |   44 
 server/meeting/meeting_service/src/main/java/com/doumee/dao/web/response/MeetingListResponse.java      |   10 
 server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/NoticeApi.java                         |   12 
 server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/RoomsApi.java                          |   73 
 server/meeting/meeting_service/src/main/java/com/doumee/service/business/impl/BookingsServiceImpl.java |   14 
 admin/src/components/common/QueryForm/queryForm.vue                                                    |  241 ++++
 server/meeting/meeting_service/src/main/java/com/doumee/dao/business/BookingsMapper.java               |    2 
 admin/src/views/business/page-components/ReportDetail.vue                                              |  422 ++++++++
 server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java                                |   18 
 admin/package.json                                                                                     |    1 
 admin/src/views/business/visitOrigin.vue                                                               |  105 ++
 admin/src/components/common/QueryForm/index.js                                                         |    3 
 /dev/null                                                                                              |   38 
 admin/src/components/common/GlobalWindow.vue                                                           |    8 
 admin/src/views/task/taskDetail.vue                                                                    |  417 ++++++++
 admin/src/views/task/index.vue                                                                         |   86 +
 server/meeting/meeting_admin/src/main/java/com/doumee/api/business/BookingsController.java             |    3 
 admin/src/views/application/index.vue                                                                  |   79 +
 h5/App.vue                                                                                             |   16 
 server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/UtilApi.java                           |    8 
 25 files changed, 2,322 insertions(+), 570 deletions(-)

diff --git a/admin/package-lock.json b/admin/package-lock.json
index c401a1d..f4e509d 100644
--- a/admin/package-lock.json
+++ b/admin/package-lock.json
@@ -1876,63 +1876,6 @@
           "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
           "dev": true
         },
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
         "ssri": {
           "version": "8.0.1",
           "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-8.0.1.tgz?cache=0&sync_timestamp=1617826515595&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
@@ -1940,28 +1883,6 @@
           "dev": true,
           "requires": {
             "minipass": "^3.1.1"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        },
-        "vue-loader-v16": {
-          "version": "npm:vue-loader@16.8.3",
-          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
-          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chalk": "^4.1.0",
-            "hash-sum": "^2.0.0",
-            "loader-utils": "^2.0.0"
           }
         }
       }
@@ -2934,8 +2855,7 @@
     "big.js": {
       "version": "5.2.2",
       "resolved": "https://registry.nlark.com/big.js/download/big.js-5.2.2.tgz?cache=0&sync_timestamp=1620132748267&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbig.js%2Fdownload%2Fbig.js-5.2.2.tgz",
-      "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=",
-      "dev": true
+      "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg="
     },
     "binary-extensions": {
       "version": "2.2.0",
@@ -4606,6 +4526,11 @@
       "integrity": "sha1-LnG/CxGRU9u0zE6I2epaz7UNwFw=",
       "dev": true
     },
+    "dayjs": {
+      "version": "1.11.11",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
+    },
     "de-indent": {
       "version": "1.0.2",
       "resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
@@ -5136,6 +5061,15 @@
       "resolved": "https://registry.npm.taobao.org/ejs/download/ejs-2.7.4.tgz?cache=0&sync_timestamp=1612643435705&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fejs%2Fdownload%2Fejs-2.7.4.tgz",
       "integrity": "sha1-SGYSh1c9zFPjZsehrlLDoSDuybo=",
       "dev": true
+    },
+    "el-tree-transfer": {
+      "version": "2.4.7",
+      "resolved": "https://registry.npmjs.org/el-tree-transfer/-/el-tree-transfer-2.4.7.tgz",
+      "integrity": "sha512-wcjQyqzmiJMDhF3qHR1NcqXp27Q65Td1EsMOVkqqOo9Z2mkVC+cGJEu3V4L90x8c1XgEciQL7tMuSjCP7/8G4g==",
+      "requires": {
+        "lodash": "^4.17.20",
+        "wl-core": "^1.1.4"
+      }
     },
     "electron-to-chromium": {
       "version": "1.3.728",
@@ -13937,6 +13871,87 @@
         }
       }
     },
+    "vue-loader-v16": {
+      "version": "npm:vue-loader@16.8.3",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "hash-sum": "^2.0.0",
+        "loader-utils": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
     "vue-property-decorator": {
       "version": "8.5.1",
       "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz",
@@ -14737,6 +14752,15 @@
       "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz",
       "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
     },
+    "wl-core": {
+      "version": "1.1.9",
+      "resolved": "https://registry.npmjs.org/wl-core/-/wl-core-1.1.9.tgz",
+      "integrity": "sha512-7L83qEnrVW3YmPVqSwnlagoWJyVq/uSXkCFzND64nwtSdDm7o1RZQWiVgQcEilZxE0qLrRQKmjuAihNT6fWCjA==",
+      "requires": {
+        "big.js": "^5.2.2",
+        "dayjs": "^1.8.25"
+      }
+    },
     "word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz",
diff --git a/admin/package.json b/admin/package.json
index 9b74e33..27e418b 100644
--- a/admin/package.json
+++ b/admin/package.json
@@ -16,6 +16,7 @@
     "axios": "^0.21.1",
     "core-js": "^3.6.5",
     "echarts": "^5.4.3",
+    "el-tree-transfer": "^2.4.7",
     "element-tiptap": "^1.27.1",
     "element-ui": "^2.3.6",
     "js-cookie": "^2.2.1",
diff --git a/admin/src/assets/style/style.scss b/admin/src/assets/style/style.scss
index 4718bce..d281a72 100644
--- a/admin/src/assets/style/style.scss
+++ b/admin/src/assets/style/style.scss
@@ -20,6 +20,7 @@
     margin: 0;
     overflow: scroll;
     overflow: hidden;
+    font-size: 14px;
     scrollbar-width: none; /* firefox */
     -ms-overflow-style: none; /* IE 10+ */
     &::-webkit-scrollbar {
@@ -124,3 +125,163 @@
     top: 1px;
   }
 }
+
+.main_app {
+  background-color: #fff;
+  padding: 30px;
+  margin: 0 16px;
+}
+/** 鍩虹閫氱敤 **/
+ // 澶у皬 澶栬竟璺�
+ .flex1{
+  flex: 1;
+ }
+ .w100{
+  width: 100px !important;
+ }
+ .w120{
+  width: 120px !important;
+ }
+ .w200{
+  width: 200px !important;
+ }
+ .w300{
+  width: 300px;
+ }
+ .w400{
+  width: 400px !important;
+ }
+ .pt5 {
+  padding-top: 5px;
+}
+
+.pr5 {
+  padding-right: 5px;
+}
+
+.pb5 {
+  padding-bottom: 5px;
+}
+
+.mt5 {
+  margin-top: 5px;
+}
+
+.mr5 {
+  margin-right: 5px;
+}
+
+.mb5 {
+  margin-bottom: 5px;
+}
+
+.mb8 {
+  margin-bottom: 8px;
+}
+
+.ml5 {
+  margin-left: 5px;
+}
+
+.mt10 {
+  margin-top: 10px;
+}
+
+.mr10 {
+  margin-right: 10px;
+}
+
+.mb10 {
+  margin-bottom: 10px;
+}
+
+.ml10 {
+  margin-left: 10px;
+}
+
+.mt20 {
+  margin-top: 20px;
+}
+
+.mr20 {
+  margin-right: 20px;
+}
+
+.mb20 {
+  margin-bottom: 20px;
+}
+.red{
+  color: red !important;
+}
+.table_btns{
+  border-bottom: 1px solid #eee;
+  padding-bottom: 10px;
+}
+.ml20 {
+  margin-left: 20px;
+}
+.mt30 {
+  margin-top: 30px;
+}
+
+.mr30 {
+  margin-right: 30px;
+}
+
+.mb30 {
+  margin-bottom: 30px;
+}
+.pr20{
+  padding-right: 20px;
+}
+
+.ml30 {
+  margin-left: 30px;
+}
+.h24{
+  height: 24px;
+  line-height: 24px;
+}
+
+// flex甯冨眬
+.df{
+  display: flex;
+}
+.df_ac{
+  display: flex;
+  align-items: center;
+  p {
+    margin: 0;
+  }
+}
+.df_sb{
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+// 鏂囨湰鏍峰紡
+.underline{
+  text-decoration: underline;
+}
+.fs12{
+  font-size: 12px;
+}
+.fs_12{
+  font-size: 12px;
+}
+.fs_16{
+  font-size: 16px;
+}
+.fs_18{
+  font-size: 18px;
+}
+.fs_24{
+  font-size: 24px;
+}
+.text{
+  color: #333333;
+}
+.tac{
+  text-align: center;
+}
diff --git a/admin/src/components/common/GlobalWindow.vue b/admin/src/components/common/GlobalWindow.vue
index 298b468..359891b 100644
--- a/admin/src/components/common/GlobalWindow.vue
+++ b/admin/src/components/common/GlobalWindow.vue
@@ -21,7 +21,8 @@
     <div v-if="withFooter" class="window__footer">
       <slot name="footer">
         <el-button @click="confirm" :loading="confirmWorking" type="primary">{{text}}</el-button>
-        <el-button @click="close">杩斿洖</el-button>
+        <slot name="btns" />
+        <el-button @click="close">{{ backText }}</el-button>
       </slot>
     </div>
   </el-drawer>
@@ -45,6 +46,10 @@
       type: String,
       default: '纭畾'
     },
+    backText: {
+      type: String,
+      default: '杩斿洖'
+    },
     // 纭鎸夐挳loading鐘舵��
     confirmWorking: {
       type: Boolean,
@@ -66,6 +71,7 @@
       this.$emit('confirm')
     },
     close () {
+      this.$emit('close')
       this.$emit('update:visible', false)
     }
   }
diff --git a/admin/src/components/common/QueryForm/index.js b/admin/src/components/common/QueryForm/index.js
new file mode 100644
index 0000000..0114373
--- /dev/null
+++ b/admin/src/components/common/QueryForm/index.js
@@ -0,0 +1,3 @@
+import QueryForm from './queryForm.vue'
+
+export default QueryForm
diff --git a/admin/src/components/common/QueryForm/queryForm.vue b/admin/src/components/common/QueryForm/queryForm.vue
new file mode 100644
index 0000000..66563cb
--- /dev/null
+++ b/admin/src/components/common/QueryForm/queryForm.vue
@@ -0,0 +1,241 @@
+<template>
+  <div class="doumee-filter">
+    <el-form inline label-suffix="锛�" @submit.native.prevent>
+      <template v-for="(item, index) in queryFormConfig.formItems">
+        <el-form-item v-if="item.type === 'input' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label">
+          <el-input v-model="searchForm[item.filed]"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :placeholder="item.placeholder ? item.placeholder : '璇疯緭鍏�' + item.label" class="w200"
+            @change="changeForm(item.filed)" @keyup.enter.native="handlekeyup(item.keyup || false)" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'moneySelect' && (showZk || index < listLength)" :key="item.label"
+          :label="item.label">
+          <el-input v-model="searchForm[item.filedStrt]"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :placeholder="item.start" style="width: 150px" />
+          <div class="date-division-line" style="margin-left: 10px;margin-bottom: 0;">~</div>
+          <el-input v-model="searchForm[item.filedEnd]"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :placeholder="item.end" style="width: 150px" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'select' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label">
+          <el-select v-model="searchForm[item.filed]" :filterable="item.filterable || true"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :placeholder="item.placeholder ? item.placeholder : '璇烽�夋嫨' + item.label" class="w200"
+            @change="changeForm(item.filed)">
+            <el-option v-for="opt, i in item.options" :key="i" :value="item.valueCode ? opt[item.valueCode] : opt.value"
+              :label="item.labelCode ? opt[item.labelCode] : opt.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="item.type === 'date' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label || '鏃ユ湡'">
+          <el-date-picker v-model="searchForm[item.filed]" type="date" value-format="yyyy-MM-dd" class="w200"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :placeholder="item.placeholder || '璇烽�夋嫨鏃ユ湡'" :picker-options="item.pickerOptions || {}"
+            @change="changeForm(item.filed)" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'daterange' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label || ''">
+          <el-date-picker v-model="searchForm[item.filed]" value-format="yyyy-MM-dd" type="daterange"
+            range-separator="鑷�"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :start-placeholder="item.start || ''" :end-placeholder="item.end || ''"
+            :picker-options="item.pickerOptions || {}" class="w400" @change="changeForm(item.filed)" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'timePicker' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label || '閫夋嫨鏃堕棿'">
+          <el-time-picker v-model="searchForm[item.filed]" is-range range-separator="鑷�" format="HH:mm"
+            value-format="HH:mm" start-placeholder="寮�濮嬫椂闂�" end-placeholder="缁撴潫鏃堕棿" placeholder="閫夋嫨鏃堕棿鑼冨洿" class="w400"
+            @change="changeForm(item.filed)" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'datetimerange' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label || '閫夋嫨鏃ユ湡'">
+          <el-date-picker v-model="searchForm[item.filed]" format="yyyy-MM-dd HH:mm:ss"
+            value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
+            :picker-options="item.pickerOptions || pickerOptions" range-separator="鑷�"
+            :clearable="(item.clearable !== null && item.clearable !== undefined && item.clearable !== '') ? item.clearable : true"
+            :start-placeholder="item.start || '寮�濮嬫椂闂�'" :end-placeholder="item.end || '缁撴潫鏃堕棿'" class="w400"
+            @change="changeForm(item.filed)" />
+        </el-form-item>
+        <el-form-item v-if="item.type === 'slot' && (showZk || index < listLength)" :key="item.filed"
+          :label="item.label">
+          <slot :name="item.filed" />
+        </el-form-item>
+      </template>
+      <!-- 鎿嶄綔 -->
+      <el-form-item>
+        <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+        <el-button v-if="showQk" @click="clear">閲嶇疆</el-button>
+        <slot name="btns" />
+        <template v-if="queryFormConfig.formItems.length > listLength">
+          <el-button v-if="!showZk" type="text" @click="zkBtn">灞曞紑<i
+              class="el-icon-caret-bottom primaryColor" /></el-button>
+          <el-button v-if="showZk" type="text" @click="zkBtn">鏀惰捣<i class="el-icon-caret-top primaryColor" /></el-button>
+        </template>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    value: {
+      type: Object,
+      default: () => { }
+    },
+    showQk: {
+      type: Boolean,
+      default: true
+    },
+    listLength: {
+      type: Number,
+      default: 3
+    },
+    queryFormConfig: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  data() {
+    return {
+      showZk: false,
+      pickerOptions: {
+        shortcuts: [{
+          text: '杩�7澶�',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(end.getTime() - 3600 * 1000 * 24 * 6)
+            picker.$emit('pick', [start, end])
+          }
+        },
+        {
+          text: '杩�30澶�',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(end.getTime() - 3600 * 1000 * 24 * 29)
+            picker.$emit('pick', [start, end])
+          }
+        },
+        {
+          text: '杩�60澶�',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(end.getTime() - 3600 * 1000 * 24 * 59)
+            picker.$emit('pick', [start, end])
+          }
+        },
+        {
+          text: '杩�90澶�',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(end.getTime() - 3600 * 1000 * 24 * 89)
+            picker.$emit('pick', [start, end])
+          }
+        }],
+        disabledDate(time) {
+          var curDate = new Date(new Date().toLocaleDateString()).getTime()
+          var preDate = new Date(curDate + 24 * 60 * 60 * 1000 - 1)
+          return time.getTime() > preDate
+        }
+      }
+    }
+  },
+  emits: ['input', 'handleQuery', 'clear'],
+  computed: {
+    searchForm: {
+      get() {
+        return this.value
+      },
+      set(value) {
+        this.$emit('input', value)
+      }
+    }
+  },
+  methods: {
+    handleQuery() {
+      this.$emit('handleQuery')
+    },
+    handlekeyup(pd) {
+      if (pd) {
+        this.$emit('handleQuery')
+      }
+    },
+    changeForm(filed) {
+      this.$emit('changeForm', filed)
+    },
+    zkBtn() {
+      this.showZk = !this.showZk
+      this.$emit('zkBtn', this.zk)
+    },
+    clear() {
+      this.$emit('clear')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.doumee-filter {
+  display: flex;
+  align-items: center;
+  position: relative;
+  flex-wrap: wrap;
+  align-items: center;
+  background-color: #fff;
+  border-bottom: 10px solid #f7f8f9;
+  margin: 0 -30px;
+  padding: 0 0 0 30px;
+
+  .el-input,
+  .el-select {
+    width: 200px;
+    margin-right: 20px;
+    margin-bottom: 20px;
+    height: 36px;
+
+    .el-input__inner {
+      /* color: $textColor; */
+      padding: 0 16px;
+    }
+  }
+
+  .el-date-editor {
+    width: 200px;
+    margin-right: 20px;
+    margin-bottom: 20px;
+
+    .el-input__inner {
+      padding-left: 30px;
+    }
+  }
+
+  .el-button {
+    margin-bottom: 20px;
+  }
+
+  .el-form-item {
+    margin-bottom: 20px;
+    margin-right: 20px;
+
+    .el-input,
+    .el-select,
+    .el-date-editor {
+      margin-right: 0;
+    }
+
+    .el-input,
+    .el-select,
+    .el-date-editor,
+    .el-button {
+      margin-bottom: 0;
+    }
+  }
+}
+</style>
diff --git a/admin/src/views/application/index.vue b/admin/src/views/application/index.vue
new file mode 100644
index 0000000..bcf546e
--- /dev/null
+++ b/admin/src/views/application/index.vue
@@ -0,0 +1,79 @@
+<template>
+  <div class="main_app">
+    <div class="one_level" v-for="(menu, i) in dataList" :key="i">
+      <div class="title">
+        {{ menu.name }}
+      </div>
+      <div class="list">
+        <div class="item" @click="handleClick(item)" v-for="item in menu.children" :key="item.name">
+          <img src="" alt="" class="icon" />
+          <div class="name">{{ item.name }}</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      dataList: [
+        {
+          name: '涓氬姟涓績',
+          children: [
+            { name: '鐢ㄨ溅鐢宠璁板綍', url: '' },
+            { name: '浼氳瀹ら绾﹁褰�', url: '' },
+            { name: '闅忔偅闅忔墜鎷嶈褰�', url: '' },
+            { name: '鐢ㄩ璁板綍', url: '' },
+            { name: 'dddd', url: '' }
+          ]
+        },
+        {
+          name: '鏈堝彴涓績',
+          children: [
+            { name: '鐢ㄨ溅鐢宠璁板綍', url: '' },
+            { name: '浼氳瀹ら绾﹁褰�', url: '' },
+            { name: '闅忔偅闅忔墜鎷嶈褰�', url: '' },
+            { name: '鐢ㄩ璁板綍', url: '' },
+            { name: 'dddd', url: '' }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    handleClick (item) {
+      console.log(item)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.one_level {
+  padding: 16px 0;
+  .title {
+    font-size: 16px;
+    font-weight: 600;
+    border-bottom: 1px solid #cccccc;
+    padding: 12px 16px;
+    margin-bottom: 20px;
+  }
+  .list {
+    display: flex;
+    flex-wrap: wrap;
+    .item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      width: 25%;
+      .icon {
+        width: 60px;
+        height: 60px;
+        margin-right: 12px;
+      }
+    }
+  }
+}
+</style>
diff --git a/admin/src/views/business/approvalConfiguration.vue b/admin/src/views/business/approvalConfiguration.vue
index 24532ad..b2de731 100644
--- a/admin/src/views/business/approvalConfiguration.vue
+++ b/admin/src/views/business/approvalConfiguration.vue
@@ -1,132 +1,201 @@
 <template>
-    <TableLayout>
-        <template v-slot:table-wrap>
-            <div class="config">
-                <div class="config_list">
-                    <div class="config_list_head">
-                        <span>閰嶇疆娴佺▼</span>
-                        <el-button style="background: #435EBE;" type="primary">鍙戝竷</el-button>
-                    </div>
-                    <div class="config_list_list">
-                        <div class="item">
-                            <div class="item_label">鍙戣捣浜�</div>
-                            <div class="item_child">
-                                <div class="item_child_label">绋嬫槬鏋�</div>
-                                <div class="item_child_val">璁垮</div>
-                            </div>
-                            <div class="item_down">
-                                <div class="item_down_x">
-                                    <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
-                                </div>
-                            </div>
-                        </div>
-                        <div :class="item.active ? 'item yellow active' : 'item yellow'" v-for="(item, index) in list" :key="index" @click="seleItem(index)">
-                            <div class="item_label">瀹℃壒浜�</div>
-                            <div class="item_child" style="cursor: pointer;">
-                                <img class="item_child_right" src="@/assets/images/ar_more@2x.png" />
-                                <div class="item_child_label">琚浜�</div>
-                                <div class="item_child_val">璁垮</div>
-                            </div>
-                            <div class="item_down">
-                                <img class="item_down_add" v-if="list.length - 1 === index" src="@/assets/images/peizhi_add@2x.png" @click.stop="add" />
-                                <div class="item_down_x">
-                                    <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
-                                </div>
-                            </div>
-                        </div>
-                        <div class="item blue" style="height: 81px;">
-                            <div class="item_label">鎶勯�佷汉</div>
-                            <div class="item_child" style="cursor: pointer;height: 40px;">
-                                <img class="item_child_right" src="@/assets/images/ar_more@2x.png" />
-                                <div class="item_child_val" style="margin-top: 3px;">璇疯缃妱閫佷汉</div>
-                            </div>
-                            <div class="item_down">
-                                <div class="item_down_x">
-                                    <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
-                                </div>
-                            </div>
-                        </div>
-                        <div class="footer">
-                            <span>娴佺▼缁撴潫</span>
-                        </div>
-                    </div>
+  <TableLayout>
+    <template v-slot:table-wrap>
+      <el-tabs v-model="activeName">
+        <el-tab-pane label="鏅�氳瀹�" name="first"></el-tab-pane>
+        <el-tab-pane label="鏂藉伐璁垮" name="second"></el-tab-pane>
+      </el-tabs>
+      <div class="config">
+        <div class="config_list">
+          <div class="config_list_head">
+            <span>閰嶇疆娴佺▼</span>
+            <el-button style="background: #435ebe" type="primary"
+              >鍙戝竷</el-button
+            >
+          </div>
+          <div class="config_list_list">
+            <div class="item">
+              <div class="item_label">鍙戣捣浜�</div>
+              <div class="item_child">
+                <div class="item_child_label">绋嬫槬鏋�</div>
+                <div class="item_child_val">璁垮</div>
+              </div>
+              <div class="item_down">
+                <div class="item_down_x">
+                  <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
                 </div>
-                <div class="config_data">
-                    <div class="config_data_item">
-                        <div class="config_data_item_label">
-                            閫夋嫨璇ヨ妭鐐圭殑瀹℃壒浜�
-                        </div>
-                        <el-radio-group v-model="radio">
-                            <el-radio :label="0">琚浜�</el-radio>
-                            <el-radio :label="1">鎸囧畾浜哄憳</el-radio>
-                            <el-radio :label="2">閮ㄩ棬涓荤</el-radio>
-                        </el-radio-group>
-                        <div class="config_data_item_reviewed" v-if="radio === 1">
-                            <div class="config_data_item_reviewed_label">
-                                <span>鎸囧畾瀹℃牳浜�</span>
-                                <span>涓嶈秴杩�20浜�</span>
-                            </div>
-                            <div class="config_data_item_reviewed_content">
-                                <div class="config_data_item_reviewed_content_item">
-                                    <span>鏍撳瓙鍝�</span>
-                                    <i class="el-icon-close"></i>
-                                </div>
-                                <span class="add">+娣诲姞</span>
-                            </div>
-                        </div>
-                        <div class="config_data_item_reviewed" v-if="radio === 2">
-                            <div class="config_data_item_reviewed_label">
-                                <span>閮ㄩ棬涓荤</span>
-                            </div>
-                            <div class="config_data_item_reviewed_r">
-                                <span>琚浜虹殑</span>
-                                <el-select v-model="value" placeholder="璇烽�夋嫨" style="margin: 0 20px 0 10px;">
-                                    <el-option
-                                        v-for="item in options"
-                                        :key="item.value"
-                                        :label="item.label"
-                                        :value="item.value">
-                                    </el-option>
-                                </el-select>
-                                <el-checkbox v-model="checked">鎵句笉鍒颁富绠℃椂锛岀敱涓婄骇涓荤浠e鏍�</el-checkbox>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="config_data_item" v-if="radio !== 0">
-                        <div class="config_data_item_label">
-                            瀹℃壒鏂瑰紡
-                            <span>瀹℃壒浜轰负澶氫釜鏃讹紝閲囩敤鐨勫鎵规柟寮�</span>
-                        </div>
-                        <el-radio-group v-model="radio1" style="display: flex; flex-direction: column;">
-                            <el-radio :label="0" style="margin-bottom: 20px;">鎴栫锛堝叾涓竴鍚嶅鎵逛汉鍚屾剰鎴栨嫆缁濆嵆鍙級</el-radio>
-                            <el-radio :label="1">浼氱锛堟墍鏈夊鎵逛汉閮藉悓鎰忔墠鍙�氳繃锛�</el-radio>
-                        </el-radio-group>
-                    </div>
-                    <div class="config_data_item" v-if="radio === 2">
-                        <div class="config_data_item_label">
-                            瀹℃壒浜轰负绌烘椂
-                        </div>
-                        <el-checkbox-group v-model="checkList" style="display: flex; flex-direction: column;">
-                            <el-checkbox label="澶嶉�夋 A" style="margin-bottom: 20px;"></el-checkbox>
-                            <el-checkbox label="澶嶉�夋 B" style="margin-bottom: 20px;"></el-checkbox>
-                            <el-checkbox label="澶嶉�夋 C"></el-checkbox>
-                        </el-checkbox-group>
-                    </div>
-                    <div class="config_data_submit" v-if="radio !== 0">
-                        <el-button style="background: #435EBE;" type="primary">淇濇寔閰嶇疆椤�</el-button>
-                    </div>
-                </div>
+              </div>
             </div>
-        </template>
-    </TableLayout>
+            <div
+              :class="item.active ? 'item yellow active' : 'item yellow'"
+              v-for="(item, index) in list"
+              :key="index"
+              @click="seleItem(index)"
+            >
+              <div class="item_label">瀹℃壒浜�</div>
+              <div class="item_child" style="cursor: pointer">
+                <img
+                  class="item_child_right"
+                  src="@/assets/images/ar_more@2x.png"
+                />
+                <div class="item_child_label">琚浜�</div>
+                <div class="item_child_val">璁垮</div>
+              </div>
+              <div class="item_down">
+                <!-- <img
+                  class="item_down_add"
+                  v-if="list.length - 1 === index"
+                  src="@/assets/images/peizhi_add@2x.png"
+                  @click.stop="add"
+                /> -->
+                <div class="item_down_x">
+                  <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
+                </div>
+              </div>
+            </div>
+            <div class="item blue" style="height: 81px">
+              <div class="item_label">鎶勯�佷汉</div>
+              <div class="item_child" style="cursor: pointer; height: 40px">
+                <img
+                  class="item_child_right"
+                  src="@/assets/images/ar_more@2x.png"
+                />
+                <div class="item_child_val" style="margin-top: 3px">
+                  璇疯缃妱閫佷汉
+                </div>
+              </div>
+              <div class="item_down">
+                <div class="item_down_x">
+                  <img src="@/assets/images/peizhi_ar@2x.png" alt="" />
+                </div>
+              </div>
+            </div>
+            <div class="footer">
+              <span>娴佺▼缁撴潫</span>
+            </div>
+          </div>
+        </div>
+        <div class="config_data">
+          <div class="config_data_item">
+            <div class="config_data_item_label">閫夋嫨璇ヨ妭鐐圭殑瀹℃壒浜�</div>
+            <el-radio-group v-model="radio">
+              <el-radio :label="0">琚浜�</el-radio>
+              <el-radio :label="1">鎸囧畾浜哄憳</el-radio>
+              <el-radio :label="2">閮ㄩ棬涓荤</el-radio>
+            </el-radio-group>
+            <div class="config_data_item_reviewed" v-if="radio === 1">
+              <div class="config_data_item_reviewed_label">
+                <span>鎸囧畾瀹℃牳浜�</span>
+                <span>涓嶈秴杩�20浜�</span>
+              </div>
+              <div class="config_data_item_reviewed_content">
+                <div class="config_data_item_reviewed_content_item">
+                  <span>鏍撳瓙鍝�</span>
+                  <i class="el-icon-close"></i>
+                </div>
+                <span class="add" @click="selStaff">+娣诲姞</span>
+              </div>
+            </div>
+            <div class="config_data_item_reviewed" v-if="radio === 2">
+              <div class="config_data_item_reviewed_label">
+                <span>閮ㄩ棬涓荤</span>
+              </div>
+              <div class="config_data_item_reviewed_r">
+                <span>琚浜虹殑</span>
+                <el-select
+                  v-model="value"
+                  placeholder="璇烽�夋嫨"
+                  style="margin: 0 20px 0 10px"
+                >
+                  <el-option
+                    v-for="item in options"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+                <el-checkbox v-model="checked"
+                  >鎵句笉鍒颁富绠℃椂锛岀敱涓婄骇涓荤浠e鏍�</el-checkbox
+                >
+              </div>
+            </div>
+          </div>
+          <div class="config_data_item" v-if="radio !== 0">
+            <div class="config_data_item_label">
+              瀹℃壒鏂瑰紡
+              <span>瀹℃壒浜轰负澶氫釜鏃讹紝閲囩敤鐨勫鎵规柟寮�</span>
+            </div>
+            <el-radio-group
+              v-model="radio1"
+              style="display: flex; flex-direction: column"
+            >
+              <el-radio :label="0" style="margin-bottom: 20px"
+                >鎴栫锛堝叾涓竴鍚嶅鎵逛汉鍚屾剰鎴栨嫆缁濆嵆鍙級</el-radio
+              >
+              <el-radio :label="1">浼氱锛堟墍鏈夊鎵逛汉閮藉悓鎰忔墠鍙�氳繃锛�</el-radio>
+            </el-radio-group>
+          </div>
+          <div class="config_data_item" v-if="radio === 2">
+            <div class="config_data_item_label">瀹℃壒浜轰负绌烘椂</div>
+            <el-checkbox-group
+              v-model="checkList"
+              style="display: flex; flex-direction: column"
+            >
+              <el-checkbox
+                label="澶嶉�夋 A"
+                style="margin-bottom: 20px"
+              ></el-checkbox>
+              <el-checkbox
+                label="澶嶉�夋 B"
+                style="margin-bottom: 20px"
+              ></el-checkbox>
+              <el-checkbox label="澶嶉�夋 C"></el-checkbox>
+            </el-checkbox-group>
+          </div>
+          <div class="config_data_submit" v-if="radio !== 0">
+            <el-button style="background: #435ebe" type="primary"
+              >淇濇寔閰嶇疆椤�</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </template>
+    <!--  -->
+    <el-dialog title="閫夋嫨鍛樺伐" :visible.sync="isShowTransfer" width="800px">
+      <tree-transfer
+        v-model="param.menuIds"
+        :title="['鏈��', '宸查��']"
+        :from_data="fromData"
+        :to_data="selData"
+        :defaultProps="{ label: 'label' }"
+        mode="transfer"
+        height="500px"
+        filter
+        openAll
+        ref="treeTransfer"
+      >
+      </tree-transfer>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowTransfer = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="isShowTransfer = false"
+          >纭� 瀹�</el-button
+        >
+      </span>
+    </el-dialog>
+  </TableLayout>
 </template>
 
 <script>
 import TableLayout from '@/layouts/TableLayout'
+import treeTransfer from 'el-tree-transfer'
 export default {
   name: 'config',
-  components: { TableLayout },
-  data () {
+  components: {
+    TableLayout,
+    treeTransfer
+  },
+  data() {
     return {
       list: [
         {
@@ -139,17 +208,60 @@
       radio: 0,
       radio1: 0,
       checked: '',
-      checkList: []
+      checkList: [],
+
+      param: {},
+      activeName: 'first',
+      isShowTransfer: false,
+      fromData: [
+        {
+          id: '1',
+          pid: 0,
+          label: '涓�绾� 1',
+          children: [
+            {
+              id: '1-1',
+              pid: '1',
+              label: '浜岀骇 1-1',
+              disabled: true,
+              children: []
+            },
+            {
+              id: '1-2',
+              pid: '1',
+              label: '浜岀骇 1-2',
+              children: [
+                {
+                  id: '1-2-1',
+                  pid: '1-2',
+                  children: [],
+                  label: '浜岀骇 1-2-1'
+                },
+                {
+                  id: '1-2-2',
+                  pid: '1-2',
+                  children: [],
+                  label: '浜岀骇 1-2-2'
+                }
+              ]
+            }
+          ]
+        }
+      ],
+      selData: []
     }
   },
   methods: {
-    add () {
+    add() {
       this.list.push({
         name: '',
         active: false
       })
     },
-    seleItem (i) {
+    selStaff() {
+      this.isShowTransfer = true
+    },
+    seleItem(i) {
       this.list.forEach((item, index) => {
         item.active = index === i
       })
@@ -159,254 +271,254 @@
 </script>
 
 <style lang="scss" scoped>
-    .config {
-        width: 100%;
-        padding-bottom: 20px;
-        box-sizing: border-box;
-        height: calc(100vh - 140px);
+.config {
+  width: 100%;
+  padding-bottom: 20px;
+  box-sizing: border-box;
+  height: calc(100vh - 140px);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .config_list {
+    width: 543px;
+    height: 100%;
+    flex-shrink: 0;
+    border-radius: 2px;
+    padding: 20px;
+    box-sizing: border-box;
+    border: 1px solid #eeeeee;
+    background: #f7f7f7;
+    .config_list_head {
+      width: 100%;
+      height: 40px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      span {
+        font-size: 18px;
+        font-weight: 500;
+        color: #222222;
+      }
+    }
+    .config_list_list {
+      width: 100%;
+      height: calc(100% - 40px);
+      padding-top: 45px;
+      box-sizing: border-box;
+      overflow-y: scroll;
+      display: flex;
+      align-items: center;
+      flex-direction: column;
+      &::-webkit-scrollbar {
+        width: 0;
+      }
+      .active {
+        border: 2px solid #e84a08 !important;
+      }
+      .yellow {
+        background: #ee8921 !important;
+      }
+      .blue {
+        background: #435ebe !important;
+      }
+      .footer {
+        width: 106px;
+        height: 41px;
+        background: #ffffff;
+        box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
+        border-radius: 25px;
         display: flex;
         align-items: center;
+        justify-content: center;
+        span {
+          font-size: 15px;
+          font-weight: 400;
+          color: #333333;
+        }
+      }
+      .item {
+        width: 200px;
+        height: 102px;
+        background: #7999d9;
+        box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1);
+        border-radius: 4px;
+        padding: 4px;
+        box-sizing: border-box;
+        display: flex;
+        flex-direction: column;
         justify-content: space-between;
-        .config_list {
-            width: 543px;
-            height: 100%;
-            flex-shrink: 0;
-            border-radius: 2px;
-            padding: 20px;
-            box-sizing: border-box;
-            border: 1px solid #EEEEEE;
-            background: #F7F7F7;
-            .config_list_head {
-                width: 100%;
-                height: 40px;
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                span {
-                    font-size: 18px;
-                    font-weight: 500;
-                    color: #222222;
-                }
-            }
-            .config_list_list {
-                width: 100%;
-                height: calc(100% - 40px);
-                padding-top: 45px;
-                box-sizing: border-box;
-                overflow-y: scroll;
-                display: flex;
-                align-items: center;
-                flex-direction: column;
-                &::-webkit-scrollbar {
-                    width: 0;
-                }
-                .active {
-                    border: 2px solid #E84A08 !important;
-                }
-                .yellow {
-                    background: #EE8921 !important;
-                }
-                .blue {
-                    background: #435EBE !important;
-                }
-                .footer {
-                    width: 106px;
-                    height: 41px;
-                    background: #FFFFFF;
-                    box-shadow: 0px 0px 8px 0px rgba(0,0,0,0.1);
-                    border-radius: 25px;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    span {
-                        font-size: 15px;
-                        font-weight: 400;
-                        color: #333333;
-                    }
-                }
-                .item {
-                    width: 200px;
-                    height: 102px;
-                    background: #7999D9;
-                    box-shadow: 0 0 8px 0 rgba(0,0,0,0.1);
-                    border-radius: 4px;
-                    padding: 4px;
-                    box-sizing: border-box;
-                    display: flex;
-                    flex-direction: column;
-                    justify-content: space-between;
-                    position: relative;
-                    margin-bottom: 60px;
-                    &:last-child {
-                        margin: 0 !important;
-                    }
-                    .item_down {
-                        position: absolute;
-                        bottom: -60px;
-                        width: 100%;
-                        height: 60px;
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                        .item_down_add {
-                            width: 46px;
-                            height: 46px;
-                            position: absolute;
-                            z-index: 3;
-                            top: 5px;
-                            cursor: pointer;
-                        }
-                        .item_down_x {
-                            width: 1px;
-                            height: 60px;
-                            background: #B2B2B2;
-                            position: relative;
-                            img {
-                                position: absolute;
-                                bottom: 0;
-                                left: -4px;
-                                width: 9px;
-                                height: 9px;
-                            }
-                        }
-                    }
-                    .item_label {
-                        width: 100%;
-                        height: 30px;
-                        display: flex;
-                        align-items: center;
-                        font-size: 15px;
-                        font-weight: 400;
-                        color: #FFFFFF;
-                    }
-                    .item_child {
-                        width: 100%;
-                        height: 61px;
-                        padding: 10px;
-                        box-sizing: border-box;
-                        background: #FFFFFF;
-                        border-radius: 4px;
-                        position: relative;
-                        .item_child_right {
-                            position: absolute;
-                            right: 10px;
-                            top: 13px;
-                            width: 8px;
-                            height: 14px;
-                        }
-                        .item_child_label {
-                            font-size: 14px;
-                            font-weight: 400;
-                            color: #333333;
-                            margin-bottom: 4px;
-                        }
-                        .item_child_val {
-                            font-size: 12px;
-                            font-weight: 400;
-                            color: #999999;
-                        }
-                    }
-                }
-            }
+        position: relative;
+        margin-bottom: 60px;
+        &:last-child {
+          margin: 0 !important;
         }
-        .config_data {
-            flex: 1;
-            height: 100%;
-            margin-left: 20px;
-            .config_data_submit {
-                margin-top: 50px;
+        .item_down {
+          position: absolute;
+          bottom: -60px;
+          width: 100%;
+          height: 60px;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          .item_down_add {
+            width: 46px;
+            height: 46px;
+            position: absolute;
+            z-index: 3;
+            top: 5px;
+            cursor: pointer;
+          }
+          .item_down_x {
+            width: 1px;
+            height: 60px;
+            background: #b2b2b2;
+            position: relative;
+            img {
+              position: absolute;
+              bottom: 0;
+              left: -4px;
+              width: 9px;
+              height: 9px;
             }
-            .config_data_item {
-                width: 100%;
-                display: flex;
-                flex-direction: column;
-                margin-bottom: 30px;
-                &:last-child {
-                    margin: 0 !important;
-                }
-                .config_data_item_label {
-                    font-size: 16px;
-                    font-weight: 500;
-                    color: #222222;
-                    margin-bottom: 20px;
-                    span {
-                        font-size: 12px;
-                        font-weight: 400;
-                        color: #999999;
-                        margin-left: 10px;
-                    }
-                }
-                .config_data_item_reviewed {
-                    width: 100%;
-                    margin-top: 20px;
-                    .config_data_item_reviewed_r {
-                        margin-top: 10px;
-                        width: 100%;
-                        display: flex;
-                        align-items: center;
-                        span {
-                            flex-shrink: 0;
-                            font-size: 14px;
-                            font-weight: 400;
-                            color: #666666;
-                        }
-                    }
-                    .config_data_item_reviewed_label {
-                        display: flex;
-                        align-items: center;
-                        span {
-                            &:nth-child(1) {
-                                font-size: 14px;
-                                font-weight: 400;
-                                color: #222222;
-                            }
-                            &:nth-child(2) {
-                                font-size: 12px;
-                                font-weight: 400;
-                                color: #999999;
-                                margin-left: 8px;
-                            }
-                        }
-                    }
-                    .config_data_item_reviewed_content {
-                        width: 400px;
-                        margin-top: 10px;
-                        height: 110px;
-                        padding: 12px;
-                        box-sizing: border-box;
-                        border-radius: 2px;
-                        border: 1px solid #DFE2E8;
-                        display: flex;
-                        align-items: flex-start;
-                        flex-wrap: wrap;
-                        .add {
-                            font-size: 12px;
-                            font-weight: 400;
-                            color: #435EBE;
-                            cursor: pointer;
-                            margin-top: 3px;
-                        }
-                        .config_data_item_reviewed_content_item {
-                            padding: 3px 5px;
-                            background: #F4F7FC;
-                            border-radius: 2px;
-                            box-sizing: border-box;
-                            margin-right: 10px;
-                            margin-bottom: 10px;
-                            span {
-                                font-size: 12px;
-                                font-weight: 400;
-                                color: #333333;
-                            }
-                            i {
-                                color: #949BA2;
-                                margin-left: 10px;
-                                cursor: pointer;
-                            }
-                        }
-                    }
-                }
-            }
+          }
         }
+        .item_label {
+          width: 100%;
+          height: 30px;
+          display: flex;
+          align-items: center;
+          font-size: 15px;
+          font-weight: 400;
+          color: #ffffff;
+        }
+        .item_child {
+          width: 100%;
+          height: 61px;
+          padding: 10px;
+          box-sizing: border-box;
+          background: #ffffff;
+          border-radius: 4px;
+          position: relative;
+          .item_child_right {
+            position: absolute;
+            right: 10px;
+            top: 13px;
+            width: 8px;
+            height: 14px;
+          }
+          .item_child_label {
+            font-size: 14px;
+            font-weight: 400;
+            color: #333333;
+            margin-bottom: 4px;
+          }
+          .item_child_val {
+            font-size: 12px;
+            font-weight: 400;
+            color: #999999;
+          }
+        }
+      }
     }
+  }
+  .config_data {
+    flex: 1;
+    height: 100%;
+    margin-left: 20px;
+    .config_data_submit {
+      margin-top: 50px;
+    }
+    .config_data_item {
+      width: 100%;
+      display: flex;
+      flex-direction: column;
+      margin-bottom: 30px;
+      &:last-child {
+        margin: 0 !important;
+      }
+      .config_data_item_label {
+        font-size: 16px;
+        font-weight: 500;
+        color: #222222;
+        margin-bottom: 20px;
+        span {
+          font-size: 12px;
+          font-weight: 400;
+          color: #999999;
+          margin-left: 10px;
+        }
+      }
+      .config_data_item_reviewed {
+        width: 100%;
+        margin-top: 20px;
+        .config_data_item_reviewed_r {
+          margin-top: 10px;
+          width: 100%;
+          display: flex;
+          align-items: center;
+          span {
+            flex-shrink: 0;
+            font-size: 14px;
+            font-weight: 400;
+            color: #666666;
+          }
+        }
+        .config_data_item_reviewed_label {
+          display: flex;
+          align-items: center;
+          span {
+            &:nth-child(1) {
+              font-size: 14px;
+              font-weight: 400;
+              color: #222222;
+            }
+            &:nth-child(2) {
+              font-size: 12px;
+              font-weight: 400;
+              color: #999999;
+              margin-left: 8px;
+            }
+          }
+        }
+        .config_data_item_reviewed_content {
+          width: 400px;
+          margin-top: 10px;
+          height: 110px;
+          padding: 12px;
+          box-sizing: border-box;
+          border-radius: 2px;
+          border: 1px solid #dfe2e8;
+          display: flex;
+          align-items: flex-start;
+          flex-wrap: wrap;
+          .add {
+            font-size: 12px;
+            font-weight: 400;
+            color: #435ebe;
+            cursor: pointer;
+            margin-top: 3px;
+          }
+          .config_data_item_reviewed_content_item {
+            padding: 3px 5px;
+            background: #f4f7fc;
+            border-radius: 2px;
+            box-sizing: border-box;
+            margin-right: 10px;
+            margin-bottom: 10px;
+            span {
+              font-size: 12px;
+              font-weight: 400;
+              color: #333333;
+            }
+            i {
+              color: #949ba2;
+              margin-left: 10px;
+              cursor: pointer;
+            }
+          }
+        }
+      }
+    }
+  }
+}
 </style>
diff --git a/admin/src/views/business/page-components/ReportDetail.vue b/admin/src/views/business/page-components/ReportDetail.vue
new file mode 100644
index 0000000..697baf3
--- /dev/null
+++ b/admin/src/views/business/page-components/ReportDetail.vue
@@ -0,0 +1,422 @@
+<template>
+  <GlobalWindow
+    :title="title"
+    text="鍚屾剰"
+    backText="鎷掔粷"
+    :visible.sync="isShowModal"
+    @confirm="confirm"
+    @close="reject"
+  >
+    <div class="modal_wrap">
+      <div class="modal_content">
+        <div class="header">
+          <div class="left">
+            <div class="h1">璁垮棰勭害</div>
+            <div class="time">鎻愪氦鏃堕棿锛�</div>
+          </div>
+          <div class="right">寰呭鏍�</div>
+        </div>
+        <div class="info">
+          <div class="title">璁垮鎶ュ璇︽儏</div>
+          <div class="list">
+            <div class="item">
+              <div class="label">琚浜�</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鎷滆鏃堕棿</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鍏ュ洯杞﹁締</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏉ヨ鍗曚綅</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鑱旂郴浜�</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">闅忚溅浜烘暟</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏉ヨ浜嬬敱</div>
+              <div class="value"></div>
+            </div>
+          </div>
+        </div>
+        <div class="table_info">
+          <div class="title">璁垮淇℃伅</div>
+          <el-table :data="detail.datalist" border fit>
+            <el-table-column label="濮撳悕" prop="" min-width="150">
+              <template slot-scope="{ row }">
+                <div class="name_wrap">
+                  <image src="" class="avatar" mode="" />
+                  <div class="content">
+                    <div class="line">
+                      <div class="name">鏉庝笢</div>
+                      <div class="tag">鐢宠浜�</div>
+                    </div>
+                    <div class="line placeholder9">1888888</div>
+                  </div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎬у埆" prop="" min-width="40" />
+            <el-table-column label="璇佷欢绫诲瀷" prop="" min-width="80" />
+            <el-table-column label="璇佷欢鍙风爜" prop="" min-width="120" />
+            <el-table-column label="鍏徃鍚嶇О" prop="" min-width="120" />
+            <el-table-column label="浜鸿劯鐓х墖" prop="" min-width="80">
+              <template slot-scope="{ row }">
+                <el-image :src="row.url" :preview-src-list="[row.url]">
+                </el-image>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div class="side">
+        <div class="side_title">瀹℃壒娴佺▼</div>
+        <div class="list">
+          <div class="item">
+            <div class="separate"></div>
+            <div class="info">
+              <i class="el-icon-success icon"></i>
+              <img src="" class="avatar" alt="" />
+              <div class="content">
+                <div class="line">
+                  <div class="name">鍒樻煇鍒樻煇</div>
+                  <div class="time">2020-02-02 12:20</div>
+                </div>
+                <div class="line">
+                  <div class="company">涓浗绉诲姩鏈夐檺鍏徃</div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="item">
+            <!-- <div v-if="" class="separate"></div> -->
+            <div class="info">
+              <i class="el-icon-success icon"></i>
+              <img src="" class="avatar" alt="" />
+              <div class="content">
+                <div class="line">
+                  <div class="name">鍒樻煇鍒樻煇</div>
+                  <div class="time">2020-02-02 12:20</div>
+                </div>
+                <div class="line">
+                  <div class="company">
+                    涓浗绉诲姩鏈夐檺鍏徃( <span class="status">宸插悓鎰�</span> )
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="remark">鎻愪氦绾﹀ソ鐨�</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!--  -->
+    <template #btns>
+      <el-button type="primary" plain @click="handleTransfer">杞氦</el-button>
+    </template>
+    <!--  鍚屾剰/鎷掔粷 -->
+    <el-dialog
+      append-to-body
+      :title="apprTitle"
+      :visible.sync="isShowAppr"
+      width="480px"
+    >
+      <el-input
+        type="textarea"
+        :placeholder="apprTitle + '璇存槑锛岄潪蹇呭~'"
+        :rows="4"
+        v-model="param.explain"
+      />
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowAppr = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="isShowAppr = false">纭畾</el-button>
+      </span>
+    </el-dialog>
+    <!-- 闅愭偅 -->
+    <el-dialog
+      append-to-body
+      title="闅愭偅"
+      :visible.sync="isShowProblem"
+      width="480px"
+    >
+      <el-form :model="param" :rules="rules" ref="ruleForm" label-width="100px">
+        <el-form-item label="閫�鍥炴椂闂�">
+          <el-date-picker
+            class="w300"
+            value-format="yyyy-MM-dd"
+            type="date"
+            placeholder="閫夋嫨鏃ユ湡"
+            v-model="param.date"
+          />
+        </el-form-item>
+        <el-form-item label="鏁存敼鍓�">
+          <div class="df_ac">
+            <img src="@/assets/avatar/man.png" />
+            <el-upload
+              class="avatar-uploader"
+              action="https://jsonplaceholder.typicode.com/posts/"
+              :show-file-list="false"
+              :on-success="handleAvatarSuccess"
+              :before-upload="beforeAvatarUpload"
+            >
+              <img v-if="param.url" :src="param.url" class="avatar" />
+              <div v-else class="upload_box">
+                <el-icon class="el-icon-plus icon" />
+                <div class="text">鍥剧墖/瑙嗛</div>
+              </div>
+            </el-upload>
+          </div>
+        </el-form-item>
+        <el-form-item label="閫�鍥炶鏄�">
+          <el-input
+            type="textarea"
+            placeholder="璇峰~鍐欒鏄�"
+            :rows="4"
+            v-model="param.explain"
+          />
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowProblem = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="isShowProblem = false"
+          >纭畾</el-button
+        >
+      </span>
+    </el-dialog>
+  </GlobalWindow>
+</template>
+
+<script>
+import GlobalWindow from '@/components/common/GlobalWindow'
+export default {
+  components: { GlobalWindow },
+  data() {
+    return {
+      title: '璁垮棰勭害璇︽儏',
+      isShowModal: false,
+      detail: {
+        datalist: [{}]
+      },
+
+      isShowAppr: false,
+      apprTitle: '鍚屾剰',
+      param: {},
+
+      isShowProblem: false,
+      rules: {}
+    }
+  },
+  methods: {
+    confirm() {
+      console.log('--')
+    },
+    handleTransfer() {
+      this.isShowProblem = true
+    },
+    reject() { },
+    handleAvatarSuccess() { },
+    beforeAvatarUpload() { }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.upload_box {
+  width: 84px;
+  height: 84px;
+  border-radius: 4px;
+  background-color: #f7f7f7;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  color: #999999;
+  border: 1px solid #e4e4e4;
+  .icon {
+    font-size: 24px;
+  }
+  .text {
+    font-size: 12px;
+  }
+}
+.modal_wrap {
+  display: flex;
+  height: 100%;
+  .modal_content {
+    flex: 1;
+    padding: 0px 30px;
+    border-radius: 8px;
+    overflow: hidden;
+    height: 100%;
+
+    .title {
+      font-weight: 600;
+      font-size: 18px;
+      color: #333333;
+      margin-bottom: 20px;
+      margin-top: 30px;
+    }
+
+    .info {
+      .list {
+        display: flex;
+        flex-wrap: wrap;
+
+        .item {
+          display: flex;
+          width: 40%;
+          margin-bottom: 20px;
+          &:nth-of-type(2n) {
+            width: 60%;
+          }
+
+          .label {
+            color: #888888;
+            width: 68px;
+          }
+
+          .value {
+            color: #111111;
+          }
+        }
+      }
+    }
+
+    .header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20px 30px;
+      margin: 0 -30px;
+      border-radius: 8px 8px 0 0;
+      background: linear-gradient(to right, #f2f6fe, #cadffa);
+
+      .h1 {
+        font-weight: 600;
+        font-size: 22px;
+        color: #111111;
+        margin-bottom: 8px;
+      }
+
+      .time {
+        font-size: 14px;
+        color: #999999;
+      }
+
+      .right {
+        height: 40px;
+        font-size: 16px;
+        color: #ffffff;
+        line-height: 40px;
+        padding: 0 20px;
+        background: #207ff7;
+        box-shadow: 4px 4px 0px 0px rgba(32, 127, 247, 0.16);
+        border-radius: 16px 0px 16px 0px;
+      }
+    }
+    .table_info {
+      .name_wrap {
+        display: flex;
+        align-items: center;
+        .avatar {
+          width: 40px;
+          height: 40px;
+          border-radius: 50%;
+          margin-right: 12px;
+        }
+        .content {
+          .line {
+            display: flex;
+          }
+          .tag {
+            color: #b2cbf9;
+            border: 1px solid #b2cbf9;
+            padding: 0px 4px;
+            border-radius: 4px;
+            margin-left: 6px;
+          }
+        }
+      }
+    }
+  }
+
+  .side {
+    height: 100%;
+    width: 420px;
+    background: #ffffff;
+    border-left: 20px solid #f7f7f7;
+    .list {
+      .item {
+        padding: 8px 0;
+        position: relative;
+        .separate {
+          position: absolute;
+          border-left: 2px dashed #cccccc;
+          left: 51px;
+          height: calc(100% - 24px);
+          top: 46px;
+        }
+        .info {
+          display: flex;
+          align-items: center;
+          margin-left: 40px;
+          .icon {
+            position: relative;
+            z-index: 11;
+            color: #53b76f;
+            font-size: 24px;
+          }
+          .avatar {
+            width: 40px;
+            height: 40px;
+            border-radius: 50%;
+            margin: 0 12px 0 16px;
+            border: 1px solid;
+          }
+          .content {
+            flex: 1;
+            .line {
+              display: flex;
+              justify-content: space-between;
+              align-content: center;
+              margin-bottom: 6px;
+              .name {
+                font-weight: 600;
+                font-size: 16px;
+                color: #111111;
+              }
+              .time {
+                color: #888888;
+              }
+              .company {
+                font-size: 13px;
+                color: #888888;
+                .status {
+                  color: #00ba67;
+                }
+              }
+            }
+          }
+        }
+        .remark {
+          background: #f7f7f7;
+          border-radius: 4px;
+          padding: 13px 15px;
+          color: #666666;
+          margin-left: 120px;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/admin/src/views/business/reportRecord.vue b/admin/src/views/business/reportRecord.vue
new file mode 100644
index 0000000..348d2ef
--- /dev/null
+++ b/admin/src/views/business/reportRecord.vue
@@ -0,0 +1,85 @@
+<template>
+  <div class="main_app">
+    <QueryForm v-model="filters" :query-form-config="queryFormConfig" @handleQuery="getList(1)" @clear="clear" />
+    <el-table v-loading="loading" :data="list" stripe row-key="id" default-expand-all>
+      <el-table-column prop="" label="鍏ュ洯杞﹁締" min-width="100" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="鍏徃鍚嶇О" min-width="120" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="鑱旂郴浜轰俊鎭�" min-width="100" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="鎵嬫満鍙�" min-width="120" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="琚浜�" min-width="120" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="鎷滆鏃堕棿" min-width="120" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" label="鎷滆浜嬬敱" min-width="80" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="" fixed="right" label="鐘舵��" min-width="100"></el-table-column>
+      <el-table-column label="鎿嶄綔" width="230" fixed="right">
+        <template slot-scope="{row}">
+          <el-button type="text" @click="handleDetail(row)" v-permissions="['business:company:update']">鏌ョ湅璇︽儏</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination @size-change="handleSizeChange" @current-change="getList" :pagination="pagination" />
+    <ReportDetail v-if="isShowDetail" ref="DetailRef" />
+  </div>
+</template>
+
+<script>
+import Pagination from '@/components/common/Pagination'
+import QueryForm from '@/components/common/QueryForm'
+import ReportDetail from './page-components/ReportDetail.vue'
+export default {
+  components: {
+    ReportDetail,
+    QueryForm,
+    Pagination
+  },
+  data () {
+    return {
+      isShowDetail: false,
+      activeTab: '0',
+      filters: {},
+      queryFormConfig: {
+        formItems: [
+          {
+            filed: 'idCard',
+            type: 'input',
+            label: '杞︾墝鍙�'
+          },
+          {
+            filed: 'name',
+            type: 'input',
+            label: '鍏徃鍚嶇О'
+          }
+        ],
+        online: true
+      },
+      loading: false,
+      sorting: false,
+      searchForm: {
+        // type: 1
+      },
+      pagination: {
+        capacity: 10,
+        page: 1
+      },
+      list: [{}],
+      total: 0
+    }
+  },
+  methods: {
+    handleDetail () {
+      this.isShowDetail = true
+      this.$nextTick(() => {
+        this.$refs.DetailRef.isShowModal = true
+      })
+    },
+    getList (page) {},
+    clear () { },
+    handleSizeChange (capacity) {
+      this.pagination.capacity = capacity
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>
diff --git a/admin/src/views/business/visitOrigin.vue b/admin/src/views/business/visitOrigin.vue
new file mode 100644
index 0000000..a3b5af1
--- /dev/null
+++ b/admin/src/views/business/visitOrigin.vue
@@ -0,0 +1,105 @@
+<template>
+  <div class="main_app">
+    <div class="table_btns">
+      <el-button icon="el-icon-plus" @click="handleEdit()" type="primary"
+        >鏂板缓</el-button
+      >
+    </div>
+    <el-table v-loading="loading" :data="list" stripe>
+      <el-table-column
+        prop="name"
+        label="鎷滆浜嬬敱"
+        min-width="100"
+      ></el-table-column>
+      <el-table-column
+        prop="name"
+        label="鎺掑簭鐮�"
+        min-width="80"
+      ></el-table-column>
+      <el-table-column label="鎿嶄綔" width="230" fixed="right">
+        <!-- v-permissions="['business:company:update']" -->
+        <template slot-scope="{ row }">
+          <el-button type="text" icon="el-icon-edit" @click="handleEdit(row)"
+            >缂栬緫</el-button
+          >
+          <el-button
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDetail(row)"
+            class="red"
+            >鍒犻櫎</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      @size-change="handleSizeChange"
+      @current-change="getList"
+      :pagination="pagination"
+    />
+    <!--  -->
+    <el-dialog title="鎷滆浜嬬敱" :visible.sync="isShowEdit" width="480px">
+      <el-form :model="param" :rules="rules" ref="ruleForm" label-width="100px">
+        <el-form-item label="鎷滆浜嬬敱">
+          <el-input type="text" placeholder="璇疯緭鍏�" v-model="param.explain" />
+        </el-form-item>
+        <el-form-item label="鎺掑簭鐮�">
+          <el-input
+            type="text"
+            placeholder="璇疯緭鍏�"
+            oninput="value=value.replace(/^(0+)|[^\d]+/g, '').slice(0, 6)"
+            v-model="param.sortNum"
+          />
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowEdit = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSub">纭畾</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import Pagination from '@/components/common/Pagination'
+export default {
+  components: {
+    Pagination
+  },
+  data() {
+    return {
+      loading: false,
+      pagination: {
+        capacity: 10,
+        page: 1
+      },
+      list: [{}],
+      total: 0,
+
+      isShowEdit: false,
+      param: {},
+      rules: {}
+    }
+  },
+  methods: {
+    handleSub() {
+      this.$refs.ruleForm.validate((valid) => {
+        if (valid) {
+          alert('submit!')
+        }
+      })
+    },
+    handleEdit() {
+      this.isShowEdit = true
+    },
+    getList(page) { },
+    clear() { },
+    handleSizeChange(capacity) {
+      this.pagination.capacity = capacity
+    }
+  }
+}
+</script>
+
+<style>
+</style>
diff --git a/admin/src/views/task/index.vue b/admin/src/views/task/index.vue
new file mode 100644
index 0000000..131db2c
--- /dev/null
+++ b/admin/src/views/task/index.vue
@@ -0,0 +1,86 @@
+<template>
+  <div class="main_app">
+    <QueryForm v-model="filters" :query-form-config="queryFormConfig" @handleQuery="getList(1)" @clear="clear" />
+    <!--  -->
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="寰呭鐞�" name="0"></el-tab-pane>
+      <el-tab-pane label="宸插鐞�" name="1"></el-tab-pane>
+      <el-tab-pane label="鎴戝彂璧风殑" name="2"></el-tab-pane>
+      <el-tab-pane label="鎶勯�佹垜鐨�" name="3"></el-tab-pane>
+    </el-tabs>
+    <el-table v-loading="loading" :data="list" stripe row-key="id" default-expand-all>
+      <el-table-column prop="name" label="浠诲姟绫诲瀷" min-width="100"></el-table-column>
+      <el-table-column prop="name" label="鎻愪氦浜�" min-width="80"></el-table-column>
+      <el-table-column prop="companyNamePath" label="鎻愪氦鏃堕棿" min-width="100"></el-table-column>
+      <el-table-column label="鎿嶄綔" width="230" fixed="right">
+        <template slot-scope="{row}">
+          <el-button type="text" @click="handleDetail(row)" v-permissions="['business:company:update']">鏌ョ湅璇︽儏</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination @size-change="handleSizeChange" @current-change="getList" :pagination="pagination" />
+    <TaskDetail v-if="isShowDetail" ref="DetailRef" />
+  </div>
+</template>
+
+<script>
+import Pagination from '@/components/common/Pagination'
+import QueryForm from '@/components/common/QueryForm'
+import TaskDetail from './taskDetail.vue'
+export default {
+  components: {
+    TaskDetail,
+    QueryForm,
+    Pagination
+  },
+  data () {
+    return {
+      isShowDetail: false,
+      activeTab: '0',
+      filters: {},
+      queryFormConfig: {
+        formItems: [
+          {
+            filed: 'taskType',
+            type: 'select',
+            label: '浠诲姟绫诲瀷',
+            options: []
+          },
+          {
+            filed: 'status',
+            type: 'daterange',
+            label: ''
+          }
+        ],
+        online: true
+      },
+      loading: false,
+      sorting: false,
+      searchForm: {
+        // type: 1
+      },
+      pagination: {
+        capacity: 10,
+        page: 1
+      },
+      list: [{}],
+      total: 0
+    }
+  },
+  methods: {
+    handleDetail () {
+      this.isShowDetail = true
+      this.$nextTick(() => {
+        this.$refs.DetailRef.isShowModal = true
+      })
+    },
+    getList (page) { },
+    clear () { },
+    handleSizeChange (capacity) {
+      this.pagination.capacity = capacity
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/admin/src/views/task/taskDetail.vue b/admin/src/views/task/taskDetail.vue
new file mode 100644
index 0000000..3337491
--- /dev/null
+++ b/admin/src/views/task/taskDetail.vue
@@ -0,0 +1,417 @@
+<template>
+  <GlobalWindow
+    :title="title"
+    text="鍚屾剰"
+    backText="鎷掔粷"
+    :visible.sync="isShowModal"
+    @confirm="confirm"
+    @close="reject"
+  >
+    <div class="modal_wrap">
+      <div class="modal_content">
+        <div class="header">
+          <div class="left">
+            <div class="h1">璁垮棰勭害</div>
+            <div class="time">鎻愪氦鏃堕棿锛�</div>
+          </div>
+          <div class="right">寰呭鏍�</div>
+        </div>
+        <div class="info">
+          <div class="title">璁垮棰勭害淇℃伅</div>
+          <div class="list">
+            <div class="item">
+              <div class="label">琚浜�</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏉ヨ鏃堕棿</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏉ヨ浜嬬敱</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">闅忚杞﹁締</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏂藉伐浜哄憳</div>
+              <div class="value"></div>
+            </div>
+            <div class="item">
+              <div class="label">鏂藉伐鍐呭</div>
+              <div class="value"></div>
+            </div>
+          </div>
+        </div>
+        <div class="table_info">
+          <div class="title">璁垮淇℃伅</div>
+          <el-table :data="detail.datalist" border fit>
+            <el-table-column label="濮撳悕" prop="" min-width="150">
+              <template slot-scope="{ row }">
+                <div class="name_wrap">
+                  <image src="" class="avatar" mode="" />
+                  <div class="content">
+                    <div class="line">
+                      <div class="name">鏉庝笢</div>
+                      <div class="tag">鐢宠浜�</div>
+                    </div>
+                    <div class="line placeholder9">1888888</div>
+                  </div>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎬у埆" prop="" min-width="40" />
+            <el-table-column label="璇佷欢绫诲瀷" prop="" min-width="80" />
+            <el-table-column label="璇佷欢鍙风爜" prop="" min-width="120" />
+            <el-table-column label="鍏徃鍚嶇О" prop="" min-width="120" />
+            <el-table-column label="浜鸿劯鐓х墖" prop="" min-width="80">
+              <template slot-scope="{ row }">
+                <el-image :src="row.url" :preview-src-list="[row.url]"> </el-image>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div class="side">
+        <div class="side_title">瀹℃壒娴佺▼</div>
+        <div class="list">
+          <div class="item">
+            <div class="separate"></div>
+            <div class="info">
+              <i class="el-icon-success icon"></i>
+              <img src="" class="avatar" alt="" />
+              <div class="content">
+                <div class="line">
+                  <div class="name">鍒樻煇鍒樻煇</div>
+                  <div class="time">2020-02-02 12:20</div>
+                </div>
+                <div class="line">
+                  <div class="company">涓浗绉诲姩鏈夐檺鍏徃</div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="item">
+            <!-- <div v-if="" class="separate"></div> -->
+            <div class="info">
+              <i class="el-icon-success icon"></i>
+              <img src="" class="avatar" alt="" />
+              <div class="content">
+                <div class="line">
+                  <div class="name">鍒樻煇鍒樻煇</div>
+                  <div class="time">2020-02-02 12:20</div>
+                </div>
+                <div class="line">
+                  <div class="company">
+                    涓浗绉诲姩鏈夐檺鍏徃( <span class="status">宸插悓鎰�</span> )
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="remark">鎻愪氦绾﹀ソ鐨�</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!--  -->
+    <template #btns>
+      <el-button type="primary" plain @click="handleTransfer">杞氦</el-button>
+    </template>
+    <!--  鍚屾剰/鎷掔粷 -->
+    <el-dialog
+      append-to-body
+      :title="apprTitle"
+      :visible.sync="isShowAppr"
+      width="480px"
+    >
+      <el-input
+        type="textarea"
+        :placeholder="apprTitle + '璇存槑锛岄潪蹇呭~'"
+        :rows="4"
+        v-model="param.explain"
+      />
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowAppr = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="isShowAppr = false">纭畾</el-button>
+      </span>
+    </el-dialog>
+    <!-- 闅愭偅 -->
+    <el-dialog
+      append-to-body
+      title="闅愭偅"
+      :visible.sync="isShowProblem"
+      width="480px"
+    >
+      <el-form :model="param" :rules="rules" ref="ruleForm" label-width="100px">
+        <el-form-item label="閫�鍥炴椂闂�">
+          <el-date-picker
+            class="w300"
+            value-format="yyyy-MM-dd"
+            type="date"
+            placeholder="閫夋嫨鏃ユ湡"
+            v-model="param.date"
+          />
+        </el-form-item>
+        <el-form-item label="鏁存敼鍓�">
+          <div class="df_ac">
+            <img src="@/assets/avatar/man.png" />
+            <el-upload
+              class="avatar-uploader"
+              action="https://jsonplaceholder.typicode.com/posts/"
+              :show-file-list="false"
+              :on-success="handleAvatarSuccess"
+              :before-upload="beforeAvatarUpload"
+            >
+              <img v-if="param.url" :src="param.url" class="avatar" />
+              <div v-else class="upload_box">
+                <el-icon class="el-icon-plus icon" />
+                <div class="text">鍥剧墖/瑙嗛</div>
+              </div>
+            </el-upload>
+          </div>
+        </el-form-item>
+        <el-form-item label="閫�鍥炶鏄�">
+          <el-input
+            type="textarea"
+            placeholder="璇峰~鍐欒鏄�"
+            :rows="4"
+            v-model="param.explain"
+          />
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="isShowProblem = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="isShowProblem = false"
+          >纭畾</el-button
+        >
+      </span>
+    </el-dialog>
+  </GlobalWindow>
+</template>
+
+<script>
+import GlobalWindow from '@/components/common/GlobalWindow'
+export default {
+  components: { GlobalWindow },
+  data() {
+    return {
+      title: '璁垮棰勭害璇︽儏',
+      isShowModal: false,
+      detail: {
+        datalist: [{}]
+      },
+
+      isShowAppr: false,
+      apprTitle: '鍚屾剰',
+      param: {},
+
+      isShowProblem: false,
+      rules: {}
+    }
+  },
+  methods: {
+    confirm() {
+      console.log('--')
+    },
+    handleTransfer() {
+      this.isShowProblem = true
+    },
+    reject() { },
+    handleAvatarSuccess() { },
+    beforeAvatarUpload() { }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.upload_box {
+  width: 84px;
+  height: 84px;
+  border-radius: 4px;
+  background-color: #f7f7f7;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  color: #999999;
+  border: 1px solid #e4e4e4;
+  .icon {
+    font-size: 24px;
+  }
+  .text {
+    font-size: 12px;
+  }
+}
+.modal_wrap {
+  display: flex;
+  height: 100%;
+  .modal_content {
+    flex: 1;
+    padding: 0px 30px;
+    border-radius: 8px;
+    overflow: hidden;
+    height: 100%;
+
+    .title {
+      font-weight: 600;
+      font-size: 18px;
+      color: #333333;
+      margin-bottom: 20px;
+      margin-top: 30px;
+    }
+
+    .info {
+      .list {
+        display: flex;
+        flex-wrap: wrap;
+
+        .item {
+          display: flex;
+          width: 40%;
+          margin-bottom: 20px;
+          &:nth-of-type(2n) {
+            width: 60%;
+          }
+
+          .label {
+            color: #888888;
+            width: 68px;
+          }
+
+          .value {
+            color: #111111;
+          }
+        }
+      }
+    }
+
+    .header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20px 30px;
+      margin: 0 -30px;
+      border-radius: 8px 8px 0 0;
+      background: linear-gradient(to right, #f2f6fe, #cadffa);
+
+      .h1 {
+        font-weight: 600;
+        font-size: 22px;
+        color: #111111;
+        margin-bottom: 8px;
+      }
+
+      .time {
+        font-size: 14px;
+        color: #999999;
+      }
+
+      .right {
+        height: 40px;
+        font-size: 16px;
+        color: #ffffff;
+        line-height: 40px;
+        padding: 0 20px;
+        background: #207ff7;
+        box-shadow: 4px 4px 0px 0px rgba(32, 127, 247, 0.16);
+        border-radius: 16px 0px 16px 0px;
+      }
+    }
+    .table_info {
+      .name_wrap {
+        display: flex;
+        align-items: center;
+        .avatar {
+          width: 40px;
+          height: 40px;
+          border-radius: 50%;
+          margin-right: 12px;
+        }
+        .content {
+          .line {
+            display: flex;
+          }
+          .tag {
+            color: #b2cbf9;
+            border: 1px solid #b2cbf9;
+            padding: 0px 4px;
+            border-radius: 4px;
+            margin-left: 6px;
+          }
+        }
+      }
+    }
+  }
+
+  .side {
+    height: 100%;
+    width: 420px;
+    background: #ffffff;
+    border-left: 20px solid #f7f7f7;
+    .list {
+      .item {
+        padding: 8px 0;
+        position: relative;
+        .separate {
+          position: absolute;
+          border-left: 2px dashed #cccccc;
+          left: 51px;
+          height: calc(100% - 24px);
+          top: 46px;
+        }
+        .info {
+          display: flex;
+          align-items: center;
+          margin-left: 40px;
+          .icon {
+            position: relative;
+            z-index: 11;
+            color: #53b76f;
+            font-size: 24px;
+          }
+          .avatar {
+            width: 40px;
+            height: 40px;
+            border-radius: 50%;
+            margin: 0 12px 0 16px;
+            border: 1px solid;
+          }
+          .content {
+            flex: 1;
+            .line {
+              display: flex;
+              justify-content: space-between;
+              align-content: center;
+              margin-bottom: 6px;
+              .name {
+                font-weight: 600;
+                font-size: 16px;
+                color: #111111;
+              }
+              .time {
+                color: #888888;
+              }
+              .company {
+                font-size: 13px;
+                color: #888888;
+                .status {
+                  color: #00ba67;
+                }
+              }
+            }
+          }
+        }
+        .remark {
+          background: #f7f7f7;
+          border-radius: 4px;
+          padding: 13px 15px;
+          color: #666666;
+          margin-left: 120px;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/admin/vue.config.js b/admin/vue.config.js
index efad125..ee1ea41 100644
--- a/admin/vue.config.js
+++ b/admin/vue.config.js
@@ -1,5 +1,10 @@
 // 璇︾粏閰嶇疆璇峰弬鑰僪ttps://cli.vuejs.org/zh/config/#vue-config-js
 // const outputDir = process.env.VUE_APP_CONTEXT_PATH.substring(1, process.env.VUE_APP_CONTEXT_PATH.length - 1)
+const path = require('path')
+
+function resolve (dir) {
+  return path.join(__dirname, dir)
+}
 module.exports = {
   publicPath: process.env.VUE_APP_CONTEXT_PATH,
   outputDir: 'admin',
@@ -13,9 +18,18 @@
         target: process.env.VUE_APP_API_URL,
         changeOrigin: true,
         pathRewrite: {
-         [`^${[process.env.VUE_APP_API_PREFIX]}`]: ''
+          [`^${[process.env.VUE_APP_API_PREFIX]}`]: ''
         }
       }
     }
+  },
+  configureWebpack: {
+    // provide the app's title in webpack's name field, so that
+    // it can be accessed in index.html to inject the correct title.
+    resolve: {
+      alias: {
+        '@': resolve('src')
+      }
+    }
   }
 }
diff --git a/h5/App.vue b/h5/App.vue
index 71871fd..cfca3fb 100644
--- a/h5/App.vue
+++ b/h5/App.vue
@@ -177,14 +177,20 @@
 	margin: 0;
 	display: flex;
 }
-
+input{
+	font-size: 30rpx
+}
 textarea {
 	box-sizing: border-box;
-	background-color: #f7f7f7;
-	font-size: 28rpx;
-	color: #333333;
-	padding: 24rpx;
+	// background-color: #f7f7f7;
+	font-size: 30rpx !important;
+	padding: 0;
 	border-radius: 8rpx;
+	color: #333333 !important;
+}
+.u-textarea{
+	padding: 0 !important;
+	color: #333333 !important;
 }
 
 .df_ac {
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/api/business/BookingsController.java b/server/meeting/meeting_admin/src/main/java/com/doumee/api/business/BookingsController.java
index bfeec82..c4552b2 100644
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/api/business/BookingsController.java
+++ b/server/meeting/meeting_admin/src/main/java/com/doumee/api/business/BookingsController.java
@@ -87,8 +87,7 @@
     @PostMapping("/updateById")
     @RequiresPermissions("business:bookings:update")
     public ApiResponse updateById(@RequestBody Bookings bookings) {
-        LoginUserInfo user = getLoginUser(null);
-        bookings.setCreator(user.getId());
+        bookings.setLoginUserInfo(getLoginUser(null));
         bookingsService.updateById(bookings);
         return ApiResponse.success(null);
     }
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/ApiController.java b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/ApiController.java
deleted file mode 100644
index c392575..0000000
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/ApiController.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.doumee.cloud.web;
-
-import com.doumee.config.Jwt.JwtTokenUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Controller鍩虹被
- * @author Eva.Caesar Liu
- * @date 2022/03/15 09:54
- */
-@Slf4j
-public class ApiController {
-
-
-    /**
-     * 寰楀埌request瀵硅薄
-     *
-     * @return
-     */
-    public HttpServletRequest getRequest() {
-        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
-        return request;
-    }
-    /**
-     * 鑾峰彇鐢ㄦ埛ID
-     *
-     * @return
-     */
-    protected Integer getMemberId() {
-        Object obj = this.getRequest().getAttribute(JwtTokenUtil.UserId_Name);
-        return obj != null ? (Integer) obj : null;
-    }
-
-}
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/MeetingApi.java b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/MeetingApi.java
index 81c8fad..6fbef3f 100644
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/MeetingApi.java
+++ b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/MeetingApi.java
@@ -1,10 +1,13 @@
 package com.doumee.cloud.web;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.doumee.api.BaseController;
 import com.doumee.config.Jwt.JwtTokenUtil;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.model.PageWrap;
+import com.doumee.core.utils.Constants;
 import com.doumee.core.utils.DateUtil;
 import com.doumee.core.utils.QrCodeUtils;
 import com.doumee.dao.business.model.Bookings;
@@ -38,9 +41,9 @@
 @Api(tags = "2銆侀瀹氫細璁笟鍔�")
 @Trace(exclude = true)
 @RestController
-@RequestMapping("/web/meeting")
+@RequestMapping(Constants.CLOUD_SERVICE_URL_INDEX+"/web/meeting")
 @Slf4j
-public class MeetingApi extends ApiController{
+public class MeetingApi extends BaseController {
 
     @Autowired
     private BookingsService bookingsService;
@@ -52,13 +55,14 @@
     @ApiOperation(value = "褰撴湀浼氳琛�", notes = "褰撴湀浼氳琛�")
     @GetMapping("/monthMeeting")
     @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
             @ApiImplicitParam(paramType = "query", dataType = "String", name = "yearMonth", value = "骞存湀  yyyy-MM", required = true)
     })
-    public ApiResponse<List<MonthDataResponse>> monthDay(@RequestParam String yearMonth) {
+    public ApiResponse<List<MonthDataResponse>> monthDay(@RequestParam String yearMonth
+            ,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+        LoginUserInfo user = getLoginUser(token);
         List<String> dataList = DateUtil.getDayByMonth(yearMonth);
         List<MonthDataResponse> monthDataResponseList = new ArrayList<>();
-        List<Bookings> bookings = bookingsService.getMyBookings(getMemberId(),yearMonth);
+        List<Bookings> bookings = bookingsService.getMyBookings(user.getId(),yearMonth);
         for (String str:dataList) {
             MonthDataResponse  monthDataResponse = new MonthDataResponse();
             monthDataResponse.setWeekMsg(DateUtil.getWeek(DateUtil.StringToDate(str,"yyyy-MM-dd")).getChineseName());
@@ -72,11 +76,10 @@
 
     @ApiOperation("鎴戠殑浼氳鍒楄〃")
     @PostMapping("/myMeetingPage")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public ApiResponse<IPage<MeetingListResponse>> myMeetingPage(@RequestBody PageWrap<MeetingPageRequest> pageWrap) {
-        pageWrap.getModel().setUserId(getMemberId());
+    public ApiResponse<IPage<MeetingListResponse>> myMeetingPage(@RequestBody PageWrap<MeetingPageRequest> pageWrap
+            ,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+        LoginUserInfo user = getLoginUser(token);
+        pageWrap.getModel().setUserId(user.getId());
         IPage<MeetingListResponse> page = bookingsService.getMyMeetingPage(pageWrap);
         return ApiResponse.success("鏌ヨ鎴愬姛",page);
     }
@@ -85,7 +88,6 @@
     @ApiOperation("浼氳璇︽儏")
     @GetMapping("/meetingDetail")
     @ApiImplicitParams({
-//            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
             @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳涓婚敭", required = true),
     })
     public ApiResponse<MeetingDetailResponse> meetingDetail(@RequestParam Integer id) {
@@ -93,7 +95,7 @@
     }
 
 
-    @ApiOperation("鑾峰彇浼氳寮�闂ㄤ簩缁寸爜")
+   /* @ApiOperation("鑾峰彇浼氳寮�闂ㄤ簩缁寸爜")
     @GetMapping("/getQrCode")
     @ApiImplicitParams({
             @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
@@ -116,7 +118,7 @@
         response.setContentType("image/jpeg");
         String content =bookingsService.getQrCode(id,memberId);
         QrCodeUtils.encode(content,null, response.getOutputStream(), true);
-    }
+    }*/
 
 /*
     @LoginRequired
@@ -134,23 +136,21 @@
 
     @ApiOperation("浼氳棰勭害")
     @PostMapping("/reservationMeeting")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public ApiResponse<Integer> reservationMeeting(@RequestBody BookingsRequest bookingsRequest) {
-        bookingsRequest.setCreator(getMemberId());
-        bookingsRequest.setEditor(getMemberId());
+    public ApiResponse<Integer> reservationMeeting(@RequestBody BookingsRequest bookingsRequest ,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+        LoginUserInfo user = getLoginUser(token);
+        bookingsRequest.setCreator(user.getId());
+        bookingsRequest.setEditor(user.getId());
         return ApiResponse.success("鎿嶄綔鎴愬姛",bookingsService.reservationMeeting(bookingsRequest));
     }
 
     @ApiOperation("鍙栨秷浼氳棰勭害")
     @GetMapping("/reservationCancel")
     @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
             @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳涓婚敭", required = true),
     })
-    public ApiResponse reservationCancel(@RequestParam Integer id) {
-        bookingsService.reservationCancel(id,getMemberId());
+    public ApiResponse reservationCancel(@RequestParam Integer id,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+        LoginUserInfo user = getLoginUser(token);
+        bookingsService.reservationCancel(id,user.getId());
         return ApiResponse.success("鎿嶄綔鎴愬姛");
     }
 
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/NoticeApi.java b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/NoticeApi.java
index b7bb358..c32250a 100644
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/NoticeApi.java
+++ b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/NoticeApi.java
@@ -1,7 +1,9 @@
 package com.doumee.cloud.web;
 
+import com.doumee.api.BaseController;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
 import com.doumee.core.utils.Constants;
@@ -16,9 +18,9 @@
 @Api(tags = "娑堟伅閫氱煡淇′笟鍔�")
 @Trace(exclude = true)
 @RestController
-@RequestMapping("/web/notice")
+@RequestMapping(Constants.CLOUD_SERVICE_URL_INDEX+"/web/notice")
 @Slf4j
-public class NoticeApi extends ApiController{
+public class NoticeApi extends BaseController {
 
     @Autowired
     private NoticesService noticeService;
@@ -31,8 +33,10 @@
      */
     @ApiOperation(value = "鏌ヨ鐢ㄦ埛閫氱煡", notes = "灏忕▼搴忕")
     @PostMapping("/findNoticePage")
-    public ApiResponse<PageData<Notices>> findNoticePage(@RequestBody PageWrap<Notices> pageWrap){
-        pageWrap.getModel().setUserId(getMemberId());
+    public ApiResponse<PageData<Notices>> findNoticePage(@RequestBody PageWrap<Notices> pageWrap
+            ,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
+        LoginUserInfo user = getLoginUser(token);
+        pageWrap.getModel().setUserId(user.getId());
         return ApiResponse.success("鏌ヨ鎴愬姛",noticeService.findPage(pageWrap));
     }
 
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/RoomsApi.java b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/RoomsApi.java
index 841e890..e98eae7 100644
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/RoomsApi.java
+++ b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/RoomsApi.java
@@ -1,10 +1,13 @@
 package com.doumee.cloud.web;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.doumee.api.BaseController;
 import com.doumee.config.Jwt.JwtTokenUtil;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.model.PageWrap;
+import com.doumee.core.utils.Constants;
 import com.doumee.core.utils.QrCodeUtils;
 import com.doumee.dao.business.model.RoomTime;
 import com.doumee.dao.web.request.RoomTimeRequest;
@@ -33,9 +36,9 @@
 @Api(tags = "3銆佷細璁涓氬姟")
 @Trace(exclude = true)
 @RestController
-@RequestMapping("/web/rooms")
+@RequestMapping(Constants.CLOUD_SERVICE_URL_INDEX+"/web/rooms")
 @Slf4j
-public class RoomsApi extends ApiController{
+public class RoomsApi extends BaseController {
 
     @Autowired
     private RoomsService roomsService;
@@ -43,57 +46,48 @@
     @Autowired
     private RoomTimeService roomTimeService;
 
-    @ApiOperation("鑾峰彇浼氳瀹ゅ紑闂ㄤ簩缁寸爜")
-    @GetMapping("/getQrCode")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳瀹や富閿�", required = true),
-    })
-    public ApiResponse<String> getQrCode(@RequestParam Integer id) {
-        return ApiResponse.success("鏌ヨ鎴愬姛", roomsService.getQrCode(id,getMemberId()));
-    }
+//    @ApiOperation("鑾峰彇浼氳瀹ゅ紑闂ㄤ簩缁寸爜")
+//    @GetMapping("/getQrCode")
+//    @ApiImplicitParams({
+//            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+//            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳瀹や富閿�", required = true),
+//    })
+//    public ApiResponse<String> getQrCode(@RequestParam Integer id) {
+//        return ApiResponse.success("鏌ヨ鎴愬姛", roomsService.getQrCode(id,getMemberId()));
+//    }
 
-    @ApiOperation("鑾峰彇浼氳瀹ゅ紑闂ㄤ簩缁寸爜-鍥剧墖娴�")
-    @GetMapping("/getQrCodeImg")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳瀹や富閿�", required = true),
-            @ApiImplicitParam(paramType = "query", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public void getQrCodeImg(@RequestParam Integer id,@RequestParam String token, HttpServletResponse response) throws  Exception {
-        Integer memberId = JwtTokenUtil.getJwtPayLoad(token).getMemberId();
-        response.setHeader("Cache-Control", "no-store, no-cache");
-        response.setContentType("image/jpeg");
-        String content =roomsService.getQrCode(id,memberId);
-        QrCodeUtils.encode(content,null, response.getOutputStream(), true);
-    }
+//    @ApiOperation("鑾峰彇浼氳瀹ゅ紑闂ㄤ簩缁寸爜-鍥剧墖娴�")
+//    @GetMapping("/getQrCodeImg")
+//    @ApiImplicitParams({
+//            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "id", value = "浼氳瀹や富閿�", required = true),
+//            @ApiImplicitParam(paramType = "query", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+//    })
+//    public void getQrCodeImg(@RequestParam Integer id,@RequestParam String token, HttpServletResponse response) throws  Exception {
+//        Integer memberId = JwtTokenUtil.getJwtPayLoad(token).getMemberId();
+//        response.setHeader("Cache-Control", "no-store, no-cache");
+//        response.setContentType("image/jpeg");
+//        String content =roomsService.getQrCode(id,memberId);
+//        QrCodeUtils.encode(content,null, response.getOutputStream(), true);
+//    }
 
 
     @ApiOperation("浼氳瀹ゅ垪琛�")
     @GetMapping("/roomsList")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public ApiResponse<List<RoomsResponse>> roomsList() {
+    public ApiResponse<List<RoomsResponse>> roomsList(@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
         return ApiResponse.success("鏌ヨ鎴愬姛",roomsService.getRoomsList());
     }
 
-
     @ApiOperation("浼氳瀹ゆ椂闂村紑鏀惧垪琛�")
     @PostMapping("/getRoomUseTime")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public ApiResponse<List<RoomTime>> getRoomUseTime(@RequestBody RoomTimeRequest roomTimeRequest) {
+    public ApiResponse<List<RoomTime>> getRoomUseTime(@RequestBody RoomTimeRequest roomTimeRequest,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
         return ApiResponse.success("鏌ヨ鎴愬姛",roomTimeService.getRoomUseTime(roomTimeRequest));
     }
 
     @ApiOperation("鎴戠殑浼氳瀹ゅ垪琛�")
     @PostMapping("/myRoomsPage")
-    @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
-    })
-    public ApiResponse<IPage<RoomsResponse>> myRoomsPage(@RequestBody PageWrap<RoomsRequest> pageWrap) {
-        pageWrap.getModel().setUserId(getMemberId());
+    public ApiResponse<IPage<RoomsResponse>> myRoomsPage(@RequestBody PageWrap<RoomsRequest> pageWrap,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
+        LoginUserInfo user = getLoginUser(token);
+        pageWrap.getModel().setUserId(user.getId());
         IPage<RoomsResponse> page = roomsService.getRoomsPage(pageWrap);
         return ApiResponse.success("鏌ヨ鎴愬姛",page);
     }
@@ -102,10 +96,9 @@
     @ApiOperation("浼氳瀹よ鎯�")
     @GetMapping("/getRoomDetail")
     @ApiImplicitParams({
-            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
             @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "roomId", value = "浼氳瀹や富閿�", required = true),
     })
-    public ApiResponse<RoomsResponse> getRoomDetail(@RequestParam Integer roomId) {
+    public ApiResponse<RoomsResponse> getRoomDetail(@RequestParam Integer roomId,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
         return ApiResponse.success("鏌ヨ鎴愬姛",roomsService.getRoomDetail(roomId));
     }
 
diff --git a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/UtilApi.java b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/UtilApi.java
index 091bf94..cde100f 100644
--- a/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/UtilApi.java
+++ b/server/meeting/meeting_admin/src/main/java/com/doumee/cloud/web/UtilApi.java
@@ -1,8 +1,10 @@
 package com.doumee.cloud.web;
 
+import com.doumee.api.BaseController;
 import com.doumee.biz.system.SystemDictDataBiz;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
+import com.doumee.core.utils.Constants;
 import com.doumee.dao.system.model.SystemDictData;
 import com.doumee.service.business.UtilService;
 import io.swagger.annotations.Api;
@@ -29,9 +31,9 @@
 @Api(tags = "99銆佸府鍔╀笟鍔�")
 @Trace(exclude = true)
 @RestController
-@RequestMapping("/web/util")
+@RequestMapping(Constants.CLOUD_SERVICE_URL_INDEX+"/web/util")
 @Slf4j
-public class UtilApi extends ApiController{
+public class UtilApi extends BaseController {
 
     @Autowired
     private UtilService utilService;
@@ -78,7 +80,5 @@
 
         }
     }
-
-
 
 }
diff --git a/server/meeting/meeting_service/src/main/java/com/doumee/dao/business/BookingsMapper.java b/server/meeting/meeting_service/src/main/java/com/doumee/dao/business/BookingsMapper.java
index cc0769d..e8e58bc 100644
--- a/server/meeting/meeting_service/src/main/java/com/doumee/dao/business/BookingsMapper.java
+++ b/server/meeting/meeting_service/src/main/java/com/doumee/dao/business/BookingsMapper.java
@@ -22,7 +22,7 @@
 
 
 
-    @Select(" select a.id , b.`NAME` as roomName , a.`NAME` as meetingName  ,date_format(a.START_TIME,'%Y-%m-%d') as meetingDate ," +
+    @Select(" select a.id , b.`NAME` as roomName , a.`NAME` as meetingName  ,date_format(a.START_TIME,'%Y-%m-%d') as meetingDate , a.START_TIME as startTime, a.status ," +
             " CONCAT(date_format(a.START_TIME,'%H:%i') , ' ~ ',date_format(a.END_TIME,'%H:%i')) as meetingTime,  c.REALNAME as bookingUser ," +
             " CASE  WHEN a.START_TIME > now() and a.`STATUS` = 0  THEN 1  WHEN a.END_TIME < now()  or a.`STATUS` = 1  THEN 3 ELSE 2  END meetingStatus , b.IMGURL as imgUrl " +
             " from meeting_book a inner join meeting_rooms b  on a.ROOM_ID = b.ID  " +
diff --git a/server/meeting/meeting_service/src/main/java/com/doumee/dao/web/response/MeetingListResponse.java b/server/meeting/meeting_service/src/main/java/com/doumee/dao/web/response/MeetingListResponse.java
index 9788683..4c21bae 100644
--- a/server/meeting/meeting_service/src/main/java/com/doumee/dao/web/response/MeetingListResponse.java
+++ b/server/meeting/meeting_service/src/main/java/com/doumee/dao/web/response/MeetingListResponse.java
@@ -6,6 +6,7 @@
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.Date;
 
 /**
  * Created by IntelliJ IDEA.
@@ -32,6 +33,13 @@
     @ApiModelProperty(value = "浼氳鏃堕棿 ( a ~ b)")
     private String meetingTime;
 
+
+    @ApiModelProperty(value = "浼氳寮�濮嬫椂闂�",hidden = true)
+    private Date startTime;
+
+    @ApiModelProperty(value = "鐘舵�� 0宸查绾� 1宸叉挙閿� ",hidden = true)
+    private Integer status;
+
     @ApiModelProperty(value = "浼氳棰勭害浜�")
     private String bookingUser;
 
@@ -41,7 +49,7 @@
     @ApiModelProperty(value = "鍓嶇紑")
     private String prefixUrl;
 
-    @ApiModelProperty(value = "浼氳鐘舵��: 1=鏈紑濮嬶紱2=杩涜涓紱3=宸茬粨鏉�")
+    @ApiModelProperty(value = "浼氳鐘舵��: 1=鏈紑濮嬶紱2=杩涜涓紱3=宸茬粨鏉� ; 4=鍗冲皢寮�濮�; 5=宸叉挙閿�")
     private Integer meetingStatus;
 
 }
diff --git a/server/meeting/meeting_service/src/main/java/com/doumee/service/business/impl/BookingsServiceImpl.java b/server/meeting/meeting_service/src/main/java/com/doumee/service/business/impl/BookingsServiceImpl.java
index d3a0a58..0a6fb11 100644
--- a/server/meeting/meeting_service/src/main/java/com/doumee/service/business/impl/BookingsServiceImpl.java
+++ b/server/meeting/meeting_service/src/main/java/com/doumee/service/business/impl/BookingsServiceImpl.java
@@ -120,7 +120,7 @@
     @Override
     @Transactional(rollbackFor = {BusinessException.class, Exception.class})
     public Integer create(Bookings bookings) {
-        LoginUserInfo user = new LoginUserInfo();
+        LoginUserInfo user = bookings.getLoginUserInfo();
         user.setId(bookings.getCreator());
         isCreateParamValid(bookings, user);
         bookings.setCreateDate(new Date());
@@ -778,6 +778,18 @@
         String path = systemDictDataBiz.queryByCode(MeetConstants.FTP, MeetConstants.FTP_RESOURCE_PATH).getCode() + systemDictDataBiz.queryByCode(MeetConstants.FTP, MeetConstants.PROJECTS).getCode();
         page.getRecords().forEach(i -> {
             i.setPrefixUrl(path);
+            if(i.getMeetingStatus().equals(Constants.ZERO)){
+                if(i.getStatus()==Constants.ONE){
+                    i.setMeetingStatus(5);
+                }else{
+                    //寮�濮嬪墠5鍒嗛挓 澶т簬褰撳墠鏃堕棿 鍒欐樉绀哄嵆灏嗗紑濮�
+                    if(DateUtil.afterMinutesDate(i.getStartTime(),-5).getTime()>System.currentTimeMillis()){
+                        i.setMeetingStatus(4);
+                    }
+                }
+
+            }
+
         });
         return page;
     }
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java b/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
index 0b94829..269002c 100644
--- a/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
+++ b/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
@@ -2849,9 +2849,9 @@
 
     public static void main(String[] args) {
         try {
-            Date date = getISO8601DateByStr("2024-04-15T07:46:36.014+08:00");
-            Date date1 = getISO8601DateByStr("2024-06-14T08:46:36.014+08:00");
-            System.out.println(daysBetweenDates11(date1,date)+1);
+//            Date date = getISO8601DateByStr("2024-04-15T07:46:36.014+08:00");
+//            Date date1 = getISO8601DateByStr("2024-06-14T08:46:36.014+08:00");
+            System.out.println(DateUtil.afterMinutesDate(-5));
 
         } catch (Exception ex) {
             ex.printStackTrace();
@@ -3108,6 +3108,18 @@
     }
 
     /**
+     * X 鍒嗛挓鍚庢椂闂�
+     * @param minutes
+     * @return
+     */
+    public static Date afterMinutesDate(Date date,Integer minutes){
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.MINUTE,minutes);
+        return cal.getTime();
+    }
+
+    /**
      * LocalDateTime to date
      * @param now
      * @return

--
Gitblit v1.9.3