Browse Source

change port

master
godo 6 months ago
parent
commit
dff8f99a89
  1. 1
      README.md
  2. 9155
      frontend/package-lock.json
  3. 11
      frontend/package.json
  4. 695
      frontend/src/components/setting/SetSystem.vue
  5. 4
      frontend/src/components/window/IframeFile.vue
  6. 4
      frontend/src/system/applist.ts
  7. 6
      frontend/src/system/config.ts
  8. 9
      frontend/src/util/goutil.ts
  9. 16
      godo/cmd/main.go
  10. 22
      godo/libs/dir.go

1
README.md

@ -27,6 +27,7 @@
- markdown新增ai优化/续写/纠错/翻译/总结,生成大纲,根据大纲一键创建文章 - markdown新增ai优化/续写/纠错/翻译/总结,生成大纲,根据大纲一键创建文章
- 更改文档存储方式,支持选择文件夹 - 更改文档存储方式,支持选择文件夹
- 内网聊天新增ai对话,可保存对话历史,可更换模型和prompt - 内网聊天新增ai对话,可保存对话历史,可更换模型和prompt
- 新增可定义端口和访问路径,支持web端系统重启
## 🏭 第三阶段目标(十二月底发布) ## 🏭 第三阶段目标(十二月底发布)
1. **文档处理与Markdown智能升级** 1. **文档处理与Markdown智能升级**

9155
frontend/package-lock.json

File diff suppressed because it is too large

11
frontend/package.json

@ -1,11 +1,11 @@
{ {
"name": "godoos", "name": "godoos",
"private": true, "private": true,
"version": "1.0.2", "version": "1.0.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vue-tsc --noEmit && vite build", "build": "vite build",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
@ -19,20 +19,16 @@
"jszip": "^3.10.1", "jszip": "^3.10.1",
"lunar-typescript": "^1.7.6", "lunar-typescript": "^1.7.6",
"moment": "^2.30.1", "moment": "^2.30.1",
"nanoid": "^5.0.9",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persist": "^1.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vue": "^3.4.31", "vue": "^3.4.31",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-router": "^4.4.0", "vue-router": "^4.4.0",
"vue-svg-icon": "^1.2.9",
"vue-web-screen-shot": "^1.5.3", "vue-web-screen-shot": "^1.5.3",
"vue3-lottie": "^3.3.1" "vue3-lottie": "^3.3.1"
}, },
"devDependencies": { "devDependencies": {
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/nanoid": "^3.0.0",
"@types/node": "^20.14.10", "@types/node": "^20.14.10",
"@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue": "^5.0.5",
"sass": "^1.77.8", "sass": "^1.77.8",
@ -40,7 +36,6 @@
"typescript": "^5.5.3", "typescript": "^5.5.3",
"unplugin-auto-import": "^0.18.0", "unplugin-auto-import": "^0.18.0",
"unplugin-vue-components": "^0.27.2", "unplugin-vue-components": "^0.27.2",
"vite": "^5.3.3", "vite": "^5.3.3"
"vue-tsc": "^2.0.26"
} }
} }

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

