diff --git a/config/lib/multer.js b/config/lib/multer.js
index 68c61fa9..e7c5b333 100644
--- a/config/lib/multer.js
+++ b/config/lib/multer.js
@@ -78,9 +78,11 @@ module.exports.createUploadAttachFilename = function (req, file, cb) {
}
if (fs.existsSync(config.uploads.attach.file.dest + filename)) {
- var err = new Error();
- err.code = 'FILE_ALREADY_EXISTS';
- cb(err, null);
+ var ext = file.originalname.replace(/^.+\./, '');
+ var regex = new RegExp(ext, 'g');
+ filename = filename.replace(regex, Date.now() + '.' + ext);
+
+ cb(null, filename);
} else {
cb(null, filename);
}
diff --git a/modules/core/client/app/trans-string-en.js b/modules/core/client/app/trans-string-en.js
index e4817731..97fd743f 100644
--- a/modules/core/client/app/trans-string-en.js
+++ b/modules/core/client/app/trans-string-en.js
@@ -680,6 +680,15 @@
TODAY_NEW_COUNT_ALL: '(Today: {{topic}} topics, {{reply}} replies)',
TODAY_NEW_COUNT_TOPIC: '(Today: {{topic}} topics)',
TODAY_NEW_COUNT_REPLY: '(Today: {{reply}} replies)',
+ UPLOAD_ATTACH_SUCCESSFULLY: 'Upload attach file successfully',
+ UPLOAD_ATTACH_FAILED: 'Upload attach file failed',
+ ATTACH_UPLOAD_TOOLTIP: 'Attach files by dragging & dropping to here, The picture file will be displayed automatically, Others file can only be downloaded.',
+ ATTACH_UPLOADING: 'Uploading',
+ ATTACH_LIST_HEADER: 'Attach files list:',
+ ATTACH_FILE_SIZE: 'Size:',
+ ATTACH_DOWN_COUNT: 'Downloaded:',
+ ATTACHE_DOWNLOAD_SUCCESSFULLY: 'Attach file download successfully',
+ ATTACHE_DOWNLOAD_FAILED: 'Attach file download failed',
CATEGORY: {
AFFAIRS: 'Affairs',
diff --git a/modules/core/client/app/trans-string-zh.js b/modules/core/client/app/trans-string-zh.js
index edc6de7b..0465e7c1 100644
--- a/modules/core/client/app/trans-string-zh.js
+++ b/modules/core/client/app/trans-string-zh.js
@@ -680,6 +680,15 @@
TODAY_NEW_COUNT_ALL: '(今日: {{topic}} 话题, {{reply}} 回复)',
TODAY_NEW_COUNT_TOPIC: '(今日: {{topic}} 话题)',
TODAY_NEW_COUNT_REPLY: '(今日: {{reply}} 回复)',
+ UPLOAD_ATTACH_SUCCESSFULLY: '文件上传成功',
+ UPLOAD_ATTACH_FAILED: '文件上传失败',
+ ATTACH_UPLOAD_TOOLTIP: '上传附件请将文件拖到这里面, 图片文件将会被自动显示, 其它类文件只能被下载.',
+ ATTACH_UPLOADING: '正在上传',
+ ATTACH_LIST_HEADER: '附件清单:',
+ ATTACH_FILE_SIZE: '文件大小:',
+ ATTACH_DOWN_COUNT: '下载次数:',
+ ATTACHE_DOWNLOAD_SUCCESSFULLY: '附件文件下载成功',
+ ATTACHE_DOWNLOAD_FAILED: '附件文件下载失败',
CATEGORY: {
AFFAIRS: '站务区',
diff --git a/modules/core/client/directives/mt-markdown-editor.client.directive.js b/modules/core/client/directives/mt-markdown-editor.client.directive.js
index 8a84ccda..983ba68a 100644
--- a/modules/core/client/directives/mt-markdown-editor.client.directive.js
+++ b/modules/core/client/directives/mt-markdown-editor.client.directive.js
@@ -4,12 +4,13 @@
angular.module('core')
.directive('mtMarkdownEditor', mtMarkdownEditor);
- mtMarkdownEditor.$inject = ['localStorageService'];
+ mtMarkdownEditor.$inject = ['localStorageService', '$compile', 'NotifycationService', '$timeout'];
- function mtMarkdownEditor(localStorageService) {
+ function mtMarkdownEditor(localStorageService, $compile, NotifycationService, $timeout) {
var directive = {
restrict: 'A',
require: 'ngModel',
+ replace: true,
link: link
};
@@ -25,6 +26,83 @@
fullscreen: {enable: false},
onChange: function (e) {
ngModel.$setViewValue($('#' + attrs.mtMarkdownEditor)[0].value);
+ },
+ onShow: function (e) {
+ scope.uFile = undefined;
+ scope.uProgress = 0;
+ scope.uFiles = [];
+ scope.uImages = [];
+
+ var eleUploadTip = angular.element('
{{\'FORUMS.ATTACH_UPLOAD_TOOLTIP\' | translate}}
');
+ var eleUploadBegin = angular.element(' {{\'FORUMS.ATTACH_UPLOADING\' | translate}}: {{uFile.name}}
');
+ var eleUploadList = angular.element('');
+
+ //$compile(eleUploadTip)(scope);
+ //$compile(eleUploadBegin)(scope);
+ //$compile(eleUploadList)(scope);
+
+ $('.md-editor').append(eleUploadTip);
+ $('.md-editor').append(eleUploadBegin);
+ $('.md-editor').append(eleUploadList);
+
+ scope.removeAttach = function (idx) {
+ scope.uFiles.splice(idx, 1);
+ };
+
+ $('.md-editor').bind('dragenter', function (evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ });
+ $('.md-editor').bind('dragover', function (evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ });
+
+ $('.md-editor').bind('drop', function (evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+
+ if (attrs.uploadMethod) {
+ scope.uFile = evt.originalEvent.dataTransfer.files[0];
+ scope.uProgress = 0;
+
+ scope.$eval(attrs.uploadMethod, {
+ editor: e,
+ ufile: scope.uFile,
+ progressback: function (pr) {
+ scope.uProgress = pr;
+ },
+ callback: function (fn) {
+ var uFile = {
+ name: fn,
+ size: scope.uFile.size
+ };
+ var status = '';
+ var ext = uFile.name.replace(/^.+\./, '').toLowerCase();
+ if (ext === 'jpg' || ext === 'jpeg' || ext === 'bmp' || ext === 'gif' || ext === 'png') {
+ status = '\n\n';
+ e.replaceSelection(status);
+ ngModel.$setViewValue($('#' + attrs.mtMarkdownEditor)[0].value);
+ scope.uImages.push(uFile);
+ } else {
+ scope.uFiles.push(uFile);
+ }
+
+ scope.uFile = undefined;
+ scope.uProgress = 0;
+ NotifycationService.showSuccessNotify('FORUMS.UPLOAD_ATTACH_SUCCESSFULLY');
+ },
+ errback: function (err) {
+ scope.uFile = undefined;
+ scope.uProgress = 0;
+ NotifycationService.showErrorNotify(err.data, 'FORUMS.UPLOAD_ATTACH_FAILED');
+ }
+ });
+ }
+ return false;
+ });
+
+ $compile($('.md-editor').contents())(scope);
}
});
}
diff --git a/modules/forums/client/controllers/forums-post.client.controller.js b/modules/forums/client/controllers/forums-post.client.controller.js
index d14a0306..d895ce92 100644
--- a/modules/forums/client/controllers/forums-post.client.controller.js
+++ b/modules/forums/client/controllers/forums-post.client.controller.js
@@ -5,10 +5,10 @@
.module('forums')
.controller('ForumsPostController', ForumsPostController);
- ForumsPostController.$inject = ['$scope', '$state', '$translate', 'Authentication', 'MeanTorrentConfig', 'ForumsService', 'SideOverlay', '$filter', 'NotifycationService',
+ ForumsPostController.$inject = ['$scope', '$state', '$translate', 'Authentication', 'MeanTorrentConfig', 'ForumsService', 'Upload', '$timeout', 'NotifycationService',
'marked', 'ModalConfirmService', '$stateParams', 'TopicsService'];
- function ForumsPostController($scope, $state, $translate, Authentication, MeanTorrentConfig, ForumsService, SideOverlay, $filter, NotifycationService,
+ function ForumsPostController($scope, $state, $translate, Authentication, MeanTorrentConfig, ForumsService, Upload, $timeout, NotifycationService,
marked, ModalConfirmService, $stateParams, TopicsService) {
var vm = this;
vm.forumsConfig = MeanTorrentConfig.meanTorrentConfig.forumsConfig;
@@ -49,8 +49,25 @@
return false;
}
+ var uf = [];
+ angular.forEach($scope.uFiles, function (f) {
+ uf.push({
+ filename: f.name,
+ filesize: f.size
+ });
+ });
+
+ var uimg = [];
+ angular.forEach($scope.uImages, function (f) {
+ uimg.push({
+ filename: f.name
+ });
+ });
+
var post = new TopicsService(vm.postFields);
post.forum = vm.forum._id;
+ post._attach = uf;
+ post._uImage = uimg;
post.$save(function (response) {
successCallback(response);
@@ -60,6 +77,9 @@
function successCallback(res) {
vm.postFields = {};
+ $scope.uFiles = [];
+ $scope.uImages = [];
+
$scope.$broadcast('show-errors-reset', 'vm.postForm');
NotifycationService.showSuccessNotify('FORUMS.POST_TOPIC_SUCCESSFULLY');
$state.go('forums.topic', {forumId: vm.forum._id, topicId: res._id});
@@ -70,5 +90,31 @@
}
};
+ /**
+ * uploadAttach
+ * @param editor
+ * @param ufile
+ * @param callback
+ */
+ vm.uploadAttach = function (editor, ufile, progressback, callback, errback) {
+ Upload.upload({
+ url: '/api/attach/upload',
+ data: {
+ newAttachFile: ufile
+ }
+ }).then(function (res) {
+ if (callback) {
+ callback(res.data.filename);
+ }
+ }, function (res) {
+ if (errback && res.status > 0) {
+ errback(res);
+ }
+ }, function (evt) {
+ if (progressback) {
+ progressback(parseInt(100.0 * evt.loaded / evt.total, 10));
+ }
+ });
+ };
}
}());
diff --git a/modules/forums/client/controllers/forums-topic.client.controller.js b/modules/forums/client/controllers/forums-topic.client.controller.js
index bd47b5e0..5b1d66cf 100644
--- a/modules/forums/client/controllers/forums-topic.client.controller.js
+++ b/modules/forums/client/controllers/forums-topic.client.controller.js
@@ -6,12 +6,13 @@
.controller('ForumsTopicController', ForumsTopicController);
ForumsTopicController.$inject = ['$scope', '$state', '$translate', 'Authentication', 'MeanTorrentConfig', 'ForumsService', 'ScoreLevelService', '$timeout', 'NotifycationService',
- 'marked', 'ModalConfirmService', '$stateParams', 'TopicsService', 'localStorageService', '$compile', 'RepliesService', '$filter'];
+ 'marked', 'ModalConfirmService', '$stateParams', 'TopicsService', 'localStorageService', '$compile', 'RepliesService', '$filter', 'Upload', 'DownloadService'];
function ForumsTopicController($scope, $state, $translate, Authentication, MeanTorrentConfig, ForumsService, ScoreLevelService, $timeout, NotifycationService,
- marked, ModalConfirmService, $stateParams, TopicsService, localStorageService, $compile, RepliesService, $filter) {
+ marked, ModalConfirmService, $stateParams, TopicsService, localStorageService, $compile, RepliesService, $filter, Upload, DownloadService) {
var vm = this;
vm.forumsConfig = MeanTorrentConfig.meanTorrentConfig.forumsConfig;
+ vm.appConfig = MeanTorrentConfig.meanTorrentConfig.app;
vm.user = Authentication.user;
vm.forumPath = [];
vm.postReplyFields = {};
@@ -333,9 +334,26 @@
return false;
}
+ var uf = [];
+ angular.forEach($scope.uFiles, function (f) {
+ uf.push({
+ filename: f.name,
+ filesize: f.size
+ });
+ });
+
+ var uimg = [];
+ angular.forEach($scope.uImages, function (f) {
+ uimg.push({
+ filename: f.name
+ });
+ });
+
var reply = new RepliesService(vm.postReplyFields);
reply.forum = vm.forum._id;
reply.topic = vm.topic._id;
+ reply._attach = uf;
+ reply._uImage = uimg;
reply.$save(function (response) {
successCallback(response);
@@ -346,6 +364,9 @@
function successCallback(res) {
vm.postReplyFields = {};
vm.topic = res;
+ $scope.uFiles = [];
+ $scope.uImages = [];
+
$scope.$broadcast('show-errors-reset', 'vm.replyForm');
NotifycationService.showSuccessNotify('FORUMS.POST_REPLY_SUCCESSFULLY');
}
@@ -391,5 +412,53 @@
vm.topic = res;
});
};
+
+ /**
+ * uploadAttach
+ * @param editor
+ * @param ufile
+ * @param callback
+ */
+ vm.uploadAttach = function (editor, ufile, progressback, callback, errback) {
+ Upload.upload({
+ url: '/api/attach/upload',
+ data: {
+ newAttachFile: ufile
+ }
+ }).then(function (res) {
+ if (callback) {
+ callback(res.data.filename);
+ }
+ }, function (res) {
+ if (errback && res.status > 0) {
+ errback(res);
+ }
+ }, function (evt) {
+ if (progressback) {
+ progressback(parseInt(100.0 * evt.loaded / evt.total, 10));
+ }
+ });
+ };
+
+ /**
+ * downloadAttach
+ * @param t
+ * @param r
+ * @param af
+ */
+ vm.downloadAttach = function (t, r, af) {
+ var url = '/api/attach/' + vm.topic._id.toString();
+ url += r ? '/' + r._id.toString() : '';
+ url += '?attachId=' + af._id.toString();
+
+ DownloadService.downloadFile(url, null, function (status) {
+ if (status === 200) {
+ NotifycationService.showSuccessNotify('FORUMS.ATTACHE_DOWNLOAD_SUCCESSFULLY');
+ }
+ }, function (err) {
+ console.log(err);
+ NotifycationService.showErrorNotify(err.data.message, 'FORUMS.ATTACHE_DOWNLOAD_FAILED');
+ });
+ };
}
}());
diff --git a/modules/forums/client/less/forum.less b/modules/forums/client/less/forum.less
index c8250d1f..34fbce28 100644
--- a/modules/forums/client/less/forum.less
+++ b/modules/forums/client/less/forum.less
@@ -424,6 +424,29 @@
max-width: 100%;
height: auto;
}
+ .attach-list {
+ border: solid 1px #ddd;
+ margin-top: 20px;
+ .attach-header {
+ height: 40px;
+ background-color: #f5f5f5;
+ border-bottom: 1px dashed #ddd;
+ padding: 8px 15px;
+ font-weight: 500;
+ }
+ ol {
+ margin-bottom: 0;
+ li {
+ font-size: 12px;
+ margin: 10px;
+ span {
+ &:not(:first-child) {
+ color: #999;
+ }
+ }
+ }
+ }
+ }
}
}
.reply-avatar {
@@ -459,15 +482,74 @@
}
.md-editor {
+ background-color: #f5f5f5;
textarea {
border-bottom: none;
background-color: #fff;
- min-height: 250px;
+ min-height: 300px;
+ max-height: 800px;
padding: 5px;
}
.md-preview {
padding: 5px;
border-bottom: none;
+ img {
+ max-width: 100%;
+ height: auto;
+ }
+ }
+ .attach-info {
+ color: #666;
+ height: 40px;
+ background-color: #f5f5f5;
+ border-top: 1px dashed #ddd;
+ .attach-upload-tooltip {
+ margin: 10px;
+ }
+ }
+ .attach-list {
+ color: #666;
+ min-height: 40px;
+ background-color: #f5f5f5;
+ border-top: 1px dashed #ddd;
+ ol {
+ margin-bottom: 0;
+ li {
+ font-size: 12px;
+ color: @brand-primary;
+ margin: 10px;
+ i {
+ cursor: pointer;
+ &:hover {
+ color: @mt-base-color;
+ }
+ }
+ }
+ }
+ }
+ .upload-info {
+ position: relative;
+ color: #666;
+ height: 40px;
+ background-color: #f5f5f5;
+ border-top: 1px dashed #ddd;
+ i {
+ color: @mt-base-color;
+ float: left;
+ margin: 11px 5px;
+ }
+ .attach-upload-progress {
+ height: 30px;
+ margin: 5px 30px;
+ max-width: ~"calc(100% - 40px)";
+ background-color: @brand-info;
+ }
+ .attach-upload-filename {
+ position: absolute;
+ top: 10px;
+ margin-left: 35px;
+ background-color: transparent;
+ }
}
}
diff --git a/modules/forums/client/views/post.client.view.html b/modules/forums/client/views/post.client.view.html
index a32395e5..80af48dd 100644
--- a/modules/forums/client/views/post.client.view.html
+++ b/modules/forums/client/views/post.client.view.html
@@ -52,7 +52,8 @@
+
+
+
+ -
+ {{af.filename}} (
+ {{'FORUMS.ATTACH_FILE_SIZE' | translate}} {{af.filesize | bytes}}
+ {{'FORUMS.ATTACH_DOWN_COUNT' | translate}} {{af.downCount}} )
+
+
+
[ {{vm.topic.updatedBy.displayName}} {{ 'COMMENT_EDITED_INFO' | translate}} {{vm.topic.updatedAt | date:'yyyy-MM-dd HH:mm:ss'}} ]
@@ -176,6 +187,16 @@
+
+
+
+ -
+ {{af.filename}} (
+ {{'FORUMS.ATTACH_FILE_SIZE' | translate}} {{af.filesize | bytes}}
+ {{'FORUMS.ATTACH_DOWN_COUNT' | translate}} {{af.downCount}} )
+
+
+
[ {{rep.updatedBy.displayName}} {{ 'COMMENT_EDITED_INFO' | translate}} {{rep.updatedAt | date:'yyyy-MM-dd HH:mm:ss'}} ]
@@ -201,13 +222,14 @@
-