Merge branch 'main' into lyc-dev

This commit is contained in:
lyc 2024-07-23 13:46:32 +08:00
commit 4a5fb04362
6 changed files with 263 additions and 76 deletions

View File

@ -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"
},

View File

@ -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)

View File

@ -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) {

View File

@ -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)
})

View File

@ -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) => {

View File

@ -71,7 +71,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'
import useUserStore from '@/store/modules/user'
import { homeWorkConfig } from '@/utils/config'
@ -133,7 +133,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)
})
},
@ -165,22 +165,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++) {
@ -361,7 +381,7 @@ export default {
}
.top-item{
width: 230px;
flex-wrap: wrap;
.btn{
width: 102px;