Browse Source

Merge remote-tracking branch 'origin/dev' into dev2

wangmh 7 năm trước cách đây
mục cha
commit
dd82728d46
37 tập tin đã thay đổi với 990 bổ sung156 xóa
  1. 1 1
      sso-manage-console-web/src/Constant.js
  2. 28 9
      sso-manage-console-web/src/components/accounts/appeals/AppealHome.vue
  3. 0 6
      sso-manage-console-web/src/components/accounts/enterprises/EnterpriseAdmin.vue
  4. 41 4
      sso-manage-console-web/src/components/accounts/enterprises/EnterpriseAuth.vue
  5. 1 1
      sso-manage-console-web/src/components/accounts/enterprises/EnterpriseBasicInfo.vue
  6. 1 1
      sso-manage-console-web/src/components/accounts/enterprises/EnterpriseHome.vue
  7. 5 1
      sso-manage-console-web/src/components/accounts/enterprises/common/MessageList.vue
  8. 199 0
      sso-manage-console-web/src/components/accounts/users/UserAuth.vue
  9. 79 0
      sso-manage-console-web/src/components/accounts/users/UserBaseAction.vue
  10. 77 79
      sso-manage-console-web/src/components/accounts/users/UserBasicInfo.vue
  11. 5 1
      sso-manage-console-web/src/components/accounts/users/index.js
  12. 16 5
      sso-manage-console-web/src/router/index.js
  13. 8 1
      sso-manage-console-web/src/store/modules/accounts.js
  14. 0 1
      sso-manage-console-web/src/store/modules/enterprises.js
  15. 2 0
      sso-manage-console-web/src/store/mutation-types.js
  16. 1 0
      sso-manage-console/build.gradle
  17. 18 1
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserManageController.java
  18. 10 2
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserSpaceManageController.java
  19. 39 0
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/MailService.java
  20. 12 1
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserBackendService.java
  21. 10 1
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserSpaceService.java
  22. 52 1
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/AppealServiceImpl.java
  23. 107 0
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/MailServiceImpl.java
  24. 56 3
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserBackendServiceImpl.java
  25. 47 28
      sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserSpaceServiceImpl.java
  26. 7 0
      sso-manage-console/src/main/resources/config/application-dev.properties
  27. 7 0
      sso-manage-console/src/main/resources/config/application-prod.properties
  28. 7 0
      sso-manage-console/src/main/resources/config/application-test.properties
  29. 30 0
      sso-manage-console/src/main/resources/templates/appealPass.html
  30. 30 0
      sso-manage-console/src/main/resources/templates/appealUnPass.html
  31. 3 7
      sso-manage-console/src/test/java/com/uas/sso/sso/backend/ManageConsoleApplicationTests.java
  32. 40 0
      sso-manage-console/src/test/java/com/uas/sso/sso/backend/service/MailServiceTest.java
  33. 34 0
      sso-manage-console/src/test/resources/application-dev.properties
  34. 2 2
      sso-server/src/main/java/com/uas/sso/controller/UserspaceManagerController.java
  35. 4 0
      sso-server/src/main/java/com/uas/sso/dao/UserValidDao.java
  36. 3 0
      sso-server/src/main/java/com/uas/sso/dao/UserspaceValidDao.java
  37. 8 0
      sso-server/src/main/java/com/uas/sso/entity/UserspaceValid.java

+ 1 - 1
sso-manage-console-web/src/Constant.js

@@ -1,6 +1,6 @@
 const ValidCode = [
   {
-    label: '未申请',
+    label: '未认证',
     key: 'NOT_APPLYING',
     value: 0
   }, {

+ 28 - 9
sso-manage-console-web/src/components/accounts/appeals/AppealHome.vue

@@ -60,7 +60,7 @@
         label="申诉状态"
         width="100">
         <template slot-scope="scope">
-          <span v-if="scope.row.status === 2">已认证</span>
+          <span v-if="scope.row.status === 2">已通过</span>
           <!--<span v-if="scope.row.status === 0">未认证</span>-->
           <span v-if="scope.row.status === 1" style="color: #E68615;">申诉中</span>
           <span v-if="scope.row.status === 3">未通过</span>
@@ -112,7 +112,7 @@
       </el-table-column>
       <el-table-column
         prop="contactTel"
-        label="手机号"
+        label="联系电话"
         width="120">
       </el-table-column>
       <el-table-column
@@ -152,11 +152,11 @@
         </div>
         <div class="row">
           <div class="col-lg-6">
-            <div class="message-label">手机号</div>
-            <div class="message-value" v-text="selectedAppeal.mobile"></div>
+            <div class="message-label">手机号</div>
+            <div class="message-value" v-text="selectedAppeal.oldMobile"></div>
           </div>
           <div class="col-lg-6">
-            <div class="message-label">手机号</div>
+            <div class="message-label">联系电话</div>
             <div class="message-value" v-text="selectedAppeal.contactTel"></div>
           </div>
         </div>
@@ -173,10 +173,10 @@
             </div>
           </div>
           <div class="row">
-            <div class="col-lg-6">
+            <!--<div class="col-lg-6">
               <div class="message-label">原手机号</div>
               <div class="message-value" v-text="selectedAppeal.oldMobile"></div>
-            </div>
+            </div>-->
             <div class="col-lg-6">
               <div class="message-label">绑定邮箱</div>
               <div class="message-value" v-text="selectedAppeal.oldEmail"></div>
@@ -187,8 +187,8 @@
         <div class="validate-mobile" v-if="approveType === 'validAccount'">
           <div class="row">
             <div class="col-lg-6">
-              <div class="message-label">手机号</div>
-              <div class="message-value" v-text="selectedAppeal.contactTel"></div>
+              <div class="message-label">手机号</div>
+              <div class="message-value" v-text="selectedAppeal.mobile"></div>
             </div>
             <div class="col-lg-6">
               <div class="message-label">电子邮箱</div>
@@ -299,6 +299,25 @@
             </div>
           </div>
         </div>
+        <!-- 联系人 -->
+        <div style="border-bottom: 1px solid #E5E5E5;padding: 26px 0;">
+          <div class="row">
+            <div class="col-lg-6">
+              <div class="message-label">联系人</div>
+              <div class="message-value" v-text="selectedAppeal.contactName"></div>
+            </div>
+            <div class="col-lg-6">
+              <div class="message-label">联系电话</div>
+              <div class="message-value" v-text="selectedAppeal.contactTel"></div>
+            </div>
+          </div>
+          <div class="row">
+            <div class="col-lg-6">
+              <div class="message-label">电子邮箱</div>
+              <div class="message-value" v-text="selectedAppeal.contactEmail"></div>
+            </div>
+          </div>
+        </div>
       </div>
 
       <div v-if="!canApprove">

+ 0 - 6
sso-manage-console-web/src/components/accounts/enterprises/EnterpriseAdmin.vue

@@ -191,12 +191,6 @@
               const routeLocation = {name: 'UserBasicInfo', params: enterprise.admin, replace: true}
               this.$router.push(routeLocation)
             }
-          } else if (info.label === '申诉状态' && info.value && info.value === '申诉中') {
-            info.suffixClass = 'admin-message'
-            info.action = () => {
-              const routeLocation = {name: 'AppealHome', replace: true}
-              this.$router.push(routeLocation)
-            }
           }
         }
         return adminInfo

+ 41 - 4
sso-manage-console-web/src/components/accounts/enterprises/EnterpriseAuth.vue

@@ -1,9 +1,12 @@
 <template>
   <div>
-    <message-list :messages="messages">
+    <message-list :messages="messages" v-if="spaceValid && spaceValid.validCode">
       <button class="btn btn-default btn-auth" slot="action" @click="passAuth">认证通过</button>
       <button class="btn btn-default" slot="action" @click="failAuth">不通过</button>
     </message-list>
+    <div v-if="!spaceValid || !spaceValid.validCode" style="text-align: center; padding: 15px; font-size: 18px;">
+      暂无企业认证信息
+    </div>
 
     <!-- 更换管理员对话框 -->
     <el-dialog
