diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index c5f56dfea..5b1f279c4 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -271,7 +271,7 @@ class DialogController extends AbstractController // $dialog = WebSocketDialog::checkDialog($dialog_id); // - $path = "uploads/chat/" . $user->userid . "/"; + $path = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/"; $image64 = Base::getPostValue('image64'); $fileName = Base::getPostValue('filename'); if ($image64) { diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 064dbc5ae..7f4b3e741 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -213,14 +213,23 @@ class FileController extends AbstractController ])) { return Base::retError('类型错误'); } - $ext = ''; - if (in_array($type, [ + $ext = str_replace([ + 'folder', + 'document', + 'mind', + 'drawio', 'word', 'excel', 'ppt', - ])) { - $ext = str_replace(['word', 'excel', 'ppt'], ['docx', 'xlsx', 'pptx'], $type); - } + ], [ + '', + 'md', + 'mind', + 'drawio', + 'docx', + 'xlsx', + 'pptx', + ], $type); // $userid = $user->userid; if ($pid > 0) { @@ -471,7 +480,7 @@ class FileController extends AbstractController * @apiGroup file * @apiName content__save * - * @apiParam {Number} id 文件ID + * @apiParam {Number} id 文件ID * @apiParam {Object} [D] Request Payload 提交 * - content: 内容 * @@ -481,6 +490,7 @@ class FileController extends AbstractController */ public function content__save() { + Base::checkClientVersion('0.9.13'); $user = User::auth(); // $id = Base::getPostInt('id'); @@ -494,12 +504,11 @@ class FileController extends AbstractController $isRep = false; preg_match_all("/ $text) { - $p = "uploads/files/document/" . $id . "/"; - Base::makeDir(public_path($p)); - $p.= md5($text) . "." . $matchs[1][$key]; - $r = file_put_contents(public_path($p), base64_decode($text)); - if ($r) { - $data['content'] = str_replace($matchs[0][$key], 'type) { + case 'document': + $file->ext = $contentArray['type'] ?: 'md'; + $contentString = $contentArray['content']; + break; + case 'drawio': + $file->ext = 'drawio'; + $contentString = $contentArray['xml']; + break; + case 'mind': + $file->ext = 'mind'; + $contentString = $content; + break; + } + if (isset($contentString)) { + $path = "uploads/file/" . $file->type . "/" . date("Ym") . "/" . $id . "/" . md5($contentString); + $save = public_path($path); + Base::makeDir(dirname($save)); + file_put_contents($save, $contentString); + $content = [ + 'type' => $file->ext, + 'url' => $path + ]; + $size = filesize($save); + } else { + $size = strlen($content); + } + // $content = FileContent::createInstance([ 'fid' => $file->id, 'content' => $content, 'text' => $text, - 'size' => strlen($content), + 'size' => $size, 'userid' => $user->userid, ]); $content->save(); @@ -553,7 +591,7 @@ class FileController extends AbstractController if ($status === 2) { $parse = parse_url($url); $from = 'http://' . env('APP_IPPR') . '.3' . $parse['path'] . '?' . $parse['query']; - $path = 'uploads/office/' . date("Ym") . '/' . $file->id . '/' . $user->userid . '-' . $key; + $path = 'uploads/file/' . $file->type . '/' . date("Ym") . '/' . $file->id . '/' . $key; $save = public_path($path); Base::makeDir(dirname($save)); $res = Ihttp::download($from, $save); @@ -644,7 +682,7 @@ class FileController extends AbstractController } } // - $path = 'uploads/file/' . date("Ym") . '/u' . $user->userid . '/'; + $path = 'uploads/tmp/' . date("Ym") . '/'; $data = Base::upload([ "file" => Request::file('files'), "type" => 'more', @@ -657,6 +695,9 @@ class FileController extends AbstractController $data = $data['data']; // $type = match ($data['ext']) { + 'text', 'md', 'markdown' => 'document', + 'drawio' => 'drawio', + 'mind' => 'mind', 'doc', 'docx' => "word", 'xls', 'xlsx' => "excel", 'ppt', 'pptx' => "ppt", @@ -670,7 +711,7 @@ class FileController extends AbstractController 'txt' => "txt", 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', - 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', + 'ocamlmakefile', 'make', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'rdf', 'rss', 'wsdl', 'xslt', 'atom', 'mathml', 'mml', 'xul', 'xbl', 'xaml', 'yaml', 'yml', @@ -681,6 +722,9 @@ class FileController extends AbstractController 'rp' => "axure", default => "", }; + if ($data['ext'] == 'markdown') { + $data['ext'] = 'md'; + } $file = File::createInstance([ 'pid' => $pid, 'name' => Base::rightDelete($data['name'], '.' . $data['ext']), @@ -694,6 +738,7 @@ class FileController extends AbstractController $file->size = $data['size'] * 1024; $file->save(); // + $data = Base::uploadMove($data, "uploads/file/" . $file->type . "/" . date("Ym") . "/" . $file->id . "/"); $content = FileContent::createInstance([ 'fid' => $file->id, 'content' => [ diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index cbb76c77f..da2163959 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -315,7 +315,7 @@ class SystemController extends AbstractController if (!$scale[0] && !$scale[1]) { $scale = [2160, 4160, -1]; } - $path = "uploads/picture/" . User::userid() . "/" . date("Ym") . "/"; + $path = "uploads/user/picture/" . User::userid() . "/" . date("Ym") . "/"; $image64 = trim(Base::getPostValue('image64')); $fileName = trim(Base::getPostValue('filename')); if ($image64) { @@ -360,7 +360,7 @@ class SystemController extends AbstractController if (User::userid() === 0) { return Base::retError('身份失效,等重新登录'); } - $publicPath = "uploads/picture/" . User::userid() . "/"; + $publicPath = "uploads/user/picture/" . User::userid() . "/"; $dirPath = public_path($publicPath); $dirs = $files = []; // @@ -458,7 +458,7 @@ class SystemController extends AbstractController if (User::userid() === 0) { return Base::retError('身份失效,等重新登录'); } - $path = "uploads/files/" . User::userid() . "/" . date("Ym") . "/"; + $path = "uploads/user/file/" . User::userid() . "/" . date("Ym") . "/"; $image64 = trim(Base::getPostValue('image64')); $fileName = trim(Base::getPostValue('filename')); if ($image64) { diff --git a/app/Models/FileContent.php b/app/Models/FileContent.php index 21ce768cf..45864ed8a 100644 --- a/app/Models/FileContent.php +++ b/app/Models/FileContent.php @@ -60,7 +60,7 @@ class FileContent extends AbstractModel if (empty($content)) { $content = match ($file->type) { 'document' => [ - "type" => "md", + "type" => $file->ext, "content" => "", ], default => json_decode('{}'), @@ -72,12 +72,36 @@ class FileContent extends AbstractModel $content['preview'] = false; if ($file->ext) { $filePath = public_path($content['url']); - if (in_array($file->type, ['txt', 'code']) && $file->size < 2 * 1024 * 1024) { - // 支持编辑,限制2M内的文件 + $fileType = $file->type; + if ($fileType == 'document') + { + // 文本 + $content = [ + 'type' => $file->ext, + 'content' => file_get_contents($filePath) + ]; + } + elseif ($fileType == 'drawio') + { + // 图表 + $content = [ + 'xml' => file_get_contents($filePath) + ]; + } + elseif ($fileType == 'mind') + { + // 思维导图 + $content = Base::json2array(file_get_contents($filePath)); + } + elseif (in_array($fileType, ['txt', 'code']) && $file->size < 2 * 1024 * 1024) + { + // 其他文本和代码(限制2M内的文件,支持编辑) $content['content'] = file_get_contents($filePath); - } else { + } + else + { // 支持预览 - if (in_array($file->type, ['picture', 'image', 'tif', 'media'])) { + if (in_array($fileType, ['picture', 'image', 'tif', 'media'])) { $url = Base::fillUrl($content['url']); } else { $url = 'http://' . env('APP_IPPR') . '.3/' . $content['url']; diff --git a/app/Module/Base.php b/app/Module/Base.php index 6d52f0909..2e64c3be7 100755 --- a/app/Module/Base.php +++ b/app/Module/Base.php @@ -2259,6 +2259,9 @@ class Base break; case 'more': $type = [ + 'text', 'md', 'markdown', + 'drawio', + 'mind', 'docx', 'wps', 'doc', 'xls', 'xlsx', 'ppt', 'pptx', 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'ico', 'raw', 'rar', 'zip', 'jar', '7-zip', 'tar', 'gzip', '7z', @@ -2269,7 +2272,7 @@ class Base 'txt', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', - 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', + 'ocamlmakefile', 'make', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'rdf', 'rss', 'wsdl', 'xslt', 'atom', 'mathml', 'mml', 'xul', 'xbl', 'xaml', 'yaml', 'yml', @@ -2399,6 +2402,37 @@ class Base } } + /** + * 上传文件移动 + * @param array $uploadResult + * @param string $newPath "/" 结尾 + * @return array + */ + public static function uploadMove($uploadResult, $newPath) + { + if (str_ends_with($newPath, "/") && file_exists($uploadResult['file'])) { + Base::makeDir(public_path($newPath)); + $oldPath = dirname($uploadResult['path']) . "/"; + $newFile = str_replace($oldPath, $newPath, $uploadResult['file']); + if (rename($uploadResult['file'], $newFile)) { + $oldUrl = $uploadResult['url']; + $uploadResult['file'] = $newFile; + $uploadResult['path'] = str_replace($oldPath, $newPath, $uploadResult['path']); + $uploadResult['url'] = str_replace($oldPath, $newPath, $uploadResult['url']); + if ($uploadResult['thumb'] == $oldUrl) { + $uploadResult['thumb'] = $uploadResult['url']; + } elseif ($uploadResult['thumb']) { + $oldThumb = substr($uploadResult['thumb'], strpos($uploadResult['thumb'], $newPath)); + $newThumb = str_replace($oldPath, $newPath, $oldThumb); + if (file_exists(public_path($oldThumb)) && rename(public_path($oldThumb), public_path($newThumb))) { + $uploadResult['thumb'] = str_replace($oldPath, $newPath, $uploadResult['thumb']); + } + } + } + } + return $uploadResult; + } + /** * 生成缩略图 * @param string $src_img 源图绝对完整地址{带文件名及后缀名} diff --git a/database/migrations/2022_02_20_171030_files_update_type.php b/database/migrations/2022_02_20_171030_files_update_type.php index 7512aad40..57e157bf9 100644 --- a/database/migrations/2022_02_20_171030_files_update_type.php +++ b/database/migrations/2022_02_20_171030_files_update_type.php @@ -23,6 +23,8 @@ class FilesUpdateType extends Migration */ public function down() { - // + File::whereType('drawio')->update([ + 'type' => 'flow' + ]); } } diff --git a/database/migrations/2022_02_21_203230_files_update_ext.php b/database/migrations/2022_02_21_203230_files_update_ext.php new file mode 100644 index 000000000..38c7a10a8 --- /dev/null +++ b/database/migrations/2022_02_21_203230_files_update_ext.php @@ -0,0 +1,75 @@ +where('ext', '')->orderBy('id')->chunk(100, function($files) { + /** @var File $file */ + foreach ($files as $file) { + $fileContent = FileContent::whereFid($file->id)->orderByDesc('id')->first(); + $contentArray = Base::json2array($fileContent?->content); + $contentString = ''; + // + switch ($file->type) { + case 'document': + $file->ext = $contentArray['type'] ?: 'md'; + $contentString = $contentArray['content']; + break; + case 'drawio': + $file->ext = 'drawio'; + $contentString = $contentArray['xml']; + break; + case 'mind': + $file->ext = 'mind'; + $contentString = $fileContent?->content; + break; + } + $file->save(); + // + $path = 'uploads/file/' . $file->type . '/' . date("Ym", Carbon::parse($file->created_at)->timestamp) . '/' . $file->id . '/' . md5($contentString); + $save = public_path($path); + Base::makeDir(dirname($save)); + file_put_contents($save, $contentString); + $content = [ + 'type' => $file->ext, + 'url' => $path + ]; + // + $content = FileContent::createInstance([ + 'fid' => $file->id, + 'content' => $content, + 'text' => $fileContent?->text, + 'size' => $file->size, + 'userid' => $file->userid, + ]); + $content->save(); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + File::whereIn('ext', ['mind', 'drawio', 'md'])->update([ + 'ext' => '' + ]); + // ... 退回去意义不大,文件内容不做回滚操作 + } +} diff --git a/database/seeders/FileContentsTableSeeder.php b/database/seeders/FileContentsTableSeeder.php index 8ff9c5a57..bb20410d6 100644 --- a/database/seeders/FileContentsTableSeeder.php +++ b/database/seeders/FileContentsTableSeeder.php @@ -599,7 +599,5 @@ curl -O https://task.hitosea.com/uploads/files/3/202105/ba786dfc2f4c2fe916880474 'deleted_at' => NULL, ), )); - - } } diff --git a/database/seeders/FilesTableSeeder.php b/database/seeders/FilesTableSeeder.php index 0186bf8f9..64f67c78a 100644 --- a/database/seeders/FilesTableSeeder.php +++ b/database/seeders/FilesTableSeeder.php @@ -2,6 +2,10 @@ namespace Database\Seeders; +use App\Models\File; +use App\Models\FileContent; +use App\Module\Base; +use Carbon\Carbon; use Illuminate\Database\Seeder; class FilesTableSeeder extends Seeder @@ -280,5 +284,47 @@ class FilesTableSeeder extends Seeder )); + File::whereIn('type', ['mind', 'drawio', 'document'])->where('ext', '')->orderBy('id')->chunk(100, function($files) { + /** @var File $file */ + foreach ($files as $file) { + $fileContent = FileContent::whereFid($file->id)->orderByDesc('id')->first(); + $contentArray = Base::json2array($fileContent?->content); + $contentString = ''; + // + switch ($file->type) { + case 'document': + $file->ext = $contentArray['type'] ?: 'md'; + $contentString = $contentArray['content']; + break; + case 'drawio': + $file->ext = 'drawio'; + $contentString = $contentArray['xml']; + break; + case 'mind': + $file->ext = 'mind'; + $contentString = $fileContent?->content; + break; + } + $file->save(); + // + $path = 'uploads/file/' . $file->type . '/' . date("Ym", Carbon::parse($file->created_at)->timestamp) . '/' . $file->id . '/' . md5($contentString); + $save = public_path($path); + Base::makeDir(dirname($save)); + file_put_contents($save, $contentString); + $content = [ + 'type' => $file->ext, + 'url' => $path + ]; + // + $content = FileContent::createInstance([ + 'fid' => $file->id, + 'content' => $content, + 'text' => $fileContent?->text, + 'size' => $file->size, + 'userid' => $file->userid, + ]); + $content->save(); + } + }); } } diff --git a/resources/assets/js/pages/manage/components/DialogUpload.vue b/resources/assets/js/pages/manage/components/DialogUpload.vue index d9b1be7a1..b5875ad1e 100644 --- a/resources/assets/js/pages/manage/components/DialogUpload.vue +++ b/resources/assets/js/pages/manage/components/DialogUpload.vue @@ -35,6 +35,9 @@ export default { data() { return { uploadFormat: [ + 'text', 'md', 'markdown', + 'drawio', + 'mind', 'docx', 'wps', 'doc', 'xls', 'xlsx', 'ppt', 'pptx', 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'ico', 'raw', 'rar', 'zip', 'jar', '7-zip', 'tar', 'gzip', '7z', @@ -45,7 +48,7 @@ export default { 'txt', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', - 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', + 'ocamlmakefile', 'make', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'rdf', 'rss', 'wsdl', 'xslt', 'atom', 'mathml', 'mml', 'xul', 'xbl', 'xaml', 'yaml', 'yml', diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index ba7740e97..5cb13a3ef 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -422,6 +422,9 @@ export default { uploadShow: false, uploadList: [], uploadFormat: [ + 'text', 'md', 'markdown', + 'drawio', + 'mind', 'docx', 'wps', 'doc', 'xls', 'xlsx', 'ppt', 'pptx', 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'ico', 'raw', 'rar', 'zip', 'jar', '7-zip', 'tar', 'gzip', '7z', @@ -432,7 +435,7 @@ export default { 'txt', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', - 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', + 'ocamlmakefile', 'make', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'rdf', 'rss', 'wsdl', 'xslt', 'atom', 'mathml', 'mml', 'xul', 'xbl', 'xaml', 'yaml', 'yml',