@@ -4,6 +4,7 @@ export default { | |||
'pages/project/index', | |||
'pages/recycle/index', | |||
'pages/usercenter/index', | |||
'pages/workspace/workspace', | |||
], | |||
window: { | |||
backgroundTextStyle: 'light', | |||
@@ -1,8 +1,10 @@ | |||
import { getFileUrl } from '@root/service/oss'; | |||
import { downloadFile } from '@root/utils/request'; | |||
import { ScrollView, View, MovableArea, MovableView, Image } from '@tarojs/components'; | |||
import React, { useCallback, useState } from 'react'; | |||
import { AtIcon, AtList, AtListItem } from 'taro-ui'; | |||
import styles from './fileExplorer.module.scss'; | |||
import Taro from '@tarojs/taro'; | |||
export default function FileExplorer(props) { | |||
const { className, node, nodeHash, gotoNode } = props; | |||
@@ -33,7 +35,23 @@ export default function FileExplorer(props) { | |||
title={fileNode.label} | |||
note="版本: xxx" | |||
thumb={getFileUrl('oss://assets/file-icon/default.svg')} | |||
extraThumb={getFileUrl('oss://assets/file-icon/download.png')} | |||
extraThumb={ | |||
getFileUrl('oss://assets/file-icon/download.png') | |||
} | |||
onExtraThumbClick={() => { | |||
const task = downloadFile(fileNode.data.ipfsCid, { | |||
success: (param) => { | |||
console.log('success:', param); | |||
Taro.openDocument({ | |||
filePath: param.tempFilePath, | |||
}) | |||
}, | |||
fail: (...args) => { | |||
console.log('fail:', args); | |||
}, | |||
}); | |||
console.log('task:', task); | |||
}} | |||
/> | |||
) | |||
) | |||
@@ -47,7 +65,7 @@ export default function FileExplorer(props) { | |||
const deleteBtnWidth = 64; | |||
function ListItem(props) { | |||
const { className, enableDelete = false, title, note, arrow, thumb, extraThumb, onClick } = props; | |||
const { className, enableDelete = false, title, note, arrow, thumb, extraThumb, onClick, onExtraThumbClick } = props; | |||
const [initX, setInitX] = useState(); | |||
const [swipeWidth, setSwipeWidth] = useState(0); | |||
@@ -109,7 +127,7 @@ function ListItem(props) { | |||
{ | |||
extraThumb | |||
? ( | |||
<View className={styles.itemExtraThumb}> | |||
<View className={styles.itemExtraThumb} onClick={onExtraThumbClick}> | |||
<Image className={styles.img} src={extraThumb} /> | |||
</View> | |||
) | |||
@@ -31,7 +31,13 @@ export default function ProjectListView() { | |||
</View> | |||
{ | |||
projectList.map(project => ( | |||
<View className={styles.projectItem} key={project.id}> | |||
<View | |||
className={styles.projectItem} | |||
key={project.id} | |||
onClick={() => Taro.navigateTo({ | |||
url: `/pages/workspace/workspace?projectId=${project.id}&&projectName=${project.projName}`, | |||
})} | |||
> | |||
<Image className={styles.img} src={project.showImgUrl} /> | |||
<View className={styles.label}> | |||
<Text>{project.projName}</Text> | |||
@@ -13,7 +13,7 @@ export async function fetchProjectList() { | |||
rootNode.isRoot = true; | |||
nodeHash[rootNode.id] = rootNode; | |||
(res.data || []).forEach((upperProject) => { | |||
if(!upperProject.HasFile) { return; } | |||
if (!upperProject.HasFile) { return; } | |||
// const project = firstCharToLowerCase(upperProject); | |||
const projectFolder = new FileNode(upperProject.Id, upperProject.ProjName, rootNode.id, 'folder'); | |||
projectFolder.isProject = true; | |||
@@ -42,9 +42,9 @@ export async function fetchProjectRemovedFiles(projectNode) { | |||
hideLoading(); | |||
projectNode.removeAllChildrenIds(); | |||
(res.data || []).forEach((topNode) => { | |||
if(!topNode.ProjArchives) { return ; } | |||
if (!topNode.ProjArchives) { return; } | |||
let parentNode = projectNode; | |||
if(!isMini) { | |||
if (!isMini) { | |||
const node = new FileNode(topNode.Id, topNode.FolderName, projectNode.id, 'folder'); | |||
hash[node.id] = node; | |||
projectNode.append(node.id); | |||
@@ -52,7 +52,7 @@ export async function fetchProjectRemovedFiles(projectNode) { | |||
} | |||
topNode.ProjArchives.forEach((upperFileItem) => { | |||
const fileItem = firstCharToLowerCase(upperFileItem); | |||
const lastFolder = generateFolder(hash, `${topNode.FolderName}${fileItem.relativePath ? `/${fileItem.relativePath}` : ''}`, parentNode); | |||
const lastFolder = generateFolder(hash, `${topNode.FolderName}${fileItem.relativePath ? `/${fileItem.relativePath}` : ''}`, parentNode); | |||
const file = new FileNode(fileItem.id, fileItem.archName, parentNode.id, 'file', fileItem); | |||
lastFolder.append(file.id); | |||
// parentNode.append(file); | |||
@@ -64,17 +64,11 @@ export async function fetchProjectRemovedFiles(projectNode) { | |||
} | |||
function resolveFileListToTree(upperFileList, hash) { | |||
const headListIdList = []; | |||
} | |||
function generateFolder(folderMap, filePath, topNode) { | |||
const paths = filePath.split("/"); | |||
let lastFolder = topNode; | |||
paths.forEach((_, idx) => { | |||
if(idx === 0) { // 第一位为节点文件夹的名称,已在前文创建,不在重复 | |||
if (idx === 0) { // 第一位为节点文件夹的名称,已在前文创建,不在重复 | |||
return; | |||
} | |||
const fullRelativePath = `${paths.slice(0, idx + 1).join("/")}`; | |||
@@ -86,12 +80,9 @@ function generateFolder(folderMap, filePath, topNode) { | |||
const parentNodeId = idx === 1 ? topNode.id : paths.slice(0, idx).join('/'); | |||
folder = new FileNode(fullRelativePath, folderName, parentNodeId, 'folder'); | |||
folderMap[fullRelativePath] = folder; | |||
(folderMap[folder.parentId] || topNode) | |||
.append(folder.id); | |||
} | |||
// const parentRelativePath = folder.parentFolderPath; | |||
(folderMap[folder.parentId] || topNode) | |||
.append(folder.id); | |||
lastFolder = folder; | |||
}); | |||
return lastFolder; |
@@ -0,0 +1,80 @@ | |||
import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react'; | |||
import Page from '@root/components/Page'; | |||
import { AtSearchBar } from 'taro-ui'; | |||
import styles from './workspace.module.scss'; | |||
import FileExplorer from '@root/components/FileExplorer'; | |||
import { fetchProjectFiles, fetchNodeFiles } from './workspace.service'; | |||
import { useRouter } from '@tarojs/taro'; | |||
import Taro from '@tarojs/taro'; | |||
export default function Workspace() { | |||
const { params: { projectId, projectName } } = useRouter(); | |||
const [tempKeywords, setTempKeywords] = useState(''); | |||
const [effectKeywords, setEffectKeywords] = useState(''); | |||
const [currentNode, setCurrentNode] = useState(null); | |||
const [nodeHash, setNodeHash] = useState({}); | |||
useLayoutEffect(() => { | |||
fetchProjectFiles(projectId, projectName) | |||
.then(([rootNode, nextNodeHash]) => { | |||
setCurrentNode(rootNode); | |||
setNodeHash(nextNodeHash); | |||
}) | |||
}, [projectId, projectName]); | |||
const gotoNode = useCallback((nextFileNode) => { | |||
if (nextFileNode.isProject) { | |||
fetchProjectFiles(projectId, projectName) | |||
.then(([rootNode, nextNodeHash]) => { setCurrentNode(rootNode); setNodeHash(nextNodeHash); }) | |||
} else if (nextFileNode.isNode) { | |||
fetchNodeFiles(nextFileNode) | |||
.then(([nextNodeHash]) => { | |||
setCurrentNode(nextFileNode); | |||
setNodeHash(prevHash => ({ ...prevHash, ...nextNodeHash })); | |||
}) | |||
} else { | |||
setCurrentNode(nextFileNode); | |||
} | |||
}, [projectId, projectName]) | |||
return ( | |||
<Page | |||
className={styles.page} | |||
title={ | |||
currentNode | |||
? currentNode.label | |||
: projectName | |||
} | |||
headerColor="#EBEBEB" | |||
leftText= "返回" | |||
onClickLeftIcon={() => { | |||
if(currentNode.isProject) { | |||
Taro.navigateBack(); | |||
} else { | |||
setCurrentNode(prevNode => nodeHash[prevNode.parentId]) | |||
} | |||
}} | |||
> | |||
<AtSearchBar | |||
className={styles.search} | |||
value={tempKeywords} | |||
onChange={setTempKeywords} | |||
onActionClick={() => setEffectKeywords(tempKeywords)} | |||
onClear={() => { setEffectKeywords(''); setTempKeywords(''); }} | |||
/> | |||
{ | |||
currentNode | |||
? ( | |||
<FileExplorer | |||
className={styles.list} | |||
node={currentNode} | |||
gotoNode={gotoNode} | |||
nodeHash={nodeHash} | |||
/> | |||
) | |||
: null | |||
} | |||
</Page> | |||
) | |||
} |
@@ -0,0 +1,25 @@ | |||
$searchBoxHeight: 82px; | |||
.page { | |||
background-color: #f6f6f6; | |||
} | |||
.list { | |||
height: calc(100% - #{$searchBoxHeight}); | |||
} | |||
.search { | |||
height: $searchBoxHeight; | |||
background-color: #ebebeb; | |||
border-bottom: 1px solid rgba(0, 0, 0, 0.2); | |||
padding: 12px 16px * 2; | |||
:global(.at-search-bar__input-cnt) { | |||
border-radius: 8Px; | |||
background-color: rgba(0, 0, 0, 0.05); | |||
} | |||
:global(.at-search-bar__input) { | |||
color: rgba(0, 0, 0, 0.56); | |||
} | |||
:global(.at-search-bar__action) { | |||
background-color: transparent; | |||
color: #7850FF; | |||
} | |||
} |
@@ -0,0 +1,101 @@ | |||
import getData from '@root/utils/request'; | |||
import * as storage from '@root/utils/storage'; | |||
import { FileNode, firstCharToLowerCase, isReqSuccess } from '@root/utils/tool'; | |||
import { hideLoading, showLoading } from '@tarojs/taro'; | |||
function generateFolder(folderMap, filePath, topNode) { | |||
const paths = filePath.split("/"); | |||
let lastFolder = topNode; | |||
paths.forEach((_, idx) => { | |||
if (idx === 0) { // 第一位为节点文件夹的名称,已在前文创建,不在重复 | |||
return; | |||
} | |||
const fullRelativePath = `${paths.slice(0, idx + 1).join("/")}`; | |||
let folder; | |||
if (folderMap[fullRelativePath]) { | |||
folder = folderMap[fullRelativePath]; | |||
} else { | |||
const folderName = paths[idx]; | |||
const parentNodeId = idx === 1 ? topNode.id : paths.slice(0, idx).join('/'); | |||
folder = new FileNode(fullRelativePath, folderName, parentNodeId, 'folder'); | |||
folderMap[fullRelativePath] = folder; | |||
(folderMap[folder.parentId] || topNode) | |||
.append(folder.id); | |||
} | |||
// const parentRelativePath = folder.parentFolderPath; | |||
lastFolder = folder; | |||
}); | |||
return lastFolder; | |||
} | |||
async function fetchNodeFolders(projectNode, hash) { | |||
const isMini = storage.get('isMini'); | |||
const res = await getData('folder/queryAllNodeFolderListByProjectId', { projectId: projectNode.id }); | |||
if (!isReqSuccess(res)) { return []; } | |||
const { folder } = res.data; | |||
return folder.reduce((iList, upperFolder) => { | |||
if (upperFolder.FolderName === "公共文件夹") { | |||
return iList; | |||
} | |||
if (upperFolder.NodeId === upperFolder.TemplateId) { | |||
return iList; | |||
} | |||
// const folder = firstCharToLowerCase(upperFolder); | |||
const folder = new FileNode(upperFolder.Id, upperFolder.FolderName, projectNode.id, 'folder'); | |||
folder.isNode = true; | |||
hash[folder.id] = folder; | |||
if (!isMini) { | |||
projectNode.append(folder.id); | |||
} | |||
iList.push(folder); | |||
return iList; | |||
}, []); | |||
} | |||
export async function fetchNodeFiles(parentNode, hash = {}, nodeFolderId = parentNode.id) { | |||
const accountId = storage.get('accountId'); | |||
showLoading(); | |||
const res = await getData('folder/queryFileListByFolderIdAndUserId', { folderId: nodeFolderId, userId: accountId }); | |||
hideLoading(); | |||
if (!isReqSuccess(res)) { return []; } | |||
const { myFile, workFile } = res.data; | |||
(myFile || []).concat(workFile || []).forEach((upperFileItem) => { | |||
const fileItem = firstCharToLowerCase(upperFileItem); | |||
const lastFolder = generateFolder(hash, `${parentNode.label}${fileItem.relativePath ? `/${fileItem.relativePath}` : ''}`, parentNode); | |||
const file = new FileNode(fileItem.id, fileItem.archName, parentNode.id, 'file', fileItem); | |||
lastFolder.append(file.id); | |||
// parentNode.append(file); | |||
hash[file.id] = file; | |||
}); | |||
return [hash]; | |||
} | |||
export async function fetchProjectFiles(projectId, projectName) { | |||
showLoading(); | |||
const hash = {}; | |||
const projectNode = new FileNode(projectId, projectName, null, 'folder'); | |||
projectNode.isProject = true; | |||
hash[projectNode.id] = projectNode; | |||
const isMini = storage.get('isMini'); | |||
// project -> nodeFolders | |||
const nodeList = await fetchNodeFolders(projectNode, hash); | |||
hideLoading(); | |||
// 如果是mini版本,则直接拉去第一个文件夹的内容挂在到projectNode上 | |||
if (isMini && nodeList.length) { | |||
const node = nodeList[0]; | |||
await fetchNodeFiles(projectNode, hash, node.id); | |||
} | |||
return [projectNode, hash]; | |||
} |