diff --git a/.env.docker b/.env.docker index 9b72dda0..89b4da38 100644 --- a/.env.docker +++ b/.env.docker @@ -6,6 +6,7 @@ APP_URL=http://localhost APP_PORT=2222 APP_PORT_SSL=2223 +APP_PORT_ONLYOFFICE=2224 LOG_CHANNEL=stack LOG_LEVEL=debug diff --git a/.env.example b/.env.example index db24d140..3ddb0d36 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,7 @@ APP_URL=http://localhost APP_PORT=2222 APP_PORT_SSL=2223 +APP_PORT_ONLYOFFICE=2224 LOG_CHANNEL=stack LOG_LEVEL=debug diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 00a543e0..bf33306c 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -8,8 +8,10 @@ use App\Models\FileContent; use App\Models\FileUser; use App\Models\User; use App\Module\Base; +use App\Module\Ihttp; use Arr; use Request; +use Response; /** * @apiDefine file @@ -129,6 +131,9 @@ class FileController extends AbstractController 'mind', 'sheet', 'flow', + 'word', + 'excel', + 'ppt', ])) { return Base::retError('类型错误'); } @@ -254,30 +259,32 @@ class FileController extends AbstractController } /** - * 文件内容 + * 获取文件内容 * * @apiParam {Number} id 文件ID */ public function content() { - $user = User::auth(); - // $id = intval(Request::input('id')); // $file = File::allowFind($id); // - $content = FileContent::whereFid($file->id)->orderByDesc('id')->first(); - if (empty($content)) { - $content = FileContent::createInstance([ - 'fid' => $file->id, - 'content' => '{}', - 'userid' => $user->userid, - ]); - $content->save(); + switch ($file->type) { + case "word": + return Response::download(resource_path('assets/statics/empty/empty.docx')); + + case "excel": + return Response::download(resource_path('assets/statics/empty/empty.xlsx')); + + case "ppt": + return Response::download(resource_path('assets/statics/empty/empty.pptx')); + + default: + $content = FileContent::whereFid($file->id)->orderByDesc('id')->first(); + return Base::retSuccess('success', [ + 'content' => FileContent::formatContent($file->type, $content ? $content->content : []) + ]); } - // - $content->content = $content->formatContent($file->type, $content->content); - return Base::retSuccess('success', $content); } /** @@ -296,6 +303,10 @@ class FileController extends AbstractController // $file = File::allowFind($id); // + if (in_array($file->type, ['word', 'excel', 'ppt'])) { + return Base::retError($file->type . ' 不支持此方式保存'); + } + // $text = ''; if ($file->type == 'document') { $data = Base::json2array($content); @@ -333,6 +344,44 @@ class FileController extends AbstractController return Base::retSuccess('保存成功', $content); } + /** + * 保存文件内容(office) + * + * @apiParam {Number} id 文件ID + */ + public function content__office() + { + $user = User::auth(); + // + $id = intval(Request::input('id')); + $status = intval(Request::input('status')); + $key = Request::input('key'); + $url = Request::input('url'); + // + $file = File::allowFind($id); + // + if ($status === 2) { + $parse = parse_url($url); + $url = 'http://10.22.22.6' . $parse['query'] . '?' . $parse['query']; + $path = public_path('uploads/office/' . $file->id . '/' . $key); + Base::makeDir(dirname($path)); + $res = Ihttp::download($url, $path); + if (Base::isSuccess($res)) { + FileContent::createInstance([ + 'fid' => $file->id, + 'content' => [ + 'from' => $url, + 'url' => 'uploads/office/' . $file->id . '/' . $key + ], + 'text' => '', + 'size' => filesize($path), + 'userid' => $user->userid, + ])->save(); + } + } + return ['error' => 0]; + } + /** * 获取共享信息 * diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 27f93cc3..7d18f870 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -35,5 +35,8 @@ class VerifyCsrfToken extends Middleware // 保存文件内容 'api/file/content/save/', + + // 保存文件内容(office) + 'api/file/content/office/', ]; } diff --git a/docker-compose.yml b/docker-compose.yml index 8cf29bd3..e0fb46d4 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,6 +79,21 @@ services: ipv4_address: 10.22.22.5 restart: unless-stopped + office: + container_name: "dooteak-office-${DOCKER_ID}" + image: "onlyoffice/documentserver" + ports: + - "${APP_PORT_ONLYOFFICE}:80" + volumes: + - ./docker/office/data:/var/www/onlyoffice/Data + - ./docker/office/logs:/var/log/onlyoffice + environment: + TZ: "Asia/Shanghai" + networks: + extnetwork: + ipv4_address: 10.22.22.6 + restart: unless-stopped + networks: extnetwork: name: "dooteak-networks-${DOCKER_ID}" diff --git a/docker/office/.gitignore b/docker/office/.gitignore new file mode 100644 index 00000000..cf0767a6 --- /dev/null +++ b/docker/office/.gitignore @@ -0,0 +1,2 @@ +data +logs diff --git a/resources/assets/js/components/OnlyOffice.vue b/resources/assets/js/components/OnlyOffice.vue new file mode 100644 index 00000000..4d6967d6 --- /dev/null +++ b/resources/assets/js/components/OnlyOffice.vue @@ -0,0 +1,129 @@ + + + + diff --git a/resources/assets/js/pages/manage/components/FileContent.vue b/resources/assets/js/pages/manage/components/FileContent.vue index 5d0d86bd..bd767c60 100644 --- a/resources/assets/js/pages/manage/components/FileContent.vue +++ b/resources/assets/js/pages/manage/components/FileContent.vue @@ -12,7 +12,7 @@ [{{$L('未保存')}}*] - {{file.name}} + {{formatName(file.name, file.type)}}
+
@@ -72,10 +73,11 @@ const MDEditor = () => import('../../../components/MDEditor/index'); const TEditor = () => import('../../../components/TEditor'); const LuckySheet = () => import('../../../components/LuckySheet'); const Flow = () => import('../../../components/flow'); +const OnlyOffice = () => import('../../../components/OnlyOffice'); export default { name: "FileContent", - components: {TEditor, MDEditor, LuckySheet, Flow}, + components: {TEditor, MDEditor, LuckySheet, Flow, OnlyOffice}, props: { file: { type: Object, @@ -168,6 +170,11 @@ export default { this.contentDetail = this.fileContent[this.fileId]; return; } + if (['word', 'excel', 'ppt'].includes(this.file.type)) { + this.contentDetail = $A.cloneJSON(this.file); + this.updateBak(); + return; + } this.loadIng++; this.loadContent++; this.$store.dispatch("call", { @@ -255,7 +262,18 @@ export default { unsaveSave() { this.handleClick('save'); this.unsaveTip = false; - } + }, + + formatName(name, type) { + if (type == 'word') { + name += ".docx"; + } else if (type == 'excel') { + name += ".xlsx"; + } else if (type == 'ppt') { + name += ".pptx"; + } + return name; + }, } } diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index e8b97649..1ca94392 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -17,7 +17,7 @@ @command="addFile"> - +
{{$L('新建' + type.name)}}
@@ -98,7 +98,7 @@ @on-enter="onEnter(item)"/>
-
{{item.name}}
+
{{formatName(item.name, item.type)}}
@@ -159,10 +159,13 @@ export default { types: [ {value: 'folder', name: "目录"}, - {value: 'document', name: "文本"}, + {value: 'document', name: "文本", divided: true}, {value: 'mind', name: "脑图"}, {value: 'sheet', name: "表格"}, {value: 'flow', name: "流程图"}, + {value: 'word', name: " Word 文档", label: "Word", divided: true}, + {value: 'excel', name: " Excel 工作表", label: "Excel"}, + {value: 'ppt', name: " PPT 演示文稿", label: "PPT"}, ], tableHeight: 500, @@ -304,7 +307,7 @@ export default { }, array), ]); } else { - // 编辑 + // 编辑、查看 array.push(h('QuickEdit', { props: { value: row.name, @@ -328,7 +331,7 @@ export default { } } }, [ - h('AutoTip', row.name) + h('AutoTip', this.formatName(row.name, row.type)) ])); // const iconArray = []; @@ -384,7 +387,7 @@ export default { render: (h, {row}) => { let type = this.types.find(({value}) => value == row.type); if (type) { - return h('AutoTip', type.name); + return h('AutoTip', type.label || type.name); } else { return h('div', '-') } @@ -417,6 +420,17 @@ export default { ] }, + formatName(name, type) { + if (type == 'word') { + name += ".docx"; + } else if (type == 'excel') { + name += ".xlsx"; + } else if (type == 'ppt') { + name += ".pptx"; + } + return name; + }, + getFileList() { this.loadIng++; this.$store.dispatch("getFiles", this.pid).then(() => { diff --git a/resources/assets/sass/pages/components/file-content.scss b/resources/assets/sass/pages/components/file-content.scss index 8838d20e..24c8dee7 100644 --- a/resources/assets/sass/pages/components/file-content.scss +++ b/resources/assets/sass/pages/components/file-content.scss @@ -171,20 +171,20 @@ .luckysheet { border: 0; } + } - .content-load { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 1000; - .common-loading { - margin: 0; - } + .content-load { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 42px; + left: 0; + right: 0; + bottom: 0; + z-index: 1000; + .common-loading { + margin: 0; } } } diff --git a/resources/assets/sass/pages/page-file.scss b/resources/assets/sass/pages/page-file.scss index 96fef8a5..e78924ac 100644 --- a/resources/assets/sass/pages/page-file.scss +++ b/resources/assets/sass/pages/page-file.scss @@ -270,6 +270,15 @@ &.flow:before { background-image: url("../images/file/flow.svg"); } + &.word:before { + background-image: url("../images/file/word.svg"); + } + &.excel:before { + background-image: url("../images/file/excel.svg"); + } + &.ppt:before { + background-image: url("../images/file/ppt.svg"); + } } .taskfont { color: #aaaaaa; @@ -395,6 +404,15 @@ &.flow .file-icon { background-image: url("../images/file/flow.svg"); } + &.word .file-icon { + background-image: url("../images/file/word.svg"); + } + &.excel .file-icon { + background-image: url("../images/file/excel.svg"); + } + &.ppt .file-icon { + background-image: url("../images/file/ppt.svg"); + } &:hover { background-color: #f4f5f7; .file-menu { @@ -436,5 +454,14 @@ &.flow:before { background-image: url("../images/file/flow.svg"); } + &.word:before { + background-image: url("../images/file/word.svg"); + } + &.excel:before { + background-image: url("../images/file/excel.svg"); + } + &.ppt:before { + background-image: url("../images/file/ppt.svg"); + } } } diff --git a/resources/assets/statics/empty/empty.docx b/resources/assets/statics/empty/empty.docx new file mode 100644 index 00000000..d491eadc Binary files /dev/null and b/resources/assets/statics/empty/empty.docx differ diff --git a/resources/assets/statics/empty/empty.pptx b/resources/assets/statics/empty/empty.pptx new file mode 100644 index 00000000..d2a2e2f9 Binary files /dev/null and b/resources/assets/statics/empty/empty.pptx differ diff --git a/resources/assets/statics/empty/empty.xlsx b/resources/assets/statics/empty/empty.xlsx new file mode 100644 index 00000000..026036fb Binary files /dev/null and b/resources/assets/statics/empty/empty.xlsx differ diff --git a/resources/assets/statics/public/images/file/document.svg b/resources/assets/statics/public/images/file/document.svg index 2dac4e83..e9e55f18 100644 --- a/resources/assets/statics/public/images/file/document.svg +++ b/resources/assets/statics/public/images/file/document.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/excel.svg b/resources/assets/statics/public/images/file/excel.svg new file mode 100644 index 00000000..86688755 --- /dev/null +++ b/resources/assets/statics/public/images/file/excel.svg @@ -0,0 +1 @@ + diff --git a/resources/assets/statics/public/images/file/flow.svg b/resources/assets/statics/public/images/file/flow.svg index f32e101d..1af5497f 100644 --- a/resources/assets/statics/public/images/file/flow.svg +++ b/resources/assets/statics/public/images/file/flow.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/folder.svg b/resources/assets/statics/public/images/file/folder.svg index 60788d5b..47b32776 100644 --- a/resources/assets/statics/public/images/file/folder.svg +++ b/resources/assets/statics/public/images/file/folder.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/mind.svg b/resources/assets/statics/public/images/file/mind.svg index a6636648..af2e370e 100644 --- a/resources/assets/statics/public/images/file/mind.svg +++ b/resources/assets/statics/public/images/file/mind.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/ppt.svg b/resources/assets/statics/public/images/file/ppt.svg new file mode 100644 index 00000000..3d37b593 --- /dev/null +++ b/resources/assets/statics/public/images/file/ppt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/sheet.svg b/resources/assets/statics/public/images/file/sheet.svg index 77ced9bd..d7e11669 100644 --- a/resources/assets/statics/public/images/file/sheet.svg +++ b/resources/assets/statics/public/images/file/sheet.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/statics/public/images/file/word.svg b/resources/assets/statics/public/images/file/word.svg new file mode 100644 index 00000000..d388d694 --- /dev/null +++ b/resources/assets/statics/public/images/file/word.svg @@ -0,0 +1 @@ + \ No newline at end of file