Browse Source

fix:文件加密修复

master
prr 7 months ago
parent
commit
c7eb5f72e2
  1. 3
      frontend/auto-imports.d.ts
  2. 17
      frontend/src/components/builtin/FileList.vue
  3. 8
      frontend/src/components/builtin/FileTree.vue
  4. 131
      frontend/src/components/chat/ChatUserSetting.vue
  5. 9
      frontend/src/components/computer/Computer.vue
  6. 12
      frontend/src/components/setting/SetFilePwd.vue
  7. 25
      frontend/src/components/window/IframeFile.vue
  8. 9
      frontend/src/hook/useComputer.ts
  9. 45
      frontend/src/system/core/FileOs.ts
  10. 1
      frontend/src/system/core/FileSystem.ts
  11. 17
      frontend/src/util/sharePath.ts

3
frontend/auto-imports.d.ts

@ -3,7 +3,6 @@
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
@ -71,6 +70,6 @@ declare global {
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}

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

@ -130,6 +130,8 @@ function handleOnOpen(item: OsFileWithoutContent) {
choose.path.push(item.path)
choose.close()
} else {
// console.log(' file list:',props.fileList);
props.onOpen(item);
emitEvent('desktop.app.open');
}
@ -239,6 +241,7 @@ function startDragApp(mouse: DragEvent, item: OsFileWithoutContent) {
}
function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index: number) {
if (chosenIndexs.value.length <= 1) {
chosenIndexs.value = [props.fileList.findIndex((app) => app.path === item.path)];
}
@ -280,7 +283,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
// },
];
if (item.isDirectory) {
if (item.isDirectory && !item.isShare) {
if (getSystemKey('storeType') == 'local') {
menuArr.push({
label: t('zip'),
@ -364,7 +367,10 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
chosenIndexs.value = [];
},
},
{
];
if (item.isShare && item.path.indexOf('/F/othershare') !== 0) {
fileMenus.push({
label: t('delete'),
click: async () => {
for (let i = 0; i < chosenIndexs.value.length; i++) {
@ -376,11 +382,10 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
sys.refershAppList()
}
},
},
];
})
}
const userType = sys.getConfig('userType');
if (userType == 'member') {
if (userType == 'member' && !item.isShare) {
menuArr.push(
{

8
frontend/src/components/builtin/FileTree.vue

@ -127,8 +127,14 @@ async function onOpenArrow(item: FileWithOpen) {
if (item.isOpen && !item.subFileList?.length) {
return;
}
item.isOpen = !item.isOpen;
if(isShareFile(item.path)) {
// if (item.isShare) {
// item.subFileList = (await sys.fs.readShareFileDir(getSystemConfig().userInfo.id, item?.path)).filter((file:any) => {
// return file.isDirectory;
// });
// } else
if(isShareFile(item.path)) {
item.subFileList = (await sys.fs.sharedir(getSystemConfig().userInfo.id, item?.path)).filter((file:any) => {
return file.isDirectory;
});

131
frontend/src/components/chat/ChatUserSetting.vue

@ -1,35 +1,100 @@
<script setup>
import { ref } from "vue";
import { useChatStore } from "@/stores/chat";
const store = useChatStore()
const form = ref({
nickname: '',
})
<script setup>
import { t } from '@/i18n';
import { ref, onMounted } from "vue";
import { useChatStore } from "@/stores/chat";
import { fetchGet, getSystemConfig } from "@/system/config";
const store = useChatStore()
const form = ref({
nickname: '',
})
const userInfo = getSystemConfig().userInfo
const dialogShow = ref(false)
let imgList = reactive([])
const showChange = (val) =>{
dialogShow.value = val
}
const toChangeHead = ()=>{
console.log('换头像');
}
//
const getHeadList = async() => {
const res = await fetchGet(`${userInfo.url}/files/avatarlist`)
if (res.ok) {
imgList = await res.json()
imgList = imgList.data.map(item => {
item.isChoose = false
return item
})
imgList[0].isChoose = true
}
console.log('imgList:' , imgList);
}
let pos = ref(0)
//
const chooseImg = (index) => {
imgList.forEach(item => item.isChoose = false)
imgList[index].isChoose = true
pos.value = index
}
const onSubmit = () => {
console.log('submit!')
}
onMounted(()=>{
getHeadList()
})
</script>
<template>
<div>
<el-form :model="form" label-width="160px" style="padding: 30px;">
<el-form-item label="头像">
<el-avatar :size="90" :src="store.userInfo.avatar" @click="showChange(true)"/>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="store.userInfo.nickname" />
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="store.userInfo.phone" />
</el-form-item>
<el-form-item label="工号">
<el-input v-model="store.userInfo.job_number" />
</el-form-item>
<el-form-item label="自我介绍">
<el-input v-model="store.userInfo.desc" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
<el-dialog v-model="dialogShow" title="修改头像" width="500px" draggable>
<div>
<el-avatar
v-for="(item, index) in imgList"
:key="item.name"
:size="90"
:src="item.url"
:class="{'is-active': item.isChoose}"
@click="chooseImg(index)"/>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="showChange(false)">{{ t("cancel") }}</el-button>
<el-button type="primary" @click="toChangeHead">
{{ t("confirm") }}
</el-button>
</div>
</template>
</el-dialog>
const onSubmit = () => {
console.log('submit!')
}
</div>
</template>
</script>
<template>
<el-form :model="form" label-width="160px" style="padding: 30px;">
<el-form-item label="头像">
<el-avatar shape="square" :size="80" :src="store.userInfo.avatar"/>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="store.userInfo.nickname" />
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="store.userInfo.phone" />
</el-form-item>
<el-form-item label="工号">
<el-input v-model="store.userInfo.job_number" />
</el-form-item>
<el-form-item label="自我介绍">
<el-input v-model="store.userInfo.desc" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<style scoped lang="scss">
.el-avatar {
margin: 10px;
}
.is-active {
width: 100px;
height: 100px;
border: 2px solid red;
}
</style>

9
frontend/src/components/computer/Computer.vue

@ -106,6 +106,7 @@ import { useFileDrag } from "@/hook/useFileDrag";
import { useComputer } from "@/hook/useComputer";
import { Rect, useRectChosen } from "@/hook/useRectChosen";
import { getSystemConfig } from "@/system/config";
import { isShareFile, isRootShare, turnLocalPath } from "@/util/sharePath.ts";
const { choseStart, chosing, choseEnd, getRect, Chosen } = useRectChosen();
@ -304,8 +305,12 @@ async function onTreeOpen(path: string) {
chosenTreePath.value = path;
let file:any
// const file = await system.fs.stat(path);
if (path.substring(0,2) == '/F') {
file = path.indexOf('/F/myshare') !== -1 ? shareFileList.value[0] : shareFileList.value[1]
if (isRootShare(path)) {
file = path === '/F/myshare' ? shareFileList.value[0] : shareFileList.value[1]
} else if (isShareFile(path)) {
file = await system.fs.getShareInfo(path)
file = file.fi
file.path = turnLocalPath(file.path, path, 1)
} else {
file = await system.fs.stat(path)
}

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

@ -3,7 +3,7 @@
<div v-if="setPwd">
<div class="setting-item" >
<label>文件密码</label>
<el-input v-model="filePwd" placeholder="请输入文件加密密码" type="password"/>
<el-input v-model="filePwd" placeholder="请设置6-10位的密码" type="password"/>
</div>
<div class="setting-item">
<label></label>
@ -33,7 +33,11 @@ const params = {
}
//
async function toSetFilePwd() {
params.pwd = filePwd.value || md5(filePwd.value)
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 = {
@ -51,10 +55,10 @@ async function toSetFilePwd() {
}
setSystemKey('file',params)
}
function clearPwd() {
async function clearPwd() {
setPwd.value = false
filePwd.value = ''
toSetFilePwd()
await fetchGet(`${getApiUrl()}/file/changeispwd?ispwd=0`)
}
onMounted(()=>{
setPwd.value = params.isPwd ? true : false

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

@ -7,6 +7,7 @@ import { BrowserWindow, Notify, System, Dialog } from "@/system";
import { ref, onMounted, inject, onUnmounted, toRaw } from "vue";
import { isBase64, base64ToBuffer } from "@/util/file";
import { getSplit, getSystemConfig } from "@/system/config";
import { isShareFile } from "@/util/sharePath.ts";
const SP = getSplit();
const sys: any = inject<System>("system");
@ -61,8 +62,22 @@ const eventHandler = async (e: MessageEvent) => {
} else {
path = `${SP}C${SP}Users${SP}Desktop${SP}${title}.${ext}`;
}
if (await sys?.fs.exists(path)) {
//
const isShare = ref(false)
const isWrite = ref(0)
if (isShareFile(path)) {
const file = await sys?.fs.getShareInfo(path)
console.log('文件信息:',file);
isShare.value = true
isWrite.value = file.fs.is_write
if (!isWrite.value) {
new Notify({
title: "提示",
content: "该文件没有编辑权限",
});
return;
}
}else if (await sys?.fs.exists(path)) {
let res = await Dialog.showMessageBox({
type: "info",
title: "提示",
@ -84,11 +99,11 @@ const eventHandler = async (e: MessageEvent) => {
//console.log(data.content)
}
}
//console.log(data.content)
await sys?.fs.writeFile(path, data.content);
const res = isShare ? await sys?.fs.writeShareFile(path, data.content, isWrite.value) : await sys?.fs.writeFile(path, data.content);
console.log('编写文件:', res);
new Notify({
title: "提示",
content: "文件已保存",
content: res.code === 0 ? '文件已保存' : '文件保存失败',
});
sys.refershAppList();
} else if (eventData.type == "initSuccess") {

9
frontend/src/hook/useComputer.ts

@ -1,6 +1,5 @@
import * as fspath from '../system/core/Path';
import { OsFileWithoutContent } from '../system/core/FileSystem';
import { turnFilePath } from "@/util/sharePath.ts";
export type RouterPath = string;
export const useComputer = (adpater: {
@ -22,6 +21,7 @@ export const useComputer = (adpater: {
if (path === '') path = '/';
else if (path === '/') path = '/';
else if (path.endsWith('/')) path = path.substr(0, path.length - 1);
if(path.substring(0,2) !== '/F') {
const isExist = await adpater.exists(path);
if (!isExist) {
@ -40,13 +40,13 @@ export const useComputer = (adpater: {
adpater.setFileList(result);
return;
}
if (!(await isVia(currentPath))) return;
// console.log('use computer refresh:', currentPath);
let result
if (currentPath === '/F/myshare' || currentPath === '/F/othershare') {
result = await adpater.sharedir(currentPath)
} else if (currentPath.indexOf('/F') === 0) {
// result = await adpater.readShareDir(file?.path || currentPath)
result = await adpater.readShareDir(currentPath)
} else {
result = await adpater.readdir(currentPath);
@ -72,9 +72,10 @@ export const useComputer = (adpater: {
};
const openFolder = (file: OsFileWithoutContent) => {
if (adpater.isDirectory(file)) {
const path = file?.isShare ? turnFilePath(file) : file.path
// const path = file?.isShare ? file.titleName : file.path
const path = file.path
adpater.setRouter(path);
refersh();
refersh(file);
} else {
adpater.openFile(file.path);
}

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

@ -2,9 +2,9 @@ import { getFileUrl,fetchGet,fetchPost } from "../config.ts";
const API_BASE_URL = getFileUrl()
import { OsFileMode } from '../core/FileMode';
import { getSystemConfig } from "@/system/config";
import { turnServePath, turnLocalPath } from "@/util/sharePath.ts";
import { turnServePath, turnLocalPath, isRootShare } from "@/util/sharePath.ts";
import { OsFile } from "./FileSystem.ts";
// import { notifyError } from "@/util/msg";
export async function handleReadDir(path: any): Promise<any> {
const res = await fetchGet(`${API_BASE_URL}/read?path=${encodeURIComponent(path)}`);
if (!res.ok) {
@ -60,6 +60,15 @@ export async function handleShareDetail(path: string, id: number): Promise<any>
}
return await res.json();
}
// 编写共享文件
export async function handleWriteShareFile(path: string, content: any, isWrite: number): Promise<any> {
const formData = getFormData(content);
const res = await fetchPost(`${API_BASE_URL}/writewithchmod?path=${path}&iswrite=${isWrite}`, formData);
if (!res.ok) {
return false;
}
return await res.json();
}
export async function handleStat(path: string): Promise<any> {
const res = await fetchGet(`${API_BASE_URL}/stat?path=${encodeURIComponent(path)}`);
if (!res.ok) {
@ -244,24 +253,20 @@ export const useOsFile = () => {
return {
// 分享
async sharedir(id: number, path: string) {
const response = await handleReadShareDir(id, path);
// console.log('是否是根:', isRootShare(path),path);
const fun = isRootShare(path) ? handleReadShareDir : handleShareDir
const response = await fun(id, path);
if (response && response.data) {
return response.data.map((item: {[key: string]: OsFile}) => {
item.fi.isShare = true
item.fi.path = turnLocalPath(item.fi.path ,path)
// item.fi.titleName = turnLocalPath(item.fi.titleName, path)
return item.fi
})
}
return [];
},
async readShareFile(path: string) {
const file = await handleShareDetail(path,getSystemConfig()?.userInfo.id)
// console.log('文件信息:',file, file.data.fs.is_write);
if(!file.data.fs.is_write) {
alert('该文件不能编辑')
console.log('该文件不能编辑');
return false
}
const response = await handleReadShareFile(path);
if (response && response.data) {
return response.data;
@ -271,7 +276,11 @@ export const useOsFile = () => {
async readShareFileDir(id: number, path: string) {
const response = await handleShareDir(id,path);
if (response && response.data) {
return response.data;
return response.data.map((item: {[key: string]: OsFile}) => {
item.fi.isShare = true
item.fi.path = turnLocalPath(item.fi.path ,path,1)
return item.fi
})
}
return [];
},
@ -282,6 +291,15 @@ export const useOsFile = () => {
}
return [];
},
//编写共享文件
async writeShareFile(path: string, content: any, isWrite: number) {
path = turnServePath(path)
const response = await handleWriteShareFile(path, content, isWrite);
if (response) {
return response;
}
return false;
},
async readdir(path: string) {
const response = await handleReadDir(path);
if (response && response.data) {
@ -328,14 +346,15 @@ export const useOsFile = () => {
return false;
},
async rename(oldPath: string, newPath: string) {
const response = await handleRename(oldPath, newPath);
const response = await handleRename(turnServePath(oldPath), turnServePath(newPath));
if (response) {
return response;
}
return false;
},
async rmdir(path: string) {
const response = await handleRmdir(path);
const fun = path.indexOf('/F') === 0 ? handleShareUnlink : handleRmdir
const response = await fun(path);
if (response) {
return response;
}

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

@ -103,6 +103,7 @@ class OsFile extends OsFileInfo {
isSys?: number; // 文件是否是系统文件(可选)
isShare?: boolean; // 文件是否为共享文件
isPwd?: boolean; //文件是否上锁
titleName?: string; // 文件原本路径
/**
* OsFile

17
frontend/src/util/sharePath.ts

@ -1,18 +1,27 @@
import { OsFileWithoutContent } from '../system/core/FileSystem';
export function turnServePath(path: string): string {
const replaceUrl = path.indexOf('/F/myshare') === 0 ? '/F/myshare' : '/F/othershare'
return path.replace(replaceUrl, 'data/userData')
const replaceUrl = path.indexOf('/F/myshare') === 0 ? '/F/myshare' : '/F/othershare'
return path.replace(replaceUrl, 'data/userData')
}
export function turnLocalPath(path: string, newTemp: string): string {
//将浏览器地址转化为本地地址
export function turnLocalPath(path: string, newTemp: string, type?: number): string {
if (type && type === 1) {
const arr = newTemp.split('/')
newTemp = `/${arr[1]}/${arr[2]}`
}
return path.replace('data/userData', newTemp)
}
export function isShareFile(path: string) : boolean {
// console.log('是否是共享文件:',path,path.indexOf('/F/myshare') === 0 || path.indexOf('/F/othershare') === 0);
return path.indexOf('/F/myshare') === 0 || path.indexOf('/F/othershare') === 0
}
//是否是分享根目录
export function isRootShare(path: string) : boolean {
// console.log('根路径:',path === '/F/myshare' || path === '/F/othershare');
return path === '/F/myshare' || path === '/F/othershare'
}
//返回路径
export function turnFilePath(file: OsFileWithoutContent) : string {
// console.log('是否是共享文件:',path,path.indexOf('/F/myshare') === 0 || path.indexOf('/F/othershare') === 0);
const arr = file.path.split('/')
return `/${arr[1]}/${arr[2]}/${arr[arr.length - 1]}`
}
Loading…
Cancel
Save