Browse Source

fix:前端文件bug修复

master
prr 7 months ago
parent
commit
5c7d8dd671
  1. 95
      frontend/src/components/builtin/MarkDown.vue
  2. 114
      frontend/src/components/oa/ShareFiles.vue
  3. 99
      frontend/src/components/setting/SetFilePwd.vue
  4. 5
      frontend/src/components/window/IframeFile.vue
  5. 1
      frontend/src/system/core/FileOs.ts
  6. 2
      godo/cmd/serve.go

95
frontend/src/components/builtin/MarkDown.vue

@ -1,15 +1,15 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useHistoryStore } from "@/stores/history";
import { BrowserWindow, System } from "@/system"; import { BrowserWindow, System } from "@/system";
import { inject, onMounted, ref, toRaw, onUnmounted } from "vue"; import { getSplit, getSystemConfig } from "@/system/config";
import { decodeBase64, isBase64 } from "@/util/file";
import { notifyError, notifySuccess } from "@/util/msg"; import { notifyError, notifySuccess } from "@/util/msg";
import Vditor from "vditor";
import "vditor/dist/index.css";
import { getMdOption } from "@/util/vditor"; import { getMdOption } from "@/util/vditor";
import { isBase64, decodeBase64 } from "@/util/file";
import moment from "moment";
import { useHistoryStore } from "@/stores/history";
import { getSplit } from "@/system/config";
import { saveAs } from "file-saver"; import { saveAs } from "file-saver";
import moment from "moment";
import Vditor from "vditor";
import "vditor/dist/index.css";
import { inject, onMounted, onUnmounted, ref, toRaw } from "vue";
const historyStore = useHistoryStore(); const historyStore = useHistoryStore();
@ -27,7 +27,10 @@ console.log(SP);
const debouncedHandleKeyDown = (event: KeyboardEvent) => { const debouncedHandleKeyDown = (event: KeyboardEvent) => {
// //
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "s") { if (
(event.metaKey || event.ctrlKey) &&
event.key.toLowerCase() === "s"
) {
event.stopPropagation(); // event.stopPropagation(); //
event.preventDefault(); // event.preventDefault(); //
if (!isSaveing.value) { if (!isSaveing.value) {
@ -100,15 +103,34 @@ async function saveData() {
fileTitleArr.pop(); fileTitleArr.pop();
const oldTitle = fileTitleArr.join("."); const oldTitle = fileTitleArr.join(".");
if (oldTitle != baseTitle.value) { if (oldTitle != baseTitle.value) {
filepath.value = filepath.value.replace(oldTitle, baseTitle.value); filepath.value = filepath.value.replace(
oldTitle,
baseTitle.value
);
refreshDesktop = true; refreshDesktop = true;
} }
} else { } else {
refreshDesktop = true; refreshDesktop = true;
} }
const file = await sys?.fs.getShareInfo(filepath.value);
const isWrite =
file.fs.sender === getSystemConfig().userInfo.id
? 1
: file.fs.is_write;
//console.log(path) //console.log(path)
await sys?.fs.writeFile(filepath.value, vditor.value.getValue()); const res = file.fi.isShare
notifySuccess("保存成功!"); ? await sys?.fs.writeShareFile(
filepath.value,
vditor.value.getValue(),
isWrite
)
: await sys?.fs.writeFile(filepath.value, vditor.value.getValue());
if (res.success) {
notifySuccess(res.message || "保存成功!");
} else {
notifyError(res.message || "保存失败");
}
isSaveing.value = false; isSaveing.value = false;
if (refreshDesktop) { if (refreshDesktop) {
sys.refershAppList(); sys.refershAppList();
@ -126,7 +148,10 @@ function uploadFile(event: any) {
} }
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e: any) => { reader.onload = (e: any) => {
baseTitle.value = file.name.substring(0, file.name.lastIndexOf(".")); baseTitle.value = file.name.substring(
0,
file.name.lastIndexOf(".")
);
vditor.value.setValue(e.target.result); vditor.value.setValue(e.target.result);
}; };
reader.readAsText(file); reader.readAsText(file);
@ -144,7 +169,9 @@ function download() {
notifyError("内容不能为空"); notifyError("内容不能为空");
return; return;
} }
let blob = new Blob([contentData], { type: "text/plain;charset=utf-8" }); let blob = new Blob([contentData], {
type: "text/plain;charset=utf-8",
});
saveAs(blob, baseTitle.value + ".md"); saveAs(blob, baseTitle.value + ".md");
} }
</script> </script>
@ -176,12 +203,29 @@ function download() {
</div> </div>
</div> </div>
</el-drawer> </el-drawer>
<el-row justify="space-between" :gutter="20" :span="24" style="margin: 10px 20px"> <el-row
justify="space-between"
:gutter="20"
:span="24"
style="margin: 10px 20px"
>
<el-col :span="5"> <el-col :span="5">
<el-button @click.stop="drawerBox = !drawerBox" icon="Menu" circle /> <el-button
<el-button @click.stop="importMd" icon="Upload" circle /> @click.stop="drawerBox = !drawerBox"
icon="Menu"
circle
/>
<el-button
@click.stop="importMd"
icon="Upload"
circle
/>
<el-button @click.stop="download" icon="Download" circle /> <el-button
@click.stop="download"
icon="Download"
circle
/>
<input <input
type="file" type="file"
ref="fileInput" ref="fileInput"
@ -191,13 +235,24 @@ function download() {
/> />
</el-col> </el-col>
<el-col :span="15"> <el-col :span="15">
<el-input v-model="baseTitle" placeholder="输入标题" /> <el-input
v-model="baseTitle"
placeholder="输入标题"
/>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<el-button @click.stop="saveData()" icon="Finished" :loading="isSaveing" circle /> <el-button
@click.stop="saveData()"
icon="Finished"
:loading="isSaveing"
circle
/>
</el-col> </el-col>
</el-row> </el-row>
<div id="vditorContainer" style="margin: 10px 20px"></div> <div
id="vditorContainer"
style="margin: 10px 20px"
></div>
</template> </template>
<style scoped> <style scoped>
@import "@/assets/left.scss"; @import "@/assets/left.scss";

114
frontend/src/components/oa/ShareFiles.vue

@ -1,78 +1,110 @@
<template> <template>
<el-form :model="form" label-width="auto" style="max-width: 560px;margin-top:20px;padding: 20px;"> <el-form
:model="form"
label-width="auto"
style="max-width: 560px; margin-top: 20px; padding: 20px"
>
<el-form-item label="分享给"> <el-form-item label="分享给">
<el-select v-model="form.receverid" filterable multiple clearable collapse-tags placeholder="选择人员" <el-select
popper-class="custom-header" :max-collapse-tags="1" value-key="id" style="width: 240px" @change="checkUsers"> v-model="form.receverid"
filterable
multiple
clearable
collapse-tags
placeholder="选择人员"
popper-class="custom-header"
:max-collapse-tags="1"
value-key="id"
style="width: 240px"
@change="checkUsers"
>
<template #header> <template #header>
<el-checkbox v-model="checkAll" @change="handleCheckAll"> <el-checkbox
v-model="checkAll"
@change="handleCheckAll"
>
全选 全选
</el-checkbox> </el-checkbox>
</template> </template>
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /> <el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="编辑权限"> <el-form-item label="编辑权限">
<el-switch v-model="form.iswrite" active-value="1" inactive-value="0" /> <el-switch
v-model="form.iswrite"
active-value="1"
inactive-value="0"
/>
</el-form-item> </el-form-item>
<div class="btn-group"> <div class="btn-group">
<el-button type="primary" @click="onSubmit">发布分享</el-button> <el-button
type="primary"
@click="onSubmit"
>发布分享</el-button
>
</div> </div>
</el-form> </el-form>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, inject, onMounted } from 'vue'; import { BrowserWindow, useSystem } from "@/system";
import { useSystem, BrowserWindow } from '@/system'; import { fetchPost, getSystemConfig } from "@/system/config";
import { getSystemConfig, fetchPost } from "@/system/config"; import { notifyError, notifySuccess } from "@/util/msg";
import { notifySuccess, notifyError } from "@/util/msg"; import { inject, onMounted, ref } from "vue";
const window: BrowserWindow | undefined = inject("browserWindow"); const window: BrowserWindow | undefined = inject("browserWindow");
const sys = useSystem() const sys = useSystem();
const userInfo: any = sys.getConfig('userInfo') const userInfo: any = sys.getConfig("userInfo");
let userList = ref(userInfo.user_shares) let userList = ref(userInfo.user_shares);
const checkAll = ref(false) const checkAll = ref(false);
const form: any = ref({ const form: any = ref({
senderid: '', senderid: "",
receverid: [], receverid: [],
path: '', path: "",
iswrite: '0' iswrite: "0",
}) });
const config = ref(getSystemConfig()) const config = ref(getSystemConfig());
const handleCheckAll = (val: any) => { const handleCheckAll = (val: any) => {
if (val) { if (val) {
form.value.receverid = userList.value.map((d: any) => d.value) form.value.receverid = userList.value.map((d: any) => d.value);
} else { } else {
form.value.receverid.value = [] form.value.receverid.value = [];
}
} }
};
const checkUsers = (val: any) => { const checkUsers = (val: any) => {
const res:any = [] const res: any = [];
val.forEach((item: any) => { val.forEach((item: any) => {
if (item) { if (item) {
res.push(item) res.push(item);
}
})
form.value.receverid = res
} }
});
form.value.receverid = res;
};
const onSubmit = async () => { const onSubmit = async () => {
const apiUrl = config.value.userInfo.url + '/files/share' const apiUrl = config.value.userInfo.url + "/files/share";
form.value.senderid = config.value.userInfo.id form.value.senderid = config.value.userInfo.id;
form.value.path = window?.config.path || '' form.value.path = window?.config.path || "";
const temp = {...form.value} const temp = { ...form.value };
temp.senderid = temp.senderid.toString() temp.senderid = temp.senderid.toString();
temp.receverid = temp.receverid.map((item:any) => item.toString()) temp.receverid = temp.receverid.map((item: any) => item.toString());
const res = await fetchPost(apiUrl, new URLSearchParams(temp)) const res = await fetchPost(apiUrl, new URLSearchParams(temp));
const result = await res.json();
if (res.ok) { if (res.ok) {
notifySuccess("分享文件成功") notifySuccess(result.message || "分享文件成功");
} else { } else {
notifyError("分享文件失败") notifyError(result.message || "分享文件失败");
}
} }
};
onMounted(() => { onMounted(() => {
userList.value = userList.value.filter((item: any) => { userList.value = userList.value.filter((item: any) => {
return item?.id !== config.value.userInfo.id return item?.id !== config.value.userInfo.id;
}) });
}) });
</script> </script>
<style scoped> <style scoped>
.btn-group { .btn-group {

99
frontend/src/components/setting/SetFilePwd.vue

@ -3,70 +3,95 @@
<div v-if="setPwd"> <div v-if="setPwd">
<div class="setting-item"> <div class="setting-item">
<label>文件密码</label> <label>文件密码</label>
<el-input v-model="filePwd" placeholder="请设置6-10位的密码" type="password" show-password/> <el-input
v-model="filePwd"
placeholder="请设置6-10位的密码"
type="password"
show-password
/>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<label></label> <label></label>
<el-button @click="toSetFilePwd" type="primary">{{ t("setFilePwd") }}</el-button> <el-button
<el-button @click="clearPwd" type="primary">取消文件加密</el-button> @click="toSetFilePwd"
type="primary"
>{{ t("setFilePwd") }}</el-button
>
<el-button
@click="clearPwd"
type="primary"
>取消文件加密</el-button
>
</div> </div>
</div> </div>
<div v-else class="setting-item"> <div
v-else
class="setting-item"
>
<label></label> <label></label>
<el-button @click="setPwd = true" type="primary">设置文件密码</el-button> <el-button
@click="setPwd = true"
type="primary"
>设置文件密码</el-button
>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { md5 } from "js-md5";
import { ref, onMounted } from "vue";
import { t } from "@/system"; import { t } from "@/system";
import { fetchGet, getApiUrl, setSystemKey, getSystemConfig } from "@/system/config"; import {
import { notifySuccess, notifyError } from "@/util/msg"; fetchGet,
const filePwd = ref('') getApiUrl,
const setPwd = ref(false) getSystemConfig,
const config = getSystemConfig() setSystemKey,
} from "@/system/config";
import { notifyError, notifySuccess } from "@/util/msg";
import { md5 } from "js-md5";
import { onMounted, ref } from "vue";
const filePwd = ref("");
const setPwd = ref(false);
const config = getSystemConfig();
const params = { const params = {
isPwd: 1, isPwd: 1,
pwd: '', pwd: "",
salt: getSystemConfig().file.salt salt: getSystemConfig().file.salt,
} };
// //
async function toSetFilePwd() { async function toSetFilePwd() {
if (filePwd.value.length < 6 || filePwd.value.length > 10) { if (filePwd.value.length < 6 || filePwd.value.length > 10) {
notifyError("密码长度应该在6-10位之间") notifyError("密码长度应该在6-10位之间");
return return;
} }
params.pwd = md5(filePwd.value) params.pwd = md5(filePwd.value);
params.isPwd = filePwd.value === '' ? 0 : 1 params.isPwd = filePwd.value === "" ? 0 : 1;
const url = getApiUrl() + '/file/setfilepwd' const url = getApiUrl() + "/file/setfilepwd";
const header = { const header = {
'Salt': params.salt ? params.salt : 'vIf_wIUedciAd0nTm6qjJA==', salt: params.salt ? params.salt : "vIf_wIUedciAd0nTm6qjJA==",
'FilePwd': params.pwd pwd: params.pwd,
} };
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=${params.isPwd}`) await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=${params.isPwd}`);
const res = await fetchGet(url, header) const res = await fetchGet(url, header);
if (res.ok) { if (res.ok) {
notifySuccess("设置文件密码成功"); notifySuccess("设置文件密码成功");
} else { } else {
params.isPwd = 0 params.isPwd = 0;
params.pwd = '' params.pwd = "";
notifyError("设置文件密码失败") notifyError("设置文件密码失败");
} }
setSystemKey('file',params) setSystemKey("file", params);
} }
async function clearPwd() { async function clearPwd() {
setPwd.value = false setPwd.value = false;
filePwd.value = '' filePwd.value = "";
params.isPwd = 0 params.isPwd = 0;
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=0`) await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=0`);
setSystemKey('file',params) setSystemKey("file", params);
} }
onMounted(() => { onMounted(() => {
params.isPwd = config.file.isPwd params.isPwd = config.file.isPwd;
setPwd.value = params.isPwd ? true : false setPwd.value = params.isPwd ? true : false;
}) });
</script> </script>
<style scoped> <style scoped>

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

@ -75,7 +75,7 @@
if (isShareFile(path)) { if (isShareFile(path)) {
const file = await sys?.fs.getShareInfo(path); const file = await sys?.fs.getShareInfo(path);
isShare.value = true; isShare.value = true;
isWrite.value = file.fs.is_write; isWrite.value = file.fs.sender === getSystemConfig().userInfo.id ? 1 : file.fs.is_write;
if ( if (
!isWrite.value && !isWrite.value &&
file.fs.sender !== getSystemConfig().userInfo.id file.fs.sender !== getSystemConfig().userInfo.id
@ -119,7 +119,8 @@
// console.log("", res, isShare); // console.log("", res, isShare);
new Notify({ new Notify({
title: "提示", title: "提示",
content: res.code === 0 ? "文件已保存" : "文件保存失败", content: res.message
// content: res.code === 0 ? "" : res.message,
}); });
sys.refershAppList(); sys.refershAppList();
} else if (eventData.type == "initSuccess") { } else if (eventData.type == "initSuccess") {

1
frontend/src/system/core/FileOs.ts

@ -427,7 +427,6 @@ export const useOsFile = () => {
} }
} }
} }
//console.log('创建露肩:', path);
const response = await handleWriteFile(path, content, head); const response = await handleWriteFile(path, content, head);
if (response) { if (response) {

2
godo/cmd/serve.go

@ -86,7 +86,7 @@ func (l loggingMiddleware) Middleware(next http.Handler) http.Handler {
// CORS 中间件 // CORS 中间件
func corsMiddleware() mux.MiddlewareFunc { func corsMiddleware() mux.MiddlewareFunc {
allowHeaders := "Content-Type, Accept, Authorization, Origin,filePwd,salt" allowHeaders := "Content-Type, Accept, Authorization, Origin,pwd,salt"
allowMethods := "GET, POST, PUT, DELETE, OPTIONS" allowMethods := "GET, POST, PUT, DELETE, OPTIONS"
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {

Loading…
Cancel
Save