star7th %!s(int64=7) %!d(string=hai) anos
pai
achega
c9b05510e4

+ 14 - 1
server/Application/Api/Controller/BaseController.class.php

@@ -123,7 +123,7 @@ class BaseController extends Controller {
 		$this->sendResult($array);
 	}
 
-	//判断某用户是否有项目管理权限(项目成员member_group_id为1,以及 项目创建者)
+	//判断某用户是否有项目管理权限(项目成员member_group_id为1,是项目所在团队的成员并且成员权限为1 ,以及 项目创建者)
 	protected function checkItemPermn($uid , $item_id){
 
 		if (!$uid) {
@@ -144,6 +144,13 @@ class BaseController extends Controller {
 			session("mamage_item_".$item_id , 1 );
 			return true;
 		}
+
+		$ItemMember = D("TeamItemMember")->where("item_id = '%d' and member_uid = '%d' and member_group_id = 1 ",array($item_id,$uid))->find();
+		if ($ItemMember) {
+			session("mamage_item_".$item_id , 1 );
+			return true;
+		}
+
 		return false;
 	}
 
@@ -180,6 +187,12 @@ class BaseController extends Controller {
 			session("visit_item_".$item_id , 1 );
 			return true;
 		}
+		
+		$TeamItemMember = D("TeamItemMember")->where("item_id = '%d' and member_uid = '%d'  ",array($item_id,$uid))->find();
+		if ($TeamItemMember) {
+			session("visit_item_".$item_id , 1 );
+			return true;
+		}
 
 		$item = D("Item")->where("item_id = '%d' ",array($item_id))->find();
 		if ($item['password']) {

+ 16 - 2
server/Application/Api/Controller/ItemController.class.php

@@ -7,7 +7,7 @@ class ItemController extends BaseController {
     //单个项目信息
     public function info(){
         $this->checkLogin(false);
-        $item_id = I("item_id");
+        $item_id = I("item_id/d");
         $item_domain = I("item_domain/s");
         $current_page_id = I("page_id/d");
         if (! is_numeric($item_id)) {
@@ -168,7 +168,21 @@ class ItemController extends BaseController {
     //我的项目列表
     public function myList(){
         $login_user = $this->checkLogin();        
-        $items  = D("Item")->field("item_id,item_name,last_update_time,item_description,is_del")->where("uid = '$login_user[uid]' or item_id in ( select item_id from ".C('DB_PREFIX')."item_member where uid = '$login_user[uid]' ) ")->order("item_id asc")->select();
+        $member_item_ids = array(-1) ; 
+        $item_members = D("ItemMember")->where("uid = '$login_user[uid]'")->select();
+        if ($item_members) {
+            foreach ($item_members as $key => $value) {
+                $member_item_ids[] = $value['item_id'] ;
+            }
+        }
+        $team_item_members = D("TeamItemMember")->where("member_uid = '$login_user[uid]'")->select();
+        if ($team_item_members) {
+            foreach ($team_item_members as $key => $value) {
+                $member_item_ids[] = $value['item_id'] ;
+            }
+        }
+        $items  = D("Item")->field("item_id,item_name,item_domain,item_type,last_update_time,item_description,is_del")->where("uid = '$login_user[uid]' or item_id in ( ".implode(",", $member_item_ids)." ) ")->order("item_id asc")->select();
+        
         
         foreach ($items as $key => $value) {
             //如果项目已标识为删除

+ 6 - 0
server/Application/Api/Controller/TeamController.class.php

@@ -44,6 +44,12 @@ class TeamController extends BaseController {
         }
         if ($ret) {
             foreach ($ret as $key => &$value) {
+                //获取该团队成员数
+                $value['memberCount'] = D("TeamMember")->where(" team_id = '$value[id]' ")->count();
+
+                //获取该团队涉及项目数
+                $value['itemCount'] = D("TeamItem")->where(" team_id = '$value[id]' ")->count();
+
                 $value['addtime'] = date("Y-m-d H:i:s" , $value['addtime']);
             }
            $this->sendResult($ret);

+ 28 - 1
server/Application/Api/Controller/TeamItemController.class.php

@@ -60,7 +60,7 @@ class TeamItemController extends BaseController {
         
     }
 
-    //获取列表
+    //根据项目来获取其绑定的团队列表
     public function getList(){
         $login_user = $this->checkLogin();
         $uid = $login_user['uid'] ;
@@ -84,6 +84,33 @@ class TeamItemController extends BaseController {
             $this->sendResult(array());
         }
     }
+    
+    //根据团队来获取项目列表
+    public function getListByTeam(){
+        $login_user = $this->checkLogin();
+        $uid = $login_user['uid'] ;
+
+        $team_id = I("team_id/d");
+
+        $teamInfo = D("Team")->where(" id = '$team_id' and uid = '$login_user[uid]' ")->find();
+        if (!$teamInfo) {
+            $this->sendError(10209,"无此团队或者你无管理此团队的权限");
+            return ;
+        } 
+
+        $sql  = "select item.*,team_item.team_id , team_item.id as id from item left join team_item on item.item_id = team_item.item_id where team_item.team_id = '$team_id' and item.is_del = 0 ";
+        $ret = D("Item")->query($sql);
+
+        if ($ret) {
+            foreach ($ret as $key => &$value) {
+                $value['addtime'] = date("Y-m-d H:i:s" , $value['addtime']);
+            }
+           $this->sendResult($ret);
+        }else{
+            $this->sendResult(array());
+        }
+    }
+
 
     //删除
     public function delete(){

+ 3 - 0
server/Application/Api/Model/ItemModel.class.php

@@ -290,6 +290,9 @@ class ItemModel extends BaseModel {
         D("Page")->where("item_id = '$item_id' ")->delete();
         D("Catalog")->where("item_id = '$item_id' ")->delete();
         D("PageHistory")->where("item_id = '$item_id' ")->delete();
+        D("ItemMember")->where("item_id = '$item_id' ")->delete();
+        D("TeamItem")->where("item_id = '$item_id' ")->delete();
+        D("TeamItemMember")->where("item_id = '$item_id' ")->delete();
         return D("Item")->where("item_id = '$item_id' ")->delete();
 
     }

+ 2 - 2
web_src/src/components/item/Index.vue

@@ -11,8 +11,8 @@
           </div>
           <div class="header-btn-group pull-right">
             <el-button type="text"  @click="feedback">{{$t("feedback")}}</el-button>
-            
-            <router-link to="/admin/index" v-if="isAdmin">&nbsp;&nbsp;&nbsp;{{$t("management_backstage")}}</router-link>
+            <router-link to="/team/index" >&nbsp;&nbsp;&nbsp;{{$t('team_mamage')}}</router-link>
+            <router-link to="/admin/index" v-if="isAdmin">&nbsp;&nbsp;&nbsp;{{$t('background')}}</router-link>
             &nbsp;&nbsp;&nbsp;
             <el-dropdown @command="dropdown_callback">
               <span class="el-dropdown-link">

+ 2 - 1
web_src/src/components/item/setting/Index.vue

@@ -117,7 +117,8 @@ export default {
 .center-card{
   text-align: center;
   width: 600px;
-  height: 500px;
+  min-height: 500px;
+  max-height: 700px;
 }
 
 .infoForm{

+ 234 - 39
web_src/src/components/item/setting/Member.vue

@@ -1,13 +1,17 @@
 <template>
   <div class="hello">
     <el-button  type="text" class="add-member" @click="dialogFormVisible = true">{{$t('add_member')}}</el-button>
+    <el-button  type="text" class="add-member" @click="dialogFormTeamVisible = true">{{$t('add_team')}}</el-button>
+
+    <!-- 单个成员列表 -->
      <el-table align="left"
+          v-if="members.length>0"
           :data="members"
-           height="300"
+           height="200"
           style="width: 100%">
           <el-table-column
             prop="username"
-            :label="$t('username')"
+            :label="$t('member_username')"
             width="100">
           </el-table-column>
           <el-table-column
@@ -28,28 +32,118 @@
           </el-table-column>
         </el-table>
 
-    <el-dialog :visible.sync="dialogFormVisible" :modal="false" top="10vh">
+    
+     <!-- 团队列表 -->
+     <el-table align="left"
+          v-if="teamItems.length>0"
+          :data="teamItems"
+           height="200"
+          style="width: 100%">
+          <el-table-column
+            prop="team_name"
+            :label="'团队名'"
+           >
+          </el-table-column>
+          <el-table-column
+            prop="addtime"
+            :label="$t('add_time')"
+            >
+          </el-table-column>
+
+          <el-table-column
+            prop=""
+            :label="$t('operation')">
+            <template slot-scope="scope">
+              <el-button @click="getTeamItemMember(scope.row.team_id)" type="text" size="small">{{$t('member_authority')}}</el-button>
+              <el-button @click="deleteTeam(scope.row.id)" type="text" size="small">{{$t('delete')}}</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+      <!-- 添加单个成员弹窗 -->
+      <el-dialog :visible.sync="dialogFormVisible" :modal="false" top="10vh">
       <el-form >
           <el-form-item label="" >
-            <el-autocomplete  
-            :placeholder="$t('input_target_member')"  
-            v-model="MyForm.username" 
-            :fetch-suggestions="querySearch" 
-            ></el-autocomplete>
+            <el-input  :placeholder="$t('input_target_member')" v-model="MyForm.username"></el-input>
           </el-form-item>
           <el-form-item label="" class="readonly-checkbox" >
             <el-checkbox v-model="MyForm.is_readonly">{{$t('readonly')}}</el-checkbox>
           </el-form-item>
       </el-form>
 
-      <p class="tips">
-        {{$t('member_authority_tips')}}
-      </p>
-      <div slot="footer" class="dialog-footer">
-        <el-button @click="dialogFormVisible = false">{{$t('cancel')}}</el-button>
-        <el-button type="primary" @click="MyFormSubmit" >{{$t('confirm')}}</el-button>
-      </div>
-    </el-dialog>
+
+        <p class="tips">
+          {{$t('member_authority_tips')}}
+        </p>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">{{$t('cancel')}}</el-button>
+          <el-button type="primary" @click="MyFormSubmit" >{{$t('confirm')}}</el-button>
+        </div>
+      </el-dialog>
+
+      <!-- 添加团队弹窗 -->
+      <el-dialog :visible.sync="dialogFormTeamVisible" :modal="false" top="10vh">
+      <el-form >
+          <el-form-item label="选择团队" >
+            <el-select  class="" v-model="MyForm2.team_id">
+              <el-option  v-for="team in teams " :key="team.team_name" :label="team.team_name" :value="team.id"></el-option>
+            </el-select>
+
+          </el-form-item>
+          <router-link to="/team/index" target="_blank">{{$t('go_to_new_an_team')}}</router-link>
+      </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormTeamVisible = false">{{$t('cancel')}}</el-button>
+          <el-button type="primary" @click="addTeam" >{{$t('confirm')}}</el-button>
+        </div>
+      </el-dialog>
+
+      <!-- 成员权限弹窗 -->
+      <el-dialog :visible.sync="dialogFormTeamMemberVisible" :modal="false" top="10vh" :title="$t('adjust_member_authority')" width="90%">
+
+           <el-table align="left"
+                :empty-text="$t('team_member_empty_tips')"
+                :data="teamItemMembers"
+                style="width: 100%">
+                <el-table-column
+                  prop="member_username"
+                  :label="$t('username')"
+                 >
+                </el-table-column>
+                <el-table-column
+                  prop="member_group_id"
+                  :label="$t('authority')"
+                  width="130"
+                  >
+                  <template slot-scope="scope">
+                    <el-select size="mini" v-model="scope.row.member_group_id" @change="changeTeamItemMemberGroup($event,scope.row.id)" :placeholder="$t('please_choose')">
+                      <el-option
+                        v-for="item in authorityOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                        
+                        >
+                      </el-option>
+                    </el-select>
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  prop="addtime"
+                  :label="$t('add_time')"
+                  >
+                </el-table-column>
+
+              </el-table>
+        <br>
+        <p class="tips">
+          {{$t('team_member_authority_tips')}}
+        </p>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormTeamMemberVisible = false">{{$t('close')}}</el-button>
+        </div>
+      </el-dialog>
+
 
   </div>
 </template>
@@ -68,9 +162,26 @@ export default {
         username:'',
         is_readonly:false
       },
+      MyForm2:{
+        team_id:'',
+      },
       members:[],
       dialogFormVisible:false,
-      all_user:[]
+      dialogFormTeamVisible:false,
+      dialogFormTeamMemberVisible:false,
+      teams:[],
+      teamItems:[],
+      teamItemMembers:[],
+      authorityOptions:[
+          {
+            label:"编辑",
+            value:'1',
+          },
+          {
+            label:"只读",
+            value:'0',
+          }
+      ]
     }
 
   },
@@ -92,6 +203,55 @@ export default {
             
           });
       },
+      get_teams(){
+        var that = this ;
+        var url = DocConfig.server+'/api/team/getList';
+        var params = new URLSearchParams();
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data
+              that.teams =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+      },
+      getTeamItem(){
+        var that = this ;
+        var url = DocConfig.server+'/api/teamItem/getList';
+        var params = new URLSearchParams();
+        params.append('item_id',  that.$route.params.item_id);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data
+              that.teamItems =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+      },
+      getTeamItemMember(team_id){
+        var that = this ;
+        this.dialogFormTeamMemberVisible = true;
+        var url = DocConfig.server+'/api/teamItemMember/getList';
+        var params = new URLSearchParams();
+        params.append('item_id',  that.$route.params.item_id);
+        params.append('team_id',  team_id);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data
+              that.teamItemMembers =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          })
+      },
       MyFormSubmit() {
           var that = this ;
           var url = DocConfig.server+'/api/member/save';
@@ -121,7 +281,26 @@ export default {
               console.log(error);
             });
       },
+      addTeam() {
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItem/save';
 
+          var params = new URLSearchParams();
+          params.append('item_id',  that.$route.params.item_id);
+          params.append('team_id', this.MyForm2.team_id);
+
+          that.axios.post(url, params)
+          .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.dialogFormTeamVisible = false;
+                that.getTeamItem() ;
+                that.MyForm.team_id = '';
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+          });
+      },
       delete_member(item_member_id){
           var that = this ;
           var url = DocConfig.server+'/api/member/delete';
@@ -146,35 +325,51 @@ export default {
           })
 
       },
-      get_all_user(){
-        var that = this ;
-        var url = DocConfig.server+'/api/user/allUser';
-        that.axios.post(url)
+      deleteTeam(id){
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItem/delete';
+
+          this.$confirm(that.$t('confirm_delete'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('id',  id);
+            that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.getTeamItem() ;
+              }else{
+                that.$alert(response.data.error_message);
+              }
+            }); 
+          })
+      },
+      changeTeamItemMemberGroup(member_group_id,id){
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItemMember/save';
+
+          var params = new URLSearchParams();
+          params.append('member_group_id',  member_group_id);
+          params.append('id', id);
+
+          that.axios.post(url, params)
           .then(function (response) {
-            if (response.data.error_code === 0 ) {
-              that.all_user = response.data.data
-            }else{
-              that.$alert(response.data.error_message);
-            }
-            
+              if (response.data.error_code === 0 ) {
+                 that.$message('权限保存成功');
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
           });
-      },
-      querySearch(queryString, cb) {
-        var all_user = this.all_user;
-        var results = queryString ? all_user.filter(this.createFilter(queryString)) : all_user;
-        // 调用 callback 返回建议列表的数据
-        cb(results);
-      },
-      createFilter(queryString) {
-        return (all_user) => {
-          return (all_user.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
-        } 
       }
   },
 
   mounted(){
     this.get_members();
-    this.get_all_user();
+    this.get_teams();
+    this.getTeamItem();
   }
 }
 </script>

