757 lines
21 KiB
Vue
757 lines
21 KiB
Vue
<template>
|
||
<view class="status-bar"></view>
|
||
|
||
<!-- ===== 新建文件夹设置弹窗 ===== -->
|
||
<view v-if="showNewFolder" class="popup-overlay" @click="closeNewFolderModal">
|
||
<view class="popup-card" @click.stop>
|
||
<!-- 关闭按钮 -->
|
||
<view class="close-popup-card" @click="closeNewFolderModal">
|
||
<view class="iconfont icon-quxiao"></view>
|
||
</view>
|
||
<!-- 标题 -->
|
||
<view class="popup-title">新建工作区目录</view>
|
||
|
||
<!-- 目录名称输入 -->
|
||
<view class="new-folder-name">目录名称</view>
|
||
<view class="create-folder-name" :class="{'has-value': isNFNFocused || newFolderName}">
|
||
<input v-model="newFolderName" @focus="isNFNFocused=true" @blur="isNFNFocused=false" type="text"
|
||
placeholder="输入目录名称,如:项目资料/设计图" />
|
||
</view>
|
||
|
||
<!-- 当前路径 -->
|
||
<view class="nf-path-label">当前路径</view>
|
||
<view class="nf-path-display">{{ currentFolderPath }}</view>
|
||
|
||
<!-- 路径预览 -->
|
||
<view class="nf-path-label">路径预览</view>
|
||
<view class="nf-path-preview">{{ folderPathPreview }}</view>
|
||
|
||
<!-- 底部按钮 -->
|
||
<view class="option-wrapper">
|
||
<view class="opt-btn opt-cancel" @click="closeNewFolderModal">取消</view>
|
||
<view class="opt-btn opt-confirm" @click="confirmCreateFolder">确认</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="workspace-container page-container">
|
||
<view class="workspace-header">
|
||
<view class="custom-navbar">
|
||
<view class="navbar-left" @click="handleBackOrCheck ">
|
||
<view class="iconfont icon-fanhui custom-navbar-icon"></view>
|
||
<view class="navbar-before-title workspace-text">{{isSelectFolder?'全选':navbarBeforeTitle}}</view>
|
||
</view>
|
||
|
||
<view class="navbar-title workspace-text">{{navbarTitle}}</view>
|
||
<view class="navbar-right">
|
||
<view v-if="isSelectFolder" class="navbar-right-text workspace-text" @click="handleSelectFolder()">
|
||
完成</view>
|
||
<view v-else class="iconfont icon-gengduo" :class="isMenuOpen ?'menu-open':'custom-navbar-icon'"
|
||
@click="handleMenu"></view>
|
||
</view>
|
||
<view v-if="isMenuOpen" class="menu-card">
|
||
<!-- <view class="menu-card-item" @click="handleSelectFolder();handleMenu()">选择</view>
|
||
<view class="solid-line"></view> -->
|
||
<view class="menu-card-item" @click="handleUploadFile();handleMenu()">上传文件</view>
|
||
<view class="solid-line"></view>
|
||
<view class="menu-card-item" @click="newWorkspaceFolder();handleMenu()">新建文件夹</view>
|
||
</view>
|
||
</view>
|
||
<view class="search-file-warpper">
|
||
<view class="search-file">
|
||
<view class="iconfont icon-sousuo"></view>
|
||
<input class="search-file-input" placeholder="搜索" @focus="handleSearchFocus"
|
||
v-model="searchKeyword" />
|
||
</view>
|
||
<view v-if="isSearchFocus" class="cancel-search" @click="handleSearchFocus">取消</view>
|
||
</view>
|
||
|
||
</view>
|
||
<view class="workspace-content">
|
||
<view class="folder-null" v-if="currentFolderList.length===0">
|
||
<view class="iconfont icon-wenjianjia"></view>
|
||
文件夹为空
|
||
</view>
|
||
<view class="folder-grid" v-if="currentFolderList.length>0">
|
||
<view class="folder-item" :class="{'select-folder':selectFileList.includes(folder.path)}"
|
||
v-for="folder in currentFolderList" :key="folder.path"
|
||
@click="isSelectFolder?selectFolder(folder.path):handleFolderClick(folder)"
|
||
@longpress="handleLongPress(folder)">
|
||
<view v-if="folder.type === 'directory'"
|
||
class="iconfont icon-a-wenjianjiawenjian folder-item-style"></view>
|
||
<view v-else class="iconfont folder-item-style" :class="getFileIcon(folder.extension)"></view>
|
||
<view class="folder-name">{{folder.name}}</view>
|
||
<view v-if="isSelectFolder" class="folder-checkbox"
|
||
:class="{'select-folder':selectFileList.includes(folder.path)}">
|
||
<uni-icons v-if="selectFileList.includes(folder.path)" type="checkmarkempty"
|
||
color="#fff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-if="isSelectFolder" class="workspace-footer" :class="{'folder-actions':selectFileList.length>0}">
|
||
<view class="iconfont icon-shangchuan" @click="handleUploadFile"></view>
|
||
<!-- <view class="iconfont icon-fuzhi"></view> -->
|
||
<!-- <view class="iconfont icon-wenjian"></view> -->
|
||
<view class="iconfont icon-del"></view>
|
||
<!-- <view class="iconfont icon-gengduo"></view> -->
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
onMounted,
|
||
ref,
|
||
computed
|
||
} from 'vue';
|
||
import {
|
||
getWorkspaceId,
|
||
getToken
|
||
} from '@/utils/user-info.js'
|
||
import {
|
||
chooseFile
|
||
} from '@/uni_modules/lime-choose-file';
|
||
import {
|
||
getWorkspaceList,
|
||
createWorkspaceFolder,
|
||
daleteWorkspace,
|
||
getWorkspaceFileURL,
|
||
uploadFileToShortStorage,
|
||
workspaceUploadFileByURL,
|
||
updateWorkspaceFileName
|
||
} from '@/utils/cloud-api.js'
|
||
|
||
const UserToken = ref('')
|
||
const workspaceId = ref('')
|
||
const navbarBeforeTitle = ref('');
|
||
const navbarTitle = ref('工作区');
|
||
|
||
// 选择文件模式
|
||
const isSelectFolder = ref(false);
|
||
const selectFileList = ref([]);
|
||
const handleSelectFolder = () => {
|
||
if (isSelectFolder.value) {
|
||
selectFileList.value = []
|
||
}
|
||
isSelectFolder.value = !isSelectFolder.value;
|
||
}
|
||
const selectFolder = (id) => {
|
||
const index = selectFileList.value.indexOf(id);
|
||
if (index !== -1) {
|
||
selectFileList.value.splice(index, 1);
|
||
} else {
|
||
selectFileList.value.push(id);
|
||
}
|
||
}
|
||
// 新建文件夹
|
||
const showNewFolder = ref(false)
|
||
const isNFNFocused = ref(false)
|
||
const newFolderName = ref('')
|
||
const closeNewFolderModal = () => {
|
||
showNewFolder.value = false
|
||
newFolderName.value = ''
|
||
}
|
||
const newWorkspaceFolder = () => {
|
||
showNewFolder.value = true
|
||
}
|
||
|
||
// ========== 上传文件 ==========
|
||
const handleUploadFile = () => {
|
||
chooseFile({
|
||
count: 10,
|
||
type: 'all',
|
||
success: async (res) => {
|
||
const files = res.tempFiles || [];
|
||
if (files.length === 0) {
|
||
uni.showToast({
|
||
title: '未选择文件',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
await doUploadWorkspaceFiles(files);
|
||
},
|
||
fail: (err) => {
|
||
console.error('选择文件失败:', err);
|
||
}
|
||
});
|
||
};
|
||
|
||
const doUploadWorkspaceFiles = async (files) => {
|
||
uni.showLoading({
|
||
title: '上传中...'
|
||
});
|
||
try {
|
||
const dirPath = folderStack.value.length > 0 ?
|
||
'./' + folderStack.value.map(f => f.name).join('/') + '/' :
|
||
'/';
|
||
|
||
// 1. 一次性上传所有文件到短存云端,获取 URL 数组
|
||
const results = await uploadFileToShortStorage(
|
||
workspaceId.value,
|
||
files,
|
||
dirPath
|
||
);
|
||
// results: [{ url, success }, ...]
|
||
|
||
// 2. 收集成功的 URL,批量上传到工作区
|
||
const successUrls = results
|
||
.filter(r => r.success)
|
||
.map(r => r.url);
|
||
|
||
if (successUrls.length === 0) {
|
||
const errors = results.filter(r => !r.success).map(r => r.error).join('; ');
|
||
throw new Error(errors || '所有文件上传失败');
|
||
}
|
||
|
||
await workspaceUploadFileByURL(
|
||
UserToken.value,
|
||
workspaceId.value,
|
||
successUrls,
|
||
dirPath
|
||
);
|
||
|
||
uni.hideLoading();
|
||
const total = files.length;
|
||
const failed = total - successUrls.length;
|
||
const msg = failed > 0 ?
|
||
`上传完成:成功 ${successUrls.length},失败 ${failed}` :
|
||
`成功上传 ${total} 个文件`;
|
||
uni.showToast({
|
||
title: msg,
|
||
icon: successUrls.length > 0 ? 'success' : 'error'
|
||
});
|
||
// 刷新文件列表
|
||
initCurrentFolderList();
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
console.error('上传文件失败:', error);
|
||
uni.showToast({
|
||
title: typeof error === 'string' ? error : '上传失败,请重试',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
};
|
||
|
||
// 当前文件夹路径
|
||
const currentFolderPath = computed(() => {
|
||
if (folderStack.value.length === 0) return '根目录'
|
||
return '/' + folderStack.value.map(f => f.name).join('/')
|
||
})
|
||
|
||
// 路径预览:./ + 当前路径 + 新文件夹名
|
||
const folderPathPreview = computed(() => {
|
||
const folderPath = folderStack.value.map(f => f.name).join('/')
|
||
const name = newFolderName.value.trim()
|
||
if (name) {
|
||
return folderPath ? `./${folderPath}/${name}` : `./${name}`
|
||
}
|
||
return folderPath ? `./${folderPath}/` : './'
|
||
})
|
||
|
||
// 确认创建文件夹
|
||
const confirmCreateFolder = async () => {
|
||
const name = newFolderName.value.trim()
|
||
if (!name) {
|
||
uni.showToast({
|
||
title: '请输入目录名称',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
try {
|
||
// 拼接路径:./ 开头,如 ./项目资料/设计图
|
||
const folderPath = folderStack.value.map(f => f.name).join('/')
|
||
const dirPath = folderPath ? `./${folderPath}/${name}` : `./${name}`
|
||
await createWorkspaceFolder(UserToken.value, workspaceId.value, dirPath)
|
||
uni.showToast({
|
||
title: '创建成功',
|
||
icon: 'success'
|
||
})
|
||
closeNewFolderModal()
|
||
initCurrentFolderList()
|
||
} catch (error) {
|
||
console.error('创建文件夹失败:', error)
|
||
uni.showToast({
|
||
title: '创建失败,请重试',
|
||
icon: 'error'
|
||
})
|
||
}
|
||
}
|
||
|
||
// 长按文件
|
||
const handleLongPress = (folder) => {
|
||
if (isSelectFolder.value) return;
|
||
uni.showActionSheet({
|
||
itemList: ['下载', '删除'], // ['删除', '下载', '压缩', '重命名']
|
||
success: (res) => {
|
||
switch (res.tapIndex) {
|
||
case 0:
|
||
handleDownload(folder);
|
||
break;
|
||
case 1:
|
||
handleDelete(folder);
|
||
break;
|
||
// case 2:
|
||
// handleDownload(folder);
|
||
// break;
|
||
// case 3:
|
||
// handleRename(folder);
|
||
// break;
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 重命名
|
||
const handleRename = async (folder) => {
|
||
uni.showModal({
|
||
title: '重命名',
|
||
content: '请输入新名称',
|
||
editable: true,
|
||
placeholderText: folder.name,
|
||
success: async (res) => {
|
||
if (res.confirm && res.content) {
|
||
try {
|
||
uni.showLoading({
|
||
title: '重命名中...'
|
||
});
|
||
// 构建文件路径:当前目录 + 文件名
|
||
const dirPath = folderStack.value.length > 0 ?
|
||
'./' + folderStack.value.map(f => f.name).join('/') + '/' :
|
||
'/';
|
||
const filePath = dirPath + folder.name;
|
||
await updateWorkspaceFileName(
|
||
workspaceId.value,
|
||
filePath,
|
||
res.content
|
||
);
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: '重命名成功',
|
||
icon: 'success'
|
||
});
|
||
// 刷新文件列表
|
||
initCurrentFolderList();
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
console.error('重命名失败:', error);
|
||
uni.showToast({
|
||
title: typeof error === 'string' ? error : '重命名失败,请重试',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleDownload = async (folder) => {
|
||
// 目录不能下载
|
||
if (folder.type === 'directory') {
|
||
uni.showToast({
|
||
title: '暂不支持下载目录',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
try {
|
||
uni.showLoading({
|
||
title: '获取下载链接...'
|
||
});
|
||
|
||
// 构建文件路径,去掉开头的 ./
|
||
const filePath = folder.path.startsWith('./') ? folder.path.slice(2) : folder.path;
|
||
const result = await getWorkspaceFileURL(UserToken.value, workspaceId.value, filePath);
|
||
|
||
uni.hideLoading();
|
||
|
||
// 接口返回数组,取第一个文件的 url
|
||
const fileInfo = Array.isArray(result) ? result[0] : result;
|
||
if (!fileInfo || !fileInfo.url) {
|
||
uni.showToast({
|
||
title: '获取下载链接失败',
|
||
icon: 'error'
|
||
});
|
||
return;
|
||
}
|
||
|
||
const downloadUrl = fileInfo.url;
|
||
const fileName = folder.name;
|
||
|
||
uni.showLoading({
|
||
title: '下载中...'
|
||
});
|
||
|
||
uni.downloadFile({
|
||
url: downloadUrl,
|
||
name: fileName,
|
||
success: (downloadRes) => {
|
||
uni.hideLoading();
|
||
if (downloadRes.statusCode === 200) {
|
||
const tempPath = downloadRes.tempFilePath;
|
||
// 下载成功,保存到 yxd 目录
|
||
saveFileToYxd(fileName, tempPath);
|
||
} else {
|
||
uni.showToast({
|
||
title: '下载失败',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
uni.hideLoading();
|
||
console.error('下载文件失败:', err);
|
||
uni.showToast({
|
||
title: '下载失败,请重试',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
});
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
console.error('获取下载链接失败:', error);
|
||
uni.showToast({
|
||
title: '获取下载链接失败,请重试',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
};
|
||
|
||
// 将下载的文件保存到外部存储 yxd 目录
|
||
const saveFileToYxd = (fileName, tempPath) => {
|
||
// #ifdef APP-PLUS
|
||
// App 端:复制文件到 /storage/emulated/0/yxd/
|
||
const YXD_PATH = '/storage/emulated/0/yxd/';
|
||
|
||
const ensureYxdDir = (callback) => {
|
||
plus.io.resolveLocalFileSystemURL(YXD_PATH, (dirEntry) => {
|
||
callback(dirEntry);
|
||
}, () => {
|
||
plus.io.resolveLocalFileSystemURL('/storage/emulated/0/', (rootEntry) => {
|
||
rootEntry.getDirectory('yxd', {
|
||
create: true
|
||
}, (dirEntry) => {
|
||
callback(dirEntry);
|
||
}, (err) => {
|
||
console.error('创建 yxd 目录失败:', JSON.stringify(err));
|
||
uni.showToast({
|
||
title: '创建目录失败',
|
||
icon: 'error'
|
||
});
|
||
openFileConfirm(fileName, tempPath);
|
||
});
|
||
}, (err) => {
|
||
console.error('访问外部存储根目录失败:', JSON.stringify(err));
|
||
uni.showToast({
|
||
title: '无法访问存储目录',
|
||
icon: 'error'
|
||
});
|
||
openFileConfirm(fileName, tempPath);
|
||
});
|
||
});
|
||
};
|
||
|
||
ensureYxdDir((yxdDirEntry) => {
|
||
plus.io.resolveLocalFileSystemURL(tempPath, (fileEntry) => {
|
||
fileEntry.copyTo(
|
||
yxdDirEntry,
|
||
fileName,
|
||
() => {
|
||
const targetPath = YXD_PATH + fileName;
|
||
console.log('文件已保存到:', targetPath);
|
||
openFileConfirm(fileName, targetPath);
|
||
},
|
||
(err) => {
|
||
console.error('复制文件失败:', JSON.stringify(err));
|
||
openFileConfirm(fileName, tempPath);
|
||
}
|
||
);
|
||
}, (err) => {
|
||
console.error('读取临时文件失败:', JSON.stringify(err));
|
||
openFileConfirm(fileName, tempPath);
|
||
});
|
||
});
|
||
// #endif
|
||
// #ifndef APP-PLUS
|
||
uni.saveFile({
|
||
tempFilePath: tempPath,
|
||
success: (saveRes) => {
|
||
openFileConfirm(fileName, saveRes.savedFilePath);
|
||
},
|
||
fail: () => {
|
||
openFileConfirm(fileName, tempPath);
|
||
}
|
||
});
|
||
// #endif
|
||
};
|
||
|
||
// 下载成功后确认是否打开文件
|
||
const openFileConfirm = (fileName, filePath) => {
|
||
uni.showActionSheet({
|
||
title: `${fileName} 下载完成`,
|
||
itemList: ['打开文件', '选择其他应用打开', '仅保存'],
|
||
success: (res) => {
|
||
switch (res.tapIndex) {
|
||
case 0:
|
||
openFile(filePath);
|
||
break;
|
||
case 1:
|
||
openFileWithMenu(filePath);
|
||
break;
|
||
case 2:
|
||
uni.showToast({
|
||
title: '文件已保存到 yxd 目录',
|
||
icon: 'success'
|
||
});
|
||
break;
|
||
}
|
||
},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '文件已保存到 yxd 目录',
|
||
icon: 'success'
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 使用系统默认应用打开
|
||
const openFile = (filePath) => {
|
||
uni.openDocument({
|
||
filePath: filePath,
|
||
success: () => uni.showToast({
|
||
title: '打开成功',
|
||
icon: 'success'
|
||
}),
|
||
fail: (err) => {
|
||
console.error('打开文件失败:', err);
|
||
uni.showToast({
|
||
title: '无法打开此文件',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 选择其他应用打开
|
||
const openFileWithMenu = (filePath) => {
|
||
uni.openDocument({
|
||
filePath: filePath,
|
||
showMenu: true,
|
||
success: () => uni.showToast({
|
||
title: '打开成功',
|
||
icon: 'success'
|
||
}),
|
||
fail: (err) => {
|
||
console.error('打开文件失败:', err);
|
||
uni.showToast({
|
||
title: '无法打开此文件',
|
||
icon: 'error'
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 删除
|
||
const handleDelete = (folder) => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: `确定要删除"${folder.name}"吗?`,
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
try {
|
||
// 路径加 ./ 前缀
|
||
const filePath = `./${folder.path}`
|
||
console.log("删除的是:", filePath);
|
||
await daleteWorkspace(UserToken.value, workspaceId.value, filePath)
|
||
uni.showToast({
|
||
title: '删除成功',
|
||
icon: 'success'
|
||
})
|
||
initCurrentFolderList()
|
||
} catch (error) {
|
||
console.error('删除失败:', error)
|
||
uni.showToast({
|
||
title: '删除失败,请重试',
|
||
icon: 'error'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
// const handleFolderClick = (id) => {
|
||
// console.log(id);
|
||
// }
|
||
|
||
// 菜单
|
||
const isMenuOpen = ref(false)
|
||
const handleMenu = () => {
|
||
isMenuOpen.value = !isMenuOpen.value;
|
||
}
|
||
|
||
// 搜索框
|
||
const searchKeyword = ref('')
|
||
const isSearchFocus = ref(false)
|
||
const handleSearchFocus = () => {
|
||
isSearchFocus.value = !isSearchFocus.value
|
||
}
|
||
|
||
// 根据文件后缀返回对应图标
|
||
const getFileIcon = (ext) => {
|
||
const iconMap = {
|
||
'.png': 'icon-wenjiantupian',
|
||
'.jpg': 'icon-wenjiantupian',
|
||
'.jpeg': 'icon-wenjiantupian',
|
||
'.gif': 'icon-wenjiantupian',
|
||
'.svg': 'icon-SVG',
|
||
'.bmp': 'icon-wenjiantupian',
|
||
'.webp': 'icon-wenjiantupian',
|
||
'.mp4': 'icon-wenjianshipin',
|
||
'.avi': 'icon-wenjianshipin',
|
||
'.mov': 'icon-wenjianshipin',
|
||
'.wmv': 'icon-wenjianshipin',
|
||
'.flv': 'icon-wenjianshipin',
|
||
'.mkv': 'icon-wenjianshipin',
|
||
'.mp3': 'icon-wenjianyinpin',
|
||
'.wav': 'icon-wenjianyinpin',
|
||
'.flac': 'icon-wenjianyinpin',
|
||
'.aac': 'icon-wenjianyinpin',
|
||
'.pdf': 'icon-PDF',
|
||
'.doc': 'icon-DOC',
|
||
'.docx': 'icon-DOC',
|
||
'.xls': 'icon-XLS',
|
||
'.xlsx': 'icon-XLS',
|
||
'.ppt': 'icon-PPT',
|
||
'.pptx': 'icon-PPT',
|
||
'.txt': 'icon-TXT',
|
||
'.md': 'icon-file-markdown-fill',
|
||
'.zip': 'icon-wenjianyasuo',
|
||
'.rar': 'icon-wenjianyasuo',
|
||
'.7z': 'icon-wenjianyasuo',
|
||
'.tar': 'icon-wenjianyasuo',
|
||
'.gz': 'icon-wenjianyasuo',
|
||
'.js': 'icon-JS',
|
||
'.ts': 'icon-daimawenjia',
|
||
'.vue': 'icon-daimawenjia',
|
||
'.html': 'icon-HTML',
|
||
'.css': 'icon-CSS',
|
||
'.py': 'icon-daimawenjian',
|
||
'.java': 'icon-daimawenjian',
|
||
'.json': 'icon-JSON',
|
||
};
|
||
return iconMap[ext?.toLowerCase()] || 'icon-qitawenjian';
|
||
};
|
||
|
||
const allFoldersData = ref({})
|
||
|
||
// 文件夹路径栈
|
||
const folderStack = ref([]);
|
||
// 当前显示的文件夹列表
|
||
const currentFolderList = ref([]);
|
||
const getCurrentFolderList = () => {
|
||
console.log("当前路径为:", JSON.stringify(folderStack.value));
|
||
// 当前路径:栈为空时在根目录,路径为 "."
|
||
const currentPath = folderStack.value.length > 0 ? folderStack.value[folderStack.value.length - 1].path : '.';
|
||
// 在根目录下,直接返回根节点的 children
|
||
if (currentPath === '.') {
|
||
return allFoldersData.value?.children || [];
|
||
}
|
||
// 递归在树中按 path 查找目标节点
|
||
const findFolderByPath = (list, targetPath) => {
|
||
for (const item of list) {
|
||
if (item.path === targetPath) return item;
|
||
if (item.type === 'directory' && item.children?.length) {
|
||
const res = findFolderByPath(item.children, targetPath);
|
||
if (res) return res;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
// 从根节点的 children 开始搜索
|
||
const currentFolder = findFolderByPath(allFoldersData.value?.children || [], currentPath);
|
||
return currentFolder ? currentFolder.children : [];
|
||
}
|
||
|
||
// 初始化当前文件夹列表
|
||
const initCurrentFolderList = async () => {
|
||
workspaceId.value = getWorkspaceId();
|
||
UserToken.value = getToken();
|
||
console.log("getWorkspaceId:", workspaceId.value);
|
||
allFoldersData.value = await getWorkspaceList(UserToken.value, workspaceId.value);
|
||
currentFolderList.value = getCurrentFolderList();
|
||
};
|
||
|
||
// 处理文件夹点击(非选择模式下进入文件夹,仅目录可点击进入)
|
||
const handleFolderClick = (folder) => {
|
||
if (folder.type !== 'directory') return;
|
||
folderStack.value.push({
|
||
path: folder.path,
|
||
name: folder.name
|
||
});
|
||
navbarTitle.value = folder.name;
|
||
navbarBeforeTitle.value = folderStack.value.length > 1 ? folderStack.value[folderStack.value.length - 2].name :
|
||
'工作区';
|
||
currentFolderList.value = getCurrentFolderList();
|
||
searchKeyword.value = '';
|
||
isSearchFocus.value = false;
|
||
};
|
||
|
||
// 全选/取消全选
|
||
const handleSelectAll = () => {
|
||
if (selectFileList.value.length === currentFolderList.value.length) {
|
||
selectFileList.value = [];
|
||
} else {
|
||
selectFileList.value = currentFolderList.value.map(f => f.path);
|
||
}
|
||
};
|
||
|
||
// 返回上一级
|
||
const handleBackOrCheck = () => {
|
||
if (isSelectFolder.value) {
|
||
// 选择模式下点击全选/取消全选
|
||
handleSelectAll();
|
||
return;
|
||
}
|
||
|
||
if (folderStack.value.length > 0) {
|
||
folderStack.value.pop();
|
||
if (folderStack.value.length === 0) {
|
||
navbarTitle.value = '工作区';
|
||
navbarBeforeTitle.value = null;
|
||
} else {
|
||
navbarTitle.value = folderStack.value[folderStack.value.length - 1].name;
|
||
navbarBeforeTitle.value = folderStack.value.length > 1 ?
|
||
folderStack.value[folderStack.value.length - 2].name :
|
||
'工作区';
|
||
}
|
||
initCurrentFolderList();
|
||
// 返回后清空搜索
|
||
searchKeyword.value = '';
|
||
isSearchFocus.value = false;
|
||
} else {
|
||
// 已在根目录,返回到聊天界面
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
fail() {
|
||
console.log("返回失败,进入兜底跳转")
|
||
uni.reLaunch({
|
||
url: '/pages/Chat/Chat'
|
||
})
|
||
}
|
||
})
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
initCurrentFolderList();
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
@import url("WorkSpace.css");
|
||
</style> |