After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 413 B |
After Width: | Height: | Size: 337 B |
@ -1,204 +1,259 @@ |
|||
<script lang="ts" setup> |
|||
import { BrowserWindow, System } from "@/system"; |
|||
import { inject, onMounted, ref, toRaw, onUnmounted } from "vue"; |
|||
import { notifyError, notifySuccess } from "@/util/msg"; |
|||
import Vditor from "vditor"; |
|||
import "vditor/dist/index.css"; |
|||
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 { useHistoryStore } from "@/stores/history"; |
|||
import { BrowserWindow, System } from "@/system"; |
|||
import { getSplit, getSystemConfig } from "@/system/config"; |
|||
import { decodeBase64, isBase64 } from "@/util/file"; |
|||
import { notifyError, notifySuccess } from "@/util/msg"; |
|||
import { isShareFile } from "@/util/sharePath.ts"; |
|||
import { getMdOption } from "@/util/vditor"; |
|||
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(); |
|||
|
|||
const drawerBox = ref(false); |
|||
const baseTitle = ref(""); |
|||
const content = ref(""); |
|||
const sys: any = inject<System>("system"); |
|||
const win: any = inject<BrowserWindow>("browserWindow"); |
|||
const isSaveing = ref(false); |
|||
const vditor = ref(); |
|||
const filepath: any = ref(""); |
|||
const fileInput: any = ref(null); |
|||
const SP = getSplit(); |
|||
console.log(SP); |
|||
const drawerBox = ref(false); |
|||
const baseTitle = ref(""); |
|||
const content = ref(""); |
|||
const sys: any = inject<System>("system"); |
|||
const win: any = inject<BrowserWindow>("browserWindow"); |
|||
const isSaveing = ref(false); |
|||
const vditor = ref(); |
|||
const filepath: any = ref(""); |
|||
const fileInput: any = ref(null); |
|||
const SP = getSplit(); |
|||
console.log(SP); |
|||
|
|||
const debouncedHandleKeyDown = (event: KeyboardEvent) => { |
|||
// 确保仅在我们的按钮获得焦点时处理快捷键 |
|||
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "s") { |
|||
event.stopPropagation(); // 先阻止事件冒泡 |
|||
event.preventDefault(); // 再阻止默认行为 |
|||
if (!isSaveing.value) { |
|||
saveData(); |
|||
} |
|||
} |
|||
}; |
|||
const debouncedHandleKeyDown = (event: KeyboardEvent) => { |
|||
// 确保仅在我们的按钮获得焦点时处理快捷键 |
|||
if ( |
|||
(event.metaKey || event.ctrlKey) && |
|||
event.key.toLowerCase() === "s" |
|||
) { |
|||
event.stopPropagation(); // 先阻止事件冒泡 |
|||
event.preventDefault(); // 再阻止默认行为 |
|||
if (!isSaveing.value) { |
|||
saveData(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
const getDateTime = (t: any) => { |
|||
return moment(t).format("MM-DD HH:mm"); |
|||
}; |
|||
function getTitle() { |
|||
let title = win.getTitle(); |
|||
console.log(title); |
|||
if (title.indexOf(SP) > -1) { |
|||
title = title.split(SP).pop(); |
|||
title = title.split("."); |
|||
title.pop(); |
|||
return title.join("."); |
|||
} else { |
|||
return ""; |
|||
} |
|||
} |
|||
onMounted(async () => { |
|||
const editorOptions: any = getMdOption(); |
|||
editorOptions.input = (val: any) => { |
|||
content.value = val; |
|||
}; |
|||
const getDateTime = (t: any) => { |
|||
return moment(t).format("MM-DD HH:mm"); |
|||
}; |
|||
function getTitle() { |
|||
let title = win.getTitle(); |
|||
console.log(title); |
|||
if (title.indexOf(SP) > -1) { |
|||
title = title.split(SP).pop(); |
|||
title = title.split("."); |
|||
title.pop(); |
|||
return title.join("."); |
|||
} else { |
|||
return ""; |
|||
} |
|||
} |
|||
onMounted(async () => { |
|||
const editorOptions: any = getMdOption(); |
|||
editorOptions.input = (val: any) => { |
|||
content.value = val; |
|||
}; |
|||
|
|||
vditor.value = new Vditor("vditorContainer", editorOptions); |
|||
baseTitle.value = getTitle(); |
|||
if (win.config && win.config.content) { |
|||
let winContent = toRaw(win.config.content); |
|||
if (winContent && isBase64(winContent)) { |
|||
winContent = decodeBase64(winContent); |
|||
} |
|||
//console.log(winContent); |
|||
setTimeout(() => { |
|||
if (winContent && winContent != "") { |
|||
//console.log(winContent) |
|||
vditor.value.setValue(winContent); |
|||
} |
|||
}, 1000); |
|||
} |
|||
document.addEventListener("keydown", debouncedHandleKeyDown); |
|||
}); |
|||
// 清理监听器,确保组件卸载时移除,避免内存泄漏 |
|||
onUnmounted(() => { |
|||
document.removeEventListener("keydown", debouncedHandleKeyDown); |
|||
}); |
|||
vditor.value = new Vditor("vditorContainer", editorOptions); |
|||
baseTitle.value = getTitle(); |
|||
if (win.config && win.config.content) { |
|||
let winContent = toRaw(win.config.content); |
|||
if (winContent && isBase64(winContent)) { |
|||
winContent = decodeBase64(winContent); |
|||
} |
|||
//console.log(winContent); |
|||
setTimeout(() => { |
|||
if (winContent && winContent != "") { |
|||
//console.log(winContent) |
|||
vditor.value.setValue(winContent); |
|||
} |
|||
}, 1000); |
|||
} |
|||
document.addEventListener("keydown", debouncedHandleKeyDown); |
|||
}); |
|||
// 清理监听器,确保组件卸载时移除,避免内存泄漏 |
|||
onUnmounted(() => { |
|||
document.removeEventListener("keydown", debouncedHandleKeyDown); |
|||
}); |
|||
|
|||
async function saveData() { |
|||
if (isSaveing.value) { |
|||
return; |
|||
} |
|||
isSaveing.value = true; |
|||
if (baseTitle.value == "") { |
|||
notifyError("请输入标题"); |
|||
isSaveing.value = false; |
|||
return; |
|||
} |
|||
//console.log(win.config.path) |
|||
if (!filepath.value || filepath.value == "") { |
|||
filepath.value = `${SP}C${SP}Users${SP}Desktop${SP}${baseTitle.value}.md`; |
|||
} |
|||
let refreshDesktop = false; |
|||
if (win.config.path) { |
|||
filepath.value = win.config.path; |
|||
let fileTitleArr = filepath.value.split(SP).pop().split("."); |
|||
fileTitleArr.pop(); |
|||
const oldTitle = fileTitleArr.join("."); |
|||
if (oldTitle != baseTitle.value) { |
|||
filepath.value = filepath.value.replace(oldTitle, baseTitle.value); |
|||
refreshDesktop = true; |
|||
async function saveData() { |
|||
if (isSaveing.value) { |
|||
return; |
|||
} |
|||
isSaveing.value = true; |
|||
if (baseTitle.value == "") { |
|||
notifyError("请输入标题"); |
|||
isSaveing.value = false; |
|||
return; |
|||
} |
|||
//console.log(win.config.path) |
|||
if (!filepath.value || filepath.value == "") { |
|||
filepath.value = `${SP}C${SP}Users${SP}Desktop${SP}${baseTitle.value}.md`; |
|||
} |
|||
let refreshDesktop = false; |
|||
if (win.config.path) { |
|||
filepath.value = win.config.path; |
|||
let fileTitleArr = filepath.value.split(SP).pop().split("."); |
|||
fileTitleArr.pop(); |
|||
const oldTitle = fileTitleArr.join("."); |
|||
if (oldTitle != baseTitle.value) { |
|||
filepath.value = filepath.value.replace( |
|||
oldTitle, |
|||
baseTitle.value |
|||
); |
|||
refreshDesktop = true; |
|||
} |
|||
} else { |
|||
refreshDesktop = true; |
|||
} |
|||
let res |
|||
if (isShareFile(filepath.value)) { |
|||
const file = await sys?.fs.getShareInfo(filepath.value); |
|||
const isWrite = file.fs.sender === getSystemConfig().userInfo.id ? 1 : file.fs.is_write; |
|||
res = await sys?.fs.writeShareFile( |
|||
filepath.value, |
|||
vditor.value.getValue(), |
|||
isWrite |
|||
) |
|||
} else { |
|||
res = await sys?.fs.writeFile(filepath.value, vditor.value.getValue()); |
|||
} |
|||
} else { |
|||
refreshDesktop = true; |
|||
} |
|||
//console.log(path) |
|||
await sys?.fs.writeFile(filepath.value, vditor.value.getValue()); |
|||
notifySuccess("保存成功!"); |
|||
isSaveing.value = false; |
|||
if (refreshDesktop) { |
|||
sys.refershAppList(); |
|||
} |
|||
historyStore.addList("markdown", { |
|||
title: toRaw(baseTitle.value), |
|||
path: filepath.value, |
|||
time: Date.now(), |
|||
}); |
|||
} |
|||
function uploadFile(event: any) { |
|||
const file = event.target.files[0]; |
|||
if (!file) { |
|||
return; |
|||
} |
|||
const reader = new FileReader(); |
|||
reader.onload = (e: any) => { |
|||
baseTitle.value = file.name.substring(0, file.name.lastIndexOf(".")); |
|||
vditor.value.setValue(e.target.result); |
|||
}; |
|||
reader.readAsText(file); |
|||
} |
|||
function importMd() { |
|||
fileInput.value.click(); |
|||
} |
|||
function download() { |
|||
if (baseTitle.value == "") { |
|||
notifyError("标题不能为空"); |
|||
return; |
|||
} |
|||
const contentData = vditor.value.getValue(); |
|||
if (contentData == "") { |
|||
notifyError("内容不能为空"); |
|||
return; |
|||
} |
|||
let blob = new Blob([contentData], { type: "text/plain;charset=utf-8" }); |
|||
saveAs(blob, baseTitle.value + ".md"); |
|||
} |
|||
if (res && res.code !== -1) { |
|||
notifySuccess(res.message || "保存成功!"); |
|||
} else { |
|||
notifyError(res.message || "保存失败"); |
|||
} |
|||
|
|||
isSaveing.value = false; |
|||
if (refreshDesktop) { |
|||
sys.refershAppList(); |
|||
} |
|||
historyStore.addList("markdown", { |
|||
title: toRaw(baseTitle.value), |
|||
path: filepath.value, |
|||
time: Date.now(), |
|||
}); |
|||
} |
|||
function uploadFile(event: any) { |
|||
const file = event.target.files[0]; |
|||
if (!file) { |
|||
return; |
|||
} |
|||
const reader = new FileReader(); |
|||
reader.onload = (e: any) => { |
|||
baseTitle.value = file.name.substring( |
|||
0, |
|||
file.name.lastIndexOf(".") |
|||
); |
|||
vditor.value.setValue(e.target.result); |
|||
}; |
|||
reader.readAsText(file); |
|||
} |
|||
function importMd() { |
|||
fileInput.value.click(); |
|||
} |
|||
function download() { |
|||
if (baseTitle.value == "") { |
|||
notifyError("标题不能为空"); |
|||
return; |
|||
} |
|||
const contentData = vditor.value.getValue(); |
|||
if (contentData == "") { |
|||
notifyError("内容不能为空"); |
|||
return; |
|||
} |
|||
let blob = new Blob([contentData], { |
|||
type: "text/plain;charset=utf-8", |
|||
}); |
|||
saveAs(blob, baseTitle.value + ".md"); |
|||
} |
|||
</script> |
|||
<template> |
|||
<el-drawer |
|||
v-model="drawerBox" |
|||
direction="ltr" |
|||
style="height: 100vh" |
|||
:show-close="false" |
|||
:with-header="false" |
|||
> |
|||
<div |
|||
class="list-item" |
|||
v-for="(item, index) in historyStore.getList('markdown')" |
|||
:key="index" |
|||
> |
|||
<div class="list-title"> |
|||
<el-tooltip |
|||
class="box-item" |
|||
effect="dark" |
|||
:content="item.path" |
|||
placement="top-start" |
|||
> |
|||
{{ item.title }} |
|||
</el-tooltip> |
|||
</div> |
|||
<div class="list-time"> |
|||
{{ getDateTime(item.time) }} |
|||
</div> |
|||
</div> |
|||
</el-drawer> |
|||
<el-row justify="space-between" :gutter="20" :span="24" style="margin: 10px 20px"> |
|||
<el-col :span="5"> |
|||
<el-button @click.stop="drawerBox = !drawerBox" icon="Menu" circle /> |
|||
<el-button @click.stop="importMd" icon="Upload" circle /> |
|||
<el-drawer |
|||
v-model="drawerBox" |
|||
direction="ltr" |
|||
style="height: 100vh" |
|||
:show-close="false" |
|||
:with-header="false" |
|||
> |
|||
<div |
|||
class="list-item" |
|||
v-for="(item, index) in historyStore.getList('markdown')" |
|||
:key="index" |
|||
> |
|||
<div class="list-title"> |
|||
<el-tooltip |
|||
class="box-item" |
|||
effect="dark" |
|||
:content="item.path" |
|||
placement="top-start" |
|||
> |
|||
{{ item.title }} |
|||
</el-tooltip> |
|||
</div> |
|||
<div class="list-time"> |
|||
{{ getDateTime(item.time) }} |
|||
</div> |
|||
</div> |
|||
</el-drawer> |
|||
<el-row |
|||
justify="space-between" |
|||
:gutter="20" |
|||
:span="24" |
|||
style="margin: 10px 20px" |
|||
> |
|||
<el-col :span="5"> |
|||
<el-button |
|||
@click.stop="drawerBox = !drawerBox" |
|||
icon="Menu" |
|||
circle |
|||
/> |
|||
<el-button |
|||
@click.stop="importMd" |
|||
icon="Upload" |
|||
circle |
|||
/> |
|||
|
|||
<el-button @click.stop="download" icon="Download" circle /> |
|||
<input |
|||
type="file" |
|||
ref="fileInput" |
|||
accept=".md" |
|||
style="display: none" |
|||
@change="uploadFile" |
|||
/> |
|||
</el-col> |
|||
<el-col :span="15"> |
|||
<el-input v-model="baseTitle" placeholder="输入标题" /> |
|||
</el-col> |
|||
<el-col :span="2"> |
|||
<el-button @click.stop="saveData()" icon="Finished" :loading="isSaveing" circle /> |
|||
</el-col> |
|||
</el-row> |
|||
<div id="vditorContainer" style="margin: 10px 20px"></div> |
|||
<el-button |
|||
@click.stop="download" |
|||
icon="Download" |
|||
circle |
|||
/> |
|||
<input |
|||
type="file" |
|||
ref="fileInput" |
|||
accept=".md" |
|||
style="display: none" |
|||
@change="uploadFile" |
|||
/> |
|||
</el-col> |
|||
<el-col :span="15"> |
|||
<el-input |
|||
v-model="baseTitle" |
|||
placeholder="输入标题" |
|||
/> |
|||
</el-col> |
|||
<el-col :span="2"> |
|||
<el-button |
|||
@click.stop="saveData()" |
|||
icon="Finished" |
|||
:loading="isSaveing" |
|||
circle |
|||
/> |
|||
</el-col> |
|||
</el-row> |
|||
<div |
|||
id="vditorContainer" |
|||
style="margin: 10px 20px" |
|||
></div> |
|||
</template> |
|||
<style scoped> |
|||
@import "@/assets/left.scss"; |
|||
@import "@/assets/left.scss"; |
|||
</style> |
|||
|
@ -1,82 +1,114 @@ |
|||
<template> |
|||
<el-form :model="form" label-width="auto" style="max-width: 560px;margin-top:20px;padding: 20px;"> |
|||
<el-form-item label="分享给"> |
|||
<el-select 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> |
|||
<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-switch v-model="form.iswrite" active-value="1" inactive-value="0" /> |
|||
</el-form-item> |
|||
<div class="btn-group"> |
|||
<el-button type="primary" @click="onSubmit">发布分享</el-button> |
|||
</div> |
|||
</el-form> |
|||
<el-form |
|||
:model="form" |
|||
label-width="auto" |
|||
style="max-width: 560px; margin-top: 20px; padding: 20px" |
|||
> |
|||
<el-form-item label="分享给"> |
|||
<el-select |
|||
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> |
|||
<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-switch |
|||
v-model="form.iswrite" |
|||
active-value="1" |
|||
inactive-value="0" |
|||
/> |
|||
</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, inject, onMounted } from 'vue'; |
|||
import { useSystem, BrowserWindow } from '@/system'; |
|||
import { getSystemConfig, fetchPost } from "@/system/config"; |
|||
import { notifySuccess, notifyError } from "@/util/msg"; |
|||
const window: BrowserWindow | undefined = inject("browserWindow"); |
|||
const sys = useSystem() |
|||
const userInfo: any = sys.getConfig('userInfo') |
|||
let userList = ref(userInfo.user_shares) |
|||
const checkAll = ref(false) |
|||
const form: any = ref({ |
|||
senderid: '', |
|||
receverid: [], |
|||
path: '', |
|||
iswrite: '0' |
|||
}) |
|||
const config = ref(getSystemConfig()) |
|||
import { BrowserWindow, useSystem } from "@/system"; |
|||
import { fetchPost, getSystemConfig } from "@/system/config"; |
|||
import { notifyError, notifySuccess } from "@/util/msg"; |
|||
import { inject, onMounted, ref } from "vue"; |
|||
const window: BrowserWindow | undefined = inject("browserWindow"); |
|||
const sys = useSystem(); |
|||
const userInfo: any = sys.getConfig("userInfo"); |
|||
let userList = ref(userInfo.user_shares); |
|||
const checkAll = ref(false); |
|||
const form: any = ref({ |
|||
senderid: "", |
|||
receverid: [], |
|||
path: "", |
|||
iswrite: "0", |
|||
}); |
|||
const config = ref(getSystemConfig()); |
|||
|
|||
const handleCheckAll = (val: any) => { |
|||
if (val) { |
|||
form.value.receverid = userList.value.map((d: any) => d.value) |
|||
} else { |
|||
form.value.receverid.value = [] |
|||
} |
|||
} |
|||
const checkUsers = (val: any) => { |
|||
const res:any = [] |
|||
val.forEach((item: any) => { |
|||
if(item){ |
|||
res.push(item) |
|||
} |
|||
}) |
|||
form.value.receverid = res |
|||
} |
|||
const onSubmit = async () => { |
|||
const apiUrl = config.value.userInfo.url + '/files/share' |
|||
form.value.senderid = config.value.userInfo.id |
|||
form.value.path = window?.config.path || '' |
|||
const temp = {...form.value} |
|||
temp.senderid = temp.senderid.toString() |
|||
temp.receverid = temp.receverid.map((item:any) => item.toString()) |
|||
const res = await fetchPost(apiUrl, new URLSearchParams(temp)) |
|||
if (res.ok) { |
|||
notifySuccess("分享文件成功") |
|||
} else { |
|||
notifyError("分享文件失败") |
|||
} |
|||
} |
|||
onMounted(() => { |
|||
userList.value = userList.value.filter((item: any)=> { |
|||
return item?.id !== config.value.userInfo.id |
|||
}) |
|||
}) |
|||
const handleCheckAll = (val: any) => { |
|||
if (val) { |
|||
form.value.receverid = userList.value.map((d: any) => d.value); |
|||
} else { |
|||
form.value.receverid.value = []; |
|||
} |
|||
}; |
|||
const checkUsers = (val: any) => { |
|||
const res: any = []; |
|||
val.forEach((item: any) => { |
|||
if (item) { |
|||
res.push(item); |
|||
} |
|||
}); |
|||
form.value.receverid = res; |
|||
}; |
|||
const onSubmit = async () => { |
|||
const apiUrl = config.value.userInfo.url + "/files/share"; |
|||
form.value.senderid = config.value.userInfo.id; |
|||
form.value.path = window?.config.path || ""; |
|||
const temp = { ...form.value }; |
|||
temp.senderid = temp.senderid.toString(); |
|||
temp.receverid = temp.receverid.map((item: any) => item.toString()); |
|||
const res = await fetchPost(apiUrl, new URLSearchParams(temp)); |
|||
const result = await res.json(); |
|||
if (res.ok) { |
|||
notifySuccess(result.message || "分享文件成功"); |
|||
} else { |
|||
notifyError(result.message || "分享文件失败"); |
|||
} |
|||
}; |
|||
onMounted(() => { |
|||
userList.value = userList.value.filter((item: any) => { |
|||
return item?.id !== config.value.userInfo.id; |
|||
}); |
|||
}); |
|||
</script> |
|||
<style scoped> |
|||
.btn-group{ |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
</style> |
|||
.btn-group { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
</style> |
|||
|
@ -1,81 +1,106 @@ |
|||
<template> |
|||
<div class="file-pwd-box"> |
|||
<div v-if="setPwd"> |
|||
<div class="setting-item" > |
|||
<label>文件密码</label> |
|||
<el-input v-model="filePwd" placeholder="请设置6-10位的密码" type="password" show-password/> |
|||
</div> |
|||
<div class="setting-item"> |
|||
<label></label> |
|||
<el-button @click="toSetFilePwd" type="primary">{{ t("setFilePwd") }}</el-button> |
|||
<el-button @click="clearPwd" type="primary">取消文件加密</el-button> |
|||
</div> |
|||
</div> |
|||
<div v-else class="setting-item"> |
|||
<label></label> |
|||
<el-button @click="setPwd = true" type="primary">设置文件密码</el-button> |
|||
</div> |
|||
</div> |
|||
<div class="file-pwd-box"> |
|||
<div v-if="setPwd"> |
|||
<div class="setting-item"> |
|||
<label>文件密码</label> |
|||
<el-input |
|||
v-model="filePwd" |
|||
placeholder="请设置6-10位的密码" |
|||
type="password" |
|||
show-password |
|||
/> |
|||
</div> |
|||
<div class="setting-item"> |
|||
<label></label> |
|||
<el-button |
|||
@click="toSetFilePwd" |
|||
type="primary" |
|||
>{{ t("setFilePwd") }}</el-button |
|||
> |
|||
<el-button |
|||
@click="clearPwd" |
|||
type="primary" |
|||
>取消文件加密</el-button |
|||
> |
|||
</div> |
|||
</div> |
|||
<div |
|||
v-else |
|||
class="setting-item" |
|||
> |
|||
<label></label> |
|||
<el-button |
|||
@click="setPwd = true" |
|||
type="primary" |
|||
>设置文件密码</el-button |
|||
> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import { md5 } from "js-md5"; |
|||
import { ref, onMounted } from "vue"; |
|||
import { t } from "@/system"; |
|||
import { fetchGet, getApiUrl, setSystemKey, getSystemConfig } from "@/system/config"; |
|||
import { notifySuccess, notifyError } from "@/util/msg"; |
|||
const filePwd = ref('') |
|||
const setPwd = ref(false) |
|||
const config = getSystemConfig() |
|||
const params = { |
|||
isPwd: 1, |
|||
pwd: '', |
|||
salt: getSystemConfig().file.salt |
|||
} |
|||
// 设置文件密码 |
|||
async function toSetFilePwd() { |
|||
if (filePwd.value.length < 6 || filePwd.value.length > 10) { |
|||
notifyError("密码长度应该在6-10位之间") |
|||
return |
|||
} |
|||
params.pwd = md5(filePwd.value) |
|||
params.isPwd = filePwd.value === '' ? 0 : 1 |
|||
const url = getApiUrl() + '/file/setfilepwd' |
|||
const header = { |
|||
'Salt': params.salt ? params.salt : 'vIf_wIUedciAd0nTm6qjJA==', |
|||
'FilePwd': params.pwd |
|||
} |
|||
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=${params.isPwd}`) |
|||
const res = await fetchGet(url, header) |
|||
if (res.ok){ |
|||
notifySuccess("设置文件密码成功"); |
|||
} else { |
|||
params.isPwd = 0 |
|||
params.pwd = '' |
|||
notifyError("设置文件密码失败") |
|||
} |
|||
setSystemKey('file',params) |
|||
} |
|||
async function clearPwd() { |
|||
setPwd.value = false |
|||
filePwd.value = '' |
|||
params.isPwd = 0 |
|||
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=0`) |
|||
setSystemKey('file',params) |
|||
} |
|||
onMounted(() => { |
|||
params.isPwd = config.file.isPwd |
|||
setPwd.value = params.isPwd ? true : false |
|||
}) |
|||
import { t } from "@/system"; |
|||
import { |
|||
fetchGet, |
|||
getApiUrl, |
|||
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 = { |
|||
isPwd: 1, |
|||
pwd: "", |
|||
salt: getSystemConfig().file.salt, |
|||
}; |
|||
// 设置文件密码 |
|||
async function toSetFilePwd() { |
|||
if (filePwd.value.length < 6 || filePwd.value.length > 10) { |
|||
notifyError("密码长度应该在6-10位之间"); |
|||
return; |
|||
} |
|||
params.pwd = md5(filePwd.value); |
|||
params.isPwd = filePwd.value === "" ? 0 : 1; |
|||
const url = getApiUrl() + "/file/setfilepwd"; |
|||
const header = { |
|||
salt: params.salt ? params.salt : "vIf_wIUedciAd0nTm6qjJA==", |
|||
pwd: params.pwd, |
|||
}; |
|||
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=${params.isPwd}`); |
|||
const res = await fetchGet(url, header); |
|||
if (res.ok) { |
|||
notifySuccess("设置文件密码成功"); |
|||
} else { |
|||
params.isPwd = 0; |
|||
params.pwd = ""; |
|||
notifyError("设置文件密码失败"); |
|||
} |
|||
setSystemKey("file", params); |
|||
} |
|||
async function clearPwd() { |
|||
setPwd.value = false; |
|||
filePwd.value = ""; |
|||
params.isPwd = 0; |
|||
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=0`); |
|||
setSystemKey("file", params); |
|||
} |
|||
onMounted(() => { |
|||
params.isPwd = config.file.isPwd; |
|||
setPwd.value = params.isPwd ? true : false; |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
@import "./setStyle.css"; |
|||
.file-pwd-box { |
|||
padding-top: 20px; |
|||
} |
|||
.setting-item { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
@import "./setStyle.css"; |
|||
.file-pwd-box { |
|||
padding-top: 20px; |
|||
} |
|||
.setting-item { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,21 @@ |
|||
module.exports = { |
|||
root: true, |
|||
env: { browser: true, es2020: true }, |
|||
extends: [ |
|||
'eslint:recommended', |
|||
'plugin:react/recommended', |
|||
'plugin:react/jsx-runtime', |
|||
'plugin:react-hooks/recommended', |
|||
], |
|||
ignorePatterns: ['dist', '.eslintrc.cjs'], |
|||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, |
|||
settings: { react: { version: '18.2' } }, |
|||
plugins: ['react-refresh'], |
|||
rules: { |
|||
'react/jsx-no-target-blank': 'off', |
|||
'react-refresh/only-export-components': [ |
|||
'warn', |
|||
{ allowConstantExport: true }, |
|||
], |
|||
}, |
|||
} |
@ -0,0 +1,24 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
pnpm-debug.log* |
|||
lerna-debug.log* |
|||
|
|||
node_modules |
|||
dist |
|||
dist-ssr |
|||
*.local |
|||
|
|||
# Editor directories and files |
|||
.vscode/* |
|||
!.vscode/extensions.json |
|||
.idea |
|||
.DS_Store |
|||
*.suo |
|||
*.ntvs* |
|||
*.njsproj |
|||
*.sln |
|||
*.sw? |
@ -0,0 +1 @@ |
|||
# use the tldraw library |
@ -0,0 +1,13 @@ |
|||
<!doctype html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>draw</title> |
|||
</head> |
|||
<body> |
|||
<div id="root"></div> |
|||
<script type="module" src="/src/main.jsx"></script> |
|||
</body> |
|||
</html> |
@ -0,0 +1,31 @@ |
|||
{ |
|||
"name": "mydraw", |
|||
"private": true, |
|||
"version": "0.0.0", |
|||
"type": "module", |
|||
"scripts": { |
|||
"dev": "vite", |
|||
"build": "vite build", |
|||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", |
|||
"preview": "vite preview" |
|||
}, |
|||
"dependencies": { |
|||
"@tldraw/assets": "^2.1.4", |
|||
"react": "^18.2.0", |
|||
"react-dom": "^18.2.0", |
|||
"tldraw": "^2.1.4" |
|||
}, |
|||
"devDependencies": { |
|||
"@types/react": "^18.2.66", |
|||
"@types/react-dom": "^18.2.22", |
|||
"@vitejs/plugin-react": "^4.2.1", |
|||
"autoprefixer": "^10.4.19", |
|||
"eslint": "^8.57.0", |
|||
"eslint-plugin-react": "^7.34.1", |
|||
"eslint-plugin-react-hooks": "^4.6.0", |
|||
"eslint-plugin-react-refresh": "^0.4.6", |
|||
"postcss": "^8.4.38", |
|||
"tailwindcss": "^3.4.4", |
|||
"vite": "^5.2.0" |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
export default { |
|||
plugins: { |
|||
tailwindcss: {}, |
|||
autoprefixer: {}, |
|||
}, |
|||
} |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 846 B |
After Width: | Height: | Size: 977 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 962 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 769 B |
After Width: | Height: | Size: 526 B |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 625 B |
After Width: | Height: | Size: 540 B |
After Width: | Height: | Size: 864 B |
After Width: | Height: | Size: 846 B |
After Width: | Height: | Size: 395 KiB |
After Width: | Height: | Size: 387 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 396 KiB |
After Width: | Height: | Size: 388 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 320 B |
After Width: | Height: | Size: 501 B |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 340 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 473 B |
After Width: | Height: | Size: 291 B |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 496 B |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 182 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 621 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 1000 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 645 B |
After Width: | Height: | Size: 746 B |
After Width: | Height: | Size: 494 B |
After Width: | Height: | Size: 481 B |
After Width: | Height: | Size: 488 B |
After Width: | Height: | Size: 485 B |
After Width: | Height: | Size: 481 B |
After Width: | Height: | Size: 285 B |
After Width: | Height: | Size: 285 B |
After Width: | Height: | Size: 893 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 149 B |
After Width: | Height: | Size: 618 B |
After Width: | Height: | Size: 885 B |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 532 B |
After Width: | Height: | Size: 170 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 699 B |
After Width: | Height: | Size: 656 B |
After Width: | Height: | Size: 154 B |