zhuhao_dev #53
|
@ -30,6 +30,7 @@
|
|||
"jsencrypt": "^3.3.2",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue-cropper": "^1.0.3",
|
||||
"vue-router": "^4.4.0"
|
||||
},
|
||||
|
|
220
src/main/file.js
220
src/main/file.js
|
@ -1,16 +1,105 @@
|
|||
import CryptoJS from 'crypto-js'
|
||||
|
||||
import SparkMD5 from 'spark-md5'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
import { ElectronDownloadManager } from 'electron-dl-manager'
|
||||
import { dialog } from 'electron'
|
||||
import axios from 'axios'
|
||||
const uploadUrl = import.meta.env.VITE_APP_UPLOAD_API + '/smarttalk/file/upload'
|
||||
const asyncUploadUrl = import.meta.env.VITE_APP_UPLOAD_API + '/smarttalk/file/asyncUpload'
|
||||
const manager = new ElectronDownloadManager()
|
||||
export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||
const userDataPath = app.getPath('userData')
|
||||
const appRootFilePath = userDataPath + '\\selfFile\\'
|
||||
const appTempFilePath = userDataPath + '\\tempFile\\'
|
||||
let Spark = new SparkMD5.ArrayBuffer()
|
||||
|
||||
ipcMain.on('upload-file-change', (e, { id, fileNewName, cookie, fileType }) => {
|
||||
let filePath = appRootFilePath + fileNewName
|
||||
//执行更新,上传文件
|
||||
let formData = new FormData()
|
||||
formData.append('id', id)
|
||||
uploadFileByFS({
|
||||
url: asyncUploadUrl,
|
||||
path: filePath,
|
||||
name: fileNewName,
|
||||
cookie,
|
||||
fileType,
|
||||
formData,
|
||||
success: (response) => {
|
||||
e.reply('upload-file-change-success' + fileNewName, {
|
||||
data: response.data,
|
||||
md5: formData.md5
|
||||
})
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error uploading file:', err)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/*监听文件改变,如果有改变则返回触发*/
|
||||
ipcMain.on('listen-file-change', (e, { id, fileNewName, md5, cookie, fileType }) => {
|
||||
let filePath = appRootFilePath + fileNewName
|
||||
let uploadId = null
|
||||
let isOn = false
|
||||
setInterval(() => {
|
||||
getFileMD5(filePath).then((md5New) => {
|
||||
if (md5New !== md5) {
|
||||
md5 = md5New
|
||||
if (uploadId) {
|
||||
clearTimeout(uploadId)
|
||||
}
|
||||
if (isOn === false) {
|
||||
e.reply('listen-file-change-on' + fileNewName)
|
||||
isOn = true
|
||||
}
|
||||
//倒数十秒提交更改,十秒之内有继续修改则重置倒数
|
||||
uploadId = setTimeout(() => {
|
||||
//执行更新,上传文件
|
||||
let formData = new FormData()
|
||||
formData.append('id', id)
|
||||
uploadFileByFS({
|
||||
url: asyncUploadUrl,
|
||||
path: filePath,
|
||||
name: fileNewName,
|
||||
cookie,
|
||||
fileType,
|
||||
formData,
|
||||
success: (response) => {
|
||||
e.reply('listen-file-change-success' + fileNewName, {
|
||||
data: response.data,
|
||||
md5: formData.md5
|
||||
})
|
||||
clearTimeout(uploadId)
|
||||
isOn = false
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error uploading file:', err)
|
||||
}
|
||||
})
|
||||
}, 5000)
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
function getFileMD5(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(path, (err, dataFile) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return console.error(err)
|
||||
}
|
||||
Spark.append(dataFile)
|
||||
let md5 = Spark.end()
|
||||
resolve(md5)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* 判断是否有本地文件
|
||||
* */
|
||||
ipcMain.on('is-have-local-file', (e, fileNewName) => {
|
||||
let filePath = appRootFilePath + fileNewName
|
||||
fs.access(filePath, fs.constants.F_OK, (err) => {
|
||||
|
@ -21,10 +110,38 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
e.reply('is-have-local-file-reply' + fileNewName, true)
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
* 判断是需要同步本地文件
|
||||
* */
|
||||
ipcMain.on('is-async-local-file', (e, { fileNewName, lastModifyTime, md5 }) => {
|
||||
let filePath = appRootFilePath + fileNewName
|
||||
fs.access(filePath, fs.constants.F_OK, (err) => {
|
||||
if (err) {
|
||||
e.reply('is-async-local-file-reply' + fileNewName, { isAsync: true, type: 'down' })
|
||||
return
|
||||
}
|
||||
getFileMD5(filePath).then((localMd5) => {
|
||||
if (localMd5 === md5) {
|
||||
e.reply('is-async-local-file-reply' + fileNewName, { isAsync: false, type: '' })
|
||||
} else {
|
||||
const stats = fs.statSync(filePath)
|
||||
//如果线上时间大于线下时间,就需要从线上下载,否则则需要上传
|
||||
if (lastModifyTime > stats.mtime.getTime()) {
|
||||
e.reply('is-async-local-file-reply' + fileNewName, { isAsync: true, type: 'down' })
|
||||
} else if (lastModifyTime < stats.mtime.getTime()) {
|
||||
e.reply('is-async-local-file-reply' + fileNewName, { isAsync: true, type: 'upload' })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
//默认浏览器打开url
|
||||
ipcMain.on('open-url-browser', (e, url) => {
|
||||
shell.openPath(url)
|
||||
})
|
||||
|
||||
//使用默认应用打开本地文件
|
||||
ipcMain.on('open-path-app', (e, destination) => {
|
||||
let path = appRootFilePath + destination
|
||||
|
@ -40,65 +157,72 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
})
|
||||
})
|
||||
|
||||
//复制文件
|
||||
//导出文件
|
||||
ipcMain.on('export-file-default', (e, list) => {
|
||||
exportFile(list, (res) => {
|
||||
e.reply('export-file-default-reply', res)
|
||||
})
|
||||
})
|
||||
|
||||
function getFileMD5(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileReader = new FileReader()
|
||||
fileReader.onload = (e) => {
|
||||
const buffer = e.target.result
|
||||
let md5 = CryptoJS.MD5(buffer).toString()
|
||||
resolve(md5)
|
||||
function uploadFileByFS({ url, path, name, cookie, fileType, formData, success, error }) {
|
||||
fs.readFile(path, (err, data) => {
|
||||
if (err) {
|
||||
return console.error(err)
|
||||
}
|
||||
fileReader.readAsArrayBuffer(file)
|
||||
// 配置上传的请求
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data', // 或者其他适合上传文件的Content-Type
|
||||
Authorization: 'Bearer ' + cookie
|
||||
}
|
||||
}
|
||||
Spark.append(data)
|
||||
let md5 = Spark.end()
|
||||
// 使用axios上传文件
|
||||
let file = new File([data], name, {
|
||||
type: fileType
|
||||
})
|
||||
formData.append('file', file)
|
||||
formData.append('md5', md5)
|
||||
axios
|
||||
.post(url, formData, config)
|
||||
.then((response) => {
|
||||
success(response)
|
||||
})
|
||||
.catch((errorMsg) => {
|
||||
error(errorMsg)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*创建新的ppt文件*/
|
||||
ipcMain.on('creat-file-default', (e, { name, uploadData, cookie }) => {
|
||||
createFolder('tempFile').then(() => {
|
||||
let path = appTempFilePath + name
|
||||
fs.writeFileSync(path, '', 'utf-8')
|
||||
// 读取文件
|
||||
fs.readFile(path, (err, data) => {
|
||||
if (err) {
|
||||
return console.error(err)
|
||||
let fileType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
|
||||
let formData = new FormData()
|
||||
for (let key in uploadData) {
|
||||
if (Object.prototype.hasOwnProperty.call(uploadData, key)) {
|
||||
// 检查是否是对象自身的属性
|
||||
formData.append(key, uploadData[key])
|
||||
}
|
||||
// 配置上传的请求
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data', // 或者其他适合上传文件的Content-Type
|
||||
Authorization: 'Bearer ' + cookie
|
||||
}
|
||||
}
|
||||
formData.append('fileFlag', '教案')
|
||||
uploadFileByFS({
|
||||
url: uploadUrl,
|
||||
path,
|
||||
name,
|
||||
cookie,
|
||||
fileType,
|
||||
formData,
|
||||
success: (response) => {
|
||||
e.reply('creat-file-default-reply', response.data)
|
||||
console.log('File uploaded successfully:', response.data)
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error uploading file:', err)
|
||||
}
|
||||
let md5 = CryptoJS.MD5(data).toString()
|
||||
let formData = new FormData()
|
||||
// 使用axios上传文件
|
||||
let file = new File([data], name, {
|
||||
type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
|
||||
})
|
||||
formData.append('file', file)
|
||||
formData.append('md5',md5)
|
||||
|
||||
for (let key in uploadData) {
|
||||
if (uploadData.hasOwnProperty(key)) { // 检查是否是对象自身的属性
|
||||
formData.append(key,uploadData[key])
|
||||
}
|
||||
}
|
||||
formData.append("fileFlag","教案")
|
||||
axios
|
||||
.post(uploadUrl, formData, config)
|
||||
.then((response) => {
|
||||
e.reply('creat-file-default-reply', response.data)
|
||||
console.log('File uploaded successfully:', response.data)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error uploading file:', error)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -191,6 +315,7 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
})
|
||||
})
|
||||
|
||||
/*导出文件*/
|
||||
function exportFile(list, callback) {
|
||||
let win = BrowserWindow.getFocusedWindow()
|
||||
//通过扩展名识别文件类型
|
||||
|
@ -220,10 +345,12 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
})
|
||||
}
|
||||
|
||||
/*文件是否已经存在*/
|
||||
function isHaveFile(path) {
|
||||
return fs.existsSync(path)
|
||||
}
|
||||
|
||||
/*判断是否已经存在这个名字的文件,如果已经存在则递增导出*/
|
||||
function filterCopyFile(path, index = 0) {
|
||||
if (isHaveFile(path) === true) {
|
||||
index++
|
||||
|
@ -234,6 +361,7 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
}
|
||||
}
|
||||
|
||||
/*复制文件*/
|
||||
function copyRelFile(source, destination, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const readStream = fs.createReadStream(source)
|
||||
|
@ -256,6 +384,7 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
})
|
||||
}
|
||||
|
||||
/*复制文件*/
|
||||
function copyFile(source, destination, callback) {
|
||||
let path = appRootFilePath + destination
|
||||
createFolder('selfFile').then(() => {
|
||||
|
@ -276,6 +405,7 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
|||
})
|
||||
}
|
||||
|
||||
/*创建文件夹*/
|
||||
function createFolder(folderName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const folderPath = path.join(userDataPath, folderName)
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
<script>
|
||||
import uploaderState from '@/store/modules/uploader'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import CryptoJS from 'crypto-js'
|
||||
// import CryptoJS from 'crypto-js/md5'
|
||||
import SparkMD5 from 'spark-md5'
|
||||
import { DeleteFilled } from '@element-plus/icons-vue'
|
||||
const { ipcRenderer } = window.electron || {}
|
||||
export default {
|
||||
|
@ -147,13 +148,14 @@ export default {
|
|||
},
|
||||
getFileMD5(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileReader = new FileReader()
|
||||
fileReader.onload = (e) => {
|
||||
const buffer = e.target.result
|
||||
let md5 = CryptoJS.MD5(buffer).toString()
|
||||
let fileReader = new FileReader()
|
||||
let Spark = new SparkMD5.ArrayBuffer()
|
||||
fileReader.readAsArrayBuffer(file)
|
||||
fileReader.onload = function (e) {
|
||||
Spark.append(e.target.result)
|
||||
let md5 = Spark.end()
|
||||
resolve(md5)
|
||||
}
|
||||
fileReader.readAsArrayBuffer(file)
|
||||
})
|
||||
},
|
||||
removeUploadFile(uid) {
|
||||
|
|
|
@ -9,6 +9,15 @@ export const isHaveLocalFile = async (fileNewName) => {
|
|||
})
|
||||
}
|
||||
|
||||
export const isAsyncLocalFile = async (fileNewName, lastModifyTime, md5) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.send('is-async-local-file', { fileNewName, lastModifyTime, md5 })
|
||||
ipcRenderer.once('is-async-local-file-reply' + fileNewName, (e, { isAsync, type }) => {
|
||||
resolve({ isAsync, type })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const parseCataByNode = (node) => {
|
||||
if (node.parentNode) {
|
||||
let arr = parseCataByNode(node.parentNode)
|
||||
|
@ -31,9 +40,12 @@ export const exportFile = async (list) => {
|
|||
export const creatPPT = (name, uploadData) => {
|
||||
JSON.parse(JSON.stringify(uploadData))
|
||||
return new Promise((resolve, reject) => {
|
||||
let cookie = localStorage.getItem('Admin-Token');
|
||||
console.log(cookie)
|
||||
ipcRenderer.send('creat-file-default', { name, uploadData:JSON.parse(JSON.stringify(uploadData)), cookie })
|
||||
let cookie = localStorage.getItem('Admin-Token')
|
||||
ipcRenderer.send('creat-file-default', {
|
||||
name,
|
||||
uploadData: JSON.parse(JSON.stringify(uploadData)),
|
||||
cookie
|
||||
})
|
||||
ipcRenderer.once('creat-file-default-reply', (e, res) => {
|
||||
resolve(res)
|
||||
})
|
||||
|
|
|
@ -112,18 +112,23 @@ export default {
|
|||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: function() {
|
||||
default: function () {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: { 'on-move': null, 'on-delete': null },
|
||||
data() {
|
||||
return {
|
||||
listenList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editTalk(item) {
|
||||
ElMessageBox.prompt('请输入新的名称', '重命名', {
|
||||
|
@ -142,8 +147,7 @@ export default {
|
|||
}
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
downloadFile(item) {
|
||||
ipcRenderer.send('save-as', item.fileFullPath, item.fileShowName)
|
||||
|
@ -156,7 +160,6 @@ export default {
|
|||
})
|
||||
},
|
||||
closePopver(index) {
|
||||
console.log(this.$refs['popover_' + index])
|
||||
this.$refs['popover_' + index].hide()
|
||||
},
|
||||
moveSmarttalkFun(item) {
|
||||
|
@ -183,6 +186,25 @@ export default {
|
|||
isHaveLocalFile(item.fileNewName).then((res) => {
|
||||
if (res === true) {
|
||||
ipcRenderer.send('open-path-app', item.fileNewName)
|
||||
if (this.listenList.indexOf(item.fileNewName) === -1) {
|
||||
this.listenList.push(item.fileNewName)
|
||||
let cookie = localStorage.getItem('Admin-Token')
|
||||
ipcRenderer.send('listen-file-change', {
|
||||
id: item.id,
|
||||
fileNewName: item.fileNewName,
|
||||
md5: item.fileMd5,
|
||||
cookie,
|
||||
fileType: item.fileType
|
||||
})
|
||||
ipcRenderer.on('listen-file-change-on' + item.fileNewName, () => {
|
||||
item.async = 'on'
|
||||
})
|
||||
ipcRenderer.on('listen-file-change-success' + item.fileNewName, (e,{data,md5}) => {
|
||||
item.fileSize = data.fileSize
|
||||
item.md5 = md5
|
||||
item.async = true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item.async = 'on'
|
||||
ipcRenderer.once('download-file-default' + item.fileNewName, (e, isSuccess) => {
|
||||
|
|
|
@ -79,7 +79,7 @@ import FileListItem from '@/views/prepare/container/file-list-item.vue'
|
|||
import { getSmarttalkPage, moveSmarttalk } from '@/api/file'
|
||||
import { toTimeText } from '@/utils/date'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { isHaveLocalFile, parseCataByNode, creatPPT } from '@/utils/talkFile'
|
||||
import { isHaveLocalFile, parseCataByNode, creatPPT, isAsyncLocalFile } from '@/utils/talkFile'
|
||||
import FileOperBatch from '@/views/prepare/container/file-oper-batch.vue'
|
||||
const { ipcRenderer } = window.electron || {}
|
||||
export default {
|
||||
|
@ -134,7 +134,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
createFile() {
|
||||
creatPPT('新建ppt文档.pptx',this.uploadData).then((res) => {
|
||||
creatPPT(this.currentNode.label + '.pptx', this.uploadData).then((res) => {
|
||||
this.currentFileList.unshift(res.resData)
|
||||
})
|
||||
},
|
||||
|
@ -166,22 +166,42 @@ export default {
|
|||
this.asyncAllFileVisiable = true
|
||||
const test = (item) => {
|
||||
return new Promise((resolve) => {
|
||||
isHaveLocalFile(item.fileNewName).then((res) => {
|
||||
item.async = res
|
||||
if (res === false) {
|
||||
ipcRenderer.send('download-file-default', {
|
||||
url: item.fileFullPath,
|
||||
fileName: item.fileNewName
|
||||
})
|
||||
item.async = 'on'
|
||||
ipcRenderer.once('download-file-default' + item.fileNewName, (e, isSuccess) => {
|
||||
item.async = isSuccess
|
||||
//判断是否需要从线上拿新的文件
|
||||
isAsyncLocalFile(item.fileNewName, item.lastModifyTime, item.fileMd5).then(
|
||||
({ isAsync, type }) => {
|
||||
item.async = !isAsync
|
||||
if (isAsync === true) {
|
||||
item.async = 'on'
|
||||
if (type === 'down') {
|
||||
ipcRenderer.send('download-file-default', {
|
||||
url: item.fileFullPath,
|
||||
fileName: item.fileNewName
|
||||
})
|
||||
ipcRenderer.once('download-file-default' + item.fileNewName, (e, isSuccess) => {
|
||||
item.async = isSuccess
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
if (type === 'upload') {
|
||||
ipcRenderer.send('upload-file-change', {
|
||||
url: item.fileFullPath,
|
||||
fileName: item.fileNewName
|
||||
})
|
||||
ipcRenderer.once(
|
||||
'upload-file-change-success' + item.fileNewName,
|
||||
(e, { data, md5 }) => {
|
||||
item.fileSize = data.fileSize
|
||||
item.md5 = md5
|
||||
item.async = true
|
||||
resolve()
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
resolve()
|
||||
})
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
for (let i = 0; i < this.currentFileList.length; i++) {
|
||||
|
|
Loading…
Reference in New Issue