Ver Fonte

成员管理

wangqifan há 3 anos atrás
pai
commit
575c1b80e8

+ 5 - 0
src/main/java/com/izouma/nineth/domain/netease/Team.java

@@ -32,6 +32,9 @@ public class Team extends BaseEntityNoID {
     @Column(columnDefinition = "TEXT")
     @Convert(converter = StringArrayConverter.class)
     private List<String> banned;
+    @Column(columnDefinition = "TEXT")
+    @Convert(converter = StringArrayConverter.class)
+    private List<String> kicked;
     private String       announcement;
     private String       intro;
     private String       msg;
@@ -49,6 +52,8 @@ public class Team extends BaseEntityNoID {
     private Long           unread;
     @Transient
     private NeteaseMessage lastMsg;
+    @Transient
+    private boolean        ban;
 
     private boolean mute;
 

+ 15 - 0
src/main/java/com/izouma/nineth/dto/netease/TeamMember.java

@@ -0,0 +1,15 @@
+package com.izouma.nineth.dto.netease;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TeamMember {
+    private String  nickName;
+    private String  accid;
+    private String  avatar;
+    private boolean banned;
+}

+ 3 - 0
src/main/java/com/izouma/nineth/repo/NeteaseUserRepo.java

@@ -7,10 +7,13 @@ import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 
 import javax.transaction.Transactional;
+import java.util.List;
 
 public interface NeteaseUserRepo extends JpaRepository<NeteaseUser, Long>, JpaSpecificationExecutor<NeteaseUser> {
     @Query("update NeteaseUser t set t.del = true where t.id = ?1")
     @Modifying
     @Transactional
     void softDelete(Long id);
+
+    List<NeteaseUser> findAllByAccIdIn(List<String> accids);
 }

+ 85 - 0
src/main/java/com/izouma/nineth/service/netease/TeamService.java

@@ -7,6 +7,7 @@ import com.izouma.nineth.domain.netease.NeteaseMessage;
 import com.izouma.nineth.domain.netease.NeteaseUser;
 import com.izouma.nineth.domain.netease.Team;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.netease.TeamMember;
 import com.izouma.nineth.enums.netease.TeamType;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.AssetRepo;
@@ -58,6 +59,7 @@ public class TeamService {
                     }
                 }
             }
+            team.setBan(team.getBanned().stream().anyMatch(member -> StringUtils.equals(member, userId.toString())));
             team.setLastMsg(getTeamLastMessage(team.getTid()));
             team.setUnread(getUnreadCount(userId.toString(), team.getTid().toString()));
             team.setInTeam(inTeam);
@@ -143,10 +145,54 @@ public class TeamService {
         teamRepo.save(team);
     }
 