@@ -27,6 +30,7 @@
 </template>
 
 <script>
+  import _ from 'lodash'
   import axios from '@/assets/js/axios'
   import MessageList from './common/MessageList'
   import * as types from '@/store/mutation-types'
@@ -39,12 +43,21 @@
     data () {
       return {
         isShowReasonDialog: false,
-        reason: ''
+        reason: '',
+        spaceValid: {}
       }
     },
     computed: {
       messages () {
-        return this.$store.getters.enAuthInfo
+        const enterprise = this.spaceValid || {}
+        const messages = []
+
+        messages.push({ label: '企业名称', value: enterprise.spaceName || '' })
+        messages.push({ label: '法定代表人', value: enterprise.corporation || '' })
+        messages.push({ label: '营业执照号', value: enterprise.businessCode || '' })
+        messages.push({ label: '营业执照附件', value: enterprise.businessCodeImage || '', isLink: true })
+        messages.push({ label: '企业地址', value: enterprise.regAddress || '' })
+        return messages
       },
       enterprise () {
         return this.$store.state.enterprises.savedEnterprise
@@ -59,6 +72,7 @@
           this.$store.commit(types.CHOOSE_ENTERPRISE, userSpace)
 
           this.$message.success('保存成功')
+          this.$router.push({ path: '/accounts/enterprise/basic' })
         }
 
         this.saveAuthInfo(true, null, success, this.showErrorMessage)
@@ -79,21 +93,44 @@
 
           this.$message.success('保存成功')
           this.isShowReasonDialog = false
+          this.$router.push({ path: '/accounts/enterprise/basic' })
         }
 
         this.saveAuthInfo(false, this.reason, success, this.showErrorMessage)
       },
       saveAuthInfo (isPass, reason, success, error) {
+        console.log('Space Valid', this.spaceValid)
+        const validId = this.spaceValid.id
         const spaceUU = this.enterprise.spaceUU
-        const params = { isPass }
+        const params = { isPass, validId }
         if (!isPass) {
           params.reason = reason
         }
 
+        console.log('Auth params', params)
         return axios.put(`/api/user/space/${spaceUU}/authEnterpriseInfo`, {}, { params })
           .then(success)
           .catch(error)
       }
+    },
+    mounted () {
+      const params = { spaceUU: this.enterprise.spaceUU }
+      axios.get('/api/user/space//loadSpaceValid', { params })
+        .then(response => {
+          if (response && response.validCode === 1) {
+            const userSpace = response
+            const submitInfo = JSON.parse(userSpace.submitInfo)
+            this.spaceValid = _.defaultsDeep({}, userSpace, submitInfo)
+
+            console.log('response', this.spaceValid)
+          } else {
+            this.spaceValid = {}
+          }
+        })
+        .catch(error => {
+          console.log(error)
+          this.spaceValid = {}
+        })
     }
   }
 </script>

+ 1 - 1
sso-manage-console-web/src/components/accounts/enterprises/EnterpriseBasicInfo.vue

@@ -32,7 +32,7 @@
         </el-input>
       </el-form-item>
       <el-form-item label="企业地址">
-        <el-input v-model="enterpriseInfo.companyAddress" :readonly="false">
+        <el-input v-model="enterpriseInfo.companyAddress || enterpriseInfo.regAddress" :readonly="false">
           <i class="el-input__icon" slot="prefix" style="line-height: 16px;margin-left: 10px;">
             <img src="/static/images/loc.png" alt="Location">
           </i>

+ 1 - 1
sso-manage-console-web/src/components/accounts/enterprises/EnterpriseHome.vue

@@ -53,7 +53,7 @@
         label="认证状态"
         width="100">
         <template slot-scope="scope">
-          <span v-if="scope.row.validCode === 0">未申请</span>
+          <span v-if="scope.row.validCode === 0">未认证</span>
           <span v-if="scope.row.validCode === 1" style="color: #E68615;">待认证</span>
           <span v-if="scope.row.validCode === 2">已认证</span>
           <span v-if="scope.row.validCode === 3">未通过</span>

+ 5 - 1
sso-manage-console-web/src/components/accounts/enterprises/common/MessageList.vue

@@ -2,9 +2,13 @@
   <div class="message-panel">
     <div class="row" v-for="message in messages">
       <div class="message-label">{{ message.label }}</div>
-      <div class="message-value" :class="message.suffixClass">
+      <div class="message-value" :class="message.suffixClass" v-if="!message.isLink">
         <span @click="message.action()">{{ message.value }}</span>
         <span v-if="message.suffixClass"></span>
+        <span v-if="message.isLink"></span>
+      </div>
+      <div class="message-value" v-if="message.isLink">
+        <a :href="message.value" target="_blank">附件</a>
       </div>
     </div>
     <div class="row message-action">

+ 199 - 0
sso-manage-console-web/src/components/accounts/users/UserAuth.vue

@@ -0,0 +1,199 @@
+<template>
+  <div>
+    <message-list :messages="messages" v-if="userValid && userValid.validCode">
+      <button class="btn btn-default btn-auth" slot="action" @click="passAuth">认证通过</button>
+      <button class="btn btn-default" slot="action" @click="failAuth">不通过</button>
+    </message-list>
+    <div v-if="!userValid || !userValid.validCode" style="text-align: center; padding: 15px; font-size: 18px;">
+      暂无用户身份认证信息
+    </div>
+
+    <!-- 更换管理员对话框 -->
+    <el-dialog
+      title="未通过原因"
+      :visible.sync="isShowReasonDialog"
+      width="450px"
+      :show-close="true"
+      :append-to-body="true">
+      <!-- 对话框内容 -->
+      <!-- 用户信息展示 -->
+      <div class="input-fail-pass-reason">
+        <textarea class="form-control" rows="4" placeholder="请输入未通过原因" v-model="reason"></textarea>
+      </div>
+      <!-- 对话框尾部 -->
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFailReason">确 定</el-button>
+        <el-button @click="isShowReasonDialog = false">取 消</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import _ from 'lodash'
+  import axios from '@/assets/js/axios'
+  import MessageList from '../enterprises/common/MessageList'
+  import * as types from '@/store/mutation-types'
+
+  export default {
+    name: 'enterprise-auth',
+    components: {
+      MessageList
+    },
+    data () {
+      return {
+        isShowReasonDialog: false,
+        reason: '',
+        userValid: ''
+      }
+    },
+    computed: {
+      messages () {
+        const userInfo = this.userValid || {}
+        const messages = []
+
+        messages.push({ label: '真实姓名', value: userInfo.realName || '' })
+        messages.push({ label: '身份证号', value: userInfo.idCard || '' })
+        return messages
+      },
+      userInfo () {
+        return this.$store.state.accounts.savedUser
+      }
+    },
+    methods: {
+      showErrorMessage (error) {
+        this.$message.error(error)
+      },
+      passAuth () {
+        const success = userInfo => {
+          this.$store.commit(types.CHOOSE_USER, userInfo)
+
+          this.$message.success('保存成功')
+          this.$router.push({ path: '/accounts/user/basic' })
+        }
+
+        this.saveAuthInfo(true, null, success, this.showErrorMessage)
+      },
+      failAuth () {
+        this.reason = ''
+
+        this.isShowReasonDialog = true
+      },
+      submitFailReason () {
+        if (!this.reason) {
+          this.$message.error('不通过原因不能为空')
+          return 0
+        }
+
+        const success = userInfo => {
+          this.$store.commit(types.CHOOSE_USER, userInfo)
+
+          this.$message.success('保存成功')
+          this.isShowReasonDialog = false
+          this.$router.push({ path: '/accounts/user/basic' })
+        }
+
+        this.saveAuthInfo(false, this.reason, success, this.showErrorMessage)
+      },
+      saveAuthInfo (isPass, reason, success, error) {
+        const validId = this.userValid.id
+        const userUU = this.userInfo.userUU
+        const params = { isPass, validId }
+        if (!isPass) {
+          params.reason = reason
+        }
+
+        console.log('Auth params', params)
+        return axios.put(`/api/user/${userUU}/authUserValid`, {}, { params })
+          .then(success)
+          .catch(error)
+      }
+    },
+    mounted () {
+      const params = { userUU: this.userInfo.userUU }
+      axios.get('/api/user//loadUserValid', { params })
+        .then(valid => {
+          if (valid && valid.validCode === 1) {
+            const submitInfo = JSON.parse(valid.submitInfo)
+            this.userValid = _.defaultsDeep({}, valid, submitInfo)
+
+            console.log('User Valid:', this.userValid)
+          } else {
+            this.userValid = {}
+          }
+        })
+        .catch(error => {
+          console.log(error)
+          this.userValid = {}
+        })
+    }
+  }
+</script>
+
+<style scoped>
+  .message-panel .message-action button.btn-auth {
+    border-color: #4E8EFC;
+    background-color: #4E8EFC;
+
+    color: #FFFFFF;
+  }
+</style>
+
+<style>
+  .el-dialog {
+    border-radius: 5px;
+  }
+  .el-dialog__header {
+    padding: 14px 20px;
+    height: 44px;
+    line-height: 16px;
+    border: 1px none #D2D2D2;
+    border-bottom-style: solid;
+  }
+  .el-dialog__header .el-dialog__title {
+    color: #000000;
+    font-size: 16px;
+    font-weight: normal;
+    font-family: "SimHei", sans-serif;
+  }
+  .el-dialog__body {
+    padding: 22px 0 22px 40px;
+  }
+  .input-fail-pass-reason {
+    margin: 0 30px 30px -10px;
+    width: 400px;
+  }
+  .input-fail-pass-reason textarea {
+    width: 400px;
+    resize: none;
+  }
+  .el-select .el-input__inner {
+    border-radius: 0;
+    width: 128px;
+    height: 32px;
+  }
+  .search-group .el-input__inner {
+    width: 186px;
+    height: 30px;
+    border-radius: 0;
+    border: none;
+  }
+  .el-dialog__footer {
+    text-align: center;
+  }
+  .el-dialog__footer .el-button {
+    width: 180px;
+    height: 30px;
+    border-radius: 15px;
+    line-height: 14px;
+    padding: 8px 0;
+
+    background: none;
+
+    color: #656565;
+  }
+  .el-dialog__footer .el-button--primary {
+    background-color: #4E8EFC;
+    color: #FFFFFF;
+  }
+</style>

