diff --git a/src/actions/app.js b/src/actions/app.js
index b0ad342..6b6ea99 100644
--- a/src/actions/app.js
+++ b/src/actions/app.js
@@ -39,10 +39,26 @@ export function login({ username, password }) {
return async (dispatch, getState) => {
const res = await getData('authentication/login', { UserName: username, Password: password }, true);
if (!isReqSuccess(res)) {
- dispatch(logout());
+ // dispatch(logout());
return res;
}
const userData = firstCharToLowerCase(res.data);
+
+ const isSuperAdmin = userData.backgroundPermission === 3;
+ if(isSuperAdmin) {
+ return {
+ code: 'err',
+ msg: '该账号没有访问权限',
+ }
+ }
+
+ const companyInfoRes = await getData('company/queryFrontDeskCompanyById', { id: userData.companyId });
+ if (!isReqSuccess(companyInfoRes)) {
+ return companyInfoRes;
+ }
+
+
+ const { data: { company: { SoftwareVersion } = {} } = {} } = companyInfoRes;
// 角色判断
// const { app: appStore } = getState();
@@ -56,8 +72,10 @@ export function login({ username, password }) {
accountName: userData.cnName,
customerId: userData.companyId,
avatorUrl: userData.headImgUrl,
+ isMini: SoftwareVersion === 'Mini',
};
storage.set('accountId', payload.accountId);
+ storage.set('isMini', payload.isMini)
dispatch({
type: 'app/login',
payload,
diff --git a/src/components/FileExplorer/fileExplorer.module.scss b/src/components/FileExplorer/fileExplorer.module.scss
new file mode 100644
index 0000000..ffd965e
--- /dev/null
+++ b/src/components/FileExplorer/fileExplorer.module.scss
@@ -0,0 +1,127 @@
+.list {
+ background-color: transparent;
+ &:after {
+ content: none;
+ }
+}
+.listItem {
+ padding: 0 20px * 2 0 8px * 2;
+ &:after {
+ left: 72px * 2;
+ }
+ :global {
+ .at-list__item-thumb {
+ width: 64px * 2;
+ height: 64px * 2;
+ margin-right: 0;
+ padding: 5px * 2;
+ box-sizing: border-box;
+ }
+ .at-icon-chevron-right {
+ color: #7850FF;
+ }
+ .item-extra__image {
+ margin-right: 0;
+ }
+ }
+}
+
+.listItem2 {
+ $itemHeight: 64px * 2;
+ position: relative;
+ overflow: hidden;
+ height: $itemHeight;
+ .content {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ z-index: 2;
+ padding: 0 20px * 2 0 8px * 2;
+ transition: right 0.3s linear;
+ background-color: rgba(#f6f6f6, 1);
+ &.dragging {
+ transition: none;
+ }
+ .img {
+ width: 100%;
+ height: 100%;
+ }
+ .itemThumb {
+ width: $itemHeight;
+ height: $itemHeight;
+ padding: 10px;
+ margin-right: 0;
+ box-sizing: border-box;
+ }
+
+ .itemContent {
+ flex: 1;
+ overflow: hidden;
+ margin-right: 40px;
+ &_info {
+ &_title {
+ color: #32323c;
+ font-size: 16Px;
+ line-height: 1.5;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ &_note {
+ color: rgba(0, 0, 0, 0.56);;
+ font-size: 12Px;
+ line-height: 1.5;
+ }
+ }
+ }
+
+ .itemExtra {
+ position: relative;
+ max-width: 235px;
+ text-align: right;
+ &Thumb {
+ display: inline-block;
+ width: 56px;
+ height: 56px;
+ vertical-align: middle;
+ margin-right: 0;
+ }
+ &Icon {
+ position: relative;
+ right: -12px;
+ }
+ }
+ }
+ .actions {
+ position: absolute;
+ right: 0;
+ z-index: 1;
+ .deleteBtn {
+ background-color: #D6243A;
+ color: #fff;
+ text-align: center;
+ line-height: $itemHeight;
+ }
+ }
+
+ &:after {
+ content: "";
+ position: absolute;
+ transform-origin: center;
+ box-sizing: border-box;
+ pointer-events: none;
+ top: auto;
+ left: 144rpx;
+ right: 0;
+ bottom: 0;
+ z-index: 3;
+ transform: scaleY(0.5);
+ border-bottom: 1PX solid #d6e4ef;
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+ border-bottom-color: rgb(214, 228, 239);
+ }
+}
\ No newline at end of file
diff --git a/src/components/FileExplorer/index.jsx b/src/components/FileExplorer/index.jsx
new file mode 100644
index 0000000..040bb54
--- /dev/null
+++ b/src/components/FileExplorer/index.jsx
@@ -0,0 +1,135 @@
+import { getFileUrl } from '@root/service/oss';
+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';
+
+export default function FileExplorer(props) {
+ const { className, node, nodeHash, gotoNode } = props;
+ return (
+
+
+ {
+ node && node.mapChildrenIds(nodeId => {
+ const fileNode = nodeHash[nodeId];
+ if (!fileNode) return null;
+ return (
+ fileNode.type === 'folder'
+ ? (
+ gotoNode(fileNode)}
+ thumb={getFileUrl('oss://assets/file-icon/folder.png')}
+ />
+ )
+ : (
+
+ )
+ )
+ })
+ }
+
+
+ )
+}
+
+
+const deleteBtnWidth = 64;
+function ListItem(props) {
+ const { className, enableDelete = false, title, note, arrow, thumb, extraThumb, onClick } = props;
+ const [initX, setInitX] = useState();
+ const [swipeWidth, setSwipeWidth] = useState(0);
+
+ const onTouchStart = useCallback((e) => {
+ setInitX(e.touches[0].pageX);
+ }, [enableDelete]);
+
+ const onTouchMove = useCallback((e) => {
+ const currentX = e.touches[0].pageX;
+ const diffx = currentX - initX;
+ setSwipeWidth(prevValue => {
+ return diffx >= 0
+ ? prevValue ? Math.max(deleteBtnWidth - diffx, 0) : 0 // 右滑
+ : prevValue !== deleteBtnWidth ? Math.min(deleteBtnWidth, Math.abs(diffx)) : deleteBtnWidth; // 左滑
+ });
+
+ }, [initX, enableDelete]);
+
+ const onTouchEnd = useCallback(() => {
+ setSwipeWidth(prevWidth => prevWidth > deleteBtnWidth / 2 ? deleteBtnWidth : 0);
+ setInitX();
+ }, [enableDelete])
+
+
+ return (
+
+
+ {
+ thumb ? (
+
+
+
+ )
+ : null
+ }
+
+
+ {title}
+ {
+ note
+ ? (
+ {note}
+ )
+ : null
+ }
+
+
+
+
+ {
+ extraThumb
+ ? (
+
+
+
+ )
+ : null
+ }
+ {
+ arrow
+ ? (
+
+ )
+ : null
+ }
+
+
+
+ 删除
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/pages/recycle/index.jsx b/src/pages/recycle/index.jsx
index 8c8deb2..fd2486b 100644
--- a/src/pages/recycle/index.jsx
+++ b/src/pages/recycle/index.jsx
@@ -1,10 +1,77 @@
-import { Text, View } from '@tarojs/components';
-import React from 'react';
+import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react';
+import Page from '@root/components/Page';
+import { AtSearchBar } from 'taro-ui';
+import styles from './index.module.scss';
+import FileExplorer from '@root/components/FileExplorer';
+import { fetchProjectList, fetchProjectRemovedFiles } from './service';
export default function RecycleView() {
+ const [tempKeywords, setTempKeywords] = useState('');
+ const [effectKeywords, setEffectKeywords] = useState('');
+ const [currentNode, setCurrentNode] = useState(null);
+ const [nodeHash, setNodeHash] = useState({});
+
+ useLayoutEffect(() => {
+ fetchProjectList()
+ .then(([rootNode, nextNodeHash]) => {
+ setCurrentNode(rootNode);
+ setNodeHash(nextNodeHash);
+ })
+ }, []);
+
+ const gotoNode = useCallback((nextFileNode) => {
+ if(nextFileNode.isRoot) {
+ fetchProjectList()
+ .then(([rootNode, nextNodeHash]) => { setCurrentNode(rootNode); setNodeHash(nextNodeHash); })
+ } else if(nextFileNode.isProject) {
+ fetchProjectRemovedFiles(nextFileNode)
+ .then(([nextNodeHash]) => {
+ setCurrentNode(nextFileNode);
+ setNodeHash(prevHash => ({ ...prevHash, ...nextNodeHash }));
+ })
+ } else {
+ setCurrentNode(nextFileNode);
+ }
+ }, [])
+
return (
-
- 回收站页
-
+ {
+ setCurrentNode(prevNode => nodeHash[prevNode.parentId])
+ }}
+ >
+ setEffectKeywords(tempKeywords)}
+ onClear={() => {setEffectKeywords(''); setTempKeywords('');}}
+ />
+ {
+ currentNode
+ ? (
+
+ )
+ : null
+ }
+
+
)
}
diff --git a/src/pages/recycle/index.module.scss b/src/pages/recycle/index.module.scss
new file mode 100644
index 0000000..8441c2d
--- /dev/null
+++ b/src/pages/recycle/index.module.scss
@@ -0,0 +1,25 @@
+$searchBoxHeight: 82px;
+.page {
+ background-color: #f6f6f6;
+}
+.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;
+ }
+}
+.list {
+ height: calc(100% - #{$searchBoxHeight});
+}
\ No newline at end of file
diff --git a/src/pages/recycle/service.js b/src/pages/recycle/service.js
new file mode 100644
index 0000000..cf72005
--- /dev/null
+++ b/src/pages/recycle/service.js
@@ -0,0 +1,98 @@
+import getData from '@root/utils/request';
+import * as storage from '@root/utils/storage';
+import { FileNode, firstCharToLowerCase } from '@root/utils/tool';
+import { hideLoading, showLoading } from '@tarojs/taro';
+
+export async function fetchProjectList() {
+ const accountId = storage.get('accountId');
+ showLoading();
+ const res = await getData('project/queryAllProjectListByUserId', { userId: accountId });
+ hideLoading();
+ const nodeHash = {};
+ const rootNode = new FileNode('root', '', null, 'folder');
+ rootNode.isRoot = true;
+ nodeHash[rootNode.id] = rootNode;
+ (res.data || []).forEach((upperProject) => {
+ if(!upperProject.HasFile) { return; }
+ // const project = firstCharToLowerCase(upperProject);
+ const projectFolder = new FileNode(upperProject.Id, upperProject.ProjName, rootNode.id, 'folder');
+ projectFolder.isProject = true;
+ nodeHash[projectFolder.id] = projectFolder;
+ // if (upperProject.NodeFolder) {
+ // upperProject.NodeFolder
+ // .forEach((upperNodeFolder) => {
+ // if(upperNodeFolder.FirstFolderId === upperNodeFolder.Id ||
+ // upperNodeFolder.NodeId === '0') { return; }
+ // const folderNode = new FileNode(upperNodeFolder.Id, upperNodeFolder.FolderName, projectFolder.id, 'folder');
+ // nodeHash[folderNode.id] = folderNode;
+ // projectFolder.append(folderNode.id);
+ // });
+ // ;
+ // }
+ rootNode.append(projectFolder.id)
+ }, []);
+ return [rootNode, nodeHash];
+}
+
+export async function fetchProjectRemovedFiles(projectNode) {
+ showLoading();
+ const hash = {};
+ const isMini = storage.get('isMini');
+ const res = await getData('file/queryFilesFromRecycleBinByProjectId', { projectId: projectNode.id });
+ hideLoading();
+ projectNode.removeAllChildrenIds();
+ (res.data || []).forEach((topNode) => {
+ if(!topNode.ProjArchives) { return ; }
+ let parentNode = projectNode;
+ if(!isMini) {
+ const node = new FileNode(topNode.Id, topNode.FolderName, projectNode.id, 'folder');
+ hash[node.id] = node;
+ projectNode.append(node.id);
+ parentNode = node;
+ }
+ topNode.ProjArchives.forEach((upperFileItem) => {
+ const fileItem = firstCharToLowerCase(upperFileItem);
+ 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);
+ hash[file.id] = file;
+ });
+ });
+ console.log('fetchProjectRemovedFiles:', res);
+ return [hash];
+}
+
+
+function resolveFileListToTree(upperFileList, hash) {
+ const headListIdList = [];
+
+}
+
+
+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;
+ }
+
+ // const parentRelativePath = folder.parentFolderPath;
+
+ (folderMap[folder.parentId] || topNode)
+ .append(folder.id);
+ lastFolder = folder;
+ });
+ return lastFolder;
+}
\ No newline at end of file
diff --git a/src/reducers/app.js b/src/reducers/app.js
index 27a801d..ff73ea9 100644
--- a/src/reducers/app.js
+++ b/src/reducers/app.js
@@ -6,6 +6,7 @@ const initState = {
accountName: '',
companyId: '',
avatorUrl: '',
+ isMini: false,
}
@@ -30,6 +31,7 @@ export default (state = initState, { type, payload }) => {
accountName: '',
companyId: '',
avatorUrl: '',
+ isMini: false,
}
default:
return state;
diff --git a/src/utils/tool.js b/src/utils/tool.js
index 95e4197..838ee87 100644
--- a/src/utils/tool.js
+++ b/src/utils/tool.js
@@ -46,4 +46,35 @@ class RequestHandler {
}
}
-export const handleRequest = res => new RequestHandler(res);
\ No newline at end of file
+export const handleRequest = res => new RequestHandler(res);
+
+
+export class FileNode {
+ // type: 'folder' | 'file'
+ constructor(id, label, parentId, type, data = {}) {
+ Object.assign(this, { id, label, parentId, type, data });
+ }
+ append(childNodeId) {
+ if(!this.childrenIds) { this.childrenIds = []; }
+ this.childrenIds.push(childNodeId);
+ }
+ // sortChildren(f = sortFunc) {
+ // if(!this.hasChildren) { return this; }
+ // this.childrenIds.sort(f);
+ // return this;
+ // }
+ mapChildrenIds(f) {
+ if(!this.hasChildren) { return []; }
+ return this.childrenIds.map(f);
+ }
+ // everyChildren(f) {
+ // if(!this.hasChildren) { return false; }
+ // return this.childrenIds.every(f);
+ // }
+ get hasChildren() {
+ return this.childrenIds && !!this.childrenIds.length;
+ }
+ removeAllChildrenIds() {
+ return this.childrenIds = [];
+ }
+}
\ No newline at end of file