mirror of
https://github.com/kuaifan/dootask.git
synced 2026-03-19 04:03:38 +00:00
feat: 新增待办消息功能
This commit is contained in:
parent
d085da07cd
commit
3829ec1308
@ -10,6 +10,7 @@ use App\Models\User;
|
|||||||
use App\Models\WebSocketDialog;
|
use App\Models\WebSocketDialog;
|
||||||
use App\Models\WebSocketDialogMsg;
|
use App\Models\WebSocketDialogMsg;
|
||||||
use App\Models\WebSocketDialogMsgRead;
|
use App\Models\WebSocketDialogMsgRead;
|
||||||
|
use App\Models\WebSocketDialogMsgTodo;
|
||||||
use App\Models\WebSocketDialogUser;
|
use App\Models\WebSocketDialogUser;
|
||||||
use App\Module\Base;
|
use App\Module\Base;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@ -190,6 +191,62 @@ class DialogController extends AbstractController
|
|||||||
return Base::retSuccess('success', $array);
|
return Base::retSuccess('success', $array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} api/dialog/todo 20. 获取会话待办
|
||||||
|
*
|
||||||
|
* @apiDescription 需要token身份
|
||||||
|
* @apiVersion 1.0.0
|
||||||
|
* @apiGroup dialog
|
||||||
|
* @apiName todo
|
||||||
|
*
|
||||||
|
* @apiParam {Number} dialog_id 会话ID
|
||||||
|
*
|
||||||
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
|
* @apiSuccess {Object} data 返回数据
|
||||||
|
*/
|
||||||
|
public function todo()
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
//
|
||||||
|
$dialog_id = intval(Request::input('dialog_id'));
|
||||||
|
//
|
||||||
|
WebSocketDialog::checkDialog($dialog_id);
|
||||||
|
//
|
||||||
|
$list = WebSocketDialogMsgTodo::whereDialogId($dialog_id)->whereUserid($user->userid)->whereDoneAt(null)->orderByDesc('id')->take(50)->get();
|
||||||
|
return Base::retSuccess("success", $list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} api/dialog/top 20. 会话置顶
|
||||||
|
*
|
||||||
|
* @apiDescription 需要token身份
|
||||||
|
* @apiVersion 1.0.0
|
||||||
|
* @apiGroup dialog
|
||||||
|
* @apiName top
|
||||||
|
*
|
||||||
|
* @apiParam {Number} dialog_id 会话ID
|
||||||
|
*
|
||||||
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
|
* @apiSuccess {Object} data 返回数据
|
||||||
|
*/
|
||||||
|
public function top()
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$dialogId = intval(Request::input('dialog_id'));
|
||||||
|
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
||||||
|
if (!$dialogUser) {
|
||||||
|
return Base::retError("会话不存在");
|
||||||
|
}
|
||||||
|
$dialogUser->top_at = $dialogUser->top_at ? null : Carbon::now();
|
||||||
|
$dialogUser->save();
|
||||||
|
return Base::retSuccess("success", [
|
||||||
|
'id' => $dialogUser->dialog_id,
|
||||||
|
'top_at' => $dialogUser->top_at?->toDateTimeString(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} api/dialog/open/user 05. 打开会话
|
* @api {get} api/dialog/open/user 05. 打开会话
|
||||||
*
|
*
|
||||||
@ -412,6 +469,7 @@ class DialogController extends AbstractController
|
|||||||
//
|
//
|
||||||
if ($reDialog) {
|
if ($reDialog) {
|
||||||
$data['dialog'] = $dialog->formatData($user->userid, true);
|
$data['dialog'] = $dialog->formatData($user->userid, true);
|
||||||
|
$data['todo'] = $data['dialog']->has_todo ? WebSocketDialogMsgTodo::whereDialogId($dialog->id)->whereUserid($user->userid)->whereDoneAt(null)->orderByDesc('id')->take(50)->get() : [];
|
||||||
}
|
}
|
||||||
return Base::retSuccess('success', $data);
|
return Base::retSuccess('success', $data);
|
||||||
}
|
}
|
||||||
@ -956,33 +1014,32 @@ class DialogController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} api/dialog/top 20. 会话置顶
|
* @api {get} api/dialog/msg/todo 19. 设待办/取消待办
|
||||||
*
|
*
|
||||||
* @apiDescription 需要token身份
|
* @apiDescription 需要token身份
|
||||||
* @apiVersion 1.0.0
|
* @apiVersion 1.0.0
|
||||||
* @apiGroup dialog
|
* @apiGroup dialog
|
||||||
* @apiName top
|
* @apiName msg__todo
|
||||||
*
|
*
|
||||||
* @apiParam {Number} dialog_id 会话ID
|
* @apiParam {Number} msg_id 消息ID
|
||||||
*
|
*
|
||||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
* @apiSuccess {Object} data 返回数据
|
* @apiSuccess {Object} data 返回数据
|
||||||
*/
|
*/
|
||||||
public function top()
|
public function msg__todo()
|
||||||
{
|
{
|
||||||
$user = User::auth();
|
$user = User::auth();
|
||||||
$dialogId = intval(Request::input('dialog_id'));
|
//
|
||||||
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
$msg_id = intval(Request::input("msg_id"));
|
||||||
if (!$dialogUser) {
|
//
|
||||||
return Base::retError("会话不存在");
|
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
|
||||||
|
if (empty($msg)) {
|
||||||
|
return Base::retError("消息不存在或已被删除");
|
||||||
}
|
}
|
||||||
$dialogUser->top_at = $dialogUser->top_at ? null : Carbon::now();
|
WebSocketDialog::checkDialog($msg->dialog_id);
|
||||||
$dialogUser->save();
|
//
|
||||||
return Base::retSuccess("success", [
|
return $msg->toggleTodoMsg($user->userid);
|
||||||
'id' => $dialogUser->dialog_id,
|
|
||||||
'top_at' => $dialogUser->top_at?->toDateTimeString(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -80,6 +80,8 @@ class WebSocketDialog extends AbstractModel
|
|||||||
// 对话人数
|
// 对话人数
|
||||||
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
$builder = WebSocketDialogUser::whereDialogId($this->id);
|
||||||
$this->people = $builder->count();
|
$this->people = $builder->count();
|
||||||
|
// 有待办
|
||||||
|
$this->has_todo = WebSocketDialogMsgTodo::whereDialogId($this->id)->whereDoneAt(null)->exists();
|
||||||
}
|
}
|
||||||
// 对方信息
|
// 对方信息
|
||||||
$this->dialog_user = null;
|
$this->dialog_user = null;
|
||||||
@ -101,7 +103,8 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$this->dialog_user = $dialog_user;
|
$this->dialog_user = $dialog_user;
|
||||||
break;
|
break;
|
||||||
case "group":
|
case "group":
|
||||||
if ($this->group_type === 'project') {
|
switch ($this->group_type) {
|
||||||
|
case 'project':
|
||||||
$this->group_info = Project::withTrashed()->select(['id', 'name', 'archived_at', 'deleted_at'])->whereDialogId($this->id)->first()?->cancelAppend()->cancelHidden();
|
$this->group_info = Project::withTrashed()->select(['id', 'name', 'archived_at', 'deleted_at'])->whereDialogId($this->id)->first()?->cancelAppend()->cancelHidden();
|
||||||
if ($this->group_info) {
|
if ($this->group_info) {
|
||||||
$this->name = $this->group_info->name;
|
$this->name = $this->group_info->name;
|
||||||
@ -109,7 +112,8 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$this->name = '[Delete]';
|
$this->name = '[Delete]';
|
||||||
$this->dialog_delete = 1;
|
$this->dialog_delete = 1;
|
||||||
}
|
}
|
||||||
} elseif ($this->group_type === 'task') {
|
break;
|
||||||
|
case 'task':
|
||||||
$this->group_info = ProjectTask::withTrashed()->select(['id', 'name', 'complete_at', 'archived_at', 'deleted_at'])->whereDialogId($this->id)->first()?->cancelAppend()->cancelHidden();
|
$this->group_info = ProjectTask::withTrashed()->select(['id', 'name', 'complete_at', 'archived_at', 'deleted_at'])->whereDialogId($this->id)->first()?->cancelAppend()->cancelHidden();
|
||||||
if ($this->group_info) {
|
if ($this->group_info) {
|
||||||
$this->name = $this->group_info->name;
|
$this->name = $this->group_info->name;
|
||||||
@ -117,9 +121,11 @@ class WebSocketDialog extends AbstractModel
|
|||||||
$this->name = '[Delete]';
|
$this->name = '[Delete]';
|
||||||
$this->dialog_delete = 1;
|
$this->dialog_delete = 1;
|
||||||
}
|
}
|
||||||
} elseif ($this->group_type === 'all') {
|
break;
|
||||||
|
case 'all':
|
||||||
$this->name = Base::Lang('全体成员');
|
$this->name = Base::Lang('全体成员');
|
||||||
$this->all_group_mute = Base::settingFind('system', 'all_group_mute');
|
$this->all_group_mute = Base::settingFind('system', 'all_group_mute');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
* @property int|null $read 已阅数量
|
* @property int|null $read 已阅数量
|
||||||
* @property int|null $send 发送数量
|
* @property int|null $send 发送数量
|
||||||
* @property int|null $tag 标注会员ID
|
* @property int|null $tag 标注会员ID
|
||||||
|
* @property int|null $todo 设为待办会员ID
|
||||||
* @property int|null $link 是否存在链接
|
* @property int|null $link 是否存在链接
|
||||||
* @property int|null $modify 是否编辑
|
* @property int|null $modify 是否编辑
|
||||||
* @property int|null $reply_num 有多少条回复
|
* @property int|null $reply_num 有多少条回复
|
||||||
@ -55,6 +56,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyNum($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyNum($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereSend($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereSend($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereTag($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereTag($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereTodo($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereType($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereType($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereUserid($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereUserid($value)
|
||||||
@ -265,16 +267,14 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
if ($this->type === 'tag') {
|
if ($this->type === 'tag') {
|
||||||
return Base::retError('此消息不支持标注');
|
return Base::retError('此消息不支持标注');
|
||||||
}
|
}
|
||||||
$this->tag = $this->tag ? 0 : $sender;
|
$before = $this->tag;
|
||||||
|
$this->tag = $before ? 0 : $sender;
|
||||||
$this->save();
|
$this->save();
|
||||||
$resData = [
|
$resData = [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'tag' => $this->tag,
|
'tag' => $this->tag,
|
||||||
];
|
];
|
||||||
//
|
//
|
||||||
$dialog = WebSocketDialog::find($this->dialog_id);
|
|
||||||
$dialog?->pushMsg('update', $resData);
|
|
||||||
//
|
|
||||||
$data = [
|
$data = [
|
||||||
'update' => $resData
|
'update' => $resData
|
||||||
];
|
];
|
||||||
@ -288,6 +288,65 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
], $sender);
|
], $sender);
|
||||||
if (Base::isSuccess($res)) {
|
if (Base::isSuccess($res)) {
|
||||||
$data['add'] = $res['data'];
|
$data['add'] = $res['data'];
|
||||||
|
$dialog = WebSocketDialog::find($this->dialog_id);
|
||||||
|
$dialog->pushMsg('update', $data['update']);
|
||||||
|
} else {
|
||||||
|
$this->tag = $before;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return Base::retSuccess('sucess', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设待办、取消待办
|
||||||
|
* @param int $sender 设待办的会员ID
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function toggleTodoMsg($sender)
|
||||||
|
{
|
||||||
|
if ($this->type === 'todo') {
|
||||||
|
return Base::retError('此消息不支持社待办');
|
||||||
|
}
|
||||||
|
$before = $this->todo;
|
||||||
|
$this->todo = $before ? 0 : $sender;
|
||||||
|
$this->save();
|
||||||
|
$resData = [
|
||||||
|
'id' => $this->id,
|
||||||
|
'todo' => $this->todo,
|
||||||
|
];
|
||||||
|
//
|
||||||
|
$data = [
|
||||||
|
'update' => $resData
|
||||||
|
];
|
||||||
|
$res = self::sendMsg(null, $this->dialog_id, 'todo', [
|
||||||
|
'action' => $this->todo ? 'add' : 'remove',
|
||||||
|
'data' => [
|
||||||
|
'id' => $this->id,
|
||||||
|
'type' => $this->type,
|
||||||
|
'msg' => $this->msg,
|
||||||
|
]
|
||||||
|
], $sender);
|
||||||
|
if (Base::isSuccess($res)) {
|
||||||
|
$data['add'] = $res['data'];
|
||||||
|
$dialog = WebSocketDialog::find($this->dialog_id);
|
||||||
|
$dialog->pushMsg('update', array_merge($data['update'], ['dialog_id' => $this->dialog_id]));
|
||||||
|
//
|
||||||
|
if ($this->todo) {
|
||||||
|
$userids = $dialog->dialogUser->pluck('userid')->toArray();
|
||||||
|
foreach ($userids as $userid) {
|
||||||
|
WebSocketDialogMsgTodo::createInstance([
|
||||||
|
'dialog_id' => $this->dialog_id,
|
||||||
|
'msg_id' => $this->id,
|
||||||
|
'userid' => $userid,
|
||||||
|
])->saveOrIgnore();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WebSocketDialogMsgTodo::whereMsgId($this->id)->delete();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->todo = $before;
|
||||||
|
$this->save();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
return Base::retSuccess('sucess', $data);
|
return Base::retSuccess('sucess', $data);
|
||||||
@ -395,6 +454,9 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
case 'tag':
|
case 'tag':
|
||||||
$action = $data['msg']['action'] === 'remove' ? '取消标注' : '标注';
|
$action = $data['msg']['action'] === 'remove' ? '取消标注' : '标注';
|
||||||
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
|
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
|
||||||
|
case 'todo':
|
||||||
|
$action = $data['msg']['action'] === 'remove' ? '取消待办' : '设待办';
|
||||||
|
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
|
||||||
case 'notice':
|
case 'notice':
|
||||||
return $data['msg']['notice'];
|
return $data['msg']['notice'];
|
||||||
default:
|
default:
|
||||||
|
|||||||
46
app/Models/WebSocketDialogMsgTodo.php
Normal file
46
app/Models/WebSocketDialogMsgTodo.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App\Models\WebSocketDialogMsgTodo
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property int|null $dialog_id 对话ID
|
||||||
|
* @property int|null $msg_id 消息ID
|
||||||
|
* @property int|null $userid 接收会员ID
|
||||||
|
* @property string|null $done_at 完成时间
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereDialogId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereDoneAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereMsgId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereUserid($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class WebSocketDialogMsgTodo extends AbstractModel
|
||||||
|
{
|
||||||
|
protected $appends = [
|
||||||
|
'msg_data',
|
||||||
|
];
|
||||||
|
|
||||||
|
function __construct(array $attributes = [])
|
||||||
|
{
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->timestamps = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息详情
|
||||||
|
* @return array|mixed
|
||||||
|
*/
|
||||||
|
public function getMsgDataAttribute()
|
||||||
|
{
|
||||||
|
if (!isset($this->appendattrs['msgData'])) {
|
||||||
|
$this->appendattrs['msgData'] = WebSocketDialogMsg::select(['id', 'type', 'msg'])->whereId($this->msg_id)->first()?->cancelAppend();
|
||||||
|
}
|
||||||
|
return $this->appendattrs['msgData'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddWebSocketDialogMsgsTodo extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
|
||||||
|
if (!Schema::hasColumn('web_socket_dialog_msgs', 'todo')) {
|
||||||
|
$table->bigInteger('todo')->nullable()->default(0)->after('tag')->comment('设为待办会员ID');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
|
||||||
|
$table->dropColumn("todo");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateWebSocketDialogMsgTodosTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('web_socket_dialog_msg_todos', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->bigInteger('dialog_id')->nullable()->default(0)->comment('对话ID');
|
||||||
|
$table->bigInteger('msg_id')->nullable()->default(0)->comment('消息ID');
|
||||||
|
$table->bigInteger('userid')->nullable()->default(0)->comment('发送会员ID');
|
||||||
|
$table->timestamp('done_at')->nullable()->comment('完成时间');
|
||||||
|
$table->index(['dialog_id', 'userid', 'done_at']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('web_socket_dialog_msg_todos');
|
||||||
|
}
|
||||||
|
}
|
||||||
2
resources/assets/js/functions/web.js
vendored
2
resources/assets/js/functions/web.js
vendored
@ -492,6 +492,8 @@
|
|||||||
return `[${$A.L('文件')}] ${data.msg.name}`
|
return `[${$A.L('文件')}] ${data.msg.name}`
|
||||||
case 'tag':
|
case 'tag':
|
||||||
return `[${$A.L(data.msg.action === 'remove' ? '取消标注' : '标注')}] ${$A.getMsgSimpleDesc(data.msg.data)}`
|
return `[${$A.L(data.msg.action === 'remove' ? '取消标注' : '标注')}] ${$A.getMsgSimpleDesc(data.msg.data)}`
|
||||||
|
case 'todo':
|
||||||
|
return `[${$A.L(data.msg.action === 'remove' ? '取消待办' : '设待办')}] ${$A.getMsgSimpleDesc(data.msg.data)}`
|
||||||
case 'notice':
|
case 'notice':
|
||||||
return data.msg.notice
|
return data.msg.notice
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -5,6 +5,11 @@
|
|||||||
{{$L(source.msg.action === 'remove' ? '取消标注' : '标注了')}}
|
{{$L(source.msg.action === 'remove' ? '取消标注' : '标注了')}}
|
||||||
"{{$A.getMsgSimpleDesc(source.msg.data)}}"
|
"{{$A.getMsgSimpleDesc(source.msg.data)}}"
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="source.type === 'todo'" class="dialog-todo" @click="onViewTodo">
|
||||||
|
<div class="todo-user"><UserAvatar :userid="source.userid" :tooltipDisabled="source.userid == userId" :show-name="true" :show-icon="false"/></div>
|
||||||
|
{{$L(source.msg.action === 'remove' ? '取消待办' : '设待办')}}
|
||||||
|
"{{$A.getMsgSimpleDesc(source.msg.data)}}"
|
||||||
|
</div>
|
||||||
<div v-else-if="source.type === 'notice'" class="dialog-notice">
|
<div v-else-if="source.type === 'notice'" class="dialog-notice">
|
||||||
{{source.msg.notice}}
|
{{source.msg.notice}}
|
||||||
</div>
|
</div>
|
||||||
@ -120,6 +125,13 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onViewTodo() {
|
||||||
|
this.onViewReply({
|
||||||
|
msg_id: this.source.id,
|
||||||
|
reply_id: this.source.msg.data.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
onLongpress(e) {
|
onLongpress(e) {
|
||||||
this.dispatch("on-longpress", e)
|
this.dispatch("on-longpress", e)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -91,6 +91,10 @@
|
|||||||
<div v-if="msgData.tag" class="tag">
|
<div v-if="msgData.tag" class="tag">
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<!--待办-->
|
||||||
|
<div v-if="msgData.todo" class="todo">
|
||||||
|
<i class="taskfont"></i>
|
||||||
|
</div>
|
||||||
<!--编辑-->
|
<!--编辑-->
|
||||||
<div v-if="msgData.modify" class="modify">
|
<div v-if="msgData.modify" class="modify">
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
|
|||||||
@ -121,6 +121,14 @@
|
|||||||
@on-progress="chatFile('progress', $event)"
|
@on-progress="chatFile('progress', $event)"
|
||||||
@on-success="chatFile('success', $event)"
|
@on-success="chatFile('success', $event)"
|
||||||
@on-error="chatFile('error', $event)"/>
|
@on-error="chatFile('error', $event)"/>
|
||||||
|
<div v-if="todoList.length > 0" class="chat-todo">
|
||||||
|
<div class="todo-label">{{$L('待办')}}:</div>
|
||||||
|
<ul class="scrollbar-hidden">
|
||||||
|
<li v-for="todoItem in todoList" @click="onPositionId(todoItem.msg_id)">
|
||||||
|
{{$A.getMsgSimpleDesc(todoItem.msg_data)}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div v-if="isMute" class="chat-mute">
|
<div v-if="isMute" class="chat-mute">
|
||||||
{{$L('禁言发言')}}
|
{{$L('禁言发言')}}
|
||||||
</div>
|
</div>
|
||||||
@ -196,6 +204,10 @@
|
|||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
<span>{{ $L('新任务') }}</span>
|
<span>{{ $L('新任务') }}</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li @click="onOperate('todo')">
|
||||||
|
<i class="taskfont"></i>
|
||||||
|
<span>{{ $L(operateItem.todo ? '取消待办' : '设待办') }}</span>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem name="emoji" class="dropdown-emoji">
|
<DropdownItem name="emoji" class="dropdown-emoji">
|
||||||
@ -409,6 +421,7 @@ export default {
|
|||||||
'taskId',
|
'taskId',
|
||||||
'dialogSearchMsgId',
|
'dialogSearchMsgId',
|
||||||
'dialogMsgs',
|
'dialogMsgs',
|
||||||
|
'dialogTodos',
|
||||||
'dialogMsgTransfer',
|
'dialogMsgTransfer',
|
||||||
'cacheDialogs',
|
'cacheDialogs',
|
||||||
'wsOpenNum',
|
'wsOpenNum',
|
||||||
@ -510,6 +523,15 @@ export default {
|
|||||||
return array
|
return array
|
||||||
},
|
},
|
||||||
|
|
||||||
|
todoList() {
|
||||||
|
if (!this.dialogData.has_todo) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return this.dialogTodos.filter(item => !item.done_at && item.dialog_id == this.dialogId).sort((a, b) => {
|
||||||
|
return b.id - a.id;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
wrapperClass() {
|
wrapperClass() {
|
||||||
if (['ready', 'ing'].includes(this.recordState)) {
|
if (['ready', 'ing'].includes(this.recordState)) {
|
||||||
return ['record-ready']
|
return ['record-ready']
|
||||||
@ -1368,6 +1390,10 @@ export default {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "todo":
|
||||||
|
this.onTodo()
|
||||||
|
break;
|
||||||
|
|
||||||
case "emoji":
|
case "emoji":
|
||||||
this.onEmoji(value)
|
this.onEmoji(value)
|
||||||
break;
|
break;
|
||||||
@ -1598,17 +1624,57 @@ export default {
|
|||||||
url: 'dialog/msg/tag',
|
url: 'dialog/msg/tag',
|
||||||
data,
|
data,
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.$store.dispatch("saveDialogMsg", data.update);
|
this.tagOrTodoSuccess(data)
|
||||||
if (data.add) {
|
|
||||||
this.$store.dispatch("saveDialogMsg", data.add);
|
|
||||||
this.$store.dispatch("updateDialogLastMsg", data.add);
|
|
||||||
}
|
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
$A.messageError(msg);
|
$A.messageError(msg);
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.$store.dispatch("cancelLoad", `msg-${data.msg_id}`)
|
this.$store.dispatch("cancelLoad", `msg-${data.msg_id}`)
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onTodo() {
|
||||||
|
if (this.operateVisible) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
const data = {
|
||||||
|
msg_id: this.operateItem.id,
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$A.modalConfirm({
|
||||||
|
title: this.operateItem.todo ? '取消待办' : '设置待办',
|
||||||
|
content: this.operateItem.todo ? "撤回待办后,会话其他成员的待办也将消失。" : "设置为待办后,将通知会话所有成员。",
|
||||||
|
cancelText: '取消',
|
||||||
|
okText: '确定',
|
||||||
|
loading: true,
|
||||||
|
onOk: () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$store.dispatch("setLoad", {
|
||||||
|
key: `msg-${data.msg_id}`,
|
||||||
|
delay: 600
|
||||||
|
})
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'dialog/msg/todo',
|
||||||
|
data,
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
resolve(msg)
|
||||||
|
this.tagOrTodoSuccess(data)
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
reject(msg);
|
||||||
|
}).finally(_ => {
|
||||||
|
this.$store.dispatch("cancelLoad", `msg-${data.msg_id}`)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
tagOrTodoSuccess(data) {
|
||||||
|
this.$store.dispatch("saveDialogMsg", data.update);
|
||||||
|
if (data.add) {
|
||||||
|
this.$store.dispatch("saveDialogMsg", data.add);
|
||||||
|
this.$store.dispatch("updateDialogLastMsg", data.add);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
37
resources/assets/js/store/actions.js
vendored
37
resources/assets/js/store/actions.js
vendored
@ -2026,6 +2026,35 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话待办
|
||||||
|
* @param state
|
||||||
|
* @param dispatch
|
||||||
|
* @param dialog_id
|
||||||
|
*/
|
||||||
|
getDialogTodo({state, dispatch}, dialog_id) {
|
||||||
|
dispatch("call", {
|
||||||
|
url: 'dialog/todo',
|
||||||
|
data: {
|
||||||
|
dialog_id,
|
||||||
|
},
|
||||||
|
}).then(({data}) => {
|
||||||
|
if ($A.arrayLength(data) > 0) {
|
||||||
|
dispatch("saveDialog", {
|
||||||
|
id: dialog_id,
|
||||||
|
has_todo: true
|
||||||
|
});
|
||||||
|
state.dialogTodos = state.dialogTodos.filter(item => item.dialog_id != dialog_id)
|
||||||
|
state.dialogTodos.push(...data)
|
||||||
|
} else {
|
||||||
|
dispatch("saveDialog", {
|
||||||
|
id: dialog_id,
|
||||||
|
has_todo: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(console.warn);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开会话
|
* 打开会话
|
||||||
* @param state
|
* @param state
|
||||||
@ -2214,6 +2243,10 @@ export default {
|
|||||||
const ids = resData.list.map(({id}) => id)
|
const ids = resData.list.map(({id}) => id)
|
||||||
state.dialogMsgs = state.dialogMsgs.filter(item => item.dialog_id != data.dialog_id || ids.includes(item.id));
|
state.dialogMsgs = state.dialogMsgs.filter(item => item.dialog_id != data.dialog_id || ids.includes(item.id));
|
||||||
}
|
}
|
||||||
|
if ($A.isArray(resData.todo)) {
|
||||||
|
state.dialogTodos = state.dialogTodos.filter(item => item.dialog_id != data.dialog_id)
|
||||||
|
state.dialogTodos.push(...resData.todo)
|
||||||
|
}
|
||||||
//
|
//
|
||||||
dispatch("saveDialogMsg", resData.list)
|
dispatch("saveDialogMsg", resData.list)
|
||||||
}
|
}
|
||||||
@ -2488,6 +2521,10 @@ export default {
|
|||||||
// 更新、已读回执
|
// 更新、已读回执
|
||||||
if (state.dialogMsgs.find(({id}) => id == data.id)) {
|
if (state.dialogMsgs.find(({id}) => id == data.id)) {
|
||||||
dispatch("saveDialogMsg", data)
|
dispatch("saveDialogMsg", data)
|
||||||
|
// 更新待办
|
||||||
|
if (typeof data.todo !== "undefined") {
|
||||||
|
dispatch("getDialogTodo", dialog_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'groupAdd':
|
case 'groupAdd':
|
||||||
|
|||||||
1
resources/assets/js/store/state.js
vendored
1
resources/assets/js/store/state.js
vendored
@ -74,6 +74,7 @@ const stateData = {
|
|||||||
dialogSearchMsgId: 0,
|
dialogSearchMsgId: 0,
|
||||||
dialogIns: [],
|
dialogIns: [],
|
||||||
dialogMsgs: [],
|
dialogMsgs: [],
|
||||||
|
dialogTodos: [],
|
||||||
dialogInputCache: $A.getStorageArray("cacheDialogInput"),
|
dialogInputCache: $A.getStorageArray("cacheDialogInput"),
|
||||||
dialogMsgTransfer: {time: 0},
|
dialogMsgTransfer: {time: 0},
|
||||||
|
|
||||||
|
|||||||
@ -296,6 +296,7 @@
|
|||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
|
|
||||||
.dialog-tag,
|
.dialog-tag,
|
||||||
|
.dialog-todo,
|
||||||
.dialog-notice {
|
.dialog-notice {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
@ -315,6 +316,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-todo {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.todo-user {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dialog-avatar {
|
.dialog-avatar {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@ -756,6 +765,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tag,
|
.tag,
|
||||||
|
.todo,
|
||||||
.reply,
|
.reply,
|
||||||
.modify {
|
.modify {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -982,6 +992,39 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-todo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0;
|
||||||
|
|
||||||
|
.todo-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
flex-shrink: 0;
|
||||||
|
list-style: none;
|
||||||
|
margin-right: 8px;
|
||||||
|
background-color: #f0f1f3;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
line-height: 24px;
|
||||||
|
max-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chat-mute {
|
.chat-mute {
|
||||||
color: $primary-desc-color;
|
color: $primary-desc-color;
|
||||||
background-color: #F4F5F7;
|
background-color: #F4F5F7;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user