From aa9a3238a2b328766732791afdf78e11d7544cea Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 10 Dec 2021 17:05:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E4=BB=B6=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/FileController.php | 35 ++--- app/Models/File.php | 9 +- app/Models/FileContent.php | 42 +++--- app/Module/Base.php | 15 ++- .../2021_12_10_170751_files_add_ext.php | 47 +++++++ docker-compose.yml | 14 +- docker/nginx/default.conf | 59 +++++--- resources/assets/js/components/OnlyOffice.vue | 2 +- .../pages/manage/components/FileContent.vue | 127 ++++++++++-------- resources/assets/js/pages/manage/file.vue | 36 ++--- .../sass/pages/components/file-content.scss | 15 +++ 11 files changed, 265 insertions(+), 136 deletions(-) create mode 100644 database/migrations/2021_12_10_170751_files_add_ext.php diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 4493aece..2510b431 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -407,7 +407,8 @@ class FileController extends AbstractController $path = 'uploads/office/' . date("Ym") . '/u' . $user->userid . '/'; $data = Base::upload([ "file" => Request::file('files'), - "type" => 'office', + "type" => 'more', + "autoThumb" => false, "path" => $path, ]); if (Base::isError($data)) { @@ -415,36 +416,36 @@ class FileController extends AbstractController } $data = $data['data']; // - $type = ""; - switch ($data['ext']) { - case 'doc': - case 'docx': - $type = "word"; - break; - case 'xls': - case 'xlsx': - $type = "excel"; - break; - case 'ppt': - case 'pptx': - $type = "ppt"; - break; - } + $type = match ($data['ext']) { + 'doc', 'docx' => "word", + 'xls', 'xlsx' => "excel", + 'ppt', 'pptx' => "ppt", + 'txt', 'html', 'htm', 'asp', 'jsp', 'xml', 'json', 'properties', 'md', 'gitignore', 'log', 'java', 'py', 'c', 'cpp', 'sql', 'sh', 'bat', 'm', 'bas', 'prg', 'cmd' => "text", + 'jpg', 'jpeg', 'png', 'gif' => 'image', + 'zip', 'rar', 'jar', 'tar', 'gzip' => 'compress', + 'mp3', 'wav', 'mp4', 'flv' => 'media', + 'pdf' => 'pdf', + 'dwg' => 'cad', + default => "", + }; $file = File::createInstance([ 'pid' => $pid, 'name' => Base::rightDelete($data['name'], '.' . $data['ext']), 'type' => $type, + 'ext' => $data['ext'], 'userid' => $userid, 'created_id' => $user->userid, ]); // 开始创建 - return AbstractModel::transaction(function () use ($user, $data, $file) { + return AbstractModel::transaction(function () use ($type, $user, $data, $file) { $file->save(); // $content = FileContent::createInstance([ 'fid' => $file->id, 'content' => [ 'from' => '', + 'type' => $type, + 'ext' => $data['ext'], 'url' => $data['path'] ], 'text' => '', diff --git a/app/Models/File.php b/app/Models/File.php index 19b2eb5b..a0f105d3 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -10,18 +10,18 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Request; /** - * Class File + * App\Models\File * - * @package App\Models * @property int $id * @property int|null $pid 上级ID * @property int|null $cid 复制ID * @property string|null $name 名称 * @property string|null $type 类型 + * @property string|null $ext 后缀名 * @property int|null $size 大小(B) * @property int|null $userid 拥有者ID - * @property int|null $share 是否共享(1:共享所有人,2:指定成员) - * @property int|null $created_id 创建者ID + * @property int|null $share 是否共享 + * @property int|null $created_id 创建者 * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $deleted_at @@ -33,6 +33,7 @@ use Request; * @method static \Illuminate\Database\Eloquent\Builder|File whereCreatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|File whereCreatedId($value) * @method static \Illuminate\Database\Eloquent\Builder|File whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|File whereExt($value) * @method static \Illuminate\Database\Eloquent\Builder|File whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|File whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|File wherePid($value) diff --git a/app/Models/FileContent.php b/app/Models/FileContent.php index ced6d89b..8f183ff9 100644 --- a/app/Models/FileContent.php +++ b/app/Models/FileContent.php @@ -57,26 +57,28 @@ class FileContent extends AbstractModel return Response::download(public_path($content['url'])); } if (empty($content)) { - switch ($type) { - case 'document': - $content = [ - "type" => "md", - "content" => "", - ]; - break; - - case 'sheet': - $content = [ - [ - "name" => "Sheet1", - "config" => json_decode('{}'), - ] - ]; - break; - - default: - $content = json_decode('{}'); - break; + $content = match ($type) { + 'document' => [ + "type" => "md", + "content" => "", + ], + 'sheet' => [ + [ + "name" => "Sheet1", + "config" => json_decode('{}'), + ] + ], + default => json_decode('{}'), + }; + } else { + $content['preview'] = false; + if ($content['ext'] && !in_array($content['ext'], ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'])) { + $url = 'http://' . env('APP_IPPR') . '.3/' . $content['url']; + if ($type == 'image') { + $url = Base::fillUrl($content['url']); + } + $content['url'] = base64_encode($url); + $content['preview'] = true; } } return Base::retSuccess('success', [ 'content' => $content ]); diff --git a/app/Module/Base.php b/app/Module/Base.php index 2d90ac6a..59a14b22 100755 --- a/app/Module/Base.php +++ b/app/Module/Base.php @@ -2218,17 +2218,22 @@ class Base case 'file': $type = ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz']; break; - case 'office': - $type = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']; - break; case 'firmware': $type = ['img', 'tar', 'bin']; break; case 'md': $type = ['md']; break; - case 'node_template': - $type = ['csv']; + case 'more': + $type = [ + 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', + 'txt', 'html', 'htm', 'asp', 'jsp', 'xml', 'json', 'properties', 'md', 'gitignore', 'log', 'java', 'py', 'c', 'cpp', 'sql', 'sh', 'bat', 'm', 'bas', 'prg', 'cmd', + 'jpg', 'jpeg', 'png', 'gif', + 'zip', 'rar', 'jar', 'tar', 'gzip', + 'mp3', 'wav', 'mp4', 'flv', + 'pdf', + 'dwg' + ]; break; default: return Base::retError('错误的类型参数'); diff --git a/database/migrations/2021_12_10_170751_files_add_ext.php b/database/migrations/2021_12_10_170751_files_add_ext.php new file mode 100644 index 00000000..723fe5fa --- /dev/null +++ b/database/migrations/2021_12_10_170751_files_add_ext.php @@ -0,0 +1,47 @@ +string('ext', 20)->nullable()->default('')->after('type')->comment('后缀名'); + } + }); + if ($isAdd) { + // 更新数据 + \App\Models\File::chunkById(100, function ($lists) { + foreach ($lists as $item) { + if (in_array($item->type, ['word', 'excel', 'ppt'])) { + $item->ext = str_replace(['word', 'excel', 'ppt'], ['docx', 'xlsx', 'pptx'], $item->type); + $item->save(); + } + } + }); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('files', function (Blueprint $table) { + $table->dropColumn("ext"); + }); + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 08780ec9..9a3fe107 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,11 +41,10 @@ services: networks: extnetwork: ipv4_address: "${APP_IPPR}.3" - depends_on: - - php links: - php - office + - fileview restart: unless-stopped redis: @@ -95,6 +94,17 @@ services: ipv4_address: "${APP_IPPR}.6" restart: unless-stopped + fileview: + container_name: "dootask-fileview-${APP_ID}" + image: "kuaifan/fileview:4.1.0" + environment: + TZ: "Asia/Shanghai" + KK_CONTEXT_PATH: "/fileview" + networks: + extnetwork: + ipv4_address: "${APP_IPPR}.7" + restart: unless-stopped + networks: extnetwork: name: "dootask-networks-${APP_ID}" diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index 52918c88..89dc284d 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -10,6 +10,10 @@ upstream office { server office weight=5 max_fails=3 fail_timeout=30s; keepalive 16; } +upstream fileview { + server fileview:8012 weight=5 max_fails=3 fail_timeout=30s; + keepalive 16; +} server { listen 80; @@ -32,26 +36,12 @@ server { allow all; } - location ~* ^/(6.3.1-32|cache/files|web-apps/apps)/ { - proxy_http_version 1.1; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Real-PORT $remote_port; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header Scheme $scheme; - proxy_set_header Server-Protocol $server_protocol; - proxy_set_header Server-Name $server_name; - proxy_set_header Server-Addr $server_addr; - proxy_set_header Server-Port $server_port; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_pass http://office; - } - location =/ws { proxy_http_version 1.1; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-PORT $remote_port; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; @@ -69,6 +59,8 @@ server { proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-PORT $remote_port; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; @@ -78,6 +70,41 @@ server { proxy_set_header Server-Port $server_port; proxy_pass http://service; } + + location /office/ { + proxy_http_version 1.1; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-PORT $remote_port; + proxy_set_header X-Forwarded-Host $http_host/office; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header Scheme $scheme; + proxy_set_header Server-Protocol $server_protocol; + proxy_set_header Server-Name $server_name; + proxy_set_header Server-Addr $server_addr; + proxy_set_header Server-Port $server_port; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_pass http://office/; + } + + location /fileview { + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-PORT $remote_port; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header Scheme $scheme; + proxy_set_header Server-Protocol $server_protocol; + proxy_set_header Server-Name $server_name; + proxy_set_header Server-Addr $server_addr; + proxy_set_header Server-Port $server_port; + proxy_pass http://fileview; + } } include /etc/nginx/conf.d/conf.d/*.conf; diff --git a/resources/assets/js/components/OnlyOffice.vue b/resources/assets/js/components/OnlyOffice.vue index c80a800c..0288320c 100644 --- a/resources/assets/js/components/OnlyOffice.vue +++ b/resources/assets/js/components/OnlyOffice.vue @@ -85,7 +85,7 @@ export default { if (!url) { return; } - $A.loadScript(this.$store.state.method.apiUrl("../web-apps/apps/api/documents/api.js"), () => { + $A.loadScript(this.$store.state.method.apiUrl("../office/web-apps/apps/api/documents/api.js"), () => { this.loadFile() }) }, diff --git a/resources/assets/js/pages/manage/components/FileContent.vue b/resources/assets/js/pages/manage/components/FileContent.vue index f0c75eb9..b542f5ca 100644 --- a/resources/assets/js/pages/manage/components/FileContent.vue +++ b/resources/assets/js/pages/manage/components/FileContent.vue @@ -1,64 +1,67 @@ @@ -166,6 +169,18 @@ export default { equalContent() { return this.contentBak == $A.jsonStringify(this.contentDetail); }, + + isPreview() { + return this.contentDetail && this.contentDetail.preview === true; + }, + + previewUrl() { + if (this.isPreview) { + return this.$store.state.method.apiUrl("../fileview/onlinePreview?url=" + encodeURIComponent(this.contentDetail.url)) + } else { + return ''; + } + }, }, methods: { diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index c914c33b..16d923fc 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -85,7 +85,7 @@ @on-enter="onEnter(item)"/>
-
{{formatName(item.name, item.type)}}
+
{{formatName(item)}}
@@ -199,7 +199,7 @@ v-model="editShow" class="page-file-drawer" :mask-closable="false"> - + @@ -290,13 +290,21 @@ export default { shareLoad: 0, editShow: false, - editShowNum: 0, + editNum: 0, editInfo: {}, uploadDir: false, uploadIng: 0, - uploadFormat: ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'], - uploadAccept: ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'].join(","), + uploadFormat: [ + 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', + 'txt', 'html', 'htm', 'asp', 'jsp', 'xml', 'json', 'properties', 'md', 'gitignore', 'log', 'java', 'py', 'c', 'cpp', 'sql', 'sh', 'bat', 'm', 'bas', 'prg', 'cmd', + 'jpg', 'jpeg', 'png', 'gif', + 'zip', 'rar', 'jar', 'tar', 'gzip', + 'mp3', 'wav', 'mp4', 'flv', + 'pdf', + 'dwg' + ], + uploadAccept: '', maxSize: 204800, contextMenuItem: {}, @@ -310,6 +318,9 @@ export default { mounted() { this.tableHeight = window.innerHeight - 160; + this.uploadAccept = this.uploadFormat.map(item => { + return '.' + item + }).join(","); }, activated() { @@ -381,7 +392,7 @@ export default { editShow(val) { if (val) { - this.editShowNum++; + this.editNum++; this.$store.dispatch("websocketPath", "file/content/" + this.editInfo.id); } else { this.$store.dispatch("websocketPath", "file"); @@ -397,7 +408,6 @@ export default { title: this.$L('文件名'), key: 'name', minWidth: 200, - resizable: true, sortable: true, render: (h, {row}) => { let array = []; @@ -467,7 +477,7 @@ export default { } } }, [ - h('AutoTip', this.formatName(row.name, row.type)) + h('AutoTip', this.formatName(row)) ])); // const iconArray = []; @@ -556,13 +566,9 @@ export default { ] }, - formatName(name, type) { - if (type == 'word') { - name += ".docx"; - } else if (type == 'excel') { - name += ".xlsx"; - } else if (type == 'ppt') { - name += ".pptx"; + formatName({name, ext}) { + if (ext != '') { + name += "." + ext; } return name; }, diff --git a/resources/assets/sass/pages/components/file-content.scss b/resources/assets/sass/pages/components/file-content.scss index 89b2b1a1..6a1c2681 100644 --- a/resources/assets/sass/pages/components/file-content.scss +++ b/resources/assets/sass/pages/components/file-content.scss @@ -9,6 +9,21 @@ border-radius: 18px 18px 0 0; overflow: hidden; + .preview-iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: 0 0; + border: 0; + float: none; + margin: -1px 0 0; + max-width: none; + outline: 0; + padding: 0; + } + .edit-header { display: flex; flex-direction: row;