Browse Source

后台应用管理页面企业数据编辑

huxz 8 years ago
parent
commit
e9ef7d9037

+ 0 - 0
sso-manage-console-web/src/images/icon_brand.png → sso-manage-console-web/src/assets/images/icon_brand.png


+ 0 - 0
sso-manage-console-web/src/styles/console.css → sso-manage-console-web/src/assets/styles/console.css


+ 80 - 52
sso-manage-console-web/src/components/app/AppHome.vue

@@ -1,90 +1,118 @@
 <template>
-  <div class="x-container">
-    <div class="container">
-      <div class="x-content-wrap clearfix" style="margin: 0 -15px">
-        <div class="x-content">
-          <!-- tab切换 start-->
-          <ul class="nav nav-tabs x-nav-tabs x-navbar-right hidden-xs">
-            <li><a data-type="INNER">内部</a></li>
-            <li><a data-type="INNER">外部</a></li>
-            <li class="active"><a data-type="">全部</a></li>
+  <div>
+    <div class="x-container">
+      <div class="container">
+        <div class="x-content-wrap clearfix" style="margin: 0 -15px">
+          <div class="x-content">
+            <!-- tab切换 start-->
+            <ul class="nav nav-tabs x-nav-tabs x-navbar-right hidden-xs">
+              <li><a data-type="INNER">内部</a></li>
+              <li><a data-type="INNER">外部</a></li>
+              <li class="active"><a data-type="">全部</a></li>
+              <!--suppress HtmlUnknownTag -->
+              <h2 class="hidden-xs">
+                <i class="fa fa-file-text-o"></i> 应用
+              </h2>
+            </ul>
+            <!-- tab切换 end-->
+            <!-- 列表 start -->
+            <div class="x-mod x-list x-list-2x x-chunk-list-wrap">
+              <div class="x-mod-body">
+                <!-- tab start -->
+                <div id="app_list" class="x-chunk-list">
 
-            <h2 class="hidden-xs">
-              <i class="fa fa-file-text-o"></i> 应用
-            </h2>
-          </ul>
-          <!-- tab切换 end-->
-          <!-- 列表 start -->
-          <div class="x-mod x-list x-list-2x x-chunk-list-wrap">
-            <div class="x-mod-body">
-              <!-- tab start -->
-              <div id="app_list" class="x-chunk-list">
+                  <div class="x-item" v-for="app in appList">
+                    <div class="x-icon">
+                      <i class="fa fa-file-o"></i>
+                    </div>
+                    <p class="x-title">
+                      <a class="x-text x-editor-trigger" href="javascript:void(0)"
+                         :data-id="app.uid"
+                         v-text="app.description"
+                         @click="addOrModifyAppInfo(app)">
+                      </a>
+                    </p>
+                    <div class="text-muted">
+                    <span class="x-text">
+                      <i class="fa fa-fw fa-check-square-o"></i>{{app.uid}}
+                    </span>
+                    </div>
+                    <div class="x-text-muted">
+                      <!--suppress JSUnresolvedVariable -->
+                      绑定企业<b v-text="app.usCount">0</b>
+                    </div>
+                  </div>
 
-                <div class="x-item" v-for="app in appList">
+                </div>
+                <!-- tab end -->
+                <!-- empty tag -->
+                <!-- new app -->
+                <div class="x-item">
                   <div class="x-icon">
-                    <i class="fa fa-file-o"></i>
-                  </div>
-                  <p class="x-title">
-                    <a class="x-text x-editor-trigger" href="javascript:void(0)" :data-id="app.uid" v-text="app.description"></a>
-                  </p>
-                  <div class="text-muted">
-                    <span class="x-text"> <i class="fa fa-fw fa-check-square-o"></i>{{app.uid}}</span>
-                  </div>
-                  <div class="x-text-muted">
-                    绑定企业<b v-text="app.usCount">0</b>
+                    <a class="x-editor-trigger" href="javascript:void(0)" title="添加应用"
+                       @click="addOrModifyAppInfo()">
+                      <i class="fa fa-plus"></i>
+                    </a>
                   </div>
                 </div>
-
-              </div>
-              <!-- tab end -->
-              <!-- empty tag -->
-
-              <!-- new app -->
-
-              <div class="x-item">
-                <div class="x-icon">
-                  <a class="x-editor-trigger" href="javascript:;" title="添加应用"><i class="fa fa-plus"></i></a>
-                </div>
               </div>