+ 79 - 0
sso-manage-console-web/src/components/accounts/users/UserBaseAction.vue

@@ -0,0 +1,79 @@
+<template>
+  <div style="min-height: 570px;">
+    <div>
+      <ul class="nav nav-tabs">
+        <li @click="$router.go(-1)">
+          <img src="/static/images/go_back.png" alt="GoBack"/>
+        </li>
+        <router-link tag="li" active-class="active" :to="{name: 'UserBasicInfo'}" replace>
+          <a>基本信息</a><span class="triangle"></span></router-link>
+        <router-link tag="li" active-class="active" :to="{name: 'UserAuth'}" replace>
+          <a>认证信息</a><span class="triangle"></span></router-link>
+      </ul>
+    </div>
+
+    <router-view></router-view>
+  </div>
+</template>
+
+<script>
+  import * as types from '@/store/mutation-types'
+
+  export default {
+    name: 'common-menu',
+    beforeRouteLeave (to, from, next) {
+      // 清除 store 数据
+      this.$store.commit(types.CLEAR_USER)
+      next()
+    }
+  }
+</script>
+
+<style scoped>
+  .nav-tabs {
+    background-color: #E6EDF1;
+  }
+  .nav-tabs>li {
+    height: 60px;
+  }
+  .nav-tabs>li>img {
+    margin: 13px 38px 13px 14px;
+
+    cursor: pointer;
+  }
+  .nav-tabs>li>a {
+    margin: 13px 0;
+    border: none;
+    height: 34px;
+    padding: 9px 8px;
+    line-height: 14px;
+    background: none;
+
+    color: #646464;
+    font-size: 14px;
+    font-family: "Microsoft YaHei", sans-serif;
+  }
+  .nav-tabs>li.active>a {
+    color: #323232;
+    font-weight: bold;
+  }
+  .nav-tabs>li.active>a,
+  .nav-tabs>li.active>a:focus,
+  .nav-tabs>li.active>a:hover {
+    cursor: pointer;
+    border: none;
+    background: none;
+  }
+  .nav-tabs>li.active .triangle{
+    position: absolute;
+    width: 24px;
+    height: 12px;
+    border-right: 12px solid transparent;
+    border-left: 12px solid transparent;
+    border-bottom: 12px solid #FFFFFF;
+    z-index: 99;
+    bottom: 0;
+    left: 50%;
+    margin-left: -12px;
+  }
+</style>

+ 77 - 79
sso-manage-console-web/src/components/accounts/users/UserBasicInfo.vue

@@ -1,87 +1,78 @@
 <template>
