💄 UI: [前台]:书签管理页开发中
This commit is contained in:
parent
2e9466ad6b
commit
a05d57c95b
@ -1,18 +1,134 @@
|
||||
import httpUtil from "../../../util/httpUtil";
|
||||
import { Modal } from "antd";
|
||||
import { Modal, message } from "antd";
|
||||
|
||||
/**
|
||||
* 删除书签
|
||||
* @param {*} _this 组件实例
|
||||
* @param {*} folderList 删除的文件夹列表
|
||||
* @param {*} bookmarkList 删除的具体书签列表
|
||||
* 选中的文件夹id列表
|
||||
*/
|
||||
export function deleteBookmark(_this, folderList, bookmarkList) {
|
||||
let folderIdList = [];
|
||||
/**
|
||||
* 选中的书签id列表
|
||||
*/
|
||||
let bookmarkIdList = [];
|
||||
|
||||
/**
|
||||
* 新增书签的父节点node
|
||||
*/
|
||||
let parentNode = null;
|
||||
|
||||
/**
|
||||
* 展开/关闭
|
||||
* @param {*} keys
|
||||
*/
|
||||
export function onExpand(keys) {
|
||||
this.setState({ expandKeys: keys });
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭全部节点
|
||||
*/
|
||||
export function closeAll() {
|
||||
this.setState({ expandKeys: [] });
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中节点
|
||||
* @param {*} keys
|
||||
* @param {*} data
|
||||
*/
|
||||
export function onCheck(keys, data) {
|
||||
this.setState({ checkedKeys: keys });
|
||||
bookmarkIdList = [];
|
||||
folderIdList = [];
|
||||
parentNode = null;
|
||||
data.checkedNodes.forEach(item => {
|
||||
const bookmark = item.props.dataRef;
|
||||
parentNode = bookmark;
|
||||
bookmark.type === 0 ? bookmarkIdList.push(bookmark.bookmarkId) : folderIdList.push(bookmark.bookmarkId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出新增modal
|
||||
*/
|
||||
export function showAddModel() {
|
||||
if (this.state.checkedKeys.length > 1) {
|
||||
message.error("选中过多");
|
||||
return;
|
||||
} else if (this.state.checkedKeys.length === 1) {
|
||||
const id = this.state.checkedKeys[0];
|
||||
if (bookmarkIdList.indexOf(parseInt(id)) > -1) {
|
||||
message.error("只能选择文件夹节点");
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.setState({ isShowModal: true });
|
||||
}
|
||||
|
||||
export function addOne() {
|
||||
console.log(1);
|
||||
let body = {
|
||||
type: this.state.addType,
|
||||
path: parentNode == null ? "" : parentNode.path + "." + parentNode.bookmarkId,
|
||||
name: this.state.addName,
|
||||
url: this.state.addValue
|
||||
};
|
||||
httpUtil.put("/bookmark", body).then(res => {
|
||||
let arr;
|
||||
if (parentNode == null) {
|
||||
arr = this.data[""] ? this.data[""] : [];
|
||||
} else {
|
||||
arr = this.data[body.path] ? this.data[body.path] : [];
|
||||
}
|
||||
arr.push(res);
|
||||
if (this.state.treeData.length === 0) {
|
||||
this.state.treeData.push(arr);
|
||||
}
|
||||
this.data[body.path] = arr;
|
||||
this.setState({ treeData: [...this.state.treeData], addType: 0, addName: "", addValue: "", isShowModal: false });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
export function batchDelete() {
|
||||
console.log("1");
|
||||
const _this = this;
|
||||
Modal.confirm({
|
||||
title: "确认删除?",
|
||||
content: "删除后,无法找回",
|
||||
onOk() {
|
||||
return httpUtil.post("/dele")
|
||||
return new Promise((resolve, reject) => {
|
||||
httpUtil
|
||||
.post("/bookmark/batchDelete", { folderIdList, bookmarkIdList })
|
||||
.then(() => {
|
||||
//遍历节点树数据,并删除
|
||||
const set = new Set();
|
||||
folderIdList.forEach(item => set.add(item));
|
||||
bookmarkIdList.forEach(item => set.add(item));
|
||||
deleteTreeData(_this.state.treeData, set);
|
||||
_this.setState({ treeData: [..._this.state.treeData], checkedKeys: [] });
|
||||
resolve();
|
||||
})
|
||||
.catch(() => reject());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除已经被删除的数据
|
||||
* @param {*} treeData
|
||||
*/
|
||||
function deleteTreeData(treeData, set) {
|
||||
for (let i = 0, length = treeData.length; i < length; i++) {
|
||||
const item = treeData[i];
|
||||
if (set.has(treeData[i].bookmarkId)) {
|
||||
treeData.splice(i, 1);
|
||||
length--;
|
||||
i--;
|
||||
} else if (item.children && item.children.length > 0) {
|
||||
deleteTreeData(item.children, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React from "react";
|
||||
import { Tree, Empty, Button, Tooltip } from "antd";
|
||||
import { Icon, Tree, Empty, Button, Tooltip, Modal, Form, Input, Radio, Upload } from "antd";
|
||||
import MainLayout from "../../../layout/MainLayout";
|
||||
import httpUtil from "../../../util/httpUtil";
|
||||
import IconFont from "../../../components/IconFont";
|
||||
import styles from "./index.module.less";
|
||||
import { batchDelete, onExpand, closeAll, onCheck, addOne, showAddModel } from "./function.js";
|
||||
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
@ -14,7 +15,15 @@ export default class OverView extends React.Component {
|
||||
treeData: [],
|
||||
isEdit: false,
|
||||
isLoading: true,
|
||||
expandKeys: ["0"]
|
||||
checkedKeys: [],
|
||||
expandKeys: [],
|
||||
//显示新增弹窗
|
||||
isShowModal: false,
|
||||
//新增类别
|
||||
addType: 0,
|
||||
addName: "",
|
||||
addValue: "",
|
||||
file: null
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,12 +43,7 @@ export default class OverView extends React.Component {
|
||||
loadData = e =>
|
||||
new Promise(resolve => {
|
||||
const item = e.props.dataRef;
|
||||
let newPath;
|
||||
if (item.path === "") {
|
||||
newPath = item.bookmarkId;
|
||||
} else {
|
||||
newPath = item.path + "." + item.bookmarkId;
|
||||
}
|
||||
const newPath = item.path + "." + item.bookmarkId;
|
||||
if (this.data[newPath]) {
|
||||
item.children = this.data[newPath];
|
||||
this.setState({ treeData: [...this.state.treeData] });
|
||||
@ -48,23 +52,14 @@ export default class OverView extends React.Component {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 复制url到剪贴板
|
||||
* @param {*} key
|
||||
* @param {*} e
|
||||
*/
|
||||
copyUrl(key, e) {}
|
||||
|
||||
deleteOne = e => {
|
||||
const id = e.target.id;
|
||||
|
||||
};
|
||||
|
||||
treeNodeSelect(key, e) {
|
||||
const { expandKeys } = this.state;
|
||||
const item = e.node.props.dataRef;
|
||||
if (item.type === 0) {
|
||||
window.open(item.url);
|
||||
} else {
|
||||
expandKeys.push(item.bookmarkId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,19 +68,19 @@ export default class OverView extends React.Component {
|
||||
* @param {*} item
|
||||
*/
|
||||
renderNodeContent(item) {
|
||||
const { isEdit } = this.state;
|
||||
const bts = (
|
||||
<React.Fragment>
|
||||
<Button size="small" type="primary" name="copy" icon="copy" shape="circle" />
|
||||
<Button size="small" type="danger" id={item.bookmarkId} icon="delete" shape="circle" onClick={this.deleteOne} />
|
||||
</React.Fragment>
|
||||
);
|
||||
// const { isEdit } = this.state;
|
||||
// const bts = (
|
||||
// <div className={styles.btns}>
|
||||
// <Button size="small" type="primary" name="copy" icon="copy" shape="circle" />
|
||||
// <Button size="small" type="danger" id={item.bookmarkId} icon="delete" shape="circle" onClick={this.deleteOne} />
|
||||
// </div>
|
||||
// );
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Tooltip placement="bottom" title={item.url}>
|
||||
{item.name}
|
||||
<span>{item.name}</span>
|
||||
</Tooltip>
|
||||
{isEdit ? bts : null}
|
||||
{/* {isEdit ? bts : null} */}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@ -120,38 +115,108 @@ export default class OverView extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isLoading, isEdit, treeData, expandKeys } = this.state;
|
||||
const { isLoading, isEdit, treeData, expandKeys, checkedKeys, isShowModal, addType, addValue, addName } = this.state;
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 4 },
|
||||
sm: { span: 4 }
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 20 },
|
||||
sm: { span: 20 }
|
||||
}
|
||||
};
|
||||
const uploadProps = {
|
||||
accept: ".html,.htm",
|
||||
onChange: e => {
|
||||
this.setState({ file: e.fileList[0] });
|
||||
},
|
||||
beforeUpload: file => {
|
||||
return false;
|
||||
},
|
||||
fileList: []
|
||||
};
|
||||
return (
|
||||
<MainLayout>
|
||||
<div className={styles.main}>
|
||||
<div className={styles.header}>
|
||||
<span>我的书签树</span>
|
||||
<div>
|
||||
<div className={styles.left}>
|
||||
<span className={styles.myTree}>我的书签树</span>
|
||||
{expandKeys.length > 0 ? (
|
||||
<Button type="primary" size="small" onClick={closeAll.bind(this)}>
|
||||
收起
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
{isEdit ? (
|
||||
<React.Fragment>
|
||||
<Button size="small" type="danger" onClick={batchDelete.bind(this)}>
|
||||
删除选中
|
||||
</Button>
|
||||
<Button size="small" type="primary" onClick={showAddModel.bind(this)}>
|
||||
新增
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
) : null}
|
||||
<Button size="small" type="primary" onClick={() => this.setState({ isEdit: !isEdit })}>
|
||||
{isEdit ? "完成" : "编辑"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{treeData.length ? (
|
||||
<Tree
|
||||
showIcon
|
||||
loadData={this.loadData}
|
||||
defaultExpandParent
|
||||
checkable={isEdit}
|
||||
onSelect={this.treeNodeSelect}
|
||||
onDoubleClick={this.copyUrl}
|
||||
blockNode
|
||||
>
|
||||
{this.renderTreeNodes(treeData)}
|
||||
</Tree>
|
||||
) : null}
|
||||
{isLoading === false && treeData.length === 0 ? (
|
||||
<Empty description="还没有数据">
|
||||
<Button size="small" type="primary" onClick={() => this.setState({ isEdit: true })}>
|
||||
新增
|
||||
</Button>
|
||||
</Empty>
|
||||
) : null}
|
||||
{/* {treeData.length ? ( */}
|
||||
<Tree
|
||||
showIcon
|
||||
checkedKeys={checkedKeys}
|
||||
onCheck={onCheck.bind(this)}
|
||||
expandedKeys={expandKeys}
|
||||
loadData={this.loadData}
|
||||
onExpand={onExpand.bind(this)}
|
||||
defaultExpandParent
|
||||
checkable={isEdit}
|
||||
onSelect={this.treeNodeSelect}
|
||||
onDoubleClick={this.copyUrl}
|
||||
blockNode
|
||||
>
|
||||
{this.renderTreeNodes(treeData)}
|
||||
</Tree>
|
||||
{/* ) : null} */}
|
||||
{isLoading === false && treeData.length === 0 ? <Empty description="还没有数据" /> : null}
|
||||
|
||||
<Modal destroyOnClose title="新增" visible={isShowModal} onCancel={() => this.setState({ isShowModal: false })} footer={false}>
|
||||
<Form {...formItemLayout}>
|
||||
<Form.Item label="类别">
|
||||
<Radio.Group defaultValue={0} onChange={e => this.setState({ addType: e.target.value })}>
|
||||
<Radio value={0}>书签</Radio>
|
||||
<Radio value={1}>文件夹</Radio>
|
||||
<Radio value={2}>上传书签html</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
{addType < 2 ? (
|
||||
<Form.Item label="名称">
|
||||
<Input type="text" onChange={e => this.setState({ addName: e.target.value })} value={addName} />
|
||||
</Form.Item>
|
||||
) : null}
|
||||
{addType === 0 ? (
|
||||
<Form.Item label="URL">
|
||||
<Input type="text" value={addValue} onChange={e => this.setState({ addValue: e.target.value })} />
|
||||
</Form.Item>
|
||||
) : null}
|
||||
{addType === 2 ? (
|
||||
<Upload {...uploadProps}>
|
||||
<Button type="primary">
|
||||
<Icon type="upload" />
|
||||
{this.state.file == null ? "选择文件" : this.state.file.name.substr(0, 20)}
|
||||
</Button>
|
||||
</Upload>
|
||||
) : null}
|
||||
<div style={{ textAlign: "center", paddingTop: "1em" }}>
|
||||
<Button type="primary" onClick={addOne.bind(this)}>
|
||||
提交
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
</MainLayout>
|
||||
);
|
||||
|
@ -5,5 +5,30 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.myTree {
|
||||
font-size: 1.3em;
|
||||
line-height: 1.3em;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display: inline-block;
|
||||
max-width: 70%;
|
||||
margin-right: 1em;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -0.45em;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user