diff --git a/CHANGELOG.md b/CHANGELOG.md index 65a1300..a58026a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ ## 变更记录 +-2024-09-03 +1. 修复文件重命名错误的bug +2. 修复拖拽上传中断的bug +3. 新增可手动关闭广告 - 2024-08-27 1. 优化初始化系统,初始化系统时只请求读写一次 2. 去除浏览器存储 @@ -28,6 +32,8 @@ bug梳理: 5. web 的甘特图保存不了 6. 场景适用性:系统默认连接gitee远程软件安装包,缺少默认读取本地安装包路径的json配置文件的打包设置选项(比如在安装时自动读取安装U盘当前目录中/或已直接打包进安装包中的mysql/nginx/php/python本地离线安装包、以及企业自用OA WebApp的本地离线安装包,无需联网,直接同步离线安装) 7. 功能完整性:安装的服务型应用(如mysql/nginx/php/python)没有跟随软件环境启动后自动启动的设置选项,依赖于服务型应用的AI Web UI、php /python应用没有创建桌面快捷方式/菜单快捷方式的入口(即:AI Web UI、php /python应用无法安装和自动开箱即用)。 +8. excel读取原始文件兼容性问题 +9. word读取原始文件兼容性 ### 后续开放: 1. 优化内网聊天 diff --git a/frontend/components.d.ts b/frontend/components.d.ts index afebaeb..39b4653 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -44,9 +44,12 @@ declare module 'vue' { ElButton: typeof import('element-plus/es')['ElButton'] ElCarousel: typeof import('element-plus/es')['ElCarousel'] ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] + ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCol: typeof import('element-plus/es')['ElCol'] + ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] + ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDialog: typeof import('element-plus/es')['ElDialog'] - ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] @@ -57,12 +60,16 @@ declare module 'vue' { ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElProgress: typeof import('element-plus/es')['ElProgress'] + ElRadio: typeof import('element-plus/es')['ElRadio'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElSpace: typeof import('element-plus/es')['ElSpace'] + ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTimePicker: typeof import('element-plus/es')['ElTimePicker'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] Error: typeof import('./src/components/taskbar/Error.vue')['default'] FileIcon: typeof import('./src/components/builtin/FileIcon.vue')['default'] @@ -79,8 +86,6 @@ declare module 'vue' { InstallMember: typeof import('./src/components/install/InstallMember.vue')['default'] InstallPerson: typeof import('./src/components/install/InstallPerson.vue')['default'] LockDesktop: typeof import('./src/components/desktop/LockDesktop.vue')['default'] - LoginDeskop: typeof import('./src/components/desktop/LoginDeskop.vue')['default'] - LoginDesktop: typeof import('./src/components/desktop/LoginDesktop.vue')['default'] Magnet: typeof import('./src/components/taskbar/Magnet.vue')['default'] MarkDown: typeof import('./src/components/builtin/MarkDown.vue')['default'] MenuBar: typeof import('./src/components/window/MenuBar.vue')['default'] @@ -99,6 +104,7 @@ declare module 'vue' { OsImage: typeof import('./src/components/builtin/OsImage.vue')['default'] PdfViewer: typeof import('./src/components/builtin/PdfViewer.vue')['default'] PictureStore: typeof import('./src/components/builtin/PictureStore.vue')['default'] + PlanTasks: typeof import('./src/components/oa/PlanTasks.vue')['default'] ProcessManager: typeof import('./src/components/setting/ProcessManager.vue')['default'] QuickLink: typeof import('./src/components/computer/QuickLink.vue')['default'] RectChosen: typeof import('./src/components/builtin/RectChosen.vue')['default'] @@ -114,6 +120,7 @@ declare module 'vue' { SetSystem: typeof import('./src/components/setting/SetSystem.vue')['default'] Setting: typeof import('./src/components/setting/Setting.vue')['default'] SetUpdate: typeof import('./src/components/setting/SetUpdate.vue')['default'] + ShowNews: typeof import('./src/components/taskbar/ShowNews.vue')['default'] StartMenu: typeof import('./src/components/taskbar/StartMenu.vue')['default'] StartOption: typeof import('./src/components/taskbar/StartOption.vue')['default'] StateIcon: typeof import('./src/components/taskbar/StateIcon.vue')['default'] diff --git a/frontend/src/components/builtin/EditFileName.vue b/frontend/src/components/builtin/EditFileName.vue index 0ff203f..07abd7e 100644 --- a/frontend/src/components/builtin/EditFileName.vue +++ b/frontend/src/components/builtin/EditFileName.vue @@ -1,17 +1,12 @@ diff --git a/frontend/src/components/desktop/Notice.vue b/frontend/src/components/desktop/Notice.vue index ccb28d4..8819461 100644 --- a/frontend/src/components/desktop/Notice.vue +++ b/frontend/src/components/desktop/Notice.vue @@ -12,13 +12,15 @@ + diff --git a/frontend/src/components/oa/PlanTasks.vue b/frontend/src/components/oa/PlanTasks.vue new file mode 100644 index 0000000..9ee6b52 --- /dev/null +++ b/frontend/src/components/oa/PlanTasks.vue @@ -0,0 +1,78 @@ + + + + \ No newline at end of file diff --git a/frontend/src/components/setting/SetAccount.vue b/frontend/src/components/setting/SetAccount.vue index f045326..6e5ed07 100644 --- a/frontend/src/components/setting/SetAccount.vue +++ b/frontend/src/components/setting/SetAccount.vue @@ -2,12 +2,8 @@
\ No newline at end of file diff --git a/frontend/src/components/taskbar/ShowNews.vue b/frontend/src/components/taskbar/ShowNews.vue new file mode 100644 index 0000000..b0fdf94 --- /dev/null +++ b/frontend/src/components/taskbar/ShowNews.vue @@ -0,0 +1,45 @@ + + + \ No newline at end of file diff --git a/frontend/src/hook/useContextMenu.ts b/frontend/src/hook/useContextMenu.ts index 9c2957a..ec22b8f 100644 --- a/frontend/src/hook/useContextMenu.ts +++ b/frontend/src/hook/useContextMenu.ts @@ -44,9 +44,9 @@ function useContextMenu() { callback?.(); }); } - + //console.log(path) - let menuArr = [ + let menuArr: any = [ { label: t('refresh'), click: () => { @@ -100,29 +100,7 @@ function useContextMenu() { }, ], }, - - // { - // label: '新建报告', - // submenu: [ - // { - // label: '日报(Day)', - // click : () => clickFunc('day', '日报'), - // }, - // { - // label: '周报(Week)', - // click : () => clickFunc('week', '周报'), - // }, - // { - // label: '季报(Quarter)', - // click : () => clickFunc('quarter', '季报'), - // }, - // { - // label: '年报(Year)', - // click: () => clickFunc('year', '年报'), - // }, - // ], - // }, { label: t('paste'), click: () => { @@ -139,9 +117,26 @@ function useContextMenu() { }); }, }, - ...(system._rootState.options.contextMenus || []), ]; - + const userInfo: any = system.getConfig('userInfo'); + if (userInfo.user_auths && userInfo.user_auths.length > 0 && userInfo.user_auths != "") { + menuArr.push( + { + label: '安排任务', + click: () => { + const win = new BrowserWindow({ + title: '安排任务', + content: "PlanTasks", + width: 600, + height: 600, + center: true, + }); + win.show(); + } + } + ) + } + menuArr = [...menuArr, ...(system._rootState.options.contextMenus || [])] const menu = Menu.buildFromTemplate( uniqBy( menuArr, @@ -162,7 +157,7 @@ function useContextMenu() { } newFilePath = fspath.join(path, `${title}(${i})${ext}`); } - + const content = ''; return await system.fs.writeFile(newFilePath, content); } diff --git a/frontend/src/hook/useFileDrag.ts b/frontend/src/hook/useFileDrag.ts index 7e7ace0..15b5e3b 100644 --- a/frontend/src/hook/useFileDrag.ts +++ b/frontend/src/hook/useFileDrag.ts @@ -40,7 +40,7 @@ export function useFileDrag(system: System) { async function writeFileToInner( path: string, name?: string, - content?: string, + content?: any, process?: (path: string) => void ) { console.log(content) @@ -48,15 +48,6 @@ export function useFileDrag(system: System) { Dialog.showMessageBox({message:"上传失败", type:'error'}) return; } - // let fileNameArr = name?.split(".") - // let ext = fileNameArr?.pop() - // let title = fileNameArr?.join(".") - // let save = { - // title, - // //blob: content?.replace(/data:.*?;base64,/, '') || '' - // base64 : content || '', - // ext - // } return await system?.fs .writeFile(FsPath.join(path, name || 'unkown'), content) .then(() => { @@ -65,7 +56,8 @@ export function useFileDrag(system: System) { } // 外部文件拖到文件夹放下时 async function outerFileDrop(path: string, list: FileList | undefined, process: (path: string) => void) { - const len = list?.length || 0; + if (!list) return; + const len = list.length const { setProgress } = Dialog.showProcessDialog({ message: '正在写入到文件夹中', }); @@ -74,35 +66,32 @@ export function useFileDrag(system: System) { await new Promise((resolve) => { const item = list?.[i]; console.log(item) + if (!item) return; // let oFile = null; const reader = new FileReader(); //读取成功 reader.onload = function () { - console.log(reader); + // console.log(reader); + //console.log(reader.result) }; reader.onloadstart = function () { - console.log('读取开始'); + //console.log('读取开始'); }; reader.onloadend = async function () { - //console.log(reader.result) - await writeFileToInner(path, item?.name, reader.result as string, process); + await writeFileToInner(path, item.name, reader.result as any, process); resolve(true); }; reader.onabort = function () { - console.log('中断'); + //console.log('中断'); }; reader.onerror = function () { - console.log('读取失败'); + //console.log('读取失败'); }; reader.onprogress = function (ev) { const scale = ev.loaded / ev.total; - if (scale >= 0.5) { - reader.abort(); - } + setProgress(scale); }; - //reader.readAsDataURL(new Blob([item as BlobPart])); - //reader.readAsDataURL(item!); - reader.readAsArrayBuffer(item!); + reader.readAsArrayBuffer(item); }); } setProgress(101); diff --git a/frontend/src/stores/notify.ts b/frontend/src/stores/notify.ts index a1643f5..6360612 100644 --- a/frontend/src/stores/notify.ts +++ b/frontend/src/stores/notify.ts @@ -1,40 +1,97 @@ import { defineStore } from "pinia"; import { ref } from "vue"; -import { getSystemConfig,fetchGet } from "@/system/config"; +import { getSystemConfig, fetchGet } from "@/system/config"; +import { useUpgradeStore } from "./upgrade"; export const useNotifyStore = defineStore('notifyStore', () => { const config = getSystemConfig(); - const notifyList:any = ref([]); + const upgradeStore = useUpgradeStore() + const notifyList: any = ref([]); + const readList: any = ref([]) + const showNews = ref(false) + const newsDetail = ref({}) const page = ref({ current: 1, size: 10, total: 0, pages: 0, }) - async function getList(){ - if(config.userType == 'person'){ + async function getList() { + if (config.userType == 'person') { return - } - const complition = await fetchGet(config.userInfo.url + '/news/list?page=' + page.value.current + '&limit='+ page.value.size) - if(!complition.ok){ - return; - } - const data = await complition.json(); - if(data.success){ - page.value.total = data.data.total; - notifyList.value = data.data.list; - page.value.pages = Math.ceil(page.value.total / page.value.size) - } - + } + const complition = await fetchGet(config.userInfo.url + '/news/list?page=' + page.value.current + '&limit=' + page.value.size) + if (!complition.ok) { + return; + } + const data = await complition.json(); + if (data.success) { + page.value.total = data.data.total; + notifyList.value = data.data.list; + page.value.pages = Math.ceil(page.value.total / page.value.size) + checkNotify() + } + + } + const checkNotify = ()=> { + const list = notifyList.value.filter((item: any) => { + return readList.value.indexOf(item.id) < 0 + }) + if(list.length < 1)return; + const centerList = list.filter((item: any) => { + return item.position == 'center' + }) + const bottomList = list.filter((item: any) => { + return item.position == 'bottom' + }) + if(centerList.length > 0){ + upgradeStore.hasAd = true + upgradeStore.adList = [...centerList, ...upgradeStore.adList] + } + if(bottomList.length > 0){ + upgradeStore.hasNotice = true + upgradeStore.noticeList = [...bottomList, ...upgradeStore.noticeList] + } + + } + const addRead = (id: number) => { + if (readList.value.indexOf(id) < 0) { + readList.value.push(id) + } } const pageClick = async (pageNum: any) => { //console.log(pageNum) page.value.current = pageNum await getList() } + const viewContent = (item :any) =>{ + const timestamp = item.add_time * 1000; // 将 10 位时间戳转换为 13 位 + const date = new Date(timestamp); + item.showtime = date.toLocaleString(); + newsDetail.value = item + addRead(item.id) + showNews.value = true + } return { notifyList, + showNews, + newsDetail, getList, + addRead, page, - pageClick + pageClick, + readList, + viewContent + } +}, { + persist: { + enabled: true, + strategies: [ + { + storage: localStorage, + paths: [ + "readList", + ] + }, // name 字段用localstorage存储 + ], } }) \ No newline at end of file diff --git a/frontend/src/stores/upgrade.ts b/frontend/src/stores/upgrade.ts index 280d87d..59d8811 100644 --- a/frontend/src/stores/upgrade.ts +++ b/frontend/src/stores/upgrade.ts @@ -36,6 +36,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => { } function systemMessage(){ const config = getSystemConfig(); + const source = new EventSource(`${config.apiUrl}/system/message`); source.onmessage = function(event) { @@ -59,6 +60,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => { async function checkUpdate(res:any) { //console.log(res) const config = getSystemConfig(); + if(!config.account.ad)return; currentVersion.value = config.version; let bottomList:any = [] let centerList:any = [] @@ -68,13 +70,13 @@ export const useUpgradeStore = defineStore('upgradeStore', () => { } if(bottomList && bottomList.length > 0){ hasNotice.value = true - noticeList.value = changeUrl(bottomList) + noticeList.value = [...noticeList.value, ...changeUrl(bottomList)] } //console.log(noticeList) //console.log(centerList) if(centerList && centerList.length > 0){ hasAd.value = true - adList.value = changeUrl(centerList) + adList.value = [...adList.value, ...changeUrl(centerList)] } //console.log(adList.value) diff --git a/frontend/src/system/config.ts b/frontend/src/system/config.ts index 6cc66f2..eda6bc7 100644 --- a/frontend/src/system/config.ts +++ b/frontend/src/system/config.ts @@ -49,7 +49,9 @@ export const getSystemConfig = (ifset = false) => { roleName: '', dept_id: 0, deptName: '', - token: '' + token: '', + user_auths: '', + user_shares: '' }; } @@ -94,6 +96,7 @@ export const getSystemConfig = (ifset = false) => { // 初始化账户信息,若本地存储中已存在则不进行覆盖 if (!config.account) { config.account = { + ad: true, username: '', password: '', }; @@ -155,7 +158,7 @@ export function getFileUrl() { } else { return config.apiUrl + '/file' } - }else{ + } else { return config.userInfo.url + '/files' } @@ -207,13 +210,7 @@ export function parseJson(str: string) { }; export function getSplit() { if (isWindowsOS()) { - const storeType = getSystemKey('storeType') - //console.log(storeType) - if (storeType === 'browser') { - return "/" - } else { - return "\\" - } + return "\\" } else { return "/" } @@ -242,38 +239,38 @@ export const setSystemConfig = (config: any) => { }; export const clearSystemConfig = () => { - const storetype = localStorage.getItem('GodoOS-storeType') || 'browser'; + const storetype = localStorage.getItem('GodoOS-storeType') || 'local'; localStorage.clear() localStorage.setItem('GodoOS-storeType', storetype) //localStorage.removeItem('GodoOS-config'); }; -function bin2hex(s:string) { +function bin2hex(s: string) { s = encodeURI(s);//只会有0-127的ascii不转化 - let m:any = s.match(/%[\dA-F]{2}/g), a:any = s.split(/%[\dA-F]{2}/), i, j, n, t; + let m: any = s.match(/%[\dA-F]{2}/g), a: any = s.split(/%[\dA-F]{2}/), i, j, n, t; m.push("") for (i in a) { - if (a[i] === "") { a[i] = m[i]; continue } - n = "" - for (j in a[i]) { - t = a[i][j].charCodeAt().toString(16).toUpperCase() - if (t.length === 1) t = "0" + t - n += "%" + t - } - a[i] = n + m[i] + if (a[i] === "") { a[i] = m[i]; continue } + n = "" + for (j in a[i]) { + t = a[i][j].charCodeAt().toString(16).toUpperCase() + if (t.length === 1) t = "0" + t + n += "%" + t + } + a[i] = n + m[i] } return a.join("").split("%").join("") - } - export const getClientId = () => { - let uuid:any = localStorage.getItem("godoosClientId"); +} +export const getClientId = () => { + let uuid: any = localStorage.getItem("godoosClientId"); if (!uuid) { - let canvas = document.createElement('canvas'); - let ctx:any = canvas.getContext('2d'); - ctx.fillStyle = '#FF0000'; - ctx.fillRect(0, 0, 8, 10); - let b64 = canvas.toDataURL().replace("data:image/png;base64,", ""); - let bin = window.atob(b64); - uuid = bin2hex(bin.slice(-16, -12)); - localStorage.setItem("godoosClientId", uuid); + let canvas = document.createElement('canvas'); + let ctx: any = canvas.getContext('2d'); + ctx.fillStyle = '#FF0000'; + ctx.fillRect(0, 0, 8, 10); + let b64 = canvas.toDataURL().replace("data:image/png;base64,", ""); + let bin = window.atob(b64); + uuid = bin2hex(bin.slice(-16, -12)); + localStorage.setItem("godoosClientId", uuid); } return uuid; - } \ No newline at end of file +} \ No newline at end of file diff --git a/frontend/src/system/index.ts b/frontend/src/system/index.ts index 4c5f6da..ebc28cb 100644 --- a/frontend/src/system/index.ts +++ b/frontend/src/system/index.ts @@ -25,7 +25,7 @@ import { Tray, TrayOptions } from './menu/Tary'; import { getSystemConfig, getSystemKey, setSystemKey, setSystemConfig, clearSystemConfig, getFileUrl, fetchGet, getClientId } from './config' import { useUpgradeStore } from '@/stores/upgrade'; import { RestartApp } from '@/util/goutil'; -import { notifyError, notifySuccess } from '@/util/msg'; +import { notifyError } from '@/util/msg'; export type OsPlugin = (system: System) => void; export type FileOpener = { diff --git a/godo/files/fs.go b/godo/files/fs.go index 7240bc2..38dd655 100644 --- a/godo/files/fs.go +++ b/godo/files/fs.go @@ -228,12 +228,17 @@ func HandleRename(w http.ResponseWriter, r *http.Request) { libs.HTTPError(w, http.StatusInternalServerError, err.Error()) return } + err = CheckDeleteDesktop(oldPath) + if err != nil { + log.Printf("Error deleting file from desktop: %s", err.Error()) + } err = Rename(basePath, oldPath, newPath) if err != nil { log.Printf("Error renaming file: %s", err.Error()) libs.HTTPError(w, http.StatusConflict, err.Error()) return } + err = CheckAddDesktop(newPath) if err != nil { log.Printf("Error adding file to desktop: %s", err.Error())