-
             </div>
+            <!-- 列表 end -->
           </div>
-          <!-- 列表 end -->
         </div>
       </div>
     </div>
+    <!-- modal -->
+    <app-modal :visible.sync="showModal" :data="selectedApp" @success=""/>
   </div>
 </template>
 
+<!--suppress JSUnusedGlobalSymbols -->
 <script>
 import axios from 'axios'
+import AppModal from './modal/AppModal'
 
 export default {
   name: 'AppHome',
+  components: {
+    AppModal
+  },
   data () {
     return {
-      msg: '应用管理',
-      appList: []
+      appList: [],
+      showModal: false,
+      selectedApp: null
     }
   },
+  created () {
+    // Load data from backend server, follow docs on
+    // https://router.vuejs.org/zh-cn/advanced/data-fetching.html
+    this.fetchData()
+  },
+  watch: {
+    $route: 'fetchData'
+  },
   methods: {
-    loadAppsList() {
+    fetchData () {
+      this.loadAppsList()
+    },
+    loadAppsList () {
       axios.get('/api/app//showAllApps').then(response => {
-        console.log(response)
         this.appList = response.data
-        console.log(this.appList[0])
       }, response => {
         console.log('error', response)
       })
+    },
+    addOrModifyAppInfo (app) {
+      this.showModal = true
+      this.selectedApp = app || {}
+      console.log(this.selectedApp)
     }
-  },
-  mounted () {
-    this.loadAppsList()
   }
 }
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped>
+<style>
 
 </style>

+ 264 - 0
sso-manage-console-web/src/components/app/modal/AppModal.vue

@@ -0,0 +1,264 @@
+<template>
+  <div class="modal fade in" role="dialog" aria-labelledby="appModal_title"
+       aria-hidden="false" style="display: block;" v-if="appVisible">
+    <div class="modal-dialog x-modal-dialog modal-lg" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"
+                  @click="appVisible = false">
+            <span aria-hidden="true">&times;</span>
+          </button>
+          <h4 class="modal-title" id="appModal_title">应用</h4>
+        </div>
+        <div class="modal-body">
+          <form class="form-horizontal x-form">
+            <div class="form-group">
+              <label class="control-label col-sm-2">唯一标识</label>
+              <div class="col-sm-3">
+                <input type="text" class="form-control" name="uid" title="uid" required
+                       v-model="appInfo.uid">
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2">描述</label>
+              <div class="col-sm-10">
+                <input type="text" class="form-control" name="description" title="description" required
+                       v-model="appInfo.description">
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2">主页</label>
+              <div class="col-sm-10">
+                <input type="text" class="form-control" name="homePage" title="homePage" required
+                       v-model="appInfo.homePage">
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2">类型</label>
+              <div class="col-sm-10">
+                <label class="radio-inline">
+                  <input type="radio" name="type" value="default" v-model="appInfo.type"> 独立应用
+                </label>
+                <label class="radio-inline">
+                  <input type="radio" name="type" value="control" v-model="appInfo.type"> 级联应用
+                </label>
+                <div class="help-block">
+                  级联应用是指没有独立企业、用户及权限控制系统的应用,要借助其他应用的资源来达到控制效果
+                </div>
+              </div>
+            </div>
+            <div id="appModal_type_default" v-show="showDefault">
+              <div class="form-group">
+                <label class="control-label col-sm-2">公钥</label>
+                <div class="col-sm-10" id="keypair">
+                  <textarea name="publicKey" title="publicKey" rows="3" class="form-control" readonly
+                            v-model="appInfo.publicKey"></textarea>
+                  <ul class="help-block x-menu">
+                    <li>点击<a class="btn-create" href="javascript:void(0)">生成密钥对</a></li>
+                    <li>账户中心只保留公钥用于校验,请将私钥配置到程序中,并妥善保管</li>
+                    <li style="display:none"><a class="btn-download" target="_blank" href="/api/secret/private">下载私钥</a></li>
+                  </ul>
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">企业回调</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="backSpaceUrl" required
+                         v-model="appInfo.backSpaceUrl" placeholder="应用接口,用于企业信息有变化时回调">
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">用户回调</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="backUserUrl" required
+                         v-model="appInfo.backUserUrl" placeholder="应用接口,用于用户信息有变化时回调">
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">用户密码回调</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="backUserPwdUrl" required
+                         v-model="appInfo.backUserPwdUrl" placeholder="应用接口,用于用户密码修改时回调">
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">密码加密格式</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="encryFormat" required
+                         v-model="appInfo.encryFormat" placeholder="用户密码加密的格式">
+                  <ul class="help-block x-menu">
+                    <li><code>$password</code>表示密码明文;<code>$salt</code>表示盐值</li>
+                    <li>可任意组合,例如:<code>$password($salt)</code>;不填写表示不对密码加密</li>
+                  </ul>
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">登录回调</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="loginUrl" required
+                         v-model="appInfo.loginUrl" placeholder="应用接口,用于企业信息有变化时回调">
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">登出回调</label>
+                <div class="col-sm-10">
+                  <input type="text" class="form-control" name="logoutUrl" required
+                         v-model="appInfo.logoutUrl" placeholder="应用接口,用于企业信息有变化时回调">
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">关联应用</label>
+                <div class="col-sm-10">
+                  <textarea name="copyApps" rows="3" class="form-control" v-model="appInfo.copyApps"
+                            placeholder="填写应用唯一标识,不填表示全部;多个用逗号、分号、空格或回车分隔"></textarea>
+                  <ul class="help-block x-menu">
+                    <li>关联应用是指与当前应用有关的应用</li>
+                    <li>相关联的应用间,任何一方的企业或个人信息有修改,都会通过回调接口同步到其他应用</li>
+                  </ul>
+                </div>
+              </div>
+              <div class="form-group">
+                <label class="control-label col-sm-2">默认开通</label>
+                <div class="col-sm-10">
+                  <label class="radio-inline">
+                    <!--suppress HtmlUnknownAttribute -->
+                    <input type="radio" name="defaultUse" value="1" v-model.number="appInfo.defaultUse"> 是
+                  </label>
+                  <label class="radio-inline">
+                    <!--suppress HtmlUnknownAttribute -->
+                    <input type="radio" name="defaultUse" value="0" v-model.number="appInfo.defaultUse"> 否
+                  </label>
+                  <div class="help-block">
+                    用户注册的时候,默认为该用户开通此应用
+                  </div>
+                </div>
+              </div>
+              <!--<div class="form-group">
+                <label class="control-label col-sm-2">使用域</label>
+                <div class="col-sm-10">
+                  <label class="radio-inline"> <input type="radio" name="scope" value="PUBLIC" checked=""> 开放
+                  </label> <label class="radio-inline"> <input type="radio" name="scope" value="PROTECTED"> 受保护
+                </label> <label class="radio-inline"> <input type="radio" name="scope" value="PRIVATE"> 私有
+                </label>
+                  <div class="help-block">
+                    私有应用只能内部使用;受保护应用只能指定用户群使用
+                  </div>
+                </div>
+              </div>-->
+              <!--<div class="form-group">
+                <label class="control-label col-sm-2">应用ID唯一</label>
+                <div class="col-sm-10">
+                  <label class="radio-inline"> <input type="radio" name="dialectEnable" value="1" checked=""> 是
+                  </label> <label class="radio-inline"> <input type="radio" name="dialectEnable" value="0"> 否
+                </label>
+                  <div class="help-block">
+                    当ID唯一时,可以使用ID作为账户登录
+                  </div>
+                </div>
+              </div>-->
+              <!-- 是否支持个人账号 -->
+              <div class="form-group">
+                <label class="control-label col-sm-2">支持个人账号</label>
+                <div class="col-sm-10">
+                  <label class="radio-inline">
+                    <input type="radio" name="personalEnable" value="1" v-model="appInfo.personalEnable"> 是
+                  </label>
+                  <label class="radio-inline">
+                    <input type="radio" name="personalEnable" value="0" v-model="appInfo.personalEnable"> 否
+                  </label>
+                  <div class="help-block">
+                    用户注册的时候,该应用将根据此选项决定是否开放个人注册页面
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div id="appModal_type_control" v-show="showControl">
+              <div class="form-group">
+                <label class="control-label col-sm-2">级联应用</label>
+                <div class="col-sm-3">
+                  <input type="text" class="form-control" name="userControl" placeholder="填写应用唯一标识"
+                         required v-model="appInfo.userControl">
+                </div>
+              </div>
+            </div>
+          </form>
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-blank" data-dismiss="modal" @click="appVisible = false">取消</button>
+          <button type="button" class="btn btn-blank btn-del" style="display: none;">删除</button>
+          <button type="button" class="btn btn-default btn-submit" @click="saveAppInfo()">保存</button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+
+export default {
+  name: 'app-modal',
+  props: {
+    visible: Boolean,
+    data: Object
+  },
+  data () {
+    return {
+      appVisible: false,
+      appInfo: {}
+    }
+  },
+  watch: {
+    visible: function (value) {
+      this.appVisible = value
+    },
+    appVisible: function (value) {
+      this.$emit('update:visible', value)
+    },
+    data: function (value) {
+      console.log(value)
+      // Deep copy data to appInfo, when data changes.
+      const temp = JSON.parse(JSON.stringify(value || {}))
+      temp.type = temp.userControl ? 'control' : 'default'
+
+      // To implement two-way bindings, handle copy of prop before assign to
+      // the data of component
+      this.appInfo = temp
+
+      console.log('App type: ', this.appInfo.type)
+    }
+  },
+  methods: {
+    saveAppInfo () {
+      console.log(this.appInfo)
+      if (this.appInfo.uid) {
+        axios.put('/api/app//updateApp', this.appInfo)
+          .then(response => {
+            console.log(response.data)
+          }).catch(response => {
+            console.log(response)
+        })
+      } else {
+        axios.post('/api/app//addApp', this.appInfo)
+        .then(response => {
+          console.log(response.data)
+        }).catch(response => {
+          console.log(response)
+        })
+      }
+    }
+  },
+  computed: {
+    showDefault () {
+      return this.appInfo.type === 'default'
+    },
+    showControl () {
+      return this.appInfo.type === 'control'
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

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

@@ -5,7 +5,7 @@ import App from './App'
 import router from './router'
 import 'bootstrap/dist/css/bootstrap.min.css'
 import 'font-awesome/css/font-awesome.min.css'
-import './styles/console.css'
+import './assets/styles/console.css'
 
 Vue.config.productionTip = false
 

+ 22 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/AppManagerController.java

@@ -5,10 +5,17 @@ import com.uas.sso.sso.backend.service.AppService;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+/**
+ * App manager api interface.
+ *
+ * @author huxz
+ */
 @RestController
 @RequestMapping(path = "/api/app")
 public class AppManagerController {
@@ -22,7 +29,21 @@ public class AppManagerController {
 
     @RequestMapping(method = RequestMethod.GET, path = "//showAllApps",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-    public List<App> showAllUsers() {
+    public List<App> showAllApps() {
         return appService.findAllApps();
     }
+
+    @RequestMapping(method = RequestMethod.POST, path = "//addApp",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public Boolean addAppInfo(@RequestBody App app) {
+        appService.addAppInfo(app);
+        return true;
+    }
+
+    @RequestMapping(method = RequestMethod.PUT, path = "//updateApp",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public Boolean updateAppInfo(@RequestBody App app) {
+        appService.updateApp(app);
+        return true;
+    }
 }

+ 4 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/AppService.java

@@ -11,4 +11,8 @@ import java.util.List;
 public interface AppService {
 
     List<App> findAllApps();
+
+    void addAppInfo(App app);
+
+    void updateApp(App app);
 }

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

@@ -1,5 +1,6 @@
 package com.uas.sso.sso.backend.service.impl;
 
+import com.alibaba.druid.support.json.JSONUtils;
 import com.uas.sso.dao.AppDao;
 import com.uas.sso.entity.App;
 import com.uas.sso.sso.backend.service.AppService;
@@ -7,6 +8,8 @@ import java.util.Collections;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 
 /**
@@ -33,4 +36,16 @@ public class AppServiceImpl implements AppService {
         }
         return apps;
     }
+
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void addAppInfo(App app) {
+        System.out.println(JSONUtils.toJSONString(app));
+    }
+
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public void updateApp(App app) {
+        System.out.println(JSONUtils.toJSONString(app));
+    }
 }