+ 196 - 0
web_src/src/components/team/Index.vue

@@ -0,0 +1,196 @@
+<template>
+  <div class="hello">
+    <Header> </Header>
+
+    <el-container>
+      <el-card class="center-card">
+
+      <el-button  type="text" class="add-cat" @click="addTeam">{{$t('add_team')}}</el-button>
+      <el-button type="text" class="goback-btn" @click="goback">{{$t('goback')}}</el-button>
+       <el-table align="left"
+            :data="list"
+             height="400"
+            style="width: 100%">
+            <el-table-column
+              prop="team_name"
+              :label="$t('team_name')"
+              >
+            </el-table-column>
+            <el-table-column
+              prop="memberCount"
+              :label="$t('memberCount')"
+              width="80">
+              <template slot-scope="scope">
+                  <router-link :to="'/team/member/'+scope.row.id" >{{scope.row.memberCount}}</router-link>
+              </template>
+            </el-table-column>
+            <el-table-column
+              prop="itemCount"
+              :label="$t('itemCount')">
+              <template slot-scope="scope">
+                  <router-link :to="'/team/item/'+scope.row.id" >{{scope.row.itemCount}}</router-link>
+              </template>
+            </el-table-column>
+            <el-table-column
+              prop=""
+              width="200"
+              :label="$t('operation')">
+              <template slot-scope="scope">
+                <el-button @click="$router.push({path:'/team/member/'+scope.row.id})" type="text" size="small">{{$t('member')}}</el-button>
+                <el-button @click="$router.push({path:'/team/item/'+scope.row.id})"  type="text" size="small">{{$t('team_item')}}</el-button>
+                <el-button @click="edit(scope.row)" type="text" size="small">{{$t('edit')}}</el-button>
+                <el-button @click="deleteTeam(scope.row.id)" type="text" size="small">{{$t('delete')}}</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+
+
+            </el-card>
+            <el-dialog :visible.sync="dialogFormVisible"  width="300px">
+              <el-form >
+                  <el-form-item :label="$t('team_name')+':'" >
+                     <el-input   v-model="MyForm.team_name"></el-input>
+                  </el-form-item>
+              </el-form>
+
+              <div slot="footer" class="dialog-footer">
+                <el-button @click="dialogFormVisible = false">{{$t('cancel')}}</el-button>
+                <el-button type="primary" @click="MyFormSubmit" >{{$t('confirm')}}</el-button>
+              </div>
+            </el-dialog>
+    </el-container>
+
+    <Footer> </Footer>
+  </div>
+</template>
+
+<script>
+
+export default {
+  components : {
+ 
+  },
+  data () {
+    return {
+      MyForm:{
+        id:'',
+        team_name:''
+      },
+      list:[],
+      dialogFormVisible:false,
+      dialogMemberVisible:false,
+    }
+  }, 
+  methods: {
+
+
+      geList(){
+        var that = this ;
+        var url = DocConfig.server+'/api/team/getList';
+        var params = new URLSearchParams();
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data ;
+
+              that.list =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+      },
+      MyFormSubmit() {
+          var that = this ;
+          var url = DocConfig.server+'/api/team/save';
+
+          var params = new URLSearchParams();
+          params.append('id', this.MyForm.id);
+          params.append('team_name', this.MyForm.team_name);
+          that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.dialogFormVisible = false;
+                that.geList() ;
+                that.MyForm = {};
+              }else{
+                that.$alert(response.data.error_message);
+              }
+            });
+      },
+      edit(row){
+        this.MyForm.id = row.id;
+        this.MyForm.team_name = row.team_name;
+        this.dialogFormVisible = true;
+      },
+
+      deleteTeam(id){
+          var that = this ;
+          var url = DocConfig.server+'/api/team/delete';
+
+          this.$confirm(that.$t('confirm_delete'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('id', id);
+
+            that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.geList() ;
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+            }); 
+          })
+
+      },
+      addTeam(){
+        this.MyForm = [] ;
+        this.dialogFormVisible = true;
+
+      },
+      goback(){
+        this.$router.push({path:"/item/index"})
+      }
+  },
+
+  mounted(){
+    this.geList();
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+.hello{
+  text-align: left;
+}
+
+.add-cat{
+  margin-left: 10px;
+}
+
+.center-card{
+  text-align: left;
+  width: 600px;
+  height: 500px;
+}
+
+.goback-btn{
+  z-index: 999;
+  margin-left: 400px;
+}
+</style>
+
+<!-- 全局css -->
+<style >
+.el-table .success-row {
+  background: #f0f9eb;
+}
+
+</style>

+ 305 - 0
web_src/src/components/team/Item.vue

@@ -0,0 +1,305 @@
+<template>
+  <div class="hello">
+    <Header> </Header>
+
+    <el-container>
+      <el-card class="center-card">
+      <el-button  type="text" class="add-cat" @click="addTeamItem">{{$t('distribution_to_team')}}</el-button>
+      <el-button type="text" class="goback-btn" @click="goback">{{$t('back_to_team')}}</el-button>
+       <el-table align="left"
+            :data="list"
+             height="400"
+            style="width: 100%">
+            <el-table-column
+              prop="item_name"
+              :label="$t('item_name')"
+              >
+            </el-table-column>
+            <el-table-column
+              prop="addtime"
+              :label="$t('Join_time')"
+              >
+            </el-table-column>
+
+            <el-table-column
+              prop=""
+              width="210"
+              :label="$t('operation')">
+              <template slot-scope="scope">
+                <router-link :to="'/'+scope.row.item_id" target="_blank">{{$t('check_item')}}</router-link>
+               
+              <el-button @click="getTeamItemMember(scope.row.item_id)" type="text" size="small">{{$t('member_authority')}}</el-button>
+
+                <el-button @click="deleteTeamItem(scope.row.id)" type="text" size="small">{{$t('unassign')}}</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+
+
+            </el-card>
+
+            <el-dialog :visible.sync="dialogFormVisible"  width="300px">
+                    <el-form >
+                        <el-select size="mini" v-model="MyForm.item_id"  :placeholder="$t('please_choose')">
+                          <el-option
+                            v-for="item in itemList"
+                            :key="item.item_id"
+                            :label="item.item_name"
+                            :value="item.item_id"
+                            
+                            >
+                          </el-option>
+                        </el-select>
+                    </el-form>
+                    <br>
+                    <router-link to="/item/index" target="_blank">{{$t('go_to_new_an_item')}}</router-link>
+                    <div slot="footer" class="dialog-footer">
+                      <el-button @click="dialogFormVisible = false">{{$t('cancel')}}</el-button>
+                      <el-button type="primary" @click="MyFormSubmit" >{{$t('confirm')}}</el-button>
+                    </div>
+            </el-dialog>
+
+      <!-- 成员权限弹窗 -->
+      <el-dialog :visible.sync="dialogFormTeamMemberVisible" :modal="false" top="10vh" :title="$t('adjust_member_authority')" >
+
+           <el-table align="left"
+                :empty-text="$t('team_member_empty_tips')"
+                :data="teamItemMembers"
+                style="width: 100%">
+                <el-table-column
+                  prop="member_username"
+                  :label="$t('username')"
+                 >
+                </el-table-column>
+                <el-table-column
+                  prop="member_group_id"
+                  :label="$t('authority')"
+                  width="130"
+                  >
+                  <template slot-scope="scope">
+                    <el-select size="mini" v-model="scope.row.member_group_id" @change="changeTeamItemMemberGroup($event,scope.row.id)" :placeholder="$t('please_choose')">
+                      <el-option
+                        v-for="item in authorityOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                        
+                        >
+                      </el-option>
+                    </el-select>
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  prop="addtime"
+                  :label="$t('add_time')"
+                  >
+                </el-table-column>
+
+              </el-table>
+        <br>
+        <p class="tips">
+          {{$t('team_member_authority_tips')}}
+        </p>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormTeamMemberVisible = false">{{$t('close')}}</el-button>
+        </div>
+      </el-dialog>
+
+    </el-container>
+
+
+
+    <Footer> </Footer>
+  </div>
+</template>
+
+<script>
+
+
+export default {
+  components : {
+
+  },
+  data () {
+    return {
+      MyForm:{
+        item_id:''
+      },
+      list:[],
+      dialogFormVisible:false,
+      team_id:'',
+      itemList:[],
+      teamItemMembers:[],
+      dialogFormTeamMemberVisible:false,
+      authorityOptions:[
+          {
+            label:"编辑",
+            value:'1',
+          },
+          {
+            label:"只读",
+            value:'0',
+          }
+      ]
+    }
+  }, 
+  methods: {
+      geList(){
+        var that = this ;
+        var url = DocConfig.server+'/api/teamItem/getListByTeam';
+        var params = new URLSearchParams();
+        params.append('team_id', this.team_id);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data ;
+
+              that.list =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+      },
+      getItemList(){
+          var that = this ;
+          var url = DocConfig.server+'/api/item/myList';
+          var params = new URLSearchParams();
+          that.axios.get(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                var json = response.data.data ;
+                that.itemList = json ;
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+            });
+      },
+      MyFormSubmit() {
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItem/save';
+
+          var params = new URLSearchParams();
+          params.append('team_id', this.team_id);
+          params.append('item_id', this.MyForm.item_id);
+          that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.dialogFormVisible = false;
+                that.geList() ;
+                that.MyForm = {};
+              }else{
+                that.$alert(response.data.error_message);
+              }
+            });
+      },
+
+      deleteTeamItem(id){
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItem/delete';
+
+          this.$confirm(that.$t('confirm_unassign'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('id', id);
+
+            that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.geList() ;
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+            }); 
+          })
+
+      },
+      addTeamItem(){
+        this.MyForm = [] ;
+        this.dialogFormVisible = true;
+
+      },
+      goback(){
+        this.$router.push({path:"/team/index"})
+      },
+      getTeamItemMember(item_id){
+        var that = this ;
+        this.dialogFormTeamMemberVisible = true;
+        var url = DocConfig.server+'/api/teamItemMember/getList';
+        var params = new URLSearchParams();
+        params.append('item_id',  item_id);
+        params.append('team_id',  this.team_id);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data
+              that.teamItemMembers =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          })
+      },
+      changeTeamItemMemberGroup(member_group_id,id){
+          var that = this ;
+          var url = DocConfig.server+'/api/teamItemMember/save';
+
+          var params = new URLSearchParams();
+          params.append('member_group_id',  member_group_id);
+          params.append('id', id);
+
+          that.axios.post(url, params)
+          .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                 that.$message('权限保存成功');
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+          });
+      }
+  },
+
+  mounted(){
+    this.team_id = this.$route.params.team_id; 
+    this.geList();
+    this.getItemList() ;
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+.hello{
+  text-align: left;
+}
+
+.add-cat{
+  margin-left: 10px;
+}
+
+.center-card{
+  text-align: left;
+  width: 600px;
+  height: 500px;
+}
+
+.goback-btn{
+  z-index: 999;
+  margin-left: 300px;
+}
+</style>
+
+<!-- 全局css -->
+<style >
+.el-table .success-row {
+  background: #f0f9eb;
+}
+
+</style>

+ 181 - 0
web_src/src/components/team/Member.vue

@@ -0,0 +1,181 @@
+<template>
+  <div class="hello">
+    <Header> </Header>
+
+    <el-container>
+      <el-card class="center-card">
+      <el-button  type="text" class="add-cat" @click="addTeamMember">{{$t('add_member')}}</el-button>
+      <el-button type="text" class="goback-btn" @click="goback">{{$t('back_to_team')}}</el-button>
+       <el-table align="left"
+            :data="list"
+             height="400"
+            style="width: 100%">
+            <el-table-column
+              prop="member_username"
+              :label="$t('member_username')"
+              >
+            </el-table-column>
+            <el-table-column
+              prop="addtime"
+              :label="$t('addtime')"
+              >
+            </el-table-column>
+
+            <el-table-column
+              prop=""
+              width="180"
+              :label="$t('operation')">
+              <template slot-scope="scope">
+                <el-button @click="deleteTeamMember(scope.row.id)" type="text" size="small">{{$t('delete')}}</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+
+
+            </el-card>
+
+            <el-dialog :visible.sync="dialogFormVisible"  width="300px">
+                    <el-form >
+                        <el-form-item :label="$t('member_username')+':'" >
+                           <el-input   v-model="MyForm.member_username"></el-input>
+                        </el-form-item>
+                    </el-form>
+
+                    <div slot="footer" class="dialog-footer">
+                      <el-button @click="dialogFormVisible = false">{{$t('cancel')}}</el-button>
+                      <el-button type="primary" @click="MyFormSubmit" >{{$t('confirm')}}</el-button>
+                    </div>
+            </el-dialog>
+
+    </el-container>
+
+    <Footer> </Footer>
+  </div>
+</template>
+
+<script>
+
+
+export default {
+  components : {
+
+  },
+  data () {
+    return {
+      MyForm:{
+        id:'',
+        member_username:''
+      },
+      list:[],
+      dialogFormVisible:false,
+      team_id:'',
+    }
+  }, 
+  methods: {
+      geList(){
+        var that = this ;
+        var url = DocConfig.server+'/api/teamMember/getList';
+        var params = new URLSearchParams();
+        params.append('team_id', this.team_id);
+        that.axios.post(url, params)
+          .then(function (response) {
+            if (response.data.error_code === 0 ) {
+              var Info = response.data.data ;
+
+              that.list =  Info;
+            }else{
+              that.$alert(response.data.error_message);
+            }
+            
+          });
+      },
+      MyFormSubmit() {
+          var that = this ;
+          var url = DocConfig.server+'/api/teamMember/save';
+
+          var params = new URLSearchParams();
+          params.append('team_id', this.team_id);
+          params.append('member_username', this.MyForm.member_username);
+          that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.dialogFormVisible = false;
+                that.geList() ;
+                that.MyForm = {};
+              }else{
+                that.$alert(response.data.error_message);
+              }
+            });
+      },
+
+      deleteTeamMember(id){
+          var that = this ;
+          var url = DocConfig.server+'/api/teamMember/delete';
+
+          this.$confirm(that.$t('confirm_delete'), ' ', {
+            confirmButtonText: that.$t('confirm'),
+            cancelButtonText: that.$t('cancel'),
+            type: 'warning'
+          }).then(() => {
+            var params = new URLSearchParams();
+            params.append('id', id);
+
+            that.axios.post(url, params)
+            .then(function (response) {
+              if (response.data.error_code === 0 ) {
+                that.geList() ;
+              }else{
+                that.$alert(response.data.error_message);
+              }
+              
+            }); 
+          })
+
+      },
+      addTeamMember(){
+        this.MyForm = [] ;
+        this.dialogFormVisible = true;
+
+      },
+      goback(){
+        this.$router.push({path:"/team/index"})
+      }
+  },
+
+  mounted(){
+    this.team_id = this.$route.params.team_id; 
+    this.geList();
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+.hello{
+  text-align: left;
+}
+
+.add-cat{
+  margin-left: 10px;
+}
+
+.center-card{
+  text-align: left;
+  width: 600px;
+  height: 500px;
+}
+
+.goback-btn{
+  z-index: 999;
+  margin-left: 350px;
+}
+</style>
+
+<!-- 全局css -->
+<style >
+.el-table .success-row {
+  background: #f0f9eb;
+}
+
+</style>

+ 3 - 0
web_src/src/router/index.js

@@ -18,6 +18,9 @@ import PageDiff from '@/components/page/Diff'
 import Catalog from '@/components/catalog/Index'
 import Notice from '@/components/notice/Index'
 import Admin from '@/components/admin/Index'
+import Team from '@/components/Team/Index'
+import TeamMember from '@/components/Team/Member'
+import TeamItem from '@/components/Team/Item'
 
 Vue.use(Router)
 

+ 23 - 0
web_src/static/lang/en.js

@@ -216,4 +216,27 @@ exports.default = {
     "add_user":"add user" ,
     "search":"search" ,
 
+    "team_mamage":'teamMamage',
+    "background":'background',
+    "distribution_to_team":'distribution item',
+    "back_to_team":'back to team',
+    "check_item":'checkItem',
+    "unassign":'unassign',
+    "go_to_new_an_item":'new an item',
+    "confirm_unassign":'confirm unassign?',
+    "Join_time":'Join time',
+    "add_team":'add team',
+    "member_authority":'member authority',
+    "go_to_new_an_team":'new an team',
+    "adjust_member_authority":'adjust member authority',
+    "team_member_empty_tips":'The team has not yet had any members.',
+    "team_member_authority_tips":'Permission description: Editing permission means that members can create/edit project pages, and when deleted, they can only delete their own newly created/edited pages. Read-only permission means that the member can only view all pages of this project and can not add/edit/delete them.',
+    "member":"member",
+    "team_item":"item",
+    "add_member":"add member",
+    "member_username":"member username",
+    "team_name":"team name",
+    "memberCount":"memberCount",
+    "itemCount":"itemCount",
+
 };

+ 24 - 0
web_src/static/lang/zh-CN.js

@@ -221,4 +221,28 @@ exports.default = {
     "item_management":"项目管理" ,
     "add_user":"新增用户" ,
     "search":"查询" ,
+
+    "team_mamage":'团队管理',
+    "background":'管理后台',
+    "distribution_to_team":'分配项目给团队',
+    "back_to_team":'返回团队管理',
+    "check_item":'查看项目',
+    "unassign":'取消分配',
+    "go_to_new_an_item":'去新建项目',
+    "confirm_unassign":'确认取消分配吗?此操作会取消项目和团队之间的关联',
+    "Join_time":'加入时间',
+    "add_team":'添加团队',
+    "member_authority":'成员权限',
+    "go_to_new_an_team":'去新建团队',
+    "adjust_member_authority":'调整每一个成员的项目权限',
+    "team_member_empty_tips":'该团队尚未有任何成员',
+    "team_member_authority_tips":'权限说明:编辑权限指的是成员可以新建/编辑项目页面,删除时将只能删除自己新建/编辑的页面。 只读权限指的是,该成员对本项目所有页面都只能查看,无法新增/编辑/删除',
+    "member":"成员",
+    "team_item":"项目",
+    "add_member":"添加成员",
+    "member_username":"成员用户名",
+    "team_name":"团队名",
+    "memberCount":"成员数",
+    "itemCount":"分配项目数",
+    
 };