-  <div style="min-height: 570px;">
-    <div>
-      <ul class="nav nav-tabs">
-        <li @click="$router.go(-1)">
-          <img src="/static/images/go_back.png" alt="GoBack"/>
-        </li>
-        <li role="presentation" class="active"><a>基本信息</a><span class="triangle"></span></li>
-      </ul>
-    </div>
-    <div class="basic-user-info" style="padding: 30px 0 0;width: 490px;">
-      <el-form ref="form" :model="userInfo" label-width="150px">
-        <el-form-item label="个人UU">
-          <div>{{ userInfo.userUU }}</div>
-        </el-form-item>
-        <el-form-item label="个人名称">
-          <el-input v-model="userInfo.vipName"></el-input>
-        </el-form-item>
-        <el-form-item label="手机号">
-          <el-input v-model="userInfo.mobile"></el-input>
-        </el-form-item>
-        <el-form-item label="手机认证">
-          <el-select v-model="userInfo.mobileValidCode" placeholder="请选择认证状态">
-            <el-option label="已认证" :value="2"></el-option>
-            <el-option label="未认证" :value="0"></el-option>
-            <el-option label="申诉中" :value="1"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="邮箱">
-          <el-input v-model="userInfo.email"></el-input>
-        </el-form-item>
-        <el-form-item label="邮箱认证">
-          <el-select v-model="userInfo.emailValidCode" width="340" placeholder="请选择认证状态">
-            <el-option label="已认证" :value="2"></el-option>
-            <el-option label="未认证" :value="0"></el-option>
-            <el-option label="申诉中" :value="1"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="密码">
-          <el-input type="password" v-model="userInfo.password" auto-complete="off"></el-input>
-        </el-form-item>
-        <el-form-item label="账号冻结">
-          <el-select v-model="userInfo.lock" placeholder="请选择是否冻结账号">
-            <el-option label="是" :value="1"></el-option>
-            <el-option label="否" :value="0"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="真实姓名">
-          <el-input v-model="userInfo.realName"></el-input>
-        </el-form-item>
-        <el-form-item label="身份证号">
-          <el-input v-model="userInfo.idCard"></el-input>
-        </el-form-item>
-        <el-form-item label="实名认证">
-          <el-select v-model="userInfo.identityValidCode" placeholder="请选择认证状态">
-            <el-option label="已认证" :value="2"></el-option>
-            <el-option label="未认证" :value="0"></el-option>
-            <el-option label="待认证" :value="1"></el-option>
-            <el-option label="未通过" :value="3"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="注册时间">
-          <div v-text="formatDate(userInfo.registerDate)"></div>
-        </el-form-item>
-        <el-form-item label="上次登录">
-          <div v-text="formatDate(userInfo.lastLoginTime)"></div>
-        </el-form-item>
-        <el-form-item label="注册来源">
-          <div>{{ userInfo.fromApp }}</div>
-        </el-form-item>
-        <el-form-item>
-          <div class="action-form-item">
-            <el-button type="primary" @click="onSubmit" :disabled="!isChange">保存修改</el-button>
-            <el-button @click="$router.go(-1)">返回</el-button>
-          </div>
-        </el-form-item>
-      </el-form>
-    </div>
+  <div class="basic-user-info" style="padding: 30px 0 0;width: 490px;">
+    <el-form ref="form" :model="userInfo" label-width="150px">
+      <el-form-item label="个人UU">
+        <div>{{ userInfo.userUU }}</div>
+      </el-form-item>
+      <el-form-item label="个人名称">
+        <el-input v-model="userInfo.vipName"></el-input>
+      </el-form-item>
+      <el-form-item label="手机号">
+        <el-input v-model="userInfo.mobile"></el-input>
+      </el-form-item>
+      <el-form-item label="手机认证">
+        <el-select v-model="userInfo.mobileValidCode" placeholder="请选择认证状态">
+          <el-option label="已认证" :value="2"></el-option>
+          <el-option label="未认证" :value="0"></el-option>
+          <el-option label="申诉中" :value="1"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="邮箱">
+        <el-input v-model="userInfo.email"></el-input>
+      </el-form-item>
+      <el-form-item label="邮箱认证">
+        <el-select v-model="userInfo.emailValidCode" width="340" placeholder="请选择认证状态">
+          <el-option label="已认证" :value="2"></el-option>
+          <el-option label="未认证" :value="0"></el-option>
+          <el-option label="申诉中" :value="1"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="密码">
+        <el-input type="password" v-model="userInfo.password" auto-complete="off"></el-input>
+      </el-form-item>
+      <el-form-item label="账号冻结">
+        <el-select v-model="userInfo.lock" placeholder="请选择是否冻结账号">
+          <el-option label="是" :value="1"></el-option>
+          <el-option label="否" :value="0"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="真实姓名">
+        <el-input v-model="userInfo.realName"></el-input>
+      </el-form-item>
+      <el-form-item label="身份证号">
+        <el-input v-model="userInfo.idCard"></el-input>
+      </el-form-item>
+      <el-form-item label="实名认证">
+        <el-select v-model="userInfo.identityValidCode" placeholder="请选择认证状态">
+          <el-option label="已认证" :value="2"></el-option>
+          <el-option label="未认证" :value="0"></el-option>
+          <el-option label="待认证" :value="1"></el-option>
+          <el-option label="未通过" :value="3"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="注册时间">
+        <div v-text="formatDate(userInfo.registerDate)"></div>
+      </el-form-item>
+      <el-form-item label="上次登录">
+        <div v-text="formatDate(userInfo.lastLoginTime)"></div>
+      </el-form-item>
+      <el-form-item label="注册来源">
+        <div>{{ userInfo.fromApp }}</div>
+      </el-form-item>
+      <el-form-item>
+        <div class="action-form-item">
+          <el-button type="primary" @click="onSubmit" :disabled="!isChange">保存修改</el-button>
+          <el-button @click="$router.go(-1)">返回</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
   </div>
 </template>
 
 <script>
   import _ from 'lodash'
   import axios from '@/assets/js/axios'
+  import * as types from '@/store/mutation-types'
   import { formatDate } from '@/assets/js/utils'
 
   export default {
@@ -110,7 +101,9 @@
           ]
         )
 
