mirror of
https://github.com/kuaifan/dootask.git
synced 2026-03-02 23:27:04 +00:00
perf: 项目群、任务群可添加成员
This commit is contained in:
parent
bebef77e5c
commit
3aefe99bd9
@ -929,6 +929,8 @@ class DialogController extends AbstractController
|
||||
* @api {get} api/dialog/group/adduser 21. 添加群成员
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* - 有群主时:只有群主可以邀请
|
||||
* - 没有群主时:群内成员都可以邀请
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName group__adduser
|
||||
@ -951,7 +953,7 @@ class DialogController extends AbstractController
|
||||
return Base::retError('请选择群成员');
|
||||
}
|
||||
//
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id, "auto");
|
||||
//
|
||||
$dialog->checkGroup();
|
||||
$dialog->joinGroup($userids);
|
||||
@ -963,6 +965,8 @@ class DialogController extends AbstractController
|
||||
* @api {get} api/dialog/group/deluser 22. 移出(退出)群成员
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* - 只有群主、邀请人可以踢人
|
||||
* - 群主、任务人员、项目人员不可被踢或退出
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName group__adduser
|
||||
@ -993,10 +997,10 @@ class DialogController extends AbstractController
|
||||
return Base::retError('请选择群成员');
|
||||
}
|
||||
//
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id, $type === 'remove');
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id);
|
||||
//
|
||||
$dialog->checkGroup();
|
||||
$dialog->exitGroup($userids);
|
||||
$dialog->exitGroup($userids, $type);
|
||||
$dialog->pushMsg("groupExit", null, $userids);
|
||||
return Base::retSuccess($type === 'remove' ? '移出成功' : '退出成功');
|
||||
}
|
||||
@ -1005,6 +1009,7 @@ class DialogController extends AbstractController
|
||||
* @api {get} api/dialog/group/disband 23. 解散群组
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* - 只有群主且是个人类型群可以解散
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName group__disband
|
||||
@ -1023,7 +1028,7 @@ class DialogController extends AbstractController
|
||||
//
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
|
||||
//
|
||||
$dialog->checkGroup();
|
||||
$dialog->checkGroup('user');
|
||||
$dialog->deleteDialog();
|
||||
$dialog->pushMsg("groupDelete");
|
||||
return Base::retSuccess('解散成功');
|
||||
|
||||
@ -207,9 +207,11 @@ class Project extends AbstractModel
|
||||
WebSocketDialogUser::updateInsert([
|
||||
'dialog_id' => $this->dialog_id,
|
||||
'userid' => $userid,
|
||||
], [
|
||||
'important' => 1
|
||||
]);
|
||||
}
|
||||
WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete();
|
||||
WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->whereImportant(1)->delete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -876,9 +876,11 @@ class ProjectTask extends AbstractModel
|
||||
WebSocketDialogUser::updateInsert([
|
||||
'dialog_id' => $this->dialog_id,
|
||||
'userid' => $userid,
|
||||
], [
|
||||
'important' => 1
|
||||
]);
|
||||
}
|
||||
WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete();
|
||||
WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->whereImportant(1)->delete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -134,6 +134,8 @@ class WebSocketDialog extends AbstractModel
|
||||
WebSocketDialogUser::updateInsert([
|
||||
'dialog_id' => $this->id,
|
||||
'userid' => $value,
|
||||
], [
|
||||
'inviter' => User::userid(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -144,27 +146,34 @@ class WebSocketDialog extends AbstractModel
|
||||
/**
|
||||
* 退出聊天室
|
||||
* @param int|array $userid 加入的会员ID或会员ID组
|
||||
* @return bool
|
||||
* @param $type
|
||||
*/
|
||||
public function exitGroup($userid)
|
||||
public function exitGroup($userid, $type = 'exit')
|
||||
{
|
||||
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
||||
if (is_array($userid)) {
|
||||
$builder->whereIn('userid', $userid);
|
||||
} else {
|
||||
$builder->whereUserid($userid);
|
||||
}
|
||||
$builder->chunkById(100, function($list) {
|
||||
/** @var WebSocketDialogUser $item */
|
||||
foreach ($list as $item) {
|
||||
if ($item->userid == $this->owner_id) {
|
||||
// 群主不可退出
|
||||
continue;
|
||||
}
|
||||
$item->delete();
|
||||
$typeDesc = $type === 'remove' ? '移出' : '退出';
|
||||
AbstractModel::transaction(function () use ($typeDesc, $type, $userid) {
|
||||
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
||||
if (is_array($userid)) {
|
||||
$builder->whereIn('userid', $userid);
|
||||
} else {
|
||||
$builder->whereUserid($userid);
|
||||
}
|
||||
$builder->chunkById(100, function($list) use ($typeDesc, $type) {
|
||||
/** @var WebSocketDialogUser $item */
|
||||
foreach ($list as $item) {
|
||||
if ($type === 'remove' && !in_array(User::userid(), [$this->owner_id, $item->inviter])) {
|
||||
throw new ApiException('只有群主或邀请人可以移出成员');
|
||||
}
|
||||
if ($item->userid == $this->owner_id) {
|
||||
throw new ApiException('群主不可' . $typeDesc);
|
||||
}
|
||||
if ($item->important) {
|
||||
throw new ApiException('项目人员或任务人员不可' . $typeDesc);
|
||||
}
|
||||
$item->delete();
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,15 +205,19 @@ class WebSocketDialog extends AbstractModel
|
||||
|
||||
/**
|
||||
* 检查群组类型
|
||||
* @param string|array|null $groupType
|
||||
* @return void
|
||||
*/
|
||||
public function checkGroup($groupType = 'user')
|
||||
public function checkGroup($groupType = null)
|
||||
{
|
||||
if ($this->type !== 'group') {
|
||||
throw new ApiException('仅限群组操作');
|
||||
}
|
||||
if ($this->group_type !== $groupType) {
|
||||
throw new ApiException('操作的群组类型错误');
|
||||
if ($groupType) {
|
||||
$groupTypes = is_array($groupType) ? $groupType : [$groupType];
|
||||
if (!in_array($this->group_type, $groupTypes)) {
|
||||
throw new ApiException('操作的群组类型错误');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +273,7 @@ class WebSocketDialog extends AbstractModel
|
||||
/**
|
||||
* 获取对话(同时检验对话身份)
|
||||
* @param $dialog_id
|
||||
* @param bool $checkOwner 是否校验群组身份
|
||||
* @param bool|string $checkOwner 是否校验群组身份,'auto'时有群主为true无群主为false
|
||||
* @return self
|
||||
*/
|
||||
public static function checkDialog($dialog_id, $checkOwner = false)
|
||||
@ -271,11 +284,14 @@ class WebSocketDialog extends AbstractModel
|
||||
}
|
||||
//
|
||||
$userid = User::userid();
|
||||
if ($checkOwner === 'auto') {
|
||||
$checkOwner = $dialog->owner_id > 0;
|
||||
}
|
||||
if ($checkOwner === true && $dialog->owner_id != $userid) {
|
||||
throw new ApiException('仅限群主操作');
|
||||
}
|
||||
//
|
||||
if ($dialog->type === 'group' && $dialog->group_type === 'task') {
|
||||
if ($dialog->group_type === 'task') {
|
||||
// 任务群对话校验是否在项目内
|
||||
$project_id = intval(ProjectTask::whereDialogId($dialog->id)->value('project_id'));
|
||||
if ($project_id > 0) {
|
||||
|
||||
@ -10,6 +10,8 @@ namespace App\Models;
|
||||
* @property int|null $userid 会员ID
|
||||
* @property string|null $top_at 置顶时间
|
||||
* @property int|null $mark_unread 是否标记为未读:0否,1是
|
||||
* @property int|null $inviter 邀请人
|
||||
* @property int|null $important 是否不可移出(项目、任务人员)
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
|
||||
@ -18,6 +20,8 @@ namespace App\Models;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereDialogId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereImportant($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereInviter($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereMarkUnread($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUpdatedAt($value)
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddWebSocketDialogUsersInviterImportant extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$isAdd = false;
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) use (&$isAdd) {
|
||||
if (!Schema::hasColumn('web_socket_dialog_users', 'important')) {
|
||||
$isAdd = true;
|
||||
$table->boolean('important')->default(0)->after('mark_unread')->nullable()->comment('是否不可移出(项目、任务人员)');
|
||||
$table->bigInteger('inviter')->nullable()->default(0)->after('mark_unread')->comment('邀请人');
|
||||
}
|
||||
});
|
||||
if ($isAdd) {
|
||||
\App\Models\WebSocketDialog::whereIn('group_type', ['project', 'task'])->chunkById(100, function ($lists) {
|
||||
/** @var \App\Models\WebSocketDialog $item */
|
||||
foreach ($lists as $item) {
|
||||
\App\Models\WebSocketDialogUser::whereDialogId($item->id)->update([
|
||||
'important' => 1,
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
|
||||
$table->dropColumn("important");
|
||||
$table->dropColumn("inviter");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -19,9 +19,9 @@
|
||||
<div class="group-info-user">
|
||||
<ul>
|
||||
<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" showName tooltipDisabled/>
|
||||
<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 || item.inviter == userId" class="user-exit" type="md-exit" @click="onExit(item)"/>
|
||||
</li>
|
||||
<li v-if="userList.length === 0" class="no">
|
||||
<Loading v-if="loadIng > 0"/>
|
||||
@ -30,12 +30,10 @@
|
||||
</ul>
|
||||
</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 class="group-info-button">
|
||||
<Button v-if="dialogData.owner_id == userId || dialogData.owner_id == 0" @click="openAdd" type="primary">{{ $L("添加成员") }}</Button>
|
||||
<Button v-if="dialogData.owner_id == userId" @click="onDisband" type="error" ghost>{{ $L("解散群组") }}</Button>
|
||||
<Button v-else @click="onExit" type="error" ghost>{{ $L("退出群组") }}</Button>
|
||||
</div>
|
||||
|
||||
<!--添加成员-->
|
||||
@ -85,7 +83,7 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['cacheDialogs']),
|
||||
...mapState(['cacheDialogs', 'cacheUserBasic']),
|
||||
|
||||
dialogData() {
|
||||
return this.cacheDialogs.find(({id}) => id == this.dialogId) || {};
|
||||
@ -100,8 +98,15 @@ export default {
|
||||
},
|
||||
|
||||
userList() {
|
||||
const {dialogUser, searchKey, dialogData} = this;
|
||||
const list = dialogUser.filter(item => {
|
||||
const {dialogUser, searchKey, cacheUserBasic, dialogData} = this;
|
||||
const list = dialogUser.map(item => {
|
||||
const userBasic = cacheUserBasic.find(basic => basic.userid == item.userid)
|
||||
if (userBasic) {
|
||||
item.nickname = userBasic.nickname
|
||||
item.email = userBasic.email
|
||||
}
|
||||
return item
|
||||
}).filter(item => {
|
||||
if (searchKey && item.nickname) {
|
||||
if (!$A.strExists(item.nickname, searchKey) && !$A.strExists(item.email, searchKey)) {
|
||||
return false;
|
||||
@ -171,16 +176,6 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
userResult(user) {
|
||||
let index = this.dialogUser.findIndex(({userid}) => userid === user.userid);
|
||||
if (index > -1) {
|
||||
this.dialogUser.splice(index, 1, Object.assign(user, {
|
||||
id: this.dialogUser[index].id,
|
||||
created_at: this.dialogUser[index].created_at
|
||||
}))
|
||||
}
|
||||
},
|
||||
|
||||
openAdd() {
|
||||
this.addData = {
|
||||
dialog_id: this.dialogId,
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
|
||||
<template v-if="dialogData.type === 'group'">
|
||||
<ETooltip
|
||||
v-if="dialogData.group_type === 'user'"
|
||||
placement="top"
|
||||
:disabled="windowSmall"
|
||||
:openDelay="600"
|
||||
@ -250,7 +249,7 @@
|
||||
<DrawerOverlay
|
||||
v-model="groupInfoShow"
|
||||
placement="right"
|
||||
:size="380">
|
||||
:size="400">
|
||||
<DialogGroupInfo v-if="groupInfoShow" :dialogId="dialogId"/>
|
||||
</DrawerOverlay>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user