diff --git a/app/Models/Project.php b/app/Models/Project.php index 4ba078cb..5acd0c60 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -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); } diff --git a/app/Models/ProjectColumn.php b/app/Models/ProjectColumn.php index af2a7386..3e17d2b0 100644 --- a/app/Models/ProjectColumn.php +++ b/app/Models/ProjectColumn.php @@ -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); } } diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php index 42d1f150..2ce6c952 100644 --- a/app/Models/ProjectTask.php +++ b/app/Models/ProjectTask.php @@ -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); } diff --git a/app/Models/WebSocket.php b/app/Models/WebSocket.php index 7ebca1cf..963f4f4d 100644 --- a/app/Models/WebSocket.php +++ b/app/Models/WebSocket.php @@ -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 diff --git a/app/Services/WebSocketService.php b/app/Services/WebSocketService.php index 498805f5..661df950 100644 --- a/app/Services/WebSocketService.php +++ b/app/Services/WebSocketService.php @@ -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); + } + } } diff --git a/database/migrations/2021_06_25_182631_create_web_sockets_table.php b/database/migrations/2021_06_25_182631_create_web_sockets_table.php index 81b02f2b..4c8853e4 100644 --- a/database/migrations/2021_06_25_182631_create_web_sockets_table.php +++ b/database/migrations/2021_06_25_182631_create_web_sockets_table.php @@ -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(); }); diff --git a/resources/assets/js/pages/manage/components/FileContent.vue b/resources/assets/js/pages/manage/components/FileContent.vue index dde6ed56..bad140d0 100644 --- a/resources/assets/js/pages/manage/components/FileContent.vue +++ b/resources/assets/js/pages/manage/components/FileContent.vue @@ -14,6 +14,14 @@ {{file.name}} +
+ +
@@ -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); diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index dbef5585..c103a422 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -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; } }, diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index b827b5f2..8fef3335 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -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 diff --git a/resources/assets/sass/pages/components/file-content.scss b/resources/assets/sass/pages/components/file-content.scss index 80b9297d..ca777001 100644 --- a/resources/assets/sass/pages/components/file-content.scss +++ b/resources/assets/sass/pages/components/file-content.scss @@ -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;