+    public void muteMember(Long tid, String accid) {
+        Map<String, Object> params = new HashMap<>();
+        Team team = teamRepo.findById(tid).orElseThrow(new BusinessException("暂无"));
+        params.put("tid", tid);
+        params.put("owner", team.getOwnerid());
+        params.put("accid", accid);
+        params.put("mute", 1);
+        String result = neteaseUserService
+                .httpPost("team/muteTlist.action", "application/x-www-form-urlencoded;charset=utf-8", params);
+        JSONObject jsonObject = JSON.parseObject(result);
+        Integer code = jsonObject.getInteger("code");
+        if (code != 200) {
+            throw new BusinessException("禁言操作出错");
+        }
+        List<String> banned = new ArrayList<>(team.getBanned());
+        banned.add(accid);
+        team.setBanned(banned);
+        teamRepo.save(team);
+    }
+
+    public void cancelMuteMember(Long tid, String accid) {
+        Map<String, Object> params = new HashMap<>();
+        Team team = teamRepo.findById(tid).orElseThrow(new BusinessException("暂无"));
+        params.put("tid", tid);
+        params.put("owner", team.getOwnerid());
+        params.put("accid", accid);
+        params.put("mute", 0);
+        String result = neteaseUserService
+                .httpPost("team/muteTlist.action", "application/x-www-form-urlencoded;charset=utf-8", params);
+        JSONObject jsonObject = JSON.parseObject(result);
+        Integer code = jsonObject.getInteger("code");
+        if (code != 200) {
+            throw new BusinessException("禁言操作出错");
+        }
+        List<String> banned = new ArrayList<>(team.getBanned());
+        banned.removeIf(id -> StringUtils.equals(id, accid));
+        team.setBanned(banned);
+        teamRepo.save(team);
+    }
+
     public Team invite(String id, String tid) {
         List<String> ids = new ArrayList<>();
         ids.add(id);
         Team team = teamRepo.findById(Long.valueOf(tid)).orElseThrow(new BusinessException("未找到群聊"));
+        List<String> kicked = team.getKicked();
+        if (kicked.stream().anyMatch(member -> StringUtils.equals(member, id))) {
+            throw new BusinessException("用户被踢出,无法加入");
+        }
         Map<String, Object> params = new HashMap<>();
         params.put("tid", tid);
         params.put("owner", team.getOwnerid());
@@ -185,6 +231,27 @@ public class TeamService {
         teamRepo.save(team);
     }
 
+    public void kick(String id, String tid) {
+        Team team = teamRepo.findById(Long.valueOf(tid)).orElseThrow(new BusinessException("未找到群聊"));
+        Map<String, Object> params = new HashMap<>();
+        params.put("tid", tid);
+        params.put("accid", id);
+        String result = neteaseUserService
+                .httpPost("team/leave.action", "application/x-www-form-urlencoded;charset=utf-8", params);
+        JSONObject jsonObject = JSON.parseObject(result);
+        Integer code = jsonObject.getInteger("code");
+        if (code != 200) {
+            throw new BusinessException("退群出错");
+        }
+        List<String> members = new ArrayList<>(team.getMembers());
+        members.removeIf(member -> StringUtils.equals(member, id));
+        team.setMembers(members);
+        List<String> kicked = new ArrayList<>(team.getKicked());
+        kicked.add(id);
+        team.setKicked(kicked);
+        teamRepo.save(team);
+    }
+
     public void checkout(String accid, String tid) {
         Long ts = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
         redisTemplate.opsForValue().set(RedisKeys.USER_CHECKOUT_TIME + accid + ":" + tid, ts);
@@ -236,4 +303,22 @@ public class TeamService {
         }
         return true;
     }
+
+    public List<TeamMember> getTeamMembers(Long tid) {
+        Team team = teamRepo.findById(tid).orElseThrow(new BusinessException("未找到群组"));
+        List<String> strings = team.getMembers();
+        List<NeteaseUser> neteaseUsers = neteaseUserRepo.findAllByAccIdIn(strings);
+        List<TeamMember> result = new ArrayList<>();
+        List<String> banned = new ArrayList<>(team.getBanned());
+        neteaseUsers.forEach(member -> {
+            TeamMember teamMember = new TeamMember();
+            teamMember.setAccid(member.getAccId());
+            teamMember.setAvatar(member.getIcon());
+            teamMember.setNickName(member.getName());
+            teamMember.setBanned(banned.stream()
+                    .anyMatch(bannedOne -> StringUtils.equals(bannedOne, member.getAccId())));
+            result.add(teamMember);
+        });
+        return result;
+    }
 }

+ 22 - 0
src/main/java/com/izouma/nineth/web/netease/TeamController.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.web.netease;
 
+import com.izouma.nineth.dto.netease.TeamMember;
 import com.izouma.nineth.service.netease.TeamService;
 import com.izouma.nineth.web.BaseController;
 import com.izouma.nineth.domain.netease.Team;