-        const success = () => {
+        const success = (userInfo) => {
+          this.$store.commit(types.CHOOSE_USER, userInfo)
+
           this.isChange = false
           this.$message.success('保存成功')
         }
@@ -125,7 +118,12 @@
       }
     },
     mounted () {
-      this.userInfo = Object.assign({}, this.userInfo, this.$route.params)
+      if (this.$route.params && this.$route.params.userUU) {
+        this.$store.commit(types.CHOOSE_USER, this.$route.params)
+      }
+      const user = this.$store.state.accounts.savedUser
+
+      this.userInfo = Object.assign({}, this.userInfo, user)
     },
     watch: {
       userInfo: {

+ 5 - 1
sso-manage-console-web/src/components/accounts/users/index.js

@@ -1,7 +1,11 @@
 import UserHome from './UserHome'
+import UserBaseAction from './UserBaseAction'
 import UserBasicInfo from './UserBasicInfo'
+import UserAuth from './UserAuth'
 
 export {
   UserHome,
-  UserBasicInfo
+  UserBaseAction,
+  UserBasicInfo,
+  UserAuth
 }

+ 16 - 5
sso-manage-console-web/src/router/index.js

@@ -7,7 +7,7 @@ import {
   EnterpriseAdmin, EnterpriseApps, EnterpriseAuth, EnterpriseBaseAction,
   EnterpriseBasicInfo, EnterpriseHome, EnterpriseMembers
 } from '@/components/accounts/enterprises'
-import {UserBasicInfo, UserHome} from '@/components/accounts/users'
+import {UserBasicInfo, UserBaseAction, UserHome, UserAuth} from '@/components/accounts/users'
 import {AppealHome} from '@/components/accounts/appeals'
 
 Vue.use(Router)
@@ -87,9 +87,8 @@ export default new Router({
           component: UserHome
         },
         {
-          path: 'user/basic',
-          name: 'UserBasicInfo',
-          component: UserBasicInfo,
+          path: 'user',
+          component: UserBaseAction,
           beforeEnter: (to, from, next) => {
             const userInfo = to.params
             if (userInfo.userUU) {
@@ -97,7 +96,19 @@ export default new Router({
             } else {
               next({ name: 'UserHome', replace: true })
             }
-          }
+          },
+          children: [
+            {
+              path: 'basic',
+              name: 'UserBasicInfo',
+              component: UserBasicInfo
+            },
+            {
+              path: 'auth',
+              name: 'UserAuth',
+              component: UserAuth
+            }
+          ]
         },
         {
           path: 'appeal',

+ 8 - 1
sso-manage-console-web/src/store/modules/accounts.js

@@ -7,7 +7,8 @@ function countUnHandleAppeals () {
 
 // State
 const state = {
-  unHandleCount: 0
+  unHandleCount: 0,
+  savedUser: {}
 }
 
 // Getters
@@ -35,6 +36,12 @@ const actions = {
 const mutations = {
   [types.COUNT_UN_HANDLE_APPEALS] (state, count) {
     state.unHandleCount = count || 0
+  },
+  [types.CHOOSE_USER] (state, user) {
+    state.savedUser = user || {}
+  },
+  [types.CLEAR_USER] (state) {
+    state.savedUser = {}
   }
 }
 

+ 0 - 1
sso-manage-console-web/src/store/modules/enterprises.js

@@ -24,7 +24,6 @@ const getters = {
 
     messages.push({ label: '邮箱', value: admin.email || '' })
 
-    messages.push({ label: '申诉状态', value: validStatus[enterprise.validCode] })
     return messages
   },
   enAuthInfo: state => {

+ 2 - 0
sso-manage-console-web/src/store/mutation-types.js

@@ -6,3 +6,5 @@ export const ADD_TO_CART = 'ADD_TO_CART'
 export const SET_CART_ITEMS = 'SET_CART_ITEMS'
 export const SET_CHECKOUT_STATUS = 'SET_CHECKOUT_STATUS'
 export const RECEIVE_PRODUCTS = 'RECEIVE_PRODUCTS'
+export const CHOOSE_USER = 'CHOOSE_USER'
+export const CLEAR_USER = 'CLEAR_USER'

+ 1 - 0
sso-manage-console/build.gradle

@@ -27,6 +27,7 @@ dependencies {
   compile("org.springframework.boot:spring-boot-starter-thymeleaf")
   compile("org.springframework.boot:spring-boot-starter-data-jpa")
   compile("org.springframework.boot:spring-boot-starter-actuator")
+  compile("org.springframework.boot:spring-boot-starter-mail")
   compile("net.sourceforge.nekohtml:nekohtml:1.9.15")
 
   compile('commons-codec:commons-codec:1.11')

+ 18 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserManageController.java

@@ -1,6 +1,7 @@
 package com.uas.sso.sso.backend.api;
 
 import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserValid;
 import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import com.uas.sso.sso.backend.service.UserBackendService;
@@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Pageable;
 import org.springframework.http.MediaType;
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -69,7 +71,7 @@ public class UserManageController {
 
     @RequestMapping(method = RequestMethod.PUT, path = "//modifyUserInfo",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-    public ResultBean<Boolean> modifyUserInfo(@RequestBody UpdateUserInfo userInfo) {
+    public ResultBean<User> modifyUserInfo(@RequestBody UpdateUserInfo userInfo) {
 
         return new ResultBean<>(userBackendService.modifyUserInfo(userInfo));
     }
@@ -80,4 +82,19 @@ public class UserManageController {
 
         return new ResultBean<>(userBackendService.addNewUser(userInfo));
     }
+
+    @RequestMapping(method = RequestMethod.GET, path = "//loadUserValid",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResultBean<UserValid> loadUserValid(Long userUU) {
+
+        return new ResultBean<>(userBackendService.loadUserValid(userUU));
+    }
+
+    @RequestMapping(method = RequestMethod.PUT, path = "/{userUU}/authUserValid",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResultBean<User> authUserValid(@PathVariable("userUU") Long userUU,
+        Long validId, Boolean isPass, @RequestParam(required = false) String reason) {
+
+        return new ResultBean<>(userBackendService.authUserValid(userUU, validId, isPass, reason));
+    }
 }

+ 10 - 2
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserSpaceManageController.java

@@ -1,6 +1,7 @@
 package com.uas.sso.sso.backend.api;
 
 import com.uas.sso.entity.Userspace;
+import com.uas.sso.entity.UserspaceValid;
 import com.uas.sso.sso.backend.dto.UpdateSpaceInfo;
 import com.uas.sso.sso.backend.service.UserSpaceService;
 import com.uas.sso.sso.backend.support.ResultBean;
@@ -66,9 +67,9 @@ public class UserSpaceManageController {
     @RequestMapping(method = RequestMethod.PUT, path = "/{spaceUU}/authEnterpriseInfo",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
     public ResultBean<Userspace> authEnterpriseInfo(@PathVariable("spaceUU") Long spaceUu,
-            Boolean isPass, @RequestParam(required = false) String reason) {
+            Long validId, Boolean isPass, @RequestParam(required = false) String reason) {
 
-        return new ResultBean<>(spaceService.authEnterpriseInfo(spaceUu, isPass, reason));
+        return new ResultBean<>(spaceService.authEnterpriseInfo(spaceUu, validId, isPass, reason));
     }
 
     @RequestMapping(method = RequestMethod.PUT, path = "/{spaceUU}/addUserToSpace",
@@ -84,4 +85,11 @@ public class UserSpaceManageController {
 
         return new ResultBean<>(spaceService.bindAppWithSpace(spaceUu, appUid));
     }
+
+    @RequestMapping(method = RequestMethod.GET, path = "//loadSpaceValid",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResultBean<UserspaceValid> loadSpaceValid(Long spaceUU) {
+
+        return new ResultBean<>(spaceService.loadSpaceValid(spaceUU));
+    }
 }

+ 39 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/MailService.java

@@ -0,0 +1,39 @@
+package com.uas.sso.sso.backend.service;
+
+import java.util.Map;
+
+/**
+ * Service class is used for sending email to notify peoples.
+ *
+ * @author huxz
+ */
+public interface MailService {
+
+    /**
+     * Send simple mail.
+     *
+     * @param to    receipts
+     * @param subject   subject of mail
+     * @param content   content of mail
+     */
+    void sendSimpleMail(String to, String subject, String content);
+
+    /**
+     * Send an html mail.
+     *
+     * @param to receipt
+     * @param subject   subject of mail
+     * @param content   content of mail
+     */
+    void sendHtmlMail(String to, String subject, String content);
+
+    /**
+     * Send a mail with html template.
+     *
+     * @param to    receipt
+     * @param subject   subject of mail
+     * @param params    the params which template needs
+     * @param templateName  name of html template
+     */
+    void sendTemplateMail(String to, String subject, Map<String, String> params, String templateName);
+}

+ 12 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserBackendService.java

@@ -1,6 +1,7 @@
 package com.uas.sso.sso.backend.service;
 
 import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserValid;
 import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import java.util.List;
@@ -63,7 +64,7 @@ public interface UserBackendService {
      * @param userInfo  用户信息
      * @return  操作状态
      */
-    Boolean modifyUserInfo(UpdateUserInfo userInfo);
+    User modifyUserInfo(UpdateUserInfo userInfo);
 
     /**
      * 后台新增用户。
@@ -72,5 +73,15 @@ public interface UserBackendService {
      * @return  新创建的用户
      */
     User addNewUser(AddNewUserInfo userInfo);
+
+    /**
+     * 获取用户的身份认证信息
+     *
+     * @param userUU    用户UU
+     * @return  用户身份认证信息
+     */
+    UserValid loadUserValid(Long userUU);
+
+    User authUserValid(Long userUU, Long validId, Boolean isPass, String reason);
 }
 

+ 10 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserSpaceService.java

@@ -1,6 +1,7 @@
 package com.uas.sso.sso.backend.service;
 
 import com.uas.sso.entity.Userspace;
+import com.uas.sso.entity.UserspaceValid;
 import com.uas.sso.sso.backend.dto.UpdateSpaceInfo;
 import javax.validation.constraints.NotNull;
 import org.springframework.data.domain.Page;
@@ -29,9 +30,17 @@ public interface UserSpaceService {
 
     Userspace changeAdmin(@NotNull Long spaceUu, @NotNull Long userUU);
 
-    Userspace authEnterpriseInfo(@NotNull Long spaceUu, @NotNull Boolean isPass, String reason);
+    Userspace authEnterpriseInfo(@NotNull Long spaceUu, Long validId, @NotNull Boolean isPass, String reason);
 
     void addUserToSpace(Long spaceUu, Long userUu);
 
     Userspace bindAppWithSpace(Long spaceUu, String appUid);
+
+    /**
+     * 获取企业的认证信息
+     *
+     * @param spaceUU   企业UU
+     * @return  企业认证信息
+     */
+    UserspaceValid loadSpaceValid(Long spaceUU);
 }

+ 52 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/AppealServiceImpl.java

@@ -4,6 +4,7 @@ import static com.uas.sso.sso.backend.AuthenticationUtils.getEncryPassword;
 
 import com.alibaba.fastjson.JSONObject;
 import com.uas.sso.core.Const;
+import com.uas.sso.core.ICallable;
 import com.uas.sso.dao.AppealDao;
 import com.uas.sso.dao.UserDao;
 import com.uas.sso.dao.UserspaceDao;
@@ -16,12 +17,15 @@ import com.uas.sso.sso.backend.entity.AdminChangeRecord;
 import com.uas.sso.sso.backend.entity.AdminChangeType;
 import com.uas.sso.sso.backend.exceptions.ValidationFailedException;
 import com.uas.sso.sso.backend.service.AppealService;
+import com.uas.sso.sso.backend.service.MailService;
 import com.uas.sso.sso.backend.service.UserBackendService;
 import com.uas.sso.sso.backend.util.JacksonUtils;
+import com.uas.sso.util.ExecuteUtils;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.persistence.criteria.CriteriaBuilder;
@@ -67,14 +71,17 @@ public class AppealServiceImpl implements AppealService {
 
     private final UserBackendService userService;
 
+    private final MailService mailService;
+
     @Autowired
     public AppealServiceImpl(AppealDao appealDao, UserDao userDao,
-                             UserspaceDao spaceDao, AdminChangeRecordDao recordDao, UserBackendService userService) {
+                             UserspaceDao spaceDao, AdminChangeRecordDao recordDao, UserBackendService userService, MailService mailService) {
         this.appealDao = appealDao;
         this.userDao = userDao;
         this.spaceDao = spaceDao;
         this.recordDao = recordDao;
         this.userService = userService;
+        this.mailService = mailService;
     }
 
     @Override
@@ -137,6 +144,18 @@ public class AppealServiceImpl implements AppealService {
         appealDao.save(appeal);
 
         if (!isPass) {
+            String spaceName = null;
+            if (CHANGE_ADMIN.equals(appeal.getType())) {
+                JSONObject jsonObject = JacksonUtils.fromJson(appeal.getSubmitInfo(), JSONObject.class);
+                Assert.notNull(jsonObject, "更换管理员提交信息不能为空");
+
+                Userspace userSpace = jsonObject.getObject("userspace", Userspace.class);
+                Assert.notNull(userSpace, "更换管理员的企业信息不能为空");
+                Assert.notNull(userSpace.getSpaceUU(), "更换管理员申诉企业UU不能为空");
+
+                spaceName = userSpace.getSpaceName();
+            }
+            synSendMail(appeal.getContactEmail(), appeal.getType(), appeal.getContactName(), spaceName, isPass);
             return;
         }
 
@@ -157,6 +176,8 @@ public class AppealServiceImpl implements AppealService {
                 user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt()));
             }
             userDao.save(user);
+
+            synSendMail(appeal.getContactEmail(), appeal.getType(), appeal.getContactName(), null, isPass);
         } else if (CHANGE_ADMIN.equals(appeal.getType())) {
             JSONObject jsonObject = JacksonUtils.fromJson(appeal.getSubmitInfo(), JSONObject.class);
             Assert.notNull(jsonObject, "更换管理员提交信息不能为空");
@@ -216,11 +237,41 @@ public class AppealServiceImpl implements AppealService {
             // 更新企业认证状态
             space.setValidCode((short) 2);
             spaceDao.save(space);
+
+            synSendMail(appeal.getContactEmail(), appeal.getType(), appeal.getContactName(), space.getSpaceName(), isPass);
         } else {
             logger.info("暂无支持申诉类型");
         }
     }
 
+    private void synSendMail(String receipt, String appealType, String appealName, String spaceName, Boolean isPass) {
+        HashMap<String, String> params = new HashMap<>();
+        params.put("appealName", appealName);
+        String subject;
+        String templateName = isPass ? "appealPass" : "appealUnPass";
+
+        if (RESET_PASS.equals(appealType)) {
+            subject = "找回密码申诉";
+            params.put("appealMessage", "找回密码申诉");
+        } else if (VALID_MOBILE.equals(appealType)) {
+            subject = "绑定手机申诉";
+            params.put("appealMessage", "修改验证手机申诉");
+        } else if (CHANGE_ADMIN.equals(appealType)) {
+            subject = "更换管理员";
+            params.put("appealMessage", String.format("提交的%s更换管理员申诉", spaceName));
+        } else {
+            subject = "测试";
+            params.put("appealMessage", "测试");
+        }
+
+        ExecuteUtils.asyncExecute(new Runnable() {
+            @Override
+            public void run() {
+                mailService.sendTemplateMail(receipt, subject, params, templateName);
+            }
+        });
+    }
+
     @Override
     public Long countUnHandleAppeals() {
 

+ 107 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/MailServiceImpl.java

@@ -0,0 +1,107 @@
+package com.uas.sso.sso.backend.service.impl;
+
+import com.uas.sso.sso.backend.service.MailService;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.mail.MailException;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+
+/**
+ * A implementations of MailService.
+ *
+ * @author huxz
+ */
+@Component
+public class MailServiceImpl implements MailService {
+
+    private final Logger logger = Logger.getLogger(MailServiceImpl.class);
+
+    @Value("${mail.fromMail}")
+    private String from;
+
+    private final JavaMailSender mailSender;
+
+    private final TemplateEngine templateEngine;
+
+    @Autowired
+    public MailServiceImpl(JavaMailSender mailSender, TemplateEngine templateEngine) {
+        this.mailSender = mailSender;
+        this.templateEngine = templateEngine;
+    }
+
+    @Override
+    public void sendSimpleMail(String to, String subject, String content) {
+        long currentTimeMillis = System.currentTimeMillis();
+        if (logger.isDebugEnabled()) {
+            logger.debug("Create simple email message");
+        }
+        SimpleMailMessage message = new SimpleMailMessage();
+        message.setFrom(from);
+        message.setTo(to);
+        message.setSubject("测试");
+        message.setSentDate(new Date(currentTimeMillis));
+        message.setText(content);
+
+        try {
+            mailSender.send(message);
+
+            logger.info("邮件发送成功");
+        } catch (MailException e) {
+            e.printStackTrace();
+            logger.warn("邮件发送失败");
+        }
+    }
+
+    @Override
+    public void sendHtmlMail(String to, String subject, String content) {
+        Date current = new Date(System.currentTimeMillis());
+        if (logger.isDebugEnabled()) {
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            logger.debug(String.format("Create html mail message on %s", format.format(current)));
+        }
+
+        MimeMessage message = mailSender.createMimeMessage();
+
+        try {
+            MimeMessageHelper helper = new MimeMessageHelper(message, true);
+            helper.setFrom(from);
+            helper.setTo(to);
+            helper.setSubject(subject);
+            helper.setSentDate(current);
+            helper.setValidateAddresses(true);
+            helper.setText(content, true);
+
+            mailSender.send(message);
+            logger.info("HTML邮件发送成功");
+        } catch (MessagingException e) {
+            logger.warn("发送HTML邮件时出现异常!", e);
+        }
+    }
+
+    @Override
+    public void sendTemplateMail(String to, String subject, Map<String, String> params, String templateName) {
+        try {
+            Assert.notEmpty(params, "邮件模板的参数不能为空");
+
+            Context context = new Context();
+            context.setVariables(params);
+            String emailContent = templateEngine.process(templateName, context);
+
+            sendHtmlMail(to, subject, emailContent);
+        } catch (Exception e) {
+            logger.warn("生成邮件模板失败", e);
+        }
+    }
+}

+ 56 - 3
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserBackendServiceImpl.java

@@ -1,22 +1,28 @@
 package com.uas.sso.sso.backend.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.uas.sso.core.Const;
 import com.uas.sso.core.Status;
 import com.uas.sso.dao.AppDao;
 import com.uas.sso.dao.UserDao;
+import com.uas.sso.dao.UserValidDao;
 import com.uas.sso.entity.App;
 import com.uas.sso.entity.User;
 import com.uas.sso.entity.UserRecord;
+import com.uas.sso.entity.UserValid;
 import com.uas.sso.entity.Userspace;
 import com.uas.sso.sso.backend.AuthenticationUtils;
 import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import com.uas.sso.sso.backend.exceptions.ValidationFailedException;
 import com.uas.sso.sso.backend.service.UserBackendService;
+import com.uas.sso.sso.backend.util.JacksonUtils;
 import com.uas.sso.util.InfoAsyncUtils;
 import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
@@ -25,8 +31,11 @@ import javax.persistence.criteria.Root;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
@@ -42,10 +51,13 @@ public class UserBackendServiceImpl implements UserBackendService {
 
     private final UserDao userDao;
 
+    private final UserValidDao userValidDao;
+
     @Autowired
-    public UserBackendServiceImpl(AppDao appDao, UserDao userDao) {
+    public UserBackendServiceImpl(AppDao appDao, UserDao userDao, UserValidDao userValidDao) {
         this.appDao = appDao;
         this.userDao = userDao;
+        this.userValidDao = userValidDao;
     }
 
     @Override
@@ -175,7 +187,7 @@ public class UserBackendServiceImpl implements UserBackendService {
     }
 
     @Override
-    public Boolean modifyUserInfo(UpdateUserInfo userInfo) {
+    public User modifyUserInfo(UpdateUserInfo userInfo) {
 
         User existUser = userDao.findOne(userInfo.getUserUU());
         if (existUser == null) {
@@ -200,7 +212,7 @@ public class UserBackendServiceImpl implements UserBackendService {
         }
 
         userDao.save(existUser);
-        return true;
+        return existUser;
     }
 
     @Override
@@ -232,6 +244,47 @@ public class UserBackendServiceImpl implements UserBackendService {
         return user;
     }
 
+    @Override
+    public UserValid loadUserValid(Long userUU) {
+        Sort sort = new Sort(Direction.DESC, "submitDate");
+
+        List<UserValid> validList = userValidDao.findBySubmitterUUAndValidCode(userUU, (short) 1, sort);
+        return CollectionUtils.isEmpty(validList) ? null : validList.get(0);
+    }
+
+    @Override
+    public User authUserValid(Long userUU, Long validId, Boolean isPass, String reason) {
+        User userInfo = userDao.findOne(userUU);
+        Assert.notNull(userInfo, String.format("用户[%d]不存在", userUU));
+
+        UserValid userValid = userValidDao.findOne(validId);
+        Assert.notNull(userValid, "用户身份认证信息不能为空");
+        Assert.isTrue(userValid.getValidCode() == 1, "用户身份认证必须为待认证状态");
+
+        userValid.setAuditor("系统管理员");
+        userValid.setValidCode(isPass ? (short) Status.AUTHENTICATED.getCode() : (short) Status.NOT_PASSED.getCode());
+        userValid.setValidDate(new Timestamp(System.currentTimeMillis()));
+
+        // When admin disapproves, only handle user valid info.
+        if (!isPass) {
+            Assert.hasText(reason, "用户身份认证不通过时,不通过原因不能为空");
+            userValid.setInvalidReason(reason);
+            userValidDao.save(userValid);
+            return userInfo;
+        }
+
+        // Handle user valid and user info.
+        JSONObject newUser = JacksonUtils.fromJson(userValid.getSubmitInfo(), JSONObject.class);
+        Assert.notNull(newUser, "用户身份的企业信息不能为空");
+
+        userInfo.setRealName(newUser.getString("realName"));
+        userInfo.setIdCard(newUser.getString("idCard"));
+        userInfo.setIdentityValidCode(userValid.getValidCode());
+
+        userDao.save(userInfo);
+        return userInfo;
+    }
+
     private void emailHasRegistered(String mobile) {
         User user = userDao.findByMobile(mobile);
         if (user != null) {

+ 47 - 28
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserSpaceServiceImpl.java

@@ -7,7 +7,6 @@ import com.uas.sso.dao.UserspaceDao;
 import com.uas.sso.dao.UserspaceValidDao;
 import com.uas.sso.entity.App;
 import com.uas.sso.entity.User;
-import com.uas.sso.entity.UserAccount;
 import com.uas.sso.entity.Userspace;
 import com.uas.sso.entity.UserspaceValid;
 import com.uas.sso.sso.backend.dao.AdminChangeRecordDao;
@@ -16,7 +15,7 @@ import com.uas.sso.sso.backend.entity.AdminChangeRecord;
 import com.uas.sso.sso.backend.entity.AdminChangeType;
 import com.uas.sso.sso.backend.exceptions.ValidationFailedException;
 import com.uas.sso.sso.backend.service.UserSpaceService;
-import com.uas.sso.support.SystemSession;
+import com.uas.sso.sso.backend.util.JacksonUtils;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -32,9 +31,12 @@ import org.hibernate.jpa.criteria.OrderImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
@@ -198,36 +200,45 @@ public class UserSpaceServiceImpl implements UserSpaceService {
 
     @Override
     @Transactional(rollbackFor = RuntimeException.class)
-    public Userspace authEnterpriseInfo(@NotNull Long spaceUu, @NotNull Boolean isPass,
+    public Userspace authEnterpriseInfo(@NotNull Long spaceUu, @NotNull Long validId, @NotNull Boolean isPass,
             String reason) {
         Userspace space = assertSpaceExist(spaceUu);
-        // UserAccount account = SystemSession.getUserAccount();
-
-        if (isPass) {
-            space.setValidCode((short) Status.AUTHENTICATED.getCode());
-        } else {
-            space.setValidCode((short) Status.NOT_PASSED.getCode());
-        }
-
-        // 更新企业认证日志信息
-        List<UserspaceValid> validList = spaceValidDao.findBySpaceUUAndValidCode(spaceUu, (short) 1);
-        if (CollectionUtils.isEmpty(validList)) {
-            throw new ValidationFailedException("当前企业没有发起认证申请");
-        }
-
-        for (UserspaceValid valid : validList) {
-            valid.setAuditor("系统管理员");
-
-            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            valid.setValidDate(dateFormat.format(new Date()));
-            valid.setValidCode(space.getValidCode());
-            if (!isPass) {
-                valid.setInvalidReason(reason);
-            }
+        UserspaceValid spaceValid = spaceValidDao.findOne(validId);
+        Assert.notNull(spaceValid, "企业认证信息不能为空");
+        Assert.isTrue(spaceValid.getValidCode() == 1, "企业认证必须为待认证状态");
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String authDate = dateFormat.format(new Date());
+
+        spaceValid.setValidCode(isPass ? (short) Status.AUTHENTICATED.getCode() : (short) Status.NOT_PASSED.getCode());
+        spaceValid.setValidDate(authDate);
+
+        // When admin disapproves, only handle space valid info.
+        if (!isPass) {
+            Assert.hasText(reason, "企业认证不通过时,不通过原因不能为空");
+            spaceValid.setInvalidReason(reason);
+            spaceValidDao.save(spaceValid);
+            return space;
         }
-        spaceValidDao.save(validList);
 
-        return userspaceDao.save(space);
+        // Handle space valid and space info.
+        Userspace newSpace = JacksonUtils.fromJson(spaceValid.getSubmitInfo(), Userspace.class);
+        Assert.notNull(newSpace, "企业认证的企业信息不能为空");
+
+        space.setSpaceName(newSpace.getSpaceName());
+        space.setBusinessCode(newSpace.getBusinessCode());
+        space.setBusinessCodeImage(newSpace.getBusinessCodeImage());
+        space.setCorporation(newSpace.getCorporation());
+        space.setRegProvince(newSpace.getRegProvince());
+        space.setRegCity(newSpace.getRegCity());
+        space.setRegDistrict(newSpace.getRegDistrict());
+        space.setRegStreet(newSpace.getRegStreet());
+        space.setRegAddress(newSpace.getRegAddress());
+        space.setValidCode(spaceValid.getValidCode());
+        userspaceDao.save(space);
+
+        spaceValidDao.save(spaceValid);
+        return space;
     }
 
     @Override
@@ -268,6 +279,14 @@ public class UserSpaceServiceImpl implements UserSpaceService {
         return space;
     }
 
+    @Override
+    public UserspaceValid loadSpaceValid(Long spaceUU) {
+        Sort sort = new Sort(Direction.DESC, "submitDate");
+
+        List<UserspaceValid> validList = spaceValidDao.findBySpaceUUAndValidCode(spaceUU, (short) 1, sort);
+        return CollectionUtils.isEmpty(validList) ? null : validList.get(0);
+    }
+
     /**
      * 业务逻辑校验-企业UU对应企业是否存在
      *

+ 7 - 0
sso-manage-console/src/main/resources/config/application-dev.properties

@@ -23,3 +23,10 @@ spring.jpa.hibernate.ddl-auto=update
 
 management.security.enabled=false
 logging.level.com.uas.sso.sso.backend=debug
+
+spring.mail.host=smtp.usoftchina.com
+spring.mail.username=sso@usoftchina.com
+spring.mail.password=QWE899GHJ
+spring.mail.default-encoding=UTF-8
+
+mail.fromMail=sso@usoftchina.com

+ 7 - 0
sso-manage-console/src/main/resources/config/application-prod.properties

@@ -23,3 +23,10 @@ spring.jpa.hibernate.ddl-auto=update
 
 management.security.enabled=false
 logging.level.com.uas.sso.sso.backend=debug
+
+spring.mail.host=smtp.usoftchina.com
+spring.mail.username=sso@usoftchina.com
+spring.mail.password=QWE899GHJ
+spring.mail.default-encoding=UTF-8
+
+mail.fromMail=sso@usoftchina.com

+ 7 - 0
sso-manage-console/src/main/resources/config/application-test.properties

@@ -23,3 +23,10 @@ spring.jpa.hibernate.ddl-auto=update
 
 management.security.enabled=false
 logging.level.com.uas.sso.sso.backend=debug
+
+spring.mail.host=smtp.usoftchina.com
+spring.mail.username=sso@usoftchina.com
+spring.mail.password=QWE899GHJ
+spring.mail.default-encoding=UTF-8
+
+mail.fromMail=sso@usoftchina.com

+ 30 - 0
sso-manage-console/src/main/resources/templates/appealPass.html

@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+    <style type="text/css">
+        .message {
+            margin: 10px;
+        }
+        .message-greetings {
+        }
+        .message-content {
+            text-indent: 25px;
+            font-family: Microsoft YaHei, Microsoft YaHei UI, sans-serif, Monaco, Menlo, Consolas, "Courier New", monospace;
+        }
+        .message-greetings span:first-child {
+            color: #FF0000;
+        }
+    </style>
+</head>
+<body>
+    <div class="message">
+        <div class="message-greetings">尊敬的<span th:text="${appealName}"></span></div>
+        <div class="message-content">
+            您好,您的<span th:text="${appealMessage}"></span>已经通过,您可以通过新手机号和密码进行登录。
+            如果您在使用过程中有任何疑问,可以联系我们的客服400-830-1818
+        </div>
+    </div>
+</body>
+</html>

+ 30 - 0
sso-manage-console/src/main/resources/templates/appealUnPass.html

@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+    <style type="text/css">
+        .message {
+            margin: 10px;
+        }
+        .message-greetings {
+        }
+        .message-content {
+            text-indent: 25px;
+            font-family: Microsoft YaHei, Microsoft YaHei UI, sans-serif, Monaco, Menlo, Consolas, "Courier New", monospace;
+        }
+        .message-greetings span:first-child {
+            color: #FF0000;
+        }
+    </style>
+</head>
+<body>
+    <div class="message">
+        <div class="message-greetings">尊敬的<span th:text="${appealName}"></span></div>
+        <div class="message-content">
+            您好,您的<span th:text="${appealMessage}"></span>未能通过。如果您在使用过程中有任何疑问,
+            可以联系我们的客服400-830-1818
+        </div>
+    </div>
+</body>
+</html>

+ 3 - 7
sso-manage-console/src/test/java/com/uas/sso/sso/backend/ManageConsoleApplicationTests.java

@@ -1,16 +1,12 @@
 package com.uas.sso.sso.backend;
 
-import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 import org.springframework.test.context.junit4.SpringRunner;
 
 @RunWith(SpringRunner.class)
-@SpringBootTest
-public class ManageConsoleApplicationTests {
-
-	@Test
-	public void contextLoads() {
-	}
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+public abstract class ManageConsoleApplicationTests {
 
 }

+ 40 - 0
sso-manage-console/src/test/java/com/uas/sso/sso/backend/service/MailServiceTest.java

@@ -0,0 +1,40 @@
+package com.uas.sso.sso.backend.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+public class MailServiceTest {
+
+    @Autowired
+    private MailService mailService;
+
+    @Test
+    public void sendSimpleMail() {
+        mailService.sendSimpleMail("huxz@usoftchina.com", "测试", "邮件内容乱码了吗");
+    }
+
+    @Test
+    public void sendTemplateMail() {
+        Map<String, String> params = new HashMap<>();
+        params.put("appealName", "胡学志");
+        params.put("appealMessage", "找回密码申诉");
+
+        mailService.sendTemplateMail("huxz@usoftchina.com", "测试", params, "appealPass");
+    }
+
+    @Test
+    public void sendTemplateMailNoParams() {
+        Map<String, String> params = new HashMap<>();
+        params.put("appealMessage", "找回密码申诉");
+
+        mailService.sendTemplateMail("huxz@usoftchina.com", "测试", params, "appealPass");
+    }
+}

+ 34 - 0
sso-manage-console/src/test/resources/application-dev.properties

@@ -0,0 +1,34 @@
+app.datasource.url=jdbc:mysql://192.168.253.12:3306/sso?characterEncoding=utf-8&useSSL=false
+app.datasource.username=root
+app.datasource.password=select111***
+app.datasource.driverClassName=com.mysql.jdbc.Driver
+app.datasource.initialSize=1
+app.datasource.minIdle=1
+app.datasource.maxActive=20
+app.datasource.maxWait=60000
+app.datasource.timeBetweenEvictionRunsMillis=60000
+app.datasource.minEvictableIdleTimeMillis=300000
+app.datasource.validationQuery=SELECT 1 FROM DUAL
+app.datasource.testWhileIdle=true
+app.datasource.testOnBorrow=true
+app.datasource.testOnReturn=false
+app.datasource.poolPreparedStatements=true
+app.datasource.timeBetweenLogStatsMillis=60000
+app.datasource.maxPoolPreparedStatementPerConnectionSize=20
+app.datasource.filters=stat,slf4j
+app.datasource.connectionProperties=druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
+
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=update
+
+management.security.enabled=false
+logging.level.com.uas.sso.sso.backend=debug
+
+spring.thymeleaf.mode=LEGACYHTML5
+
+spring.mail.host=smtp.usoftchina.com
+spring.mail.username=sso@usoftchina.com
+spring.mail.password=QWE899GHJ
+spring.mail.default-encoding=UTF-8
+
+mail.fromMail=sso@usoftchina.com

+ 2 - 2
sso-server/src/main/java/com/uas/sso/controller/UserspaceManagerController.java

@@ -614,11 +614,11 @@ public class UserspaceManagerController extends BaseController {
                         page = JSON.parseObject(responseWrap.getContent(), new TypeReference<com.uas.account.support.Page<MasterInfo>>() {
                         });
                         for (MasterInfo masterInfo : page.getContent()) {
-                            Userspace userspace = userspaceService.findByBusinessCode(masterInfo.getBusinessCode());
+                            /*Userspace userspace = userspaceService.findByBusinessCode(masterInfo.getBusinessCode());
                             if (userspace != null && masterInfo.getWebsite() != null) {
                                 userspace.setWebsite(masterInfo.getWebsite());
                                 userspaceService.save(userspace);
-                            }
+                            }*/
                         }
                     } catch (Exception e) {
                         e.printStackTrace();

+ 4 - 0
sso-server/src/main/java/com/uas/sso/dao/UserValidDao.java

@@ -1,6 +1,8 @@
 package com.uas.sso.dao;
 
 import com.uas.sso.entity.UserValid;
+import java.util.List;
+import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
@@ -10,4 +12,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  * @desc 用户申请日志Dao
  **/
 public interface UserValidDao extends JpaRepository<UserValid, Long>, JpaSpecificationExecutor<UserValid> {
+
+    List<UserValid> findBySubmitterUUAndValidCode(Long userUU, short validCode, Sort sort);
 }

+ 3 - 0
sso-server/src/main/java/com/uas/sso/dao/UserspaceValidDao.java

@@ -2,6 +2,7 @@ package com.uas.sso.dao;
 
 import com.uas.sso.entity.UserspaceValid;
 import java.util.List;
+import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
@@ -21,4 +22,6 @@ public interface UserspaceValidDao extends JpaRepository<UserspaceValid, Long>,
      * @return  企业认证日志列表
      */
     List<UserspaceValid> findBySpaceUUAndValidCode(Long spaceUU, Short validCode);
+
+    List<UserspaceValid> findBySpaceUUAndValidCode(Long spaceUU, Short validCode, Sort sort);
 }

+ 8 - 0
sso-server/src/main/java/com/uas/sso/entity/UserspaceValid.java

@@ -86,6 +86,14 @@ public class UserspaceValid implements Serializable {
         this.setSubmitterUU(submitter.getUserUU());
     }
 
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
     public Timestamp getSubmitDate() {
         return submitDate;
     }