diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 5bc234098..a77320c74 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -804,6 +804,46 @@ class FileController extends AbstractController return Base::retSuccess('success', $data); } + /** + * @api {get} api/file/content/restore 13. 恢复文件历史 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup file + * @apiName content__restore + * + * @apiParam {Number} id 文件ID + * @apiParam {Number} history_id 历史数据ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function content__restore() + { + $user = User::auth(); + // + $id = intval(Request::input('id')); + $history_id = intval(Request::input('history_id')); + // + $file = File::permissionFind($id); + // + $history = FileContent::whereFid($file->id)->whereId($history_id)->first(); + if (empty($history)) { + return Base::retError('历史数据不存在或已被删除'); + } + // + $content = $history->replicate(); + $content->userid = $user->userid; + $content->save(); + // + $file->size = $content->size; + $file->save(); + $file->pushMsg('content'); + // + return Base::retSuccess('还原成功'); + } + /** * @api {get} api/file/share 13. 获取共享信息 * diff --git a/resources/assets/js/components/OnlyOffice.vue b/resources/assets/js/components/OnlyOffice.vue index 245cbf6d1..7d0c1bd54 100644 --- a/resources/assets/js/components/OnlyOffice.vue +++ b/resources/assets/js/components/OnlyOffice.vue @@ -73,6 +73,10 @@ export default { type: String, default: '' }, + historyId: { + type: Number, + default: 0 + }, value: { type: [Object, Array], default: function () { @@ -178,14 +182,20 @@ export default { break; } // - let fileKey = this.code || this.value.id; + let codeId = this.code || this.value.id; let fileName = $A.strExists(this.fileName, '.') ? this.fileName : (this.fileName + '.' + this.fileType); + let fileKey = `${this.fileType}-${fileKey}-${keyAppend}`; + let fileUrl = `http://nginx/api/file/content/?id=${codeId}&token=${this.userToken}`; + if (this.historyId > 0) { + fileKey += `-${this.historyId}` + fileUrl += `&history_id=${this.historyId}` + } const config = { "document": { "fileType": this.fileType, - "key": `${this.fileType}-${fileKey}-${keyAppend}`, "title": fileName, - "url": `http://nginx/api/file/content/?id=${fileKey}&token=${this.userToken}`, + "key": fileKey, + "url": fileUrl, }, "editorConfig": { "mode": "edit", @@ -199,18 +209,21 @@ export default { "forcesave": true, "help": false, }, - "callbackUrl": `http://nginx/api/file/content/office?id=${fileKey}&token=${this.userToken}`, - } + "callbackUrl": `http://nginx/api/file/content/office?id=${codeId}&token=${this.userToken}`, + }, + "events": { + "onDocumentReady": this.onDocumentReady, + }, }; if (/\/hideenOfficeTitle\//.test(window.navigator.userAgent)) { config.document.title = " "; } - if ($A.leftExists(fileKey, "msgFile_")) { - config.document.url = `http://nginx/api/dialog/msg/download/?msg_id=${$A.leftDelete(fileKey, "msgFile_")}&token=${this.userToken}`; - } else if ($A.leftExists(fileKey, "taskFile_")) { - config.document.url = `http://nginx/api/project/task/filedown/?file_id=${$A.leftDelete(fileKey, "taskFile_")}&token=${this.userToken}`; + if ($A.leftExists(codeId, "msgFile_")) { + config.document.url = `http://nginx/api/dialog/msg/download/?msg_id=${$A.leftDelete(codeId, "msgFile_")}&token=${this.userToken}`; + } else if ($A.leftExists(codeId, "taskFile_")) { + config.document.url = `http://nginx/api/project/task/filedown/?file_id=${$A.leftDelete(codeId, "taskFile_")}&token=${this.userToken}`; } - if (this.readOnly) { + if (this.readOnly || this.historyId > 0) { config.editorConfig.mode = "view"; config.editorConfig.callbackUrl = null; if (!config.editorConfig.user.id) { @@ -226,6 +239,10 @@ export default { this.$nextTick(() => { this.docEditor = new DocsAPI.DocEditor(this.id, config); }) + }, + + onDocumentReady() { + this.$emit("on-document-ready", this.docEditor) } } } diff --git a/resources/assets/js/components/TableAction.vue b/resources/assets/js/components/TableAction.vue index ed846c26a..dc210ecce 100644 --- a/resources/assets/js/components/TableAction.vue +++ b/resources/assets/js/components/TableAction.vue @@ -9,6 +9,7 @@ + {{item.label}} @@ -34,14 +40,22 @@
{{d.title}}
+ {{item.label}} { - return {}; - } - }, - autoWidth: { - type: Boolean, - default: true - }, - minWidth: { - type: Number, - default: 80 - }, - align: { - type: String, - default: '' - }, - menu: { - type: Array, - default: () => { - return []; - } - }, - }, - data() { - return { - width: 0, - height: 0, +export default { + name: 'TableAction', + props: { + column: { + type: Object, + default: () => { + return {}; } }, - mounted() { - this.onUpdate(); + autoWidth: { + type: Boolean, + default: true }, - activated() { - this.onUpdate(); + minWidth: { + type: Number, + default: 80 }, - beforeUpdate() { - this.onUpdate(); + align: { + type: String, + default: '' }, - computed: { - tdStyle() { - const style = {}; - const {align} = this; - switch (align.toLowerCase()) { - case 'left': - style.justifyContent = 'flex-start'; - break; - case 'center': - style.justifyContent = 'center'; - break; - case 'right': - style.justifyContent = 'flex-end'; - break; - } - return style; + menu: { + type: Array, + default: () => { + return []; } }, - methods: { - isAliIcon(icon) { - return $A.leftExists(icon, '&#') - }, - handleIn() { - if (this.$refs.action.offsetWidth != this.width) { - this.onUpdate(); + }, + data() { + return { + width: 0, + height: 0, + } + }, + mounted() { + this.onUpdate(); + }, + activated() { + this.onUpdate(); + }, + beforeUpdate() { + this.onUpdate(); + }, + computed: { + tdStyle() { + const style = {}; + const {align} = this; + switch (align.toLowerCase()) { + case 'left': + style.justifyContent = 'flex-start'; + break; + case 'center': + style.justifyContent = 'center'; + break; + case 'right': + style.justifyContent = 'flex-end'; + break; + } + return style; + } + }, + methods: { + isAliIcon(icon) { + return $A.leftExists(icon, '&#') + }, + handleIn() { + if (this.$refs.action.offsetWidth != this.width) { + this.onUpdate(); + } + }, + onUpdate() { + this.onResize({ + width: this.$refs.action.offsetWidth, + height: this.$refs.action.offsetHeight, + }) + }, + onResize({ width, height }) { + if (!this.autoWidth) { + return; + } + $A(".ivu-table-column-" + this.column.__id).each((index, el) => { + let action = $A(el).find(".td-action-container") + if (action.length > 0) { + width = Math.max(width, action[0].offsetWidth) + height = Math.max(height, action[0].offsetHeight) } - }, - onUpdate() { - this.onResize({ - width: this.$refs.action.offsetWidth, - height: this.$refs.action.offsetHeight, + }); + this.width = width; + this.height = height; + let newWidth = Math.max(this.minWidth, this.width + 26); + if (this.column.minWidth) { + newWidth = Math.max(this.column.minWidth, newWidth); + } + if (this.column.maxWidth) { + newWidth = Math.min(this.column.maxWidth, newWidth); + } + if (newWidth != this.column.width) { + this.$nextTick(() => { + this.$set(this.column, 'width', newWidth); }) - }, - onResize({ width, height }) { - if (!this.autoWidth) { - return; - } - $A(".ivu-table-column-" + this.column.__id).each((index, el) => { - let action = $A(el).find(".td-action-container") - if (action.length > 0) { - width = Math.max(width, action[0].offsetWidth) - height = Math.max(height, action[0].offsetHeight) - } - }); - this.width = width; - this.height = height; - let newWidth = Math.max(this.minWidth, this.width + 26); - if (this.column.minWidth) { - newWidth = Math.max(this.column.minWidth, newWidth); - } - if (this.column.maxWidth) { - newWidth = Math.min(this.column.maxWidth, newWidth); - } - if (newWidth != this.column.width) { - this.$nextTick(() => { - this.$set(this.column, 'width', newWidth); - }) - } - }, - onClick(action) { - this.$emit("action", action) } + }, + onClick(action) { + this.$emit("action", action) } } +} diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js index 2ba956376..1f6f466ed 100755 --- a/resources/assets/js/functions/web.js +++ b/resources/assets/js/functions/web.js @@ -388,6 +388,19 @@ text = text.replace(/]*?>/g, `[${$A.L('表情')}]`) text = text.replace(/]*?>/g, `[${$A.L('图片')}]`) return text.replace(/<[^>]+>/g,"") + }, + + /** + * 获取文件标题 + * @param file + * @returns {*} + */ + getFileName(file) { + let {name, ext} = file; + if (ext != '') { + name += "." + ext; + } + return name; } }); diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index a9c46d6a6..7ea25d590 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -302,8 +302,8 @@ export default { } if (this.$Electron) { this.$Electron.sendMessage('windowRouter', { - name: 'file-msg-' + this.msgData.id, - path: "/single/file/msg/" + this.msgData.id, + name: `file-msg-${this.msgData.id}`, + path: `/single/file/msg/${this.msgData.id}`, userAgent: "/hideenOfficeTitle/", force: false, config: { diff --git a/resources/assets/js/pages/manage/components/FileContent.vue b/resources/assets/js/pages/manage/components/FileContent.vue index dfb2ad00d..db98c3e43 100644 --- a/resources/assets/js/pages/manage/components/FileContent.vue +++ b/resources/assets/js/pages/manage/components/FileContent.vue @@ -2,7 +2,18 @@
+
@@ -151,6 +162,7 @@ export default { linkLoad: 0, historyShow: false, + officeReady: false, } }, @@ -190,6 +202,7 @@ export default { } else { this.linkShow = false; this.historyShow = false; + this.officeReady = false; } }, immediate: true, @@ -275,7 +288,7 @@ export default { } }, - getContent(history_id = 0) { + getContent() { if (this.fileId === 0) { this.contentDetail = {}; this.updateBak(); @@ -292,13 +305,10 @@ export default { url: 'file/content', data: { id: this.fileId, - history_id: history_id }, }).then(({data}) => { this.contentDetail = data.content; - if (!history_id) { - this.updateBak(); - } + this.updateBak(); }).catch(({msg}) => { $A.modalError(msg); }).finally(_ => { @@ -355,23 +365,38 @@ export default { this.loadSave--; }) break; + + case "officeReady": + this.officeReady = true + break; } }, - handleHistory(item) { + onRestoreHistory(item) { this.historyShow = false; - if (!this.equalContent) { - $A.modalConfirm({ - content: '修改的内容尚未保存,确定要读取历史记录吗?', - cancelText: '取消', - okText: '确定', - onOk: () => { - this.getContent(item.id) - } - }); - } else { - this.getContent(item.id) - } + $A.modalConfirm({ + content: `你确定文件还原至【${item.created_at}】吗?`, + cancelText: '取消', + okText: '确定', + loading: true, + onOk: () => { + this.$store.dispatch("call", { + url: 'file/content/restore', + data: { + id: this.fileId, + history_id: item.id, + } + }).then(({msg}) => { + $A.messageSuccess(msg); + this.contentDetail = null; + this.getContent(); + }).catch(({msg}) => { + $A.modalError(msg, 301); + }).finally(_ => { + this.$Modal.remove(); + }); + } + }); }, linkGet(refresh) { @@ -443,14 +468,6 @@ export default { }); }) }, - - formatName(file) { - let {name, ext} = file; - if (ext != '') { - name += "." + ext; - } - return name; - }, } } diff --git a/resources/assets/js/pages/manage/components/FileHistory.vue b/resources/assets/js/pages/manage/components/FileHistory.vue index 9594026b1..2fdc59155 100644 --- a/resources/assets/js/pages/manage/components/FileHistory.vue +++ b/resources/assets/js/pages/manage/components/FileHistory.vue @@ -1,12 +1,13 @@