@@ -42,6 +43,18 @@ public class TeamController extends BaseController {
         teamService.mute(id);
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/muteSolo")
+    public void muteSolo(Long tid, String accid) {
+        teamService.muteMember(tid, accid);
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/cancelMuteSolo")
+    public void cancelMuteSolo(Long tid, String accid) {
+        teamService.cancelMuteMember(tid, accid);
+    }
+
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/cancelMute/{id}")
     public void cancelMute(@PathVariable Long id) {
@@ -63,6 +76,15 @@ public class TeamController extends BaseController {
         teamService.leave(userId, tid);
     }
 
+    @PostMapping("/kick")
+    public void kick(@RequestParam String userId, @RequestParam String tid) {
+        teamService.kick(userId, tid);
+    }
+
+    @PostMapping("/memberInfos")
+    public List<TeamMember> memberInfos(Long tid) {
+        return teamService.getTeamMembers(tid);
+    }
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")

+ 122 - 2
src/main/vue/src/views/TeamList.vue

@@ -74,7 +74,7 @@
                     <el-button @click="mute(row)" v-if="row.mute === false" type="danger" size="mini" plain>群禁言
                     </el-button>
                     <el-button @click="cancelMute(row)" v-if="row.mute === true" size="mini" plain>解除禁言</el-button>
-                    <!--                    <el-button @click="invite(row)" size="mini" plain>添加群成员</el-button>-->
+                    <el-button @click="showMemberInfoDialog(row)" size="mini" plain>成员</el-button>
                     <!--                    <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button>-->
                 </template>
             </el-table-column>
@@ -115,6 +115,39 @@
                 <el-button type="primary" @click="inviteSolo">保存</el-button>
             </div>
         </el-dialog>
+        <el-dialog :visible.sync="showMemberInfo" width="600px">
+            <el-table :data="memberInfos" height="60vh">
+                <el-table-column prop="nickName" label="昵称"></el-table-column>
+                <el-table-column prop="accid" label="用户id"></el-table-column>
+                <!--                <el-table-column prop="icon" label="图标"-->
+                <!--                >-->
+                <!--                    <template slot-scope="{row}">-->
+                <!--                        <el-image style="width: 30px; height: 30px"-->
+                <!--                                  :src="row.avatar" fit="cover"-->
+                <!--                                  :preview-src-list="[row.avatar]"></el-image>-->
+                <!--                    </template>-->
+                <!--                </el-table-column>-->
+                <el-table-column
+                    label="操作"
+                    align="center"
+                    fixed="right"
+                    width="300">
+                    <template slot-scope="{row}">
+                        <el-button @click="kick(row)" type="danger" size="mini" plain>踢出</el-button>
+                        <el-button @click="muteMember(row)" v-if="row.banned === false" type="danger" size="mini" plain>
+                            群禁言
+                        </el-button>
+                        <el-button @click="cancelMuteMember(row)" v-if="row.banned === true" type="danger" size="mini"
+                                   plain>
+                            解除禁言
+                        </el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <div slot="footer">
+                <el-button @click="showMemberInfo = false">关闭</el-button>
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script>
@@ -131,10 +164,13 @@ export default {
             url: "/team/all",
             downloading: false,
             showInviteInfo: false,
+            selectedTid: null,
+            showMemberInfo: false,
             inviteForm: {
                 userId: '',
                 tid: ''
-            }
+            },
+            memberInfos: []
         }
     },
     computed: {
@@ -176,6 +212,90 @@ export default {
                 }
             })
         },
+        showMemberInfoDialog(row) {
+            this.selectedTid = row.tid;
+            let data = {
+                tid: row.tid
+            }
+            this.$http.post(`/team/memberInfos`, data)
+                .then((res) => {
+                    this.memberInfos = res;
+                    this.showMemberInfo = true;
+                }).catch(e => {
+                if (e !== 'cancel') {
+                    this.$message.error(e.error);
+                }
+            })
+        },
+        kick(row) {
+            let data = {
+                tid: this.selectedTid,
+                userId: row.accid
+            }
+            this.$alert('踢出后用户无法再进入本群,确定要踢出群聊?', '警告', {type: 'error'}).then(() => {
+                return this.$http.post(`/team/kick`, data)
+            }).then(() => {
+                this.$message.success('踢出成功');
+                this.$http.post(`/team/memberInfos`, {tid: this.selectedTid})
+                    .then((res) => {
+                        this.memberInfos = res;
+                    }).catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                })
+            }).catch(e => {
+                if (e !== 'cancel') {
+                    this.$message.error(e.error);
+                }
+            })
+        },
+        muteMember(row) {
+            let data = {
+                tid: this.selectedTid,
+                accid: row.accid
+            }
+            this.$alert('禁言后用户无法发言,确认要禁言么?', '警告', {type: 'error'}).then(() => {
+                return this.$http.post(`/team/muteSolo`, data)
+            }).then(() => {
+                this.$message.success('禁言成功');
+                this.$http.post(`/team/memberInfos`, {tid: this.selectedTid})
+                    .then((res) => {
+                        this.memberInfos = res;
+                    }).catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                })
+            }).catch(e => {
+                if (e !== 'cancel') {
+                    this.$message.error(e.error);
+                }
+            })
+        },
+        cancelMuteMember(row) {
+            let data = {
+                tid: this.selectedTid,
+                accid: row.accid
+            }
+            this.$alert('解禁后用户可正常发言,确定解禁吗?', '警告', {type: 'error'}).then(() => {
+                return this.$http.post(`/team/cancelMuteSolo`, data)
+            }).then(() => {
+                this.$message.success('禁言成功');
+                this.$http.post(`/team/memberInfos`, {tid: this.selectedTid})
+                    .then((res) => {
+                        this.memberInfos = res;
+                    }).catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                })
+            }).catch(e => {
+                if (e !== 'cancel') {
+                    this.$message.error(e.error);
+                }
+            })
+        },
         mute(row) {
             this.$alert('禁言后用户无法发言,确认要禁言么?', '警告', {type: 'error'}).then(() => {
                 return this.$http.post(`/team/mute/${row.tid}`)