优化群聊操作

This commit is contained in:
kuaifan 2022-04-14 22:50:39 +08:00
parent fcd6b1ddec
commit 6ca13bf263
6 changed files with 205 additions and 52 deletions

View File

@ -305,7 +305,7 @@ class DialogController extends AbstractController
$fileData['thumb'] = Base::unFillUrl($fileData['thumb']); $fileData['thumb'] = Base::unFillUrl($fileData['thumb']);
$fileData['size'] *= 1024; $fileData['size'] *= 1024;
// //
if ($dialog->type === 'group' && $dialog->group_type === 'task') { // 任务群保存文件 if ($dialog->type === 'group' && $dialog->group_type === 'task') { // 任务群保存文件
if ($image_attachment || !in_array($fileData['ext'], File::imageExt)) { // 如果是图片不保存 if ($image_attachment || !in_array($fileData['ext'], File::imageExt)) { // 如果是图片不保存
$task = ProjectTask::whereDialogId($dialog->id)->first(); $task = ProjectTask::whereDialogId($dialog->id)->first();
if ($task) { if ($task) {
@ -552,15 +552,15 @@ class DialogController extends AbstractController
} }
/** /**
* @api {get} api/dialog/group/add 15. 新增群 * @api {get} api/dialog/group/add 15. 新增群
* *
* @apiDescription 需要token身份 * @apiDescription 需要token身份
* @apiVersion 1.0.0 * @apiVersion 1.0.0
* @apiGroup dialog * @apiGroup dialog
* @apiName group__add * @apiName group__add
* *
* @apiParam {String} chat_name 群名
* @apiParam {Array} userids 群成员,格式: [userid1, userid2, userid3] * @apiParam {Array} userids 群成员,格式: [userid1, userid2, userid3]
* @apiParam {String} chat_name 群名称
* *
* @apiSuccess {Number} ret 返回状态码1正确、0错误 * @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {String} msg 返回信息(错误描述)
@ -570,8 +570,8 @@ class DialogController extends AbstractController
{ {
$user = User::auth(); $user = User::auth();
// //
$chatName = trim(Request::input('chat_name'));
$userids = Request::input('userids'); $userids = Request::input('userids');
$chatName = trim(Request::input('chat_name'));
// //
if (!is_array($userids)) { if (!is_array($userids)) {
return Base::retError('请选择群成员'); return Base::retError('请选择群成员');
@ -586,7 +586,7 @@ class DialogController extends AbstractController
$array = []; $array = [];
foreach ($userids as $userid) { foreach ($userids as $userid) {
$array[] = User::userid2nickname($userid); $array[] = User::userid2nickname($userid);
if (count($array) >= 8 || strlen(implode(", ", $array)) > 200) { if (count($array) >= 8 || strlen(implode(", ", $array)) > 100) {
$array[] = "..."; $array[] = "...";
break; break;
} }
@ -595,11 +595,53 @@ class DialogController extends AbstractController
} }
$dialog = WebSocketDialog::createGroup($chatName, $userids, 'user', $user->userid); $dialog = WebSocketDialog::createGroup($chatName, $userids, 'user', $user->userid);
if (empty($dialog)) { if (empty($dialog)) {
return Base::retError('创建群失败'); return Base::retError('创建群失败');
} }
return Base::retSuccess('创建成功', $dialog); return Base::retSuccess('创建成功', $dialog);
} }
/**
* @api {get} api/dialog/group/edit 16. 修改群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__edit
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {String} chat_name 群名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__edit()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$chatName = trim(Request::input('chat_name'));
//
if (mb_strlen($chatName) < 2) {
return Base::retError('群名称至少2个字');
}
if (mb_strlen($chatName) > 100) {
return Base::retError('群名称最长限制100个字');
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
if ($dialog->owner_id != $user->userid) {
return Base::retError('仅限群主操作');
}
//
$dialog->name = $chatName;
$dialog->save();
return Base::retSuccess('修改成功', [
'id' => $dialog->id,
'name' => $dialog->name,
]);
}
/** /**
* @api {get} api/dialog/group/user 16. 获取群成员 * @api {get} api/dialog/group/user 16. 获取群成员
* *
@ -702,4 +744,33 @@ class DialogController extends AbstractController
$dialog->exitGroup($userids); $dialog->exitGroup($userids);
return Base::retSuccess($type === 'remove' ? '移出成功' : '退出成功'); return Base::retSuccess($type === 'remove' ? '移出成功' : '退出成功');
} }
/**
* @api {get} api/dialog/group/disband 16. 解散群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName group__disband
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function group__disband()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
if ($dialog->owner_id != $user->userid) {
return Base::retError('仅限群主操作');
}
//
$dialog->disbandGroup();
return Base::retSuccess('解散成功');
}
} }

View File

@ -84,7 +84,10 @@ class WebSocketDialog extends AbstractModel
public function joinGroup($userid) public function joinGroup($userid)
{ {
if ($this->type !== 'group') { if ($this->type !== 'group') {
return false; throw new ApiException('此操作仅限群组');
}
if ($this->group_type !== 'user') {
throw new ApiException('此操作仅限个人群组');
} }
AbstractModel::transaction(function () use ($userid) { AbstractModel::transaction(function () use ($userid) {
foreach (is_array($userid) ? $userid : [$userid] as $value) { foreach (is_array($userid) ? $userid : [$userid] as $value) {
@ -106,6 +109,12 @@ class WebSocketDialog extends AbstractModel
*/ */
public function exitGroup($userid) public function exitGroup($userid)
{ {
if ($this->type !== 'group') {
throw new ApiException('此操作仅限群组');
}
if ($this->group_type !== 'user') {
throw new ApiException('此操作仅限个人群组');
}
$builder = WebSocketDialogUser::whereDialogId($this->id); $builder = WebSocketDialogUser::whereDialogId($this->id);
if (is_array($userid)) { if (is_array($userid)) {
$builder->whereIn('userid', $userid); $builder->whereIn('userid', $userid);
@ -125,6 +134,29 @@ class WebSocketDialog extends AbstractModel
return true; return true;
} }
/**
* 解散群组
* @return bool
*/
public function disbandGroup()
{
if ($this->type !== 'group') {
throw new ApiException('此操作仅限群组');
}
if ($this->group_type !== 'user') {
throw new ApiException('此操作仅限个人群组');
}
return AbstractModel::transaction(function() {
WebSocketDialogUser::whereDialogId($this->id)->chunkById(100, function($list) {
/** @var WebSocketDialogUser $item */
foreach ($list as $item) {
$item->delete();
}
});
return $this->delete();
});
}
/** /**
* 获取对话(同时检验对话身份) * 获取对话(同时检验对话身份)
* @param $dialog_id * @param $dialog_id
@ -148,7 +180,7 @@ class WebSocketDialog extends AbstractModel
} }
} }
if (!WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->exists()) { if (!WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->exists()) {
throw new ApiException('不在成员列表内'); throw new ApiException('不在成员列表内', ['dialog_id' => $dialog_id], -4003);
} }
return $dialog; return $dialog;
} }

View File

@ -16,20 +16,11 @@
clearable/> clearable/>
</div> </div>
<div v-if="dialogData.owner_id == userId" @click="openAdd" class="group-info-button">
<Icon type="md-add" />
<span>{{ $L("添加成员") }}</span>
</div>
<div v-else @click="onExit" class="group-info-button">
<Icon type="md-exit" />
<span>{{ $L("退出群聊") }}</span>
</div>
<div class="group-info-user"> <div class="group-info-user">
<ul> <ul>
<li v-for="(item, index) in userList" :key="index"> <li v-for="(item, index) in userList" :key="index">
<UserAvatar :userid="item.userid" :size="32" :user-result="userResult" showName tooltipDisabled/> <UserAvatar :userid="item.userid" :size="32" :user-result="userResult" showName tooltipDisabled/>
<Tag v-if="item.userid === dialogData.owner_id" color="primary">{{ $L("群主") }}</Tag> <div v-if="item.userid === dialogData.owner_id" class="user-tag">{{ $L("群主") }}</div>
<Icon v-else-if="dialogData.owner_id == userId" class="user-exit" type="md-exit" @click="onExit(item)"/> <Icon v-else-if="dialogData.owner_id == userId" class="user-exit" type="md-exit" @click="onExit(item)"/>
</li> </li>
<li v-if="userList.length === 0" class="no"> <li v-if="userList.length === 0" class="no">
@ -39,6 +30,14 @@
</ul> </ul>
</div> </div>
<div v-if="dialogData.owner_id == userId" class="group-info-button">
<Button @click="openAdd" type="primary">{{ $L("添加成员") }}</Button>
<Button @click="onDisband" type="error" ghost>{{ $L("解散群组") }}</Button>
</div>
<div v-else class="group-info-button">
<Button @click="onExit" type="error" ghost>{{ $L("退出群组") }}</Button>
</div>
<!--添加成员--> <!--添加成员-->
<Modal <Modal
v-model="addShow" v-model="addShow"
@ -129,8 +128,24 @@ export default {
}, },
methods: { methods: {
updateName() { updateName(val, cb) {
if (!val) {
cb()
return;
}
this.$store.dispatch("call", {
url: 'dialog/group/edit',
data: {
dialog_id: this.dialogId,
chat_name: val
}
}).then(({data}) => {
this.$store.dispatch("saveDialog", data);
cb()
}).catch(({msg}) => {
$A.modalError(msg);
cb()
});
}, },
getDialogUser() { getDialogUser() {
@ -193,10 +208,10 @@ export default {
}, },
onExit(item) { onExit(item) {
let content = "你确定要退出群吗?" let content = "你确定要退出群吗?"
let userids = []; let userids = [];
if ($A.isJson(item)) { if ($A.isJson(item)) {
content = `你确定要将【${item.nickname}】移出群吗?` content = `你确定要将【${item.nickname}】移出群吗?`
userids = [item.userid]; userids = [item.userid];
} }
$A.modalConfirm({ $A.modalConfirm({
@ -212,7 +227,7 @@ export default {
}).then(({msg}) => { }).then(({msg}) => {
this.$Modal.remove(); this.$Modal.remove();
$A.messageSuccess(msg); $A.messageSuccess(msg);
if (userids === "my") { if (userids.length > 0) {
this.getDialogUser(); this.getDialogUser();
} else { } else {
this.$store.dispatch("forgetDialog", this.dialogId); this.$store.dispatch("forgetDialog", this.dialogId);
@ -224,7 +239,31 @@ export default {
}); });
}, },
}); });
},
onDisband() {
$A.modalConfirm({
content: `你确定要解散【${this.dialogData.name}】群组吗?`,
loading: true,
okText: '解散',
onOk: () => {
this.$store.dispatch("call", {
url: 'dialog/group/disband',
data: {
dialog_id: this.dialogId,
} }
}).then(({msg}) => {
this.$Modal.remove();
$A.messageSuccess(msg);
this.$store.dispatch("forgetDialog", this.dialogId);
this.goForward({name: 'manage-messenger'});
}).catch(({msg}) => {
$A.modalError(msg, 301);
this.$Modal.remove();
});
},
});
},
} }
} }
</script> </script>

View File

@ -35,7 +35,7 @@
</template> </template>
</div> </div>
<template v-if="dialogData.type === 'group'"> <template v-if="dialogData.type === 'group'">
<ETooltip v-if="dialogData.group_type === 'user'" placement="top" :content="$L('群设置')"> <ETooltip v-if="dialogData.group_type === 'user'" placement="top" :openDelay="600" :content="$L('群设置')">
<i class="taskfont dialog-create" @click="groupInfoShow = true">&#xe6e9;</i> <i class="taskfont dialog-create" @click="groupInfoShow = true">&#xe6e9;</i>
</ETooltip> </ETooltip>
</template> </template>
@ -127,10 +127,10 @@
</div> </div>
</Modal> </Modal>
<!--创建群--> <!--创建群-->
<Modal <Modal
v-model="createGroupShow" v-model="createGroupShow"
:title="$L('创建群')" :title="$L('创建群')"
:mask-closable="false"> :mask-closable="false">
<Form :model="createGroupData" label-width="auto" @submit.native.prevent> <Form :model="createGroupData" label-width="auto" @submit.native.prevent>
<FormItem prop="userids" :label="$L('群成员')"> <FormItem prop="userids" :label="$L('群成员')">

View File

@ -191,6 +191,18 @@ body.dark-mode-reverse {
} }
} }
.dialog-group-info {
.group-info-user {
> ul {
> li {
.user-tag {
color: $primary-title-color;
}
}
}
}
}
.file-icon { .file-icon {
&:before { &:before {
background-image: url("../images/file/dark/other.svg"); background-image: url("../images/file/dark/other.svg");

View File

@ -24,29 +24,25 @@
overflow: visible; overflow: visible;
white-space: normal; white-space: normal;
} }
.quick-input {
display: flex;
flex-direction: column;
}
} }
.group-info-search { .group-info-search {
margin: 18px 24px 0; margin: 24px 24px 0;
} }
.group-info-button { .group-info-button {
display: flex;
align-items: center;
margin: 18px 24px 0;
cursor: pointer;
> i {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 32px; margin: 18px 24px;
width: 32px; cursor: pointer;
font-size: 18px; > button {
margin-right: 8px; margin: 0 8px;
border-radius: 50%;
color: #777;
border: 1px solid #ddd;
} }
} }
@ -87,14 +83,26 @@
} }
} }
.user-tag {
margin-left: 4px;
height: 22px;
line-height: 22px;
padding: 0 6px;
border-radius: 3px;
transform: scale(0.9);
transform-origin: right center;
color: #ffffff;
background-color: $primary-color;
}
.user-exit { .user-exit {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
margin-left: 4px; margin-left: 4px;
width: 20px; width: 22px;
height: 20px; height: 22px;
font-size: 12px; font-size: 12px;
color: #999999; color: #999999;
border: 1px solid #dddddd; border: 1px solid #dddddd;
@ -103,15 +111,6 @@
transform: translateX(50%); transform: translateX(50%);
transition: all 0.2s; transition: all 0.2s;
} }
.ivu-tag {
margin-left: 4px;
height: 20px;
line-height: 20px;
padding: 0 5px;
transform: scale(0.9);
transform-origin: right center;
}
} }
} }
} }