新增文件实时协同人员

This commit is contained in:
kuaifan 2021-07-06 19:13:41 +08:00
parent e2c6812b08
commit adea662eeb
10 changed files with 134 additions and 19 deletions

View File

@ -346,7 +346,7 @@ class Project extends AbstractModel
if ($userid === null) {
$userid = $this->relationUserids();
}
$lists = [
$params = [
'ignoreFd' => Request::header('fd'),
'userid' => $userid,
'msg' => [
@ -355,7 +355,7 @@ class Project extends AbstractModel
'data' => $data,
]
];
$task = new PushTask($lists, false);
$task = new PushTask($params, false);
Task::deliver($task);
}

View File

@ -119,7 +119,7 @@ class ProjectColumn extends AbstractModel
if ($userid === null) {
$userid = $this->project->relationUserids();
}
$lists = [
$params = [
'ignoreFd' => Request::header('fd'),
'userid' => $userid,
'msg' => [
@ -128,7 +128,7 @@ class ProjectColumn extends AbstractModel
'data' => $data,
]
];
$task = new PushTask($lists, false);
$task = new PushTask($params, false);
Task::deliver($task);
}
}

View File

@ -722,7 +722,7 @@ class ProjectTask extends AbstractModel
if ($userid === null) {
$userid = $this->project->relationUserids();
}
$lists = [
$params = [
'ignoreFd' => Request::header('fd'),
'userid' => $userid,
'msg' => [
@ -731,7 +731,7 @@ class ProjectTask extends AbstractModel
'data' => $data,
]
];
$task = new PushTask($lists, false);
$task = new PushTask($params, false);
Task::deliver($task);
}

View File

@ -11,6 +11,7 @@ namespace App\Models;
* @property string $key
* @property string|null $fd
* @property int|null $userid
* @property string|null $path
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket newModelQuery()
@ -20,6 +21,7 @@ namespace App\Models;
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereFd($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereKey($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket wherePath($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUserid($value)
* @mixin \Eloquent

View File

@ -132,6 +132,22 @@ class WebSocketService implements WebSocketHandlerInterface
$item->readSuccess($userid);
});
return;
/**
* 访问状态
*/
case 'path':
$row = WebSocket::whereFd($frame->fd)->first();
if ($row) {
$pathNew = $data['path'];
$pathOld = $row->path;
$row->path = $pathNew;
$row->save();
if (preg_match("/^file\/content\/\d+$/", $pathNew) || preg_match("/^file\/content\/\d+$/", $pathOld)) {
$this->pushPath($pathNew);
}
}
return;
}
//
if ($msgId) {
@ -197,4 +213,28 @@ class WebSocketService implements WebSocketHandlerInterface
{
return intval(WebSocket::whereFd($fd)->value('userid'));
}
/**
* 发送给相同访问状态的会员
* @param $path
*/
private function pushPath($path)
{
$array = WebSocket::wherePath($path)->pluck('userid')->toArray();
if ($array) {
$userids = array_values(array_filter(array_unique($array)));
$params = [
'userid' => $userids,
'msg' => [
'type' => 'path',
'data' => [
'path' => $path,
'userids' => $userids
],
]
];
$task = new PushTask($params, false);
Task::deliver($task);
}
}
}

View File

@ -17,6 +17,7 @@ class CreateWebSocketsTable extends Migration
$table->bigIncrements('id');
$table->string('key', 50)->default('')->unique('pre_ws_key_unique');
$table->string('fd', 50)->nullable()->default('');
$table->string('path', 255)->nullable()->default('');
$table->bigInteger('userid')->nullable()->default(0)->index('pre_ws_userid_index');
$table->timestamps();
});

View File

@ -14,6 +14,14 @@
</EPopover>
{{file.name}}
</div>
<div class="header-user">
<ul>
<li v-for="(userid, index) in editUser" :key="index" v-if="index <= 10">
<UserAvatar :userid="userid" :size="28" :border-witdh="2"/>
</li>
<li v-if="editUser.length > 10" class="more">{{editUser.length > 99 ? '99+' : editUser.length}}</li>
</ul>
</div>
<div v-if="file.type=='document' && contentDetail" class="header-hint">
<ButtonGroup size="small" shape="circle">
<Button :type="`${contentDetail.type!='md'?'primary':'default'}`" @click="$set(contentDetail, 'type', 'text')">{{$L('文本编辑器')}}</Button>
@ -92,6 +100,8 @@ export default {
contentDetail: null,
contentBak: {},
editUser: []
}
},
@ -107,15 +117,31 @@ export default {
deep: true,
},
parentShow(val) {
if (!val) {
this.fileContent[this.fileId] = this.contentDetail;
}
}
wsMsg: {
handler({type, data}) {
if (type == 'path') {
if (data.path == 'file/content/' + this.fileId) {
this.editUser = data.userids;
}
}
},
deep: true,
},
parentShow: {
handler(val) {
if (!val) {
this.fileContent[this.fileId] = this.contentDetail;
} else {
this.editUser = [this.userId];
}
},
immediate: true,
},
},
computed: {
...mapState(['fileContent']),
...mapState(['fileContent', 'wsMsg', 'userId']),
equalContent() {
return this.contentBak == $A.jsonStringify(this.contentDetail);

View File

@ -204,10 +204,16 @@ export default {
immediate: true
},
editShow(val) {
if (val) {
this.editShowNum++;
}
editShow: {
handler(val) {
if (val) {
this.editShowNum++;
this.$store.dispatch("websocketPath", "file/content/" + this.editInfo.id)
} else {
this.$store.dispatch("websocketPath", "file")
}
},
immediate: true
},
tableMode(val) {
@ -355,8 +361,8 @@ export default {
this.pid = item.id;
} else {
this.editHeight = window.innerHeight - 40;
this.editShow = true;
this.editInfo = item;
this.editShow = true;
}
},

View File

@ -1574,14 +1574,15 @@ export default {
/**
* 发送 websocket 消息
* @param state
* @param params {type, data, callback, msgId}
* @param params {type, data, callback}
*/
websocketSend({state}, params) {
if (!state.method.isJson(params)) {
typeof callback === "function" && callback(null, false)
return;
}
const {type, data, callback} = params;
let msgId = params.msgId;
let msgId = undefined;
if (!state.ws) {
typeof callback === "function" && callback(null, false)
return;
@ -1601,6 +1602,22 @@ export default {
}
},
/**
* 记录 websocket 访问状态
* @param state
* @param dispatch
* @param path
*/
websocketPath({state, dispatch}, path) {
clearTimeout(state.wsPathTimeout);
state.wsPathValue = path;
state.wsPathTimeout = setTimeout(() => {
if (state.wsPathValue == path) {
dispatch("websocketSend", {type: 'path', data: {path}});
}
}, 3000);
},
/**
* 监听消息
* @param state

View File

@ -41,6 +41,29 @@
}
}
}
.header-user {
margin-right: 24px;
> ul {
display: flex;
align-items: center;
> li {
list-style: none;
margin-right: -4px;
&.more {
width: 28px;
height: 28px;
text-align: center;
line-height: 24px;
font-size: 12px;
border: 2px solid #ffffff;
background-color: #8bcf70;
color: #ffffff;
z-index: 1;
border-radius: 50%;
}
}
}
}
.header-hint {
padding-right: 22px;
font-size: 12px;