Browse Source

change file bug

master
godo 9 months ago
parent
commit
09d5d60a09
  1. 6
      CHANGELOG.md
  2. 13
      frontend/components.d.ts
  3. 9
      frontend/src/components/builtin/EditFileName.vue
  4. 61
      frontend/src/components/builtin/FileList.vue
  5. 9
      frontend/src/components/desktop/Ad.vue
  6. 11
      frontend/src/components/desktop/Notice.vue
  7. 78
      frontend/src/components/oa/PlanTasks.vue
  8. 75
      frontend/src/components/setting/SetAccount.vue
  9. 8
      frontend/src/components/setting/SetSystem.vue
  10. 9
      frontend/src/components/setting/Setting.vue
  11. 48
      frontend/src/components/taskbar/MessageCenterPop.vue
  12. 45
      frontend/src/components/taskbar/ShowNews.vue
  13. 45
      frontend/src/hook/useContextMenu.ts
  14. 35
      frontend/src/hook/useFileDrag.ts
  15. 73
      frontend/src/stores/notify.ts
  16. 6
      frontend/src/stores/upgrade.ts
  17. 29
      frontend/src/system/config.ts
  18. 2
      frontend/src/system/index.ts
  19. 5
      godo/files/fs.go

6
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. 优化内网聊天

13
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']

9
frontend/src/components/builtin/EditFileName.vue

@ -1,17 +1,12 @@
<template>
<div class="outer">
<input class="win-input" v-model="name" />
<el-input class="win-input" v-model="name" />
<WinButton @click="confirm">{{ t("confirm") }}</WinButton>
</div>
</template>
<script setup lang="ts">
import { inject, ref } from "vue";
// import { OsFileWithoutContent } from '@/system/core/FileSystem';
// import { useSystem } from '../system';
// import { BrowserWindow } from '../window/BrowserWindow';
import { emitEvent } from "@/system/event";
// import { join } from '../core/Path';
// import { basename } from '@/system/core/Path';
import {
Dialog,
t,
@ -34,7 +29,7 @@ function confirm() {
});
return;
}
const newPath = join(browserWindow.config.content.path, "..", name.value);
const newPath = join(browserWindow.config.content.path, name.value);
useSystem()
?.fs.rename(browserWindow.config.content.path, newPath)
.then(() => {

61
frontend/src/components/builtin/FileList.vue

@ -64,7 +64,7 @@
</div>
</template>
<script lang="ts" setup>
import { useSystem, basename, dirname, join, OsFileWithoutContent, Notify } from '@/system/index.ts';
import { useSystem, basename, dirname, join, OsFileWithoutContent, Notify, BrowserWindow } from '@/system/index.ts';
import { getSystemKey } from '@/system/config'
import { emitEvent, mountEvent } from '@/system/event';
import { useContextMenu } from '@/hook/useContextMenu.ts';
@ -77,6 +77,7 @@ import { throttle } from '@/util/debounce';
import { dealSize } from '@/util/file';
import { Menu } from '@/system/menu/Menu';
import { useChooseStore } from "@/stores/choose";
import { log } from 'console';
const { openPropsWindow, copyFile, createLink, deleteFile } = useContextMenu();
const sys = useSystem();
const { startDrag, folderDrop } = useFileDrag(sys);
@ -161,11 +162,25 @@ const editName = ref<string>('');
function onEditNameEnd() {
const editEndName = editName.value.trim();
if (editEndName && editIndex.value >= 0) {
const editpath: any = props.fileList[editIndex.value].path.toString()
let newPath: any;
let sp = "/"
if (editpath.indexOf("/") === -1) {
sp = "\\"
}
newPath = editpath?.split(sp);
newPath.pop()
newPath.push(editEndName)
newPath = newPath.join(sp)
sys?.fs.rename(
props.fileList[editIndex.value].path,
join(dirname(props.fileList[editIndex.value].path), editEndName)
editpath,
newPath
);
props.onRefresh();
if(newPath.indexOf("Desktop") !== -1){
sys.refershAppList()
}
}
editIndex.value = -1;
}
@ -368,6 +383,46 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
},
];
const userType = sys.getConfig('userType');
if (userType == 'member') {
menuArr.push(
{
label: '分享给...',
click: () => {
const win = new BrowserWindow({
title: '分享',
content: "ShareFiles",
config: {
path: item.path,
},
width: 500,
height: 500,
center: true,
});
win.show();
},
}
)
menuArr.push(
{
label: '评论',
click: () => {
const win = new BrowserWindow({
title: '评论',
content: "CommentsFiles",
config: {
path: item.path,
},
width: 350,
height: 400,
center: true,
});
win.show();
},
}
)
}
// eslint-disable-next-line prefer-spread
menuArr.push.apply(menuArr, fileMenus)
}

