diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 019a66dc..c4ae6534 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -6,6 +6,7 @@ namespace App\Http\Controllers\Api; use App\Models\AbstractModel; use App\Models\File; use App\Models\FileContent; +use App\Models\FileLink; use App\Models\FileUser; use App\Models\User; use App\Module\Base; @@ -79,15 +80,25 @@ class FileController extends AbstractController /** * 获取单条数据 + * + * @apiParam {String} [code] 链接码(用于预览) + * @apiParam {Number} [id] 文件ID(需要权限,用于管理) + * * @return array */ public function one() { - User::auth(); - // - $id = intval(Request::input('id')); - // - $file = File::allowFind($id); + if (Request::exists("code")) { + $fileLink = FileLink::whereCode(Request::input('code'))->first(); + $file = $fileLink?->file; + if (empty($file)) { + return Base::retError('链接不存在'); + } + } else { + User::auth(); + $id = intval(Request::input('id')); + $file = File::allowFind($id); + } return Base::retSuccess('success', $file); } @@ -292,13 +303,21 @@ class FileController extends AbstractController /** * 获取文件内容 * - * @apiParam {Number} id 文件ID + * @apiParam {String} [code] 链接码(用于预览) + * @apiParam {Number} [id] 文件ID(需要权限,用于管理) */ public function content() { - $id = intval(Request::input('id')); - // - $file = File::allowFind($id); + if (Request::exists("code")) { + $fileLink = FileLink::whereCode(Request::input('code'))->first(); + $file = $fileLink?->file; + if (empty($file)) { + return Base::retError('链接不存在'); + } + } else { + $id = intval(Request::input('id')); + $file = File::allowFind($id); + } // $content = FileContent::whereFid($file->id)->orderByDesc('id')->first(); return FileContent::formatContent($file->type, $content ? $content->content : []); @@ -621,4 +640,48 @@ class FileController extends AbstractController $file->setShare(); return Base::retSuccess("退出成功"); } + + /** + * 获取链接 + * + * @apiParam {Number} id 文件ID + * @apiParam {String} refresh 刷新链接 + * - no: 只获取(默认) + * - yes: 刷新链接,之前的将失效 + */ + public function link() + { + $user = User::auth(); + // + $id = intval(Request::input('id')); + $refresh = Request::input('refresh', 'no'); + // + $file = File::allowFind($id); + // + if ($file->userid != $user->userid) { + return Base::retError('仅限所有者操作'); + } + if ($file->type == 'folder') { + return Base::retError('文件夹暂不支持此功能'); + } + // + $fileLink = FileLink::whereFileId($file->id)->first(); + if (empty($fileLink)) { + $fileLink = FileLink::createInstance([ + 'file_id' => $file->id, + 'code' => Base::generatePassword(64), + ]); + $fileLink->save(); + } else { + if ($refresh == 'yes') { + $fileLink->code = Base::generatePassword(64); + $fileLink->save(); + } + } + return Base::retSuccess('success', [ + 'id' => $file->id, + 'url' => Base::fillUrl('single/file/' . $fileLink->code), + 'num' => $fileLink->num + ]); + } } diff --git a/app/Models/File.php b/app/Models/File.php index f219a76d..e1ba6752 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -165,6 +165,8 @@ class File extends AbstractModel AbstractModel::transaction(function () { $this->delete(); $this->pushMsg('delete'); + FileLink::whereFileId($this->id)->delete(); + FileUser::whereFileId($this->id)->delete(); FileContent::whereFid($this->id)->delete(); $list = self::wherePid($this->id)->get(); if ($list->isNotEmpty()) { diff --git a/app/Models/FileLink.php b/app/Models/FileLink.php new file mode 100644 index 00000000..32085ca6 --- /dev/null +++ b/app/Models/FileLink.php @@ -0,0 +1,35 @@ +hasOne(File::class, 'id', 'file_id'); + } +} diff --git a/database/migrations/2021_12_29_170103_create_file_links_table.php b/database/migrations/2021_12_29_170103_create_file_links_table.php new file mode 100644 index 00000000..34ac0829 --- /dev/null +++ b/database/migrations/2021_12_29_170103_create_file_links_table.php @@ -0,0 +1,34 @@ +bigIncrements('id'); + $table->bigInteger('file_id')->nullable()->default(0)->comment('项目ID'); + $table->integer('num')->nullable()->default(0)->comment('累计访问'); + $table->string('code')->nullable()->default('')->comment('链接码'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('file_links'); + } +} diff --git a/database/migrations/2021_12_29_170409_file_users_add_permission.php b/database/migrations/2021_12_29_170409_file_users_add_permission.php new file mode 100644 index 00000000..2fd07f70 --- /dev/null +++ b/database/migrations/2021_12_29_170409_file_users_add_permission.php @@ -0,0 +1,55 @@ +tinyInteger('permission')->nullable()->default(0)->after('userid')->comment('权限:0只读,1读写'); + } + }); + if ($isAdd) { + // 更新数据 + File::whereShare(1)->chunkById(100, function ($lists) { + foreach ($lists as $file) { + FileUser::updateInsert([ + 'file_id' => $file->id, + 'userid' => 0, + ]); + } + }); + File::whereShare(2)->update([ + 'share' => 1, + ]); + FileUser::wherePermission(0)->update([ + 'permission' => 1, + ]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('file_users', function (Blueprint $table) { + // + }); + } +} diff --git a/resources/assets/js/components/OnlyOffice.vue b/resources/assets/js/components/OnlyOffice.vue index a1a3e001..17ff8c9a 100644 --- a/resources/assets/js/components/OnlyOffice.vue +++ b/resources/assets/js/components/OnlyOffice.vue @@ -52,16 +52,16 @@ export default { return {} } }, + code: { + type: String, + default: '' + }, }, data() { return { loadIng: 0, - fileName: null, - fileType: null, - fileUrl: null, - docEditor: null, } }, @@ -79,19 +79,29 @@ export default { computed: { ...mapState(['userToken', 'userInfo']), + + isPreview() { + return !!this.code + }, + + fileUrl() { + if (this.isPreview) { + return 'http://nginx/api/file/content/?code=' + this.code; + } else { + return 'http://nginx/api/file/content/?id=' + this.value.id + '&token=' + this.userToken; + } + }, + + fileType() { + return this.getType(this.value.type); + }, + + fileName() { + return this.value.name; + } }, watch: { - value: { - handler(val) { - this.fileUrl = 'http://nginx/api/file/content/?id=' + val.id + '&token=' + this.userToken; - this.fileType = this.getType(val.type); - this.fileName = val.name; - }, - immediate: true, - deep: true, - }, - fileUrl: { handler(url) { if (!url) { @@ -164,6 +174,19 @@ export default { "callbackUrl": 'http://nginx/api/file/content/office?id=' + this.value.id + '&token=' + this.userToken, } }; + if (this.isPreview) { + config.editorConfig.mode = "view"; + config.editorConfig.callbackUrl = null; + if (!config.editorConfig.user.id) { + let viewer = this.$store.state.method.getStorageInt("viewer") + if (!viewer) { + viewer = $A.randNum(1000, 99999); + this.$store.state.method.setStorage("viewer", viewer) + } + config.editorConfig.user.id = "viewer_" + viewer; + config.editorConfig.user.name = "Viewer_" + viewer + } + } this.$nextTick(() => { this.docEditor = new DocsAPI.DocEditor(this.id, config); }) diff --git a/resources/assets/js/pages/manage/components/FilePreview.vue b/resources/assets/js/pages/manage/components/FilePreview.vue new file mode 100644 index 00000000..87e9eba2 --- /dev/null +++ b/resources/assets/js/pages/manage/components/FilePreview.vue @@ -0,0 +1,172 @@ + + + diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index 4f2d924e..71d924ca 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -117,11 +117,11 @@ {{$L('重命名')}} - {{$L('复制')}} + {{$L('复制')}} {{$L('剪切')}}