diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index c5f56dfe..5b1f279c 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 064dbc5a..7f4b3e74 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 cbb76c77..da216395 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 21ce768c..45864ed8 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 6d52f090..2e64c3be 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 7512aad4..57e157bf 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 00000000..38c7a10a --- /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 8ff9c5a5..bb20410d 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 0186bf8f..64f67c78 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 d9b1be7a..b5875ad1 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 ba7740e9..5cb13a3e 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',