9
frontend/src/components/desktop/Ad.vue

@ -12,12 +12,15 @@
</el-icon>
</div>
</div>
<ShowNews />
</template>
<script setup lang="ts" name="layoutSponsors">
import { reactive, computed } from 'vue';
import { useUpgradeStore } from '@/stores/upgrade';
import { useNotifyStore } from '@/stores/notify';
const upgradeStore = useUpgradeStore();
const notifyStore = useNotifyStore();
//
const state = reactive({
@ -41,10 +44,14 @@ const onCarouselChange = (e: number) => {
};
//
const onSponsorsClick = () => {
const link = upgradeStore.adList[state.ad.index]?.link
const data = upgradeStore.adList[state.ad.index]
const link = data?.link
if(link){
window.open(link)
}
if(data?.content){
notifyStore.viewContent(data)
}
};
</script>

11
frontend/src/components/desktop/Notice.vue

@ -12,13 +12,15 @@
</el-icon>
</div>
</div>
<ShowNews />
</template>
<script setup lang="ts" name="layoutnotice">
import { reactive, computed } from 'vue';
import { useUpgradeStore } from '@/stores/upgrade';
import { useNotifyStore } from '@/stores/notify';
const upgradeStore = useUpgradeStore();
const notifyStore = useNotifyStore();
//
const state = reactive({
notice: {
@ -40,10 +42,15 @@ const onCarouselChange = (e: number) => {
};
//
const onnoticeClick = () => {
const link = upgradeStore.noticeList[state.notice.index]?.link
const data = upgradeStore.noticeList[state.notice.index]
const link = data?.link
if(link){
window.open(link)
}
if(data?.content){
notifyStore.viewContent(data)
}
};
</script>

78
frontend/src/components/oa/PlanTasks.vue

@ -0,0 +1,78 @@
<template>
<el-form :model="form" label-width="auto" style="max-width: 560px;margin-top:20px;padding: 20px;">
<el-form-item label="任务名称">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="任务跨度">
<el-select v-model="form.duration">
<el-option label="按天" value="1" />
<el-option label="按周" value="7" />
<el-option label="按月" value="30" />
<el-option label="按季" value="90" />
<el-option label="按年" value="365" />
</el-select>
</el-form-item>
<el-form-item label="任务模板">
<el-input v-model="form.tpl" />
</el-form-item>
<el-form-item label="选择人员">
<el-select v-model="form.users" filterable multiple clearable collapse-tags placeholder="选择人员"
popper-class="custom-header" :max-collapse-tags="1" value-key="id" style="width: 240px" @change="checkUsers">
<template #header>
<el-checkbox v-model="checkAll" @change="handleCheckAll">
全选
</el-checkbox>
</template>
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select></el-form-item>
<el-form-item label="任务描述">
<el-input v-model="form.desc" type="textarea" />
</el-form-item>
<div class="btn-group">
<el-button type="primary" @click="onSubmit">创建任务</el-button>
</div>
</el-form>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useSystem } from '@/system';
const sys = useSystem()
const userInfo: any = sys.getConfig('userInfo')
const userList = ref(userInfo.user_auths)
const checkAll = ref(false)
const form: any = ref({
name: '',
duration: '1',
tpl: '',
after: '1',
users: [],
desc: '',
})
const handleCheckAll = (val: any) => {
if (val) {
form.value.users = userList.value.map((d: any) => d.value)
} else {
form.value.users.value = []
}
}
const checkUsers = (val: any) => {
const res:any = []
val.forEach((item: any) => {
if(item){
res.push(item)
}
})
form.value.users = res
}
const onSubmit = () => {
console.log('submit!')
}
</script>
<style scoped>
.btn-group{
display: flex;
justify-content: center;
}
</style>

75
frontend/src/components/setting/SetAccount.vue

@ -2,12 +2,8 @@
<div class="container">
<div class="nav">
<ul>
<li
v-for="(item, index) in items"
:key="index"
@click="selectItem(index)"
:class="{ active: index === activeIndex }"
>
<li v-for="(item, index) in items" :key="index" @click="selectItem(index)"
:class="{ active: index === activeIndex }">
{{ item }}
</li>
</ul>
@ -15,7 +11,7 @@
<div class="setting">
<div v-if="0 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">{{ t('account.info') }}</h1>
<h1 class="setting-title">锁屏</h1>
</div>
<div class="setting-item">
<label> {{ t('account') }} </label>
@ -23,7 +19,7 @@
</div>
<div class="setting-item">
<label> {{ t('password') }} </label>
<el-input v-model="account.password" type="password" :placeholder="t('password')" clearable/>
<el-input v-model="account.password" type="password" :placeholder="t('password')" clearable />
</div>
<div class="setting-item">
@ -33,34 +29,41 @@
</el-button>
</div>
</div>
<div v-if="1 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">广告与更新提示</h1>
</div>
<div class="setting-item">
<label></label>
<el-switch
v-model="ad"
active-text="开启"
inactive-text="关闭"
size="large"
:before-change="setAd"></el-switch>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
// import WinButton from '@/components/win/WinButton.vue';
// import WinSelect from '@/components/win/WinSelect.vue';
import { ref } from 'vue';
import { Dialog,t } from '@/system/index.ts';
import { Dialog, t } from '@/system/index.ts';
import { getSystemKey, setSystemKey } from '@/system/config'
const items = [t('account.info')];
import { ElMessageBox } from 'element-plus'
const items = ['锁屏设置', '广告设置'];
const activeIndex = ref(0);
// const modelvalue = ref(system.getConfig('lang'));
// const password = ref('');
const account = ref(getSystemKey('account'));
const ad = ref(account.value.ad)
const selectItem = (index: number) => {
activeIndex.value = index;
};
async function submit() {
// await system.setConfig('lang', modelvalue.value);
// localStorage.setItem('godoOS_username', account.value);
// localStorage.setItem('godoOS_password', password.value);
setSystemKey('account', account.value);
Dialog.showMessageBox({
message: t('save.success'),
@ -70,6 +73,38 @@ async function submit() {
location.reload();
});
}
function setAd() {
const data = toRaw(account.value)
if (ad.value) {
return new Promise((resolve) => {
setTimeout(() => {
ElMessageBox.confirm(
'广告关闭后您将收不到任何系统通知和更新提示!',
'Warning',
{
confirmButtonText: '确定关闭',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
data.ad = false
setSystemKey('account', data);
return resolve(true)
})
.catch(() => {
return resolve(false)
})
}, 1000)
})
}else{
data.ad = true
setSystemKey('account', data);
return Promise.resolve(true)
}
}
</script>
<style scoped>
@import './setStyle.css';

8
frontend/src/components/setting/SetSystem.vue

@ -9,7 +9,7 @@
</ul>
</div>
<div class="setting">
<div v-if="0 === activeIndex">
<div v-if="1 === activeIndex">
<div class="setting-item" style="margin-top: 60px">
<label>存储方式</label>
<el-select v-model="config.storeType">
@ -49,7 +49,7 @@
</div>
</div>
<div v-if="1 === activeIndex">
<div v-if="2 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">备份</h1>
</div>
@ -66,7 +66,7 @@
<input type="file" accept=".zip" style="display: none" ref="zipFileInput" />
</div>
</div>
<div v-if="2 === activeIndex">
<div v-if="0 === activeIndex">
<div class="setting-item" style="margin-top: 60px">
<label>用户角色</label>
<el-select v-model="config.userType">
@ -130,7 +130,7 @@ const storeList = [
},
];
const items = ["个人存储", "备份还原", "用户角色"];
const items = ["用户角色","个人存储", "备份还原"];
const urlRegex = /^(https?:\/\/)/;
const userTypes = [
{

9
frontend/src/components/setting/Setting.vue

@ -86,7 +86,6 @@ const setList = ref([
key: "system",
title: t("system"),
desc: "存储、备份还原、用户角色",
// desc: t('brightness'),
icon: "system",
content: "SetSystem",
},
@ -94,14 +93,14 @@ const setList = ref([
{
key: "custom",
title: t("personalization"),
desc: t("background.lockscreen.color"),
desc: '壁纸',
icon: "personal",
content: "SetCustom",
},
{
key: "language",
title: t("time.and.language"),
title: '语言',
desc: t("language"),
icon: "language",
content: "SetLang",
@ -109,8 +108,8 @@ const setList = ref([
{
key: "account",
title: t("account"),
desc: t("your.account"),
title: "屏幕",
desc: '锁屏/广告',
icon: "account",
content: "SetAccount",
},

48
frontend/src/components/taskbar/MessageCenterPop.vue

@ -7,7 +7,7 @@
</div>
<div class="message-group scroll-bar">
<div class="message-item" v-for="notify in store.notifyList" :key="notify.id">
<div class="message-item-title" @click="showDetail(notify)">
<div class="message-item-title" @click="store.viewContent(notify)">
<span>{{ notify.title }}</span>
</div>
</div>
@ -20,12 +20,7 @@
</div>
</div>
</Transition>
<el-dialog v-model="showNews" :title="newsDetail.title" show-close="true" width="600">
<div class="new-content">
<div class="news-detail" v-html="newsDetail.content"></div>
<p class="new-time"><strong>发布时间:</strong> {{ newsDetail.showtime }}</p>
</div>
</el-dialog>
<ShowNews />
</template>
<script setup lang="ts">
import { useNotifyStore } from '@/stores/notify';
@ -33,8 +28,6 @@ import { ref } from 'vue';
import { mountEvent } from '@/system/event';
const store = useNotifyStore()
const isPopShow = ref(false);
const newsDetail: any = ref({})
const showNews = ref(false)
mountEvent('messagecenter.show', () => {
isPopShow.value = !isPopShow.value;
@ -46,13 +39,6 @@ onMounted(async () => {
// store.init();
await store.getList()
});
const showDetail = (notify: any) => {
const timestamp = notify.add_time * 1000; // 10 13
const date = new Date(timestamp);
notify.showtime = date.toLocaleString();
newsDetail.value = notify
showNews.value = true
}
</script>
<style lang="scss" scoped>
@import '@/assets/main.scss';
@ -166,34 +152,4 @@ const showDetail = (notify: any) => {
transform: translateX(100%);
}
.new-content {
padding: 20px;
background-color: #F5F5F5;
border: 1px solid #E5E5E5;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
.new-time {
margin-bottom: 10px;
font-size: 14px;
color: #666;
strong {
font-weight: bold;
color: #333;
}
}
.news-detail {
font-size: 16px;
line-height: 1.5;
color: #333;
white-space: pre-wrap;
}
.news-detail:deep(img){
max-width: 90%;
}
}
</style>

45
frontend/src/components/taskbar/ShowNews.vue

@ -0,0 +1,45 @@
<template>
<el-dialog v-model="store.showNews" :title="store.newsDetail.title" show-close="true" width="600">
<div class="new-content">
<div class="news-detail" v-html="store.newsDetail.content"></div>
<p class="new-time"><strong>发布时间:</strong> {{ store.newsDetail.showtime }}</p>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { useNotifyStore } from '@/stores/notify';
const store:any = useNotifyStore()
</script>
<style lang="scss" scoped>
.new-content {
padding: 20px;
background-color: #F5F5F5;
border: 1px solid #E5E5E5;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
.new-time {
margin-bottom: 10px;
font-size: 14px;
color: #666;
strong {
font-weight: bold;
color: #333;
}
}
.news-detail {
font-size: 16px;
line-height: 1.5;
color: #333;
white-space: pre-wrap;
}
.news-detail:deep(img){
max-width: 90%;
}
}
</style>

45
frontend/src/hook/useContextMenu.ts

@ -46,7 +46,7 @@ function useContextMenu() {
}
//console.log(path)
let menuArr = [
let menuArr: any = [
{
label: t('refresh'),
click: () => {
@ -101,28 +101,6 @@ 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,

35
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);

73
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){
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){
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存储
],
}
})

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

29
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 "\\"
}
} else {
return "/"
}
@ -242,14 +239,14 @@ 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 }
@ -262,12 +259,12 @@ function bin2hex(s:string) {
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');
let ctx: any = canvas.getContext('2d');
ctx.fillStyle = '#FF0000';
ctx.fillRect(0, 0, 8, 10);
let b64 = canvas.toDataURL().replace("data:image/png;base64,", "");
@ -276,4 +273,4 @@ function bin2hex(s:string) {
localStorage.setItem("godoosClientId", uuid);
}
return uuid;
}
}

2
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 = {

5
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())

Loading…
Cancel
Save