@ -2,59 +2,47 @@
<div class="container"> <div class="container">
<div class="nav"> <div class="nav">
<ul> <ul>
<li <li v-for="(item, index) in items" :key="index" @click="selectItem(index)"
v-for="(item, index) in items" :class="{ active: index === activeIndex }">
:key="index"
@click="selectItem(index)"
:class="{ active: index === activeIndex }"
>
{{ item }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="setting"> <div class="setting">
<div v-if="1 === activeIndex"> <div v-if="1 === activeIndex">
<div <div class="setting-item" style="margin-top: 60px">
class="setting-item"
style="margin-top: 60px"
>
<label>存储方式</label> <label>存储方式</label>
<el-select v-model="config.storeType"> <el-select v-model="config.storeType">
<el-option <el-option v-for="(item, key) in storeList" :key="key" :label="item.title"
v-for="(item, key) in storeList" :value="item.value" />
:key="key"
:label="item.title"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
<div <template v-if="config.storeType === 'local'">
class="setting-item" <div class="setting-item">
v-if="config.storeType === 'local'" <label>存储地址</label>
> <el-input v-model="config.storePath" @click="selectFile()"
<label>存储地址</label> placeholder="可为空,为空则取系统默认存储地址:/用户目录/.godoos/os" />
<el-input </div>
v-model="config.storePath" <div class="setting-item">
@click="selectFile()" <label>自定义端口</label>
placeholder="可为空,为空则取系统默认存储地址" <el-input v-model="config.netPort" placeholder="可为空,为空则取系统默认56780" />
/> </div>
</div> <div class="setting-item">
<label>自定义路径</label>
<el-input v-model="config.netPath" placeholder="自定义web访问路径,英文,不要加斜杠,可为空" />
</div>
</template>
<template v-if="config.storeType === 'net'"> <template v-if="config.storeType === 'net'">
<div class="setting-item"> <div class="setting-item">
<label>服务器地址</label> <label>服务器地址</label>
<el-input <el-input v-model="config.storenet.url" placeholder="可访问的地址,例如http://192.168.1.6:56780 不要加斜杠" />
v-model="config.storenet.url"
placeholder="http://192.168.1.16:56780 不要加斜杠"
/>
</div> </div>
</template> </template>
<template v-if="config.storeType === 'webdav'"> <template v-if="config.storeType === 'webdav'">
<div class="setting-item"> <div class="setting-item">
<label>服务器地址</label> <label>服务器地址</label>
<el-input <el-input v-model="config.webdavClient.url" placeholder="https://godoos.com/webdav 不要加斜杠" />
v-model="config.webdavClient.url"
placeholder="https://godoos.com/webdav 不要加斜杠"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label>登陆用户名</label> <label>登陆用户名</label>
@ -62,19 +50,13 @@
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label>登陆密码</label> <label>登陆密码</label>
<el-input <el-input v-model="config.webdavClient.password" type="password" />
v-model="config.webdavClient.password"
type="password"
/>
</div> </div>
</template> </template>
<div class="setting-item"> <div class="setting-item">
<label></label> <label></label>
<el-button <el-button @click="submitOsInfo" type="primary">
@click="submitOsInfo"
type="primary"
>
{{ t("confirm") }} {{ t("confirm") }}
</el-button> </el-button>
</div> </div>
@ -86,10 +68,7 @@
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label></label> <label></label>
<el-button <el-button @click="exportBackup" type="primary">
@click="exportBackup"
type="primary"
>
导出 导出
</el-button> </el-button>
</div> </div>
@ -98,73 +77,42 @@
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label></label> <label></label>
<el-button <el-button @click="selectZipfile" type="primary">
@click="selectZipfile"
type="primary"
>
导入 导入
</el-button> </el-button>
<input <input type="file" accept=".zip" style="display: none" ref="zipFileInput" />
type="file"
accept=".zip"
style="display: none"
ref="zipFileInput"
/>
</div> </div>
</div> </div>
<div v-if="0 === activeIndex"> <div v-if="0 === activeIndex">
<div <div class="setting-item" style="margin-top: 60px">
class="setting-item"
style="margin-top: 60px"
>
<label>用户角色</label> <label>用户角色</label>
<el-select v-model="config.userType"> <el-select v-model="config.userType">
<el-option <el-option v-for="(item, key) in userTypes" :key="key" :label="item.title"
v-for="(item, key) in userTypes" :value="item.value" />
:key="key"
:label="item.title"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
<template v-if="config.userType === 'member'"> <template v-if="config.userType === 'member'">
<div class="setting-item"> <div class="setting-item">
<label>服务器地址</label> <label>服务器地址</label>
<el-input <el-input v-model="config.userInfo.url" placeholder="网址或域名,例子:https://godoos.com 不要加斜杠" />
v-model="config.userInfo.url"
placeholder="网址或域名,例子:https://godoos.com 不要加斜杠"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label>用户名</label> <label>用户名</label>
<el-input <el-input v-model="config.userInfo.username" placeholder="登录用户名" />
v-model="config.userInfo.username"
placeholder="登录用户名"
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label>密码</label> <label>密码</label>
<el-input <el-input v-model="config.userInfo.password" type="password" placeholder="登录密码" />
v-model="config.userInfo.password"
type="password"
placeholder="登录密码"
/>
</div> </div>
</template> </template>
<div class="setting-item"> <div class="setting-item">
<label></label> <label></label>
<el-button <el-button @click="saveUserInfo" type="primary">
@click="saveUserInfo"
type="primary"
>
{{ t("confirm") }} {{ t("confirm") }}
</el-button> </el-button>
</div> </div>
</div> </div>
<div <div v-if="3 === activeIndex" class="setting-area">
v-if="3 === activeIndex"
class="setting-area"
>
<SetFilePwd v-if="config.userType === 'person'"></SetFilePwd> <SetFilePwd v-if="config.userType === 'person'"></SetFilePwd>
</div> </div>
</div> </div>
@ -172,169 +120,108 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Dialog, join, System, t } from "@/system"; import { Dialog, join, System, t } from "@/system";
import { import {
getClientId, getClientId,
getSystemConfig, getSystemConfig,
setSystemConfig, setSystemConfig,
} from "@/system/config"; } from "@/system/config";
import { OpenDirDialog, RestartApp } from "@/util/goutil"; import { OpenDirDialog, RestartApp } from "@/util/goutil";
import { notifyError, notifySuccess } from "@/util/msg"; import { notifyError, notifySuccess } from "@/util/msg";
import FileSaver from "file-saver"; import FileSaver from "file-saver";
import JSZip from "jszip"; import JSZip from "jszip";
import { inject, ref } from "vue"; import { inject, ref } from "vue";
const config = ref(getSystemConfig()); const config = ref(getSystemConfig());
const sys = inject<System>("system")!; const sys = inject<System>("system")!;
let zipFile: File | undefined = undefined; let zipFile: File | undefined = undefined;
const zipFileInput = ref(); const zipFileInput = ref();
const fileName: any = ref(""); const fileName: any = ref("");
const storeList = [ const storeList = [
// { // {
// title: "", // title: "",
// value: "browser", // value: "browser",
// }, // },
{ {
title: "本地存储", title: "本地存储",
value: "local", value: "local",
}, },
{ {
title: "远程存储", title: "远程存储",
value: "net", value: "net",
}, },
{ {
title: "webdav", title: "webdav",
value: "webdav", value: "webdav",
}, },
]; ];
const items = ["用户角色", "个人存储", "备份还原", "文件密码箱"]; const items = ["用户角色", "存储配置", "备份还原", "文件密码箱"];
const urlRegex = /^(https?:\/\/)/; const urlRegex = /^(https?:\/\/)/;
const userTypes = [ const userTypes = [
{ {
title: "独立用户", title: "独立用户",
value: "person", value: "person",
}, },
{ {
title: "企业用户", title: "企业用户",
value: "member", value: "member",
}, },
]; ];
const activeIndex = ref(0); const activeIndex = ref(0);
const selectItem = (index: number) => { const selectItem = (index: number) => {
activeIndex.value = index; activeIndex.value = index;
}; };
function selectFile() { function selectFile() {
OpenDirDialog().then((res: string) => { OpenDirDialog().then((res: string) => {
config.value.storePath = res; config.value.storePath = res;
}); });
} }
function submitOsInfo() { function submitOsInfo() {
const saveData = toRaw(config.value); const saveData = toRaw(config.value);
const postData: any = { if (saveData.storeType === "local") {
//name: "osPath", const postData = parseData(saveData);
type: saveData.storeType, const postUrl = config.value.apiUrl + "/system/setting";
}; fetch(postUrl, {
if (saveData.storeType === "browser") { method: "POST",
setSystemConfig(saveData); body: JSON.stringify(postData),
RestartApp(); })
.then((res) => res.json())
.then((res) => {
if (res.code === 0) {
setSystemConfig(saveData);
RestartApp();
} else {
Dialog.showMessageBox({
message: res.message,
type: "error",
});
}
});
}
if (saveData.storeType === "net") {
if (saveData.storenet.url === "") {
Dialog.showMessageBox({
message: "服务器地址不能为空",
type: "error",
});
return; return;
} }
if (saveData.storeType === "local") { const urlRegex = /^(https?:\/\/)[^\/]+$/;
if (saveData.storePath === "") { if (!urlRegex.test(saveData.storenet.url)) {
setSystemConfig(saveData); Dialog.showMessageBox({
RestartApp(); message: "服务器地址格式错误",
return; type: "error",
} });
postData.name = "osPath";
postData.value = saveData.storePath;
const postUrl = config.value.apiUrl + "/system/setting";
fetch(postUrl, {
method: "POST",
body: JSON.stringify([postData]),
})
.then((res) => res.json())
.then((res) => {
if (res.code === 0) {
setSystemConfig(saveData);
RestartApp();
} else {
Dialog.showMessageBox({
message: res.message,
type: "error",
});
}
});
}
if (saveData.storeType === "net") {
if (saveData.storenet.url === "") {
Dialog.showMessageBox({
message: "服务器地址不能为空",
type: "error",
});
return;
}
const urlRegex = /^(https?:\/\/)[^\/]+$/;
if (!urlRegex.test(saveData.storenet.url)) {
Dialog.showMessageBox({
message: "服务器地址格式错误",
type: "error",
});
return;
}
setSystemConfig(saveData);
RestartApp();
}
if (saveData.storeType === "webdav") {
const urlRegex = /^(https?:\/\/)/;
if (!urlRegex.test(saveData.webdavClient.url.trim())) {
Dialog.showMessageBox({
message: "服务器地址格式错误",
type: "error",
});
return;
}
if (
saveData.webdavClient.username === "" ||
saveData.webdavClient.password === ""
) {
Dialog.showMessageBox({
message: "用户名或密码不能为空",
type: "error",
});
return;
}
postData.name = "webdavClient";
postData.value = saveData.webdavClient;
const postUrl = config.value.apiUrl + "/system/setting";
fetch(postUrl, {
method: "POST",
body: JSON.stringify([postData]),
})
.then((res) => res.json())
.then((res) => {
if (res.code === 0) {
setSystemConfig(saveData);
RestartApp();
} else {
Dialog.showMessageBox({
message: res.message,
type: "error",
});
}
});
}
}
async function saveUserInfo() {
const saveData = toRaw(config.value);
if (saveData.userType == "person") {
setSystemConfig(saveData);
notifySuccess("保存成功");
RestartApp();
return; return;
} }
if (!urlRegex.test(saveData.userInfo.url.trim())) { setSystemConfig(saveData);
RestartApp();
}
if (saveData.storeType === "webdav") {
const urlRegex = /^(https?:\/\/)/;
if (!urlRegex.test(saveData.webdavClient.url.trim())) {
Dialog.showMessageBox({ Dialog.showMessageBox({
message: "服务器地址格式错误", message: "服务器地址格式错误",
type: "error", type: "error",
@ -342,8 +229,8 @@
return; return;
} }
if ( if (
saveData.userInfo.username === "" || saveData.webdavClient.username === "" ||
saveData.userInfo.password === "" saveData.webdavClient.password === ""
) { ) {
Dialog.showMessageBox({ Dialog.showMessageBox({
message: "用户名或密码不能为空", message: "用户名或密码不能为空",
@ -351,150 +238,218 @@
}); });
return; return;
} }
const password = saveData.userInfo.password; const postUrl = config.value.apiUrl + "/system/setting";
const serverUrl = saveData.userInfo.url + "/member/login"; fetch(postUrl, {
const res = await fetch(serverUrl, {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify([{
username: saveData.userInfo.username, name: "webdavClient",
password: password, value: saveData.webdavClient,
clientId: getClientId(), }]),
}), })
}); .then((res) => res.json())
if (res.status === 200) { .then((res) => {
const data = await res.json(); if (res.code === 0) {
if (data.success) { setSystemConfig(saveData);
data.data.url = saveData.userInfo.url; RestartApp();
data.data.password = password; } else {
saveData.userInfo = data.data; Dialog.showMessageBox({
setSystemConfig(saveData); message: res.message,
notifySuccess("登录成功"); type: "error",
RestartApp(); });
return; }
} else { });
notifyError(data.message); }
} }
} else {
notifyError("登录失败"); function parseData(saveData: any) {
let postData = []
if (saveData.storePath !== "") {
postData.push({ name: "osPath", value: saveData.storePath })
} }
if (saveData.netPort != "" && saveData.netPort != "56780" && !isNaN(saveData.netPort) && saveData.netPort*1 > 0 && saveData.netPort*1 < 65535) {
postData.push({
name: "netPort",
value: saveData.netPort,
});
}
if (saveData.netPath != "" && /^[A-Za-z]+$/.test(saveData.netPath)) {
postData.push({
name: "netPath",
value: saveData.netPath,
});
}
return postData;
}
async function saveUserInfo() {
const saveData = toRaw(config.value);
if (saveData.userType == "person") {
setSystemConfig(saveData);
notifySuccess("保存成功");
RestartApp();
return; return;
} }
async function exportBackup() { if (!urlRegex.test(saveData.userInfo.url.trim())) {
const { setProgress } = Dialog.showProcessDialog({ Dialog.showMessageBox({
message: `正在打包`, message: "服务器地址格式错误",
type: "error",
}); });
try { return;
const zip = new JSZip(); }
await dfsPackage("/", zip, setProgress); if (
zip.generateAsync({ type: "blob" }).then(function (content) { saveData.userInfo.username === "" ||
FileSaver.saveAs(content, "backup.zip"); saveData.userInfo.password === ""
setProgress(100); ) {
}); Dialog.showMessageBox({
} catch (error) { message: "用户名或密码不能为空",
//console.log(error); type: "error",
Dialog.showMessageBox({ });
message: "打包失败", return;
type: "error", }
}).finally(() => { const password = saveData.userInfo.password;
zipFile = undefined; const serverUrl = saveData.userInfo.url + "/member/login";
fileName.value = ""; const res = await fetch(serverUrl, {
setProgress(100); method: "POST",
}); body: JSON.stringify({
username: saveData.userInfo.username,
password: password,
clientId: getClientId(),
}),
});
if (res.status === 200) {
const data = await res.json();
if (data.success) {
data.data.url = saveData.userInfo.url;
data.data.password = password;
saveData.userInfo = data.data;
setSystemConfig(saveData);
notifySuccess("登录成功");
RestartApp();
return;
} else {
notifyError(data.message);
} }
} else {
notifyError("登录失败");
} }
async function dfsPackage(path: string, zip: JSZip, setProgress: any) { return;
const dir = await sys.fs.readdir(path); }
async function exportBackup() {
const { setProgress } = Dialog.showProcessDialog({
message: `正在打包`,
});
try {
const zip = new JSZip();
await dfsPackage("/", zip, setProgress);
zip.generateAsync({ type: "blob" }).then(function (content) {
FileSaver.saveAs(content, "backup.zip");
setProgress(100);
});
} catch (error) {
//console.log(error);
Dialog.showMessageBox({
message: "打包失败",
type: "error",
}).finally(() => {
zipFile = undefined;
fileName.value = "";
setProgress(100);
});
}
}
async function dfsPackage(path: string, zip: JSZip, setProgress: any) {
const dir = await sys.fs.readdir(path);
for (let i = 0; i < dir.length; i++) { for (let i = 0; i < dir.length; i++) {
const item = dir[i]; const item = dir[i];
const stat = await sys.fs.stat(item.path); const stat = await sys.fs.stat(item.path);
setProgress(Math.max((i / dir.length) * 100 - 0.1, 0.1)); setProgress(Math.max((i / dir.length) * 100 - 0.1, 0.1));
if (stat) { if (stat) {
if (stat.isDirectory) { if (stat.isDirectory) {
await dfsPackage(item.path, zip, setProgress); await dfsPackage(item.path, zip, setProgress);
} else { } else {
const content = await sys.fs.readFile(item.path); const content = await sys.fs.readFile(item.path);
try { try {
atob(content || ""); atob(content || "");
zip.file(item.path, content || ""); zip.file(item.path, content || "");
} catch (error) { } catch (error) {
zip.file(item.path, content || ""); zip.file(item.path, content || "");
}
} }
} }
} }
} }
function selectZipfile() { }
zipFileInput.value.click(); function selectZipfile() {
zipFileInput.value.onchange = (e: any) => { zipFileInput.value.click();
const tar: any = e.target as HTMLInputElement; zipFileInput.value.onchange = (e: any) => {
if (tar.files?.[0]) { const tar: any = e.target as HTMLInputElement;
zipFile = tar.files[0]; if (tar.files?.[0]) {
fileName.value = zipFile?.name; zipFile = tar.files[0];
importBackup(); fileName.value = zipFile?.name;
} else { importBackup();
zipFile = undefined; } else {
fileName.value = ""; zipFile = undefined;
} fileName.value = "";
};
}
async function importBackup(path = "") {
if (!zipFile) {
return;
} }
const { setProgress } = Dialog.showProcessDialog({ };
message: "正在恢复备份", }
async function importBackup(path = "") {
if (!zipFile) {
return;
}
const { setProgress } = Dialog.showProcessDialog({
message: "正在恢复备份",
});
try {
const unziped = await JSZip.loadAsync(zipFile);
const unzipArray: Array<JSZip.JSZipObject> = [];
unziped.forEach((_, zipEntry) => {
unzipArray.push(zipEntry);
}); });
try { for (let i = 0; i < unzipArray.length; i++) {
const unziped = await JSZip.loadAsync(zipFile); const zipEntry = unzipArray[i];
const unzipArray: Array<JSZip.JSZipObject> = []; setProgress((i / unzipArray.length) * 100);
unziped.forEach((_, zipEntry) => { if (zipEntry.dir) {
unzipArray.push(zipEntry); await sys.fs.mkdir(join(path, zipEntry.name));
}); } else {
for (let i = 0; i < unzipArray.length; i++) { let fileC: any = await zipEntry.async("string");
const zipEntry = unzipArray[i]; //console.log(fileC);
setProgress((i / unzipArray.length) * 100); if (!fileC.startsWith("link::")) {
if (zipEntry.dir) { fileC = await zipEntry.async("arraybuffer");
await sys.fs.mkdir(join(path, zipEntry.name));
} else {
let fileC: any = await zipEntry.async("string");
//console.log(fileC);
if (!fileC.startsWith("link::")) {
fileC = await zipEntry.async("arraybuffer");
}
sys.fs.writeFile(join(path, zipEntry.name), fileC);
} }
sys.fs.writeFile(join(path, zipEntry.name), fileC);
} }
setProgress(100);
selectItem(1);
} catch (e) {
//console.log(e);
setTimeout(() => {
Dialog.showMessageBox({
message: "恢复失败",
type: "error",
}).finally(() => {
zipFile = undefined;
fileName.value = "";
setProgress(100);
});
}, 100);
} }
setProgress(100);
selectItem(1);
} catch (e) {
//console.log(e);
setTimeout(() => {
Dialog.showMessageBox({
message: "恢复失败",
type: "error",
}).finally(() => {
zipFile = undefined;
fileName.value = "";
setProgress(100);
});
}, 100);
} }
}
</script> </script>
<style scoped> <style scoped>
@import "./setStyle.css"; @import "./setStyle.css";
.ctrl { .ctrl {
width: 100px; width: 100px;
} }
.setting-item { .setting-item {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.setting-area {
width: 100%; .setting-area {
height: 90%; width: 100%;
} height: 90%;
}
</style> </style>

4
frontend/src/components/window/IframeFile.vue

@ -6,11 +6,11 @@
import { BrowserWindow, Dialog, Notify, System } from "@/system"; import { BrowserWindow, Dialog, Notify, System } from "@/system";
import { getSplit, getSystemConfig, setSystemKey } from "@/system/config"; import { getSplit, getSystemConfig, setSystemKey } from "@/system/config";
import { base64ToBuffer, isBase64 } from "@/util/file"; import { base64ToBuffer, isBase64 } from "@/util/file";
import { generateRandomString } from "@/util/common";
import { isShareFile } from "@/util/sharePath.ts"; import { isShareFile } from "@/util/sharePath.ts";
import { inject, onMounted, onUnmounted, ref, toRaw } from "vue"; import { inject, onMounted, onUnmounted, ref, toRaw } from "vue";
import { askAi } from "@/hook/useAi"; import { askAi } from "@/hook/useAi";
import { useChooseStore } from "@/stores/choose"; import { useChooseStore } from "@/stores/choose";
import { nanoid } from "nanoid";
import eventBus from "@/system/event/eventBus"; import eventBus from "@/system/event/eventBus";
const SP = getSplit(); const SP = getSplit();
@ -34,7 +34,7 @@ const storeRef = ref<HTMLIFrameElement | null>(null);
let hasInit = false; let hasInit = false;
const choose = useChooseStore(); const choose = useChooseStore();
const componentID = nanoid(); const componentID = generateRandomString(16);
// console.log("ID", componentID); // console.log("ID", componentID);
const saveFile = async (e: any) => { const saveFile = async (e: any) => {
if (e.componentID !== componentID) return; if (e.componentID !== componentID) return;

4
frontend/src/system/applist.ts

@ -81,8 +81,8 @@ export const appList = [
name: "document", name: "document",
appIcon: "word", appIcon: "word",
url: "/docx/index.html", url: "/docx/index.html",
//url:"http://localhost:3000/", //url:"http://localhost:9000/",
width: 800, width: 1000,
frame: true, frame: true,
height: 600, height: 600,
center: true, center: true,

6
frontend/src/system/config.ts

@ -82,6 +82,12 @@ export const getSystemConfig = (ifset = false) => {
if (!config.storePath) { if (!config.storePath) {
config.storePath = ""; config.storePath = "";
} }
if(!config.netPath) {
config.netPath = "";
}
if(!config.netPort) {
config.netPort = "56780";
}
if (!config.userType) { if (!config.userType) {
config.userType = 'person'; config.userType = 'person';
} }

9
frontend/src/util/goutil.ts

@ -1,3 +1,4 @@
import { getSystemKey } from "@/system/config";
export async function OpenDirDialog() { export async function OpenDirDialog() {
if ((window as any).go) { if ((window as any).go) {
return (window as any)['go']['app']['App']['OpenDirDialog'](); return (window as any)['go']['app']['App']['OpenDirDialog']();
@ -18,7 +19,13 @@ export async function checkUrl(url: string) {
} }
export function RestartApp() { export function RestartApp() {
if (!(window as any).go) { if (!(window as any).go) {
window.location.reload(); const apiUrl = getSystemKey("apiUrl");
fetch(apiUrl + "/system/restart").then(() => {
setTimeout(() => {
window.location.reload();
}, 1000);
})
//window.location.reload();
} else { } else {
return (window as any)['go']['app']['App']['RestartApp'](); return (window as any)['go']['app']['App']['RestartApp']();
} }

16
godo/cmd/main.go

@ -36,7 +36,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
const serverAddress = ":56780" //const serverAddress = ":56780"
var srv *http.Server var srv *http.Server
@ -83,6 +83,11 @@ func OsStart() {
router.HandleFunc("/system/message", sys.HandleSystemEvents).Methods(http.MethodGet) router.HandleFunc("/system/message", sys.HandleSystemEvents).Methods(http.MethodGet)
router.HandleFunc("/system/update", sys.UpdateAppHandler).Methods(http.MethodGet) router.HandleFunc("/system/update", sys.UpdateAppHandler).Methods(http.MethodGet)
router.HandleFunc("/system/setting", sys.ConfigHandler).Methods(http.MethodPost) router.HandleFunc("/system/setting", sys.ConfigHandler).Methods(http.MethodPost)
router.HandleFunc("/system/restart", func(w http.ResponseWriter, r *http.Request) {
go OsRestart() // 使用 goroutine 来避免阻塞当前请求
w.WriteHeader(http.StatusOK)
w.Write([]byte("Restart initiated"))
}).Methods(http.MethodGet)
fileRouter := router.PathPrefix("/file").Subrouter() fileRouter := router.PathPrefix("/file").Subrouter()
fileRouter.HandleFunc("/desktop", files.HandleDesktop).Methods(http.MethodGet) fileRouter.HandleFunc("/desktop", files.HandleDesktop).Methods(http.MethodGet)
@ -156,9 +161,12 @@ func OsStart() {
distFS, _ := fs.Sub(deps.Frontendassets, "dist") distFS, _ := fs.Sub(deps.Frontendassets, "dist")
fileServer := http.FileServer(http.FS(distFS)) fileServer := http.FileServer(http.FS(distFS))
//netPath := libs.GetNetPath()
router.PathPrefix("/").Handler(fileServer) router.PathPrefix("/").Handler(fileServer)
go store.CheckActive(context.Background()) go store.CheckActive(context.Background())
serverAddress := libs.GetSytemPort()
log.Printf("Listening on port: %v", serverAddress) log.Printf("Listening on port: %v", serverAddress)
srv = &http.Server{Addr: serverAddress, Handler: router} srv = &http.Server{Addr: serverAddress, Handler: router}
Serve(srv) Serve(srv)
@ -175,3 +183,9 @@ func OsStop() {
} }
log.Println("Server stopped.") log.Println("Server stopped.")
} }
func OsRestart() {
// 停止当前服务
OsStop()
// 重新启动服务
OsStart()
}

22
godo/libs/dir.go

@ -173,6 +173,28 @@ func GetVectorPath(name string) string {
dbDir := GetDbDir() dbDir := GetDbDir()
return filepath.Join(dbDir, "vector", hashHex+".db") return filepath.Join(dbDir, "vector", hashHex+".db")
} }
func GetSytemPort() string {
netPort, ok := GetConfig("netPort")
if !ok {
return ":56780"
}
portStr, ok := netPort.(string)
if !ok || portStr == "" {
return ":56780"
}
return ":" + portStr
}
func GetNetPath() string {
netPath, ok := GetConfig("netPath")
if !ok {
return "/"
}
pathStr, ok := netPath.(string)
if !ok || pathStr == "" {
return "/"
}
return "/" + pathStr
}
func GetCacheDir() string { func GetCacheDir() string {
homeDir := GetDataDir() homeDir := GetDataDir()
cachePath := filepath.Join(homeDir, "cache") cachePath := filepath.Join(homeDir, "cache")

Loading…
Cancel
Save