feat:网页段缓存书签数据完成
This commit is contained in:
parent
d95441d860
commit
3c93016bd3
@ -106,7 +106,7 @@ public class UserController {
|
||||
/**
|
||||
* 功能描述: 校验密码,生成一个actionId
|
||||
*
|
||||
* @param password password
|
||||
* @param obj obj
|
||||
* @return com.fanxb.bookmark.common.entity.Result
|
||||
* @author fanxb
|
||||
* @date 2019/11/11 23:31
|
||||
|
@ -22,4 +22,8 @@ public class User {
|
||||
private String password;
|
||||
private long createTime;
|
||||
private long lastLoginTime;
|
||||
/**
|
||||
* 上次更新书签时间
|
||||
*/
|
||||
private long bookmarkChangeTime;
|
||||
}
|
||||
|
@ -34,5 +34,6 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script src="/js/localforage.main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
7
front/public/js/localforage.main.js
Normal file
7
front/public/js/localforage.main.js
Normal file
File diff suppressed because one or more lines are too long
@ -1,10 +1,13 @@
|
||||
import React from "react";
|
||||
import { Link, withRouter } from "react-router-dom";
|
||||
import { Menu, Dropdown, Divider } from "antd";
|
||||
import { Menu, Dropdown, Divider, Modal } from "antd";
|
||||
import httpUtil from "../../util/httpUtil";
|
||||
import { connect } from "react-redux";
|
||||
import styles from "./index.module.less";
|
||||
import * as infoAction from "../../redux/action/LoginInfoAction";
|
||||
import { checkCacheStatus, clearCache } from "../../util/cacheUtil";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return state[infoAction.DATA_NAME];
|
||||
@ -20,13 +23,44 @@ function mapDispatchToProps(dispatch) {
|
||||
class MainLayout extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
timer: null,
|
||||
//刷新数据弹窗是否展示中
|
||||
showDialog: false
|
||||
};
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
if (!this.props.username) {
|
||||
let res = await httpUtil.get("/user/currentUserInfo");
|
||||
this.props.changeUserInfo(res);
|
||||
if (this.state.timer != null) {
|
||||
clearInterval(this.state.timer);
|
||||
}
|
||||
await this.checkCache();
|
||||
this.state.timer = setInterval(this.checkCache.bind(this), 5 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
async checkCache() {
|
||||
//检查缓存情况
|
||||
if (this.state.showDialog) {
|
||||
return;
|
||||
}
|
||||
let _this = this;
|
||||
if (!(await checkCacheStatus())) {
|
||||
this.state.showDialog = true;
|
||||
confirm({
|
||||
title: "缓存过期",
|
||||
content: "书签数据有更新,是否立即刷新?",
|
||||
onOk() {
|
||||
_this.state.showDialog = false;
|
||||
clearCache();
|
||||
},
|
||||
onCancel() {
|
||||
_this.state.showDialog = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +74,11 @@ class MainLayout extends React.Component {
|
||||
);
|
||||
if (username != null) {
|
||||
return (
|
||||
<Dropdown overlay={menu} placement="bottomCenter" trigger={["hover", "click"]}>
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
placement="bottomCenter"
|
||||
trigger={["hover", "click"]}
|
||||
>
|
||||
<span style={{ cursor: "pointer" }}>
|
||||
<img className={styles.icon} src={icon} alt="icon" />
|
||||
{username}
|
||||
@ -77,20 +115,34 @@ class MainLayout extends React.Component {
|
||||
<div className={styles.main}>
|
||||
<div className={styles.header}>
|
||||
<a href="/">
|
||||
<img style={{ width: "1.5rem" }} src="/img/bookmarkLogo.png" alt="logo" />
|
||||
<img
|
||||
style={{ width: "1.5rem" }}
|
||||
src="/img/bookmarkLogo.png"
|
||||
alt="logo"
|
||||
/>
|
||||
</a>
|
||||
{this.renderUserArea()}
|
||||
</div>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<div style={{ minHeight: `calc(${document.body.clientHeight}px - 1.45rem)` }} className={styles.content}>
|
||||
<div
|
||||
style={{
|
||||
minHeight: `calc(${document.body.clientHeight}px - 1.45rem)`
|
||||
}}
|
||||
className={styles.content}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
开源地址:<a href="https://github.com/FleyX/bookmark">github.com/FleyX/bookmark</a>
|
||||
开源地址:
|
||||
<a href="https://github.com/FleyX/bookmark">
|
||||
github.com/FleyX/bookmark
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MainLayout));
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(MainLayout)
|
||||
);
|
||||
|
@ -7,8 +7,7 @@ import { stopTransfer } from "../../../util/eventUtil";
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
function menuVisible(item, visible) {
|
||||
if (visible) {
|
||||
window.copyUrl = item.url;
|
||||
if (visible) { window.copyUrl = item.url;
|
||||
}
|
||||
this.props.changeCurrentClickItem(item);
|
||||
}
|
||||
@ -56,7 +55,11 @@ export function renderNodeContent(item) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{/* 触发右键菜单 */}
|
||||
<Dropdown overlay={menu} trigger={["contextMenu"]} onVisibleChange={menuVisible.bind(this, item)}>
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
trigger={["contextMenu"]}
|
||||
onVisibleChange={menuVisible.bind(this, item)}
|
||||
>
|
||||
{item.type === 0 ? (
|
||||
<a href={item.url} className={styles.nodeContent}>
|
||||
{item.name}
|
||||
@ -66,8 +69,18 @@ export function renderNodeContent(item) {
|
||||
)}
|
||||
</Dropdown>
|
||||
{isEdit ? (
|
||||
<Dropdown overlay={menu} trigger={["click"]} onVisibleChange={menuVisible.bind(this, item)}>
|
||||
<Button size="small" onClick={stopTransfer.bind(this)} type="primary" icon="menu" shape="circle" />
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
trigger={["click"]}
|
||||
onVisibleChange={menuVisible.bind(this, item)}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={stopTransfer.bind(this)}
|
||||
type="primary"
|
||||
icon="menu"
|
||||
shape="circle"
|
||||
/>
|
||||
</Dropdown>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
@ -130,7 +143,9 @@ export function batchDelete() {
|
||||
bookmarkIdList = [];
|
||||
checkedNodes.forEach(item => {
|
||||
const data = item.props.dataRef;
|
||||
data.type === 0 ? bookmarkIdList.push(data.bookmarkId) : folderIdList.push(data.bookmarkId);
|
||||
data.type === 0
|
||||
? bookmarkIdList.push(data.bookmarkId)
|
||||
: folderIdList.push(data.bookmarkId);
|
||||
});
|
||||
deleteBookmark.call(this, folderIdList, bookmarkIdList);
|
||||
}
|
||||
@ -203,11 +218,13 @@ export function onDrop(info) {
|
||||
sort: -1
|
||||
};
|
||||
//从原来所属的节点列表中删除当前节点
|
||||
const currentBelowList = current.path === "" ? treeData : getBelowList(treeData, current);
|
||||
const currentBelowList =
|
||||
current.path === "" ? treeData : getBelowList(treeData, current);
|
||||
currentBelowList.splice(currentBelowList.indexOf(current), 1);
|
||||
if (info.dropToGap) {
|
||||
body.targetPath = target.path;
|
||||
const targetBelowList = target.path === "" ? treeData : getBelowList(treeData, target);
|
||||
const targetBelowList =
|
||||
target.path === "" ? treeData : getBelowList(treeData, target);
|
||||
const index = targetBelowList.indexOf(target);
|
||||
if (info.dropPosition > index) {
|
||||
body.sort = target.sort + 1;
|
||||
@ -236,7 +253,11 @@ export function onDrop(info) {
|
||||
current.sort = body.sort;
|
||||
//如果当前节点和目标节点不在一个层级中,需要更新当前子节点的path信息
|
||||
if (body.sourcePath !== body.targetPath) {
|
||||
updateChildrenPath(current.children, body.sourcePath + "." + body.bookmarkId, body.targetPath + "." + body.bookmarkId);
|
||||
updateChildrenPath(
|
||||
current.children,
|
||||
body.sourcePath + "." + body.bookmarkId,
|
||||
body.targetPath + "." + body.bookmarkId
|
||||
);
|
||||
}
|
||||
}
|
||||
httpUtil
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from "react";
|
||||
import { Tree, Empty, Button, Spin } from "antd";
|
||||
import MainLayout from "../../../layout/MainLayout";
|
||||
import httpUtil from "../../../util/httpUtil";
|
||||
import styles from "./index.module.less";
|
||||
import { batchDelete, renderTreeNodes, onDrop } from "./function.js";
|
||||
import { cacheBookmarkData, getBookmarkList } from "../../../util/cacheUtil";
|
||||
import AddModal from "./AddModal";
|
||||
import Search from "../../../components/Search";
|
||||
|
||||
@ -43,15 +43,11 @@ class OverView extends React.Component {
|
||||
/**
|
||||
* 初始化第一级书签
|
||||
*/
|
||||
componentDidMount() {
|
||||
async componentDidMount() {
|
||||
this.props.refresh();
|
||||
httpUtil
|
||||
.get("/bookmark/currentUser/path?path=")
|
||||
.then(res => {
|
||||
this.props.updateTreeData(res);
|
||||
await cacheBookmarkData();
|
||||
this.props.updateTreeData(getBookmarkList(""));
|
||||
this.props.changeIsInit(true);
|
||||
})
|
||||
.catch(() => this.props.changeIsInit(true));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,14 +58,12 @@ class OverView extends React.Component {
|
||||
return new Promise(resolve => {
|
||||
const item = e.props.dataRef;
|
||||
const newPath = item.path + "." + item.bookmarkId;
|
||||
httpUtil.get("/bookmark/currentUser/path?path=" + newPath).then(res => {
|
||||
item.children = res;
|
||||
item.children = getBookmarkList(newPath);
|
||||
this.props.updateTreeData([...treeData]);
|
||||
loadedKeys.push(item.bookmarkId.toString());
|
||||
this.props.changeLoadedKeys(loadedKeys);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 节点选择
|
||||
|
55
front/src/util/cacheUtil.js
Normal file
55
front/src/util/cacheUtil.js
Normal file
@ -0,0 +1,55 @@
|
||||
/* eslint-disable no-undef */
|
||||
import httpUtil from "./httpUtil";
|
||||
|
||||
/**
|
||||
* 缓存工具类
|
||||
*/
|
||||
|
||||
/**
|
||||
* 全部书签数据key
|
||||
*/
|
||||
export const TREE_LIST_KEY = "treeListData";
|
||||
/**
|
||||
* 获取全部书签时间
|
||||
*/
|
||||
export const TREE_LIST_TIME_KEY = "treeListDataTime";
|
||||
|
||||
/**
|
||||
* 缓存书签数据
|
||||
*/
|
||||
export async function cacheBookmarkData() {
|
||||
let res = await localforage.getItem(TREE_LIST_KEY);
|
||||
if (!res) {
|
||||
res = await httpUtil.get("/bookmark/currentUser");
|
||||
await localforage.setItem(TREE_LIST_KEY, res);
|
||||
await localforage.setItem(TREE_LIST_TIME_KEY, Date.now());
|
||||
}
|
||||
window[TREE_LIST_KEY] = res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存数据
|
||||
* @param {*} path path
|
||||
*/
|
||||
export function getBookmarkList(path) {
|
||||
return window[TREE_LIST_KEY][path];
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查缓存情况
|
||||
* @return 返回true说明未过期,否则说明过期了
|
||||
*/
|
||||
export async function checkCacheStatus() {
|
||||
let date = await localforage.getItem(TREE_LIST_TIME_KEY, Date.now());
|
||||
let userInfo = await httpUtil.get("/user/currentUserInfo");
|
||||
return !date || date > userInfo.bookmarkChangeTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清楚缓存数据
|
||||
*/
|
||||
export async function clearCache() {
|
||||
await localforage.removeItem(TREE_LIST_KEY);
|
||||
await localforage.removeItem(TREE_LIST_TIME_KEY);
|
||||
window.location.reload();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user