perf: 群组支持修改头像

This commit is contained in:
kuaifan 2023-03-05 00:43:53 +08:00
parent 61aa50f366
commit 10a2120fb8
7 changed files with 191 additions and 25 deletions

View File

@ -1417,8 +1417,9 @@ class DialogController extends AbstractController
* @apiGroup dialog
* @apiName group__add
*
* @apiParam {String} [avatar] 群头像
* @apiParam {String} [chat_name] 群名称
* @apiParam {Array} userids 群成员,格式: [userid1, userid2, userid3]
* @apiParam {String} chat_name 群名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@ -1428,8 +1429,10 @@ class DialogController extends AbstractController
{
$user = User::auth();
//
$userids = Request::input('userids');
$avatar = Request::input('avatar');
$avatar = $avatar ? Base::unFillUrl(is_array($avatar) ? $avatar[0]['path'] : $avatar) : '';
$chatName = trim(Request::input('chat_name'));
$userids = Request::input('userids');
//
if (!is_array($userids)) {
return Base::retError('请选择群成员');
@ -1458,6 +1461,10 @@ class DialogController extends AbstractController
if (empty($dialog)) {
return Base::retError('创建群组失败');
}
if ($avatar) {
$dialog->avatar = $avatar;
$dialog->save();
}
$data = WebSocketDialog::find($dialog->id)?->formatData($user->userid);
$userids = array_values(array_diff($userids, [$user->userid]));
$dialog->pushMsg("groupAdd", null, $userids);
@ -1473,7 +1480,9 @@ class DialogController extends AbstractController
* @apiName group__edit
*
* @apiParam {Number} dialog_id 会话ID
* @apiParam {String} chat_name 群名称
* @apiParam {String} [avatar] 群头像
* @apiParam {String} [chat_name] 群名称
* @apiParam {Number} [admin] 系统管理员操作1只判断是不是系统管理员否则判断是否群管理员
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@ -1484,23 +1493,43 @@ class DialogController extends AbstractController
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$chatName = trim(Request::input('chat_name'));
$admin = intval(Request::input('admin'));
//
if (mb_strlen($chatName) < 2) {
return Base::retError('群名称至少2个字');
}
if (mb_strlen($chatName) > 100) {
return Base::retError('群名称最长限制100个字');
if ($admin === 1) {
$user->checkAdmin();
$dialog = WebSocketDialog::find($dialog_id);
if (empty($dialog)) {
return Base::retError('对话不存在或已被删除', ['dialog_id' => $dialog_id], -4003);
}
} else {
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
}
//
$dialog = WebSocketDialog::checkDialog($dialog_id, true);
$data = ['id' => $dialog->id];
$array = [];
if (Request::exists('avatar')) {
$avatar = Request::input('avatar');
$avatar = $avatar ? Base::unFillUrl(is_array($avatar) ? $avatar[0]['path'] : $avatar) : '';
$data['avatar'] = Base::fillUrl($array['avatar'] = $avatar);
}
if (Request::exists('chat_name') && $dialog->group_type === 'user') {
$chatName = trim(Request::input('chat_name'));
if (mb_strlen($chatName) < 2) {
return Base::retError('群名称至少2个字');
}
if (mb_strlen($chatName) > 100) {
return Base::retError('群名称最长限制100个字');
}
$data['name'] = $array['name'] = $chatName;
}
//
$dialog->name = $chatName;
$dialog->save();
return Base::retSuccess('修改成功', [
'id' => $dialog->id,
'name' => $dialog->name,
]);
if ($array) {
$dialog->updateInstance($array);
$dialog->save();
WebSocketDialogUser::whereDialogId($dialog->id)->update(['updated_at' => Carbon::now()]);
}
//
return Base::retSuccess('修改成功', $data);
}
/**

View File

@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property string|null $type 对话类型
* @property string|null $group_type 聊天室类型
* @property string|null $name 对话名称
* @property string|null $avatar 头像(群)
* @property string|null $last_at 最后消息时间
* @property int|null $owner_id 群主用户ID
* @property \Illuminate\Support\Carbon|null $created_at
@ -28,6 +29,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog newQuery()
* @method static \Illuminate\Database\Query\Builder|WebSocketDialog onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog query()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereAvatar($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereGroupType($value)
@ -45,6 +47,16 @@ class WebSocketDialog extends AbstractModel
{
use SoftDeletes;
/**
* 头像地址
* @param $value
* @return string
*/
public function getAvatarAttribute($value)
{
return $value ? Base::fillUrl($value) : $value;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogsAvatar extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialogs', function (Blueprint $table) {
if (!Schema::hasColumn('web_socket_dialogs', 'avatar')) {
$table->string('avatar', 255)->nullable()->default('')->after('name')->comment('头像(群)');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('web_socket_dialogs', function (Blueprint $table) {
$table->dropColumn("avatar");
});
}
}

View File

@ -20,7 +20,8 @@
<div class="dialog-block">
<div class="dialog-avatar">
<template v-if="dialogData.type=='group'">
<i v-if="dialogData.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<EAvatar v-if="dialogData.avatar" class="img-avatar" :src="dialogData.avatar" :size="42"></EAvatar>
<i v-else-if="dialogData.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialogData.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialogData.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
@ -72,7 +73,7 @@
class="dialog-menu"
@command="onDialogMenu">
<i class="taskfont dialog-menu-icon">&#xe6e9;</i>
<EDropdownMenu slot="dropdown">
<EDropdownMenu v-slot="dropdown">
<EDropdownItem v-if="dialogData.type === 'user'" command="openCreate">
<div>{{$L('创建群组')}}</div>
</EDropdownItem>
@ -80,10 +81,18 @@
<EDropdownItem command="groupInfo">
<div>{{$L('群组设置')}}</div>
</EDropdownItem>
<EDropdownItem v-if="dialogData.owner_id != userId" command="exit">
<div style="color:#f00">{{$L('退出群组')}}</div>
</EDropdownItem>
<template v-if="dialogData.owner_id != userId">
<EDropdownItem v-if="dialogData.group_type === 'all' && userIsAdmin" command="avatarAdmin">
<div>{{$L('修改头像')}}</div>
</EDropdownItem>
<EDropdownItem command="exit">
<div style="color:#f00">{{$L('退出群组')}}</div>
</EDropdownItem>
</template>
<template v-else-if="dialogData.group_type === 'user'">
<EDropdownItem command="avatar">
<div>{{$L('修改头像')}}</div>
</EDropdownItem>
<EDropdownItem command="transfer">
<div>{{$L('转让群主')}}</div>
</EDropdownItem>
@ -287,12 +296,15 @@
:title="$L('创建群组')"
:mask-closable="false">
<Form :model="createGroupData" label-width="auto" @submit.native.prevent>
<FormItem prop="userids" :label="$L('群成员')">
<UserInput v-model="createGroupData.userids" :uncancelable="createGroupData.uncancelable" :multiple-max="100" show-bot :placeholder="$L('选择项目成员')"/>
<FormItem prop="avatar" :label="$L('群头像')">
<ImgUpload v-model="createGroupData.avatar" :num="1" :width="512" :height="512" :whcut="1"/>
</FormItem>
<FormItem prop="chat_name" :label="$L('群名称')">
<Input v-model="createGroupData.chat_name" :placeholder="$L('输入群名称(选填)')"/>
</FormItem>
<FormItem prop="userids" :label="$L('群成员')">
<UserInput v-model="createGroupData.userids" :uncancelable="createGroupData.uncancelable" :multiple-max="100" show-bot :placeholder="$L('选择项目成员')"/>
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="createGroupShow=false">{{$L('取消')}}</Button>
@ -300,6 +312,22 @@
</div>
</Modal>
<!--修改头像-->
<Modal
v-model="avatarModifyShow"
:title="$L('修改头像')"
:mask-closable="false">
<Form :model="avatarModifyData" label-width="auto" @submit.native.prevent>
<FormItem prop="avatar" :label="$L('群头像')">
<ImgUpload v-model="avatarModifyData.avatar" :num="1" :width="512" :height="512" :whcut="1"/>
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="avatarModifyShow=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="avatarModifyLoad > 0" @click="onAvatarModify">{{$L('保存')}}</Button>
</div>
</Modal>
<!-- 转发 -->
<Modal
v-model="forwardShow"
@ -438,10 +466,12 @@ import ChatInput from "./ChatInput";
import VirtualList from 'vue-virtual-scroll-list-hi'
import {Store} from "le5le-store";
import DialogSelect from "./DialogSelect";
import ImgUpload from "../../../components/ImgUpload.vue";
export default {
name: "DialogWrapper",
components: {
ImgUpload,
DialogSelect,
DialogRespond,
DialogItem,
@ -488,6 +518,10 @@ export default {
createGroupData: {},
createGroupLoad: 0,
avatarModifyShow: false,
avatarModifyData: {},
avatarModifyLoad: 0,
forwardShow: false,
forwardLoad: false,
forwardData: {
@ -1553,6 +1587,16 @@ export default {
this.createGroupShow = true
break;
case "avatar":
this.avatarModifyData = {dialog_id: this.dialogData.id, avatar: this.dialogData.avatar}
this.avatarModifyShow = true
break;
case "avatarAdmin":
this.avatarModifyData = {dialog_id: this.dialogData.id, avatar: this.dialogData.avatar, admin: 1}
this.avatarModifyShow = true
break;
case "groupInfo":
this.groupInfoShow = true
break;
@ -1668,6 +1712,23 @@ export default {
});
},
onAvatarModify() {
this.avatarModifyLoad++;
this.$store.dispatch("call", {
url: 'dialog/group/edit',
data: this.avatarModifyData
}).then(({data, msg}) => {
$A.messageSuccess(msg);
this.avatarModifyShow = false;
this.avatarModifyData = {};
this.$store.dispatch("saveDialog", data);
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.avatarModifyLoad--;
});
},
onForward(type) {
if (type === 'open') {
this.forwardData = {

View File

@ -55,7 +55,8 @@
})"
v-longpress="handleLongpress">
<template v-if="dialog.type=='group'">
<i v-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<EAvatar v-if="dialog.avatar" class="img-avatar" :src="dialog.avatar" :size="42"></EAvatar>
<i v-else-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />

View File

@ -110,6 +110,7 @@
flex-shrink: 0;
margin-right: 12px;
.img-avatar,
.user-avatar,
.icon-avatar {
width: 42px;
@ -119,6 +120,16 @@
flex-shrink: 0;
}
.img-avatar {
display: flex;
align-items: center;
justify-content: center;
> img {
width: 100%;
height: 100%;
}
}
.icon-avatar {
display: flex;
align-items: center;
@ -160,6 +171,8 @@
flex-shrink: 0;
margin: 0 6px 0 0;
padding: 0 5px;
display: flex;
align-items: center;
&.ivu-tag-success {
padding: 0 6px;
@ -168,6 +181,10 @@
&.after {
margin: 0 0 0 6px;
}
&.pointer {
cursor: pointer;
}
}
.ivu-icon {
@ -188,11 +205,13 @@
}
> em {
display: inline-block;
flex-shrink: 0;
font-style: normal;
font-size: 17px;
font-weight: 500;
padding-left: 6px;
margin-left: 6px;
cursor: pointer;
}
.load {

View File

@ -117,6 +117,7 @@
position: relative;
cursor: pointer;
list-style: none;
.img-avatar,
.user-avatar,
.icon-avatar {
width: 42px;
@ -125,6 +126,15 @@
flex-grow: 0;
flex-shrink: 0;
}
.img-avatar {
display: flex;
align-items: center;
justify-content: center;
> img {
width: 100%;
height: 100%;
}
}
.icon-avatar {
display: flex;
align-items: center;