You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

968 lines
54 KiB

<!DOCTYPE html>
<html lang="">
<head>
<title>公共开支结算系统 - EEE.DOG</title><meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">
<meta name="description" content="公共开支结算系统"/><meta name="keywords" content="iotcat,yimian,blog" /><link rel="alternate" href="/atom.xml" title="EEE.DOG"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=1.0.0" /><script>lang = ['zh', 'en'];</script>
<script type="text/javascript" src="https://cdn.yimian.xyz/ushio-js/ushio-head.min.js"></script>
<script>page.proj = 'iotcat/eee.dog-public';</script>
<!--<link rel="stylesheet" type="text/css" href="https://cdn.yimian.xyz/kayo/lib/iziModal/iziModal.min.css" />-->
<!--<link rel="stylesheet" type="text/css" href="https://cdn.yimian.xyz/kayo/lib/iziToast/iziToast.min.css" />-->
<link rel="stylesheet" media="none" onload="this.media='all'" type="text/css" href="https://cdn.yimian.xyz/shaky/shaky.css">
<link rel="canonical" href="https://www.eee.dog/tech/crown-place-erp.html"/>
<link rel="stylesheet" media="none" onload="this.media='all'" type="text/css" href="https://cdn.yimian.xyz/kayo/lib/fancybox/jquery.fancybox.css" /><script type="text/x-mathjax-config">
MathJax.Hub.Config({ tex2jax: { inlineMath: [['$','$'], ['\\(','\\)']] } });
</script>
<script type="text/javascript" async src="https://cdn.yimian.xyz/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.yimian.xyz/kayo/css/style.css?v=1.0.0" />
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-169276192-1" data-pjax></script>
<script>
pjax_google_analytics = () => {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-169276192-1');
}
</script><script id="baidu_push">
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
<script>
window.config = {"leancloud":"","toc":true,"fancybox":true,"pjax":{"enable":true,"loadingbar":true},"latex":true};
</script>
<meta name="generator" content="Hexo 4.2.1"><link rel="alternate" href="/atom.xml" title="EEE.DOG" type="application/atom+xml">
</head>
<body><div id="mobile-navbar" class="mobile-navbar">
<div class="mobile-header-logo">
<a href="/." class="logo">EEE.DOG</a>
</div>
<div class="mobile-navbar-icon">
<span></span>
<span></span>
<span></span>
</div>
<div class="loading-bar">
<div class="progress"></div>
</div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
<ul class="mobile-menu-list"><div id="mobile-menu-Home">
<a href="/">
<li class="mobile-menu-item"><span class=".en">Home</span><span class=".zh">主页</span>
</li>
</a></div><div id="mobile-menu-Archives">
<a href="/archives/">
<li class="mobile-menu-item"><span class=".en">Archives</span><span class=".zh">归档</span>
</li>
</a></div><div id="mobile-menu-Categories">
<a href="/categories/">
<li class="mobile-menu-item"><span class=".en">Categories</span><span class=".zh">分类</span>
</li>
</a></div><div id="mobile-menu-Projects">
<a href="#">
<li class="mobile-menu-item"><span class=".en">Projects</span><span class=".zh">项目</span>
</li>
</a><ul class="sub-menu" style="display: none;">
<li>
<a href="https://fp.js.org/" target="_blank" rel="noopener">
<span class=".en">fp</span><span class=".zh">fp</span>
</a>
</li>
<li>
<a href="https://wiot.js.org/" target="_blank" rel="noopener">
<span class=".en">wIoT</span><span class=".zh">wIoT</span>
</a>
</li>
<li>
<a href="https://github.com/iotcat/kms" target="_blank" rel="noopener">
<span class=".en">kms</span><span class=".zh">kms</span>
</a>
</li>
<li>
<a href="https://ushio.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">ushio</span><span class=".zh">Ushio</span>
</a>
</li>
</ul>
<script>$('#mobile-menu-Projects').click(function(){
$("#mobile-menu-Projects ul").toggle();
})</script>
</div><div id="mobile-menu-Map">
<a href="#">
<li class="mobile-menu-item"><span class=".en">Map</span><span class=".zh">导航</span>
</li>
</a><ul class="sub-menu" style="display: none;">
<li>
<a href="https://api.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">APIs</span><span class=".zh">接口</span>
</a>
</li>
<li>
<a href="https://img.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Imgs</span><span class=".zh">图库</span>
</a>
</li>
<li>
<a href="/">
<span class=".en">Imgbed</span><span class=".zh">图床</span>
</a>
</li>
<li>
<a href="https://share.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Fileshare</span><span class=".zh">文件分享</span>
</a>
</li>
<li>
<a href="https://monitor.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Server Monitor</span><span class=".zh">服务器监控</span>
</a>
</li>
<li>
<a href="https://status.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Service Status</span><span class=".zh">服务状态</span>
</a>
</li>
<li>
<a href="https://acg.watch/" target="_blank" rel="noopener">
<span class=".en">ACG.WATCH</span><span class=".zh">视频</span>
</a>
</li>
<li>
<a href="https://onedrive.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Oneindex</span><span class=".zh">网盘</span>
</a>
</li>
<li>
<a href="https://chat.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Chat</span><span class=".zh">聊天室</span>
</a>
</li>
<li>
<a href="https://proxy.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">Proxy</span><span class=".zh">下载代理</span>
</a>
</li>
<li>
<a href="https://shorturl.yimian.xyz/" target="_blank" rel="noopener">
<span class=".en">ShortenURL</span><span class=".zh">短链</span>
</a>
</li>
</ul>
<script>$('#mobile-menu-Map').click(function(){
$("#mobile-menu-Map ul").toggle();
})</script>
</div><div id="mobile-menu-About">
<a href="#">
<li class="mobile-menu-item"><span class=".en">About</span><span class=".zh">关于</span>
</li>
</a><ul class="sub-menu" style="display: none;">
<li>
<a href="/links/">
<span class=".en">links</span><span class=".zh">友链</span>
</a>
</li>
<li>
<a href="https://iotcat.me/" target="_blank" rel="noopener">
<span class=".en">Me</span><span class=".zh">关于我</span>
</a>
</li>
<li>
<a href="https://cv.yimian.xyz/contact.html" target="_blank" rel="noopener">
<span class=".en">Contact</span><span class=".zh">留言板</span>
</a>
</li>
</ul>
<script>$('#mobile-menu-About').click(function(){
$("#mobile-menu-About ul").toggle();
})</script>
</div></ul>
</nav>
<div class="container" id="mobile-panel">
<header id="header" class="header"><div class="logo-wrapper">
<a href="/." class="logo">EEE.DOG</a>
</div>
<nav class="site-navbar"><ul id="menu" class="menu"><li class="menu-item">
<a id="menu-Home" class="menu-item-link" href="/">
<span class=".en">Home</span><span class=".zh">主页</span>
</a>
</li>
<li class="menu-item">
<a id="menu-Archives" class="menu-item-link" href="/archives/">
<span class=".en">Archives</span><span class=".zh">归档</span>
</a>
</li>
<li class="menu-item">
<a id="menu-Categories" class="menu-item-link" href="/categories/">
<span class=".en">Categories</span><span class=".zh">分类</span>
</a>
</li>
<li class="menu-item">
<a id="menu-Projects" class="menu-item-link" href="#">
<span class=".en">Projects</span><span class=".zh">项目</span>
</a>
<script>
$("#menu-Projects").click(function(){
tips.question({
timeout: 20000,
close: false,
overlay: true,
displayMode: 'once',
//id: 'question',
zindex: 999,
title: 'Projects',
message: '',
position: 'center',
buttons: [
['<button><b>'+((page.tran.getLang() != 'zh')?'fp':'fp')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://fp.js.org/");
else
window.location.href="https://fp.js.org/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'wIoT':'wIoT')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://wiot.js.org/");
else
window.location.href="https://wiot.js.org/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'kms':'kms')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://github.com/iotcat/kms");
else
window.location.href="https://github.com/iotcat/kms";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'ushio':'Ushio')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://ushio.yimian.xyz/");
else
window.location.href="https://ushio.yimian.xyz/";
}, true],
['<button><b>close</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, true],
]
});
});
</script>
</li>
<li class="menu-item">
<a id="menu-Map" class="menu-item-link" href="#">
<span class=".en">Map</span><span class=".zh">导航</span>
</a>
<script>
$("#menu-Map").click(function(){
tips.question({
timeout: 20000,
close: false,
overlay: true,
displayMode: 'once',
//id: 'question',
zindex: 999,
title: 'Map',
message: '',
position: 'center',
buttons: [
['<button><b>'+((page.tran.getLang() != 'zh')?'APIs':'接口')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://api.yimian.xyz/");
else
window.location.href="https://api.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Imgs':'图库')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://img.yimian.xyz/");
else
window.location.href="https://img.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Imgbed':'图床')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("/");
else
window.location.href="undefined";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Fileshare':'文件分享')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://share.yimian.xyz/");
else
window.location.href="https://share.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Server Monitor':'服务器监控')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://monitor.yimian.xyz/");
else
window.location.href="https://monitor.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Service Status':'服务状态')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://status.yimian.xyz/");
else
window.location.href="https://status.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'ACG.WATCH':'视频')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://acg.watch/");
else
window.location.href="https://acg.watch/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Oneindex':'网盘')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://onedrive.yimian.xyz/");
else
window.location.href="https://onedrive.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Chat':'聊天室')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://chat.yimian.xyz/");
else
window.location.href="https://chat.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Proxy':'下载代理')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://proxy.yimian.xyz/");
else
window.location.href="https://proxy.yimian.xyz/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'ShortenURL':'短链')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://shorturl.yimian.xyz/");
else
window.location.href="https://shorturl.yimian.xyz/";
}, true],
['<button><b>close</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, true],
]
});
});
</script>
</li>
<li class="menu-item">
<a id="menu-About" class="menu-item-link" href="#">
<span class=".en">About</span><span class=".zh">关于</span>
</a>
<script>
$("#menu-About").click(function(){
tips.question({
timeout: 20000,
close: false,
overlay: true,
displayMode: 'once',
//id: 'question',
zindex: 999,
title: 'About',
message: '',
position: 'center',
buttons: [
['<button><b>'+((page.tran.getLang() != 'zh')?'links':'友链')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("true" == "true")
pjax.loadUrl("/links/");
else
window.location.href="/links/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Me':'关于我')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://iotcat.me/");
else
window.location.href="https://iotcat.me/";
}, true],
['<button><b>'+((page.tran.getLang() != 'zh')?'Contact':'留言板')+'</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
if("undefined" == "true")
pjax.loadUrl("https://cv.yimian.xyz/contact.html");
else
window.location.href="https://cv.yimian.xyz/contact.html";
}, true],
['<button><b>close</b></button>', function (instance, toast) {
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, true],
]
});
});
</script>
</li>
</ul></nav>
</header>
<main id="main" class="main">
<div class="content-wrapper">
<div id="content" class="content"><article class="post">
<header class="post-header">
<h1 class="post-title"><span class=".zh">公共开支结算系统</span><span class=".en" hidden>Shared Expense Management System</span>
</h1>
<div class="post-meta">
<span class="post-time">
2019-09-22
</span><span class="post-category">
<a href="/categories/tech/">tech</a>
</span>
</div>
</header>
<style>.toc-level-2 > .toc-child {display: none !important; }</style>
<div class="post-toc" id="post-toc">
<h2 class="post-toc-title">Contents</h2>
<div class="post-toc-content">
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-功能介绍"><span class="toc-text">1.功能介绍</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-系统架构"><span class="toc-text">2.系统架构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-前端"><span class="toc-text">2.1 前端</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-后端"><span class="toc-text">2.2 后端</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-3-数据库"><span class="toc-text">2.3 数据库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-4-图片上传"><span class="toc-text">2.4 图片上传</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-5-用户系统"><span class="toc-text">2.5 用户系统</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-外观"><span class="toc-text">3. 外观</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#主要收获"><span class="toc-text">主要收获</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#开发方法论"><span class="toc-text">开发方法论</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#遇到的挑战"><span class="toc-text">遇到的挑战</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#解决方法"><span class="toc-text">解决方法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#新功能"><span class="toc-text">新功能</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#体验"><span class="toc-text">体验</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-Function-introduction"><span class="toc-text">1. Function introduction</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-System-Architecture"><span class="toc-text">2. System Architecture</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-Frontend"><span class="toc-text">2.1 Frontend</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-Backend"><span class="toc-text">2.2 Backend</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-3-Database"><span class="toc-text">2.3 Database</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-4-Image-upload"><span class="toc-text">2.4 Image upload</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-5-User-System"><span class="toc-text">2.5 User System</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-Appearance"><span class="toc-text">3. Appearance</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Main-gains"><span class="toc-text">Main gains</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Development-Methodology"><span class="toc-text">Development Methodology</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Challenges-encountered"><span class="toc-text">Challenges encountered</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Solution"><span class="toc-text">Solution</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#New-features"><span class="toc-text">New features</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Experience"><span class="toc-text">Experience</span></a></li></ol>
</div>
</div>
<script>var arr = [];var ts = '';if($('.post-toc-content').children().length>1){var el = '.post-toc-content';ts = ($(el).children('ol')[0].outerHTML);}else{var el = '.toc';};for(var i = 0; i < $(el).children('li').length; i++){arr.push($(el).children('li')[i].outerHTML);}; arr.splice(arr.length / 2, 0, '</span><span class=".en">');arr.unshift(ts);arr.unshift('<span class=".zh">');arr.push('</span>');$(el).html(arr.join(''));</script><div class="post-content"><span class=".zh">
<p>在英国留学与4个室友合租,为了更好的控制和监管公共支出,以及维持彼此之间的公共支出平衡,我利用迎新周三天时间设计并开发除了此ERP公共开支计划系统。希望此系统能够便捷接下来一年的生活,减少大家之间的矛盾,促使充满幸福感的公共支出项目持久化OωO</p>
</span>
<span class=".en">
<p>I studied in the UK and shared with 4 roommates. In order to better control and monitor public expenditures and maintain the balance of public expenditures between each other, I designed and developed this ERP public expenditure planning system during the welcome Wednesday. I hope that this system will make life easier for the next year, reduce conflicts between everyone, and promote the sustainability of public expenditure projects full of happiness OωO</p>
</span>
<a id="more"></a>
<script>
session.onload(function(){
if(page.tran.getLang() == 'en'){
tips.warning({
title: 'Caution',
position: 'topRight',
message: 'This page was translated by Machine!!',
buttons: [['<button>Show Original Page</button>', function (instance, toast) {
page.tran.setLang('zh');
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, true]]
});
}
});
</script>
<span class=".zh">
<h2 id="1-功能介绍"><a href="#1-功能介绍" class="headerlink" title="1.功能介绍"></a>1.功能介绍</h2><ul>
<li>统计日均周均流水,让公共支出可视化</li>
<li>用户申报一次公共支出,并提交发票照片留证</li>
<li>监视各成员间支出不均衡程度,计算方差,并可视化显示</li>
<li>对比本周与上周的开支,给出增减比例</li>
<li>当存在一人支出超出均值阈值,并且存在至少一人支出少于均值阈值,则会邮件这两个人产生一次内部交易</li>
<li>邮件通知内部交易的双方</li>
<li>当上例中收款人收到款项后,需要到平台确认收到</li>
<li>平台所有历史公共开支及发票可查</li>
</ul>
<h2 id="2-系统架构"><a href="#2-系统架构" class="headerlink" title="2.系统架构"></a>2.系统架构</h2><h3 id="2-1-前端"><a href="#2-1-前端" class="headerlink" title="2.1 前端"></a>2.1 前端</h3><p>前端基于一个网上找到的比特币网站平台模板,深度改造实现。值得一提的是,前端使用<a href="https://github.com/iotcat/ushio-js" target="_blank" rel="noopener">Ushio-js项目</a>作为安全及日志插件,并得到了<a href="https://ushio.yimian.xyz" target="_blank" rel="noopener">Ushio</a>系统做背后支持。</p>
<h3 id="2-2-后端"><a href="#2-2-后端" class="headerlink" title="2.2 后端"></a>2.2 后端</h3><p>后端使用php语言编写。提供5个接口,分别提供获取账户事件,获取内部流通信息,获取公共支出信息,获取周报表,操作的功能。</p>
<p>mail系统使用<a href="https://www.eee.dog/tech/mail-api.html">Yimian Mail API</a>快速构建。</p>
<h3 id="2-3-数据库"><a href="#2-3-数据库" class="headerlink" title="2.3 数据库"></a>2.3 数据库</h3><p>数据库使用yimian-db/mysql。构建了三个表,分别用于存储流水,公共支出详情,内部流通。</p>
<h3 id="2-4-图片上传"><a href="#2-4-图片上传" class="headerlink" title="2.4 图片上传"></a>2.4 图片上传</h3><p>直接引用<a href="https://imgbed.yimian.xyz" target="_blank" rel="noopener">呓喵酱の图床</a>代码,少量改写。</p>
<h3 id="2-5-用户系统"><a href="#2-5-用户系统" class="headerlink" title="2.5 用户系统"></a>2.5 用户系统</h3><p>目前用额外网页简单实现,等待<a href="https://github.com/iotcat/ushio-auth" target="_blank" rel="noopener">ushio-auth项目</a>完成后统一整合。</p>
<h2 id="3-外观"><a href="#3-外观" class="headerlink" title="3. 外观"></a>3. 外观</h2><p>没啥可说的,摆图,自己看<br><img src="https://api.yimian.xyz/img/?path=imgbed/img_ed08c497_1080x6654_8_null_normal.jpeg" alt="imgbed_ed08c497"></p>
<p><img src="https://api.yimian.xyz/img/?path=imgbed/img_ea04ad82_1080x5082_8_null_normal.jpeg" alt="imgbed_ea04ad82"></p>
<p><img src="https://api.yimian.xyz/img/?path=imgbed/img_a8b3adb0_1080x2160_8_null_normal.jpeg" alt="imgbed_a8b3adb0"></p>
<hr>
<p><strong>2020-03-22 更新</strong> </p>
<p>由于疫情原因,考虑到大家都已撤回中国。为节约服务器费用,停止提供服务。</p>
<p>结合过去半年运行状况,我做了一些分析总结:</p>
<h2 id="主要收获"><a href="#主要收获" class="headerlink" title="主要收获"></a>主要收获</h2><ol>
<li>分析客户真需求的经验</li>
<li>快速搭建生产环境网站工具的能力</li>
<li>室友对我能力的认可</li>
</ol>
<h2 id="开发方法论"><a href="#开发方法论" class="headerlink" title="开发方法论"></a>开发方法论</h2><ol>
<li>基于一系列自己过去的项目,3天时间快速立项并投入使用</li>
<li>仔细研究需求,判断哪些是真需求,哪些是伪需求。</li>
</ol>
<h2 id="遇到的挑战"><a href="#遇到的挑战" class="headerlink" title="遇到的挑战"></a>遇到的挑战</h2><ol>
<li>快速开发,因为大家在抵达英国后已经开始大量花钱买公共用品,因此,急需使用这个系统</li>
<li>算法一定要稳定可靠,因为是牵扯到大家钱的东西</li>
<li>本系统的目的是为了更加方便,把会计的工作交给系统来自动化处理。以此一定要在保证公平的前提下,使得大家之间的内部交易的次数尽可能少,且指示明确。</li>
<li>如何让大家对系统产生信任。</li>
</ol>
<h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><ol>
<li>基于大量自己先前的项目。用1天开发成型,1天测试debug,1天优化前端,加入方差,百分比等功能。</li>
<li>参考记账表,使用了表格模式。每次有新的上传,就会实时计算出新的状态。多次测试,充分验证后才投入使用。</li>
<li>使用“平衡”的构想,关注差异,当差异过大时使支出最多者和支出最少者产生内部交易。且内部交易值为整数。比如我们生产场景应用的是20磅。</li>
<li>在系统算法稳定的情况下,参考支付宝的设计。内部交易有两个步骤。首选支出者和收入者都收到邮件,告知给谁(从谁收),多少钱。然后在支出者把钱给收入者后,收入者需要登录网页或从邮件链接进行确认。截至此时,系统才认为一笔内部交易完成。</li>
</ol>
<hr>
<p><strong>2020-9-8 更新</strong></p>
<p>基于Ushio用户系统,结合过去半年的运行情况和大家的需求变化,我重构并开发出了新一版的公共支出系统。</p>
<h2 id="新功能"><a href="#新功能" class="headerlink" title="新功能"></a>新功能</h2><ul>
<li>实现了Ushio用户系统的接入</li>
<li>用户能够随时注册并新建公共账单</li>
<li>同一个用户能够同时在多个账单</li>
<li>用户能够随时加入公共账单</li>
<li>用户能够随时结算并退出某个公共账单</li>
<li>更加智能的结算算法</li>
<li>使用LocalStorage优化了二次访问的速度</li>
</ul>
<h2 id="体验"><a href="#体验" class="headerlink" title="体验"></a>体验</h2><p>cp-acc现在已经对公众开放,您可以进入其<a href="https://cp-acc.yimian.xyz" target="_blank" rel="noopener">网站</a>进行体验。不过在体验前,您需要先通过ushio用户系统使用您的邮箱登录,以便接收账单消息。</p>
</span>
<span class=".en">
<h2 id="1-Function-introduction"><a href="#1-Function-introduction" class="headerlink" title="1. Function introduction"></a>1. Function introduction</h2><ul>
<li>Calculate the daily average weekly flow rate to visualize public expenditure</li>
<li>The user declares a public expenditure and submits the invoice photo certificate</li>
<li>Monitor the disequilibrium of expenditure among members, calculate the variance, and display it visually</li>
<li>Compare spending this week and last week, and give the percentage increase or decrease</li>
<li>When there is one person whose expenditure exceeds the average threshold, and there is at least one person whose expenditure is less than the average threshold, the two people will be emailed to generate an internal transaction</li>
<li>When the recipient receives the money in the above example, he needs to go to the platform to confirm receipt</li>
<li>All historical public expenditures and invoices on the platform can be checked</li>
</ul>
<h2 id="2-System-Architecture"><a href="#2-System-Architecture" class="headerlink" title="2. System Architecture"></a>2. System Architecture</h2><h3 id="2-1-Frontend"><a href="#2-1-Frontend" class="headerlink" title="2.1 Frontend"></a>2.1 Frontend</h3><p>The front end is based on a Bitcoin website platform template found on the Internet, and a deep transformation is realized. It is worth mentioning that the front end uses <a href="https://github.com/iotcat/ushio-js" target="_blank" rel="noopener">Ushio-js project</a> as a security and logging plug-in, and got <a href="https://ushio.yimian.xyz" target="_blank" rel="noopener">Ushio</a> The system does behind the scenes.</p>
<h3 id="2-2-Backend"><a href="#2-2-Backend" class="headerlink" title="2.2 Backend"></a>2.2 Backend</h3><p>The backend is written in php language. Provides 5 interfaces, which respectively provide the functions of obtaining account events, obtaining internal circulation information, obtaining public expenditure information, obtaining weekly statements, and operating.</p>
<p>The mail system is quickly constructed using <a href="https://www.eee.dog/tech/mail-api.html">Yimian Mail API</a>.</p>
<h3 id="2-3-Database"><a href="#2-3-Database" class="headerlink" title="2.3 Database"></a>2.3 Database</h3><p>The database uses yimian-db/mysql. Three tables are constructed, which are used to store flow, public expenditure details, and internal circulation.</p>
<h3 id="2-4-Image-upload"><a href="#2-4-Image-upload" class="headerlink" title="2.4 Image upload"></a>2.4 Image upload</h3><p>Directly quote the code of <a href="https://imgbed.yimian.xyz" target="_blank" rel="noopener">呓喵酱の图床</a> with a small amount of rewriting.</p>
<h3 id="2-5-User-System"><a href="#2-5-User-System" class="headerlink" title="2.5 User System"></a>2.5 User System</h3><p>At present, it is simple to implement with additional web pages, waiting for the <a href="https://github.com/iotcat/ushio-auth" target="_blank" rel="noopener">ushio-auth project</a> to complete the unified integration.</p>
<h2 id="3-Appearance"><a href="#3-Appearance" class="headerlink" title="3. Appearance"></a>3. Appearance</h2><p><img src="https://api.yimian.xyz/img/?path=imgbed/img_ed08c497_1080x6654_8_null_normal.jpeg" alt="imgbed_ed08c497"></p>
<p><img src="https://api.yimian.xyz/img/?path=imgbed/img_ea04ad82_1080x5082_8_null_normal.jpeg" alt="imgbed_ea04ad82"></p>
<p><img src="https://api.yimian.xyz/img/?path=imgbed/img_a8b3adb0_1080x2160_8_null_normal.jpeg" alt="imgbed_a8b3adb0"></p>
<hr>
<p><strong>2020-03-22 update</strong></p>
<p>Due to the epidemic, considering that everyone has withdrawn to China. To save server costs, stop providing services.</p>
<p>Combining the operation status of the past six months, I have made some analysis and summary:</p>
<h2 id="Main-gains"><a href="#Main-gains" class="headerlink" title="Main gains"></a>Main gains</h2><ol>
<li>Experience in analyzing the real needs of customers</li>
<li>Ability to quickly build production environment website tools</li>
<li>My roommate’s recognition of my ability</li>
</ol>
<h2 id="Development-Methodology"><a href="#Development-Methodology" class="headerlink" title="Development Methodology"></a>Development Methodology</h2><ol>
<li>Based on a series of past projects, quickly set up and put into use in 3 days</li>
<li>Carefully study the requirements and determine which are true and which are false.</li>
</ol>
<h2 id="Challenges-encountered"><a href="#Challenges-encountered" class="headerlink" title="Challenges encountered"></a>Challenges encountered</h2><ol>
<li>Rapid development, because everyone has started to spend a lot of money on public goods after arriving in the UK, so there is an urgent need to use this system</li>
<li>The algorithm must be stable and reliable, because it involves everyone’s money</li>
<li>The purpose of this system is to make it more convenient to delegate the accounting work to the system for automated processing. In this way, the number of internal transactions between everyone must be as few as possible and the instructions must be clear under the premise of ensuring fairness.</li>
<li>How to make everyone trust the system.</li>
</ol>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><ol>
<li>Based on a large number of own previous projects. It takes 1 day to develop and form, 1 day to test debug, 1 day to optimize the front-end, add variance, percentage and other functions.</li>
<li>Refer to the accounting table and use the table mode. Every time there is a new upload, the new status will be calculated in real time. Tested many times and put into use after full verification.</li>
<li>Use the concept of “balance” and pay attention to differences. When the differences are too large, make internal transactions between those who spend the most and those who spend the least. And the internal transaction value is an integer. For example, our production scenario uses 20 pounds.</li>
<li>When the system algorithm is stable, refer to the design of Alipay. There are two steps to internal transactions. Both the first-choice payer and the earner receive emails telling to whom (from whom) and how much money. Then after the payer gives the money to the earner, the earner needs to log in to the web page or confirm it from the email link. As of this time, the system considers that an internal transaction is complete.</li>
</ol>
<hr>
<p><strong>2020-9-8 update</strong></p>
<p>Based on the Ushio user system, combined with the operation of the past six months and the changes in everyone’s needs, I reconstructed and developed a new version of the public expenditure system.</p>
<h2 id="New-features"><a href="#New-features" class="headerlink" title="New features"></a>New features</h2><ul>
<li>Achieved access to Ushio user system</li>
<li>Users can register and create new public bills at any time</li>
<li>The same user can be in multiple bills at the same time</li>
<li>Users can join the public bill at any time</li>
<li>Users can settle and exit a public bill at any time</li>
<li>Smarter settlement algorithm</li>
<li>Use LocalStorage to optimize the speed of secondary access</li>
</ul>
<h2 id="Experience"><a href="#Experience" class="headerlink" title="Experience"></a>Experience</h2><p>cp-acc is now open to the public, you can go to its <a href="https://cp-acc.yimian.xyz" target="_blank" rel="noopener">website</a> to experience it. But before the experience, you need to log in with your email address through the ushio user system in order to receive bill messages.</p>
</span>
</div>
<div class="post-copyright">
<p class="copyright-item">
<span>Author: </span>
<a href="https://iotcat.me/" target="_blank" rel="noopener">IoTcat</a>
</p>
<p class="copyright-item">
<span>Link: </span>
<a href="https://www.eee.dog/tech/crown-place-erp.html">https://www.eee.dog/tech/crown-place-erp.html</a>
</p>
<p class="copyright-item">
<span>License: </span><a rel="license" href="http://creativecommons.org/licenses/by-nc/4.0/" target="_blank">知识共享署名-非商业性使用 4.0 国际许可协议</a>
</p>
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/crown-place/">crown-place</a>
<a href="/tags/uk/">uk</a>
<a href="/tags/liverpool/">liverpool</a>
<a href="/tags/erp/">erp</a>
<a href="/tags/system/">system</a>
</div>
<nav class="post-nav"><a class="prev" href="/life/liverpool-accom-inves.html">
<i class="iconfont icon-left"></i>
<span class="prev-text nav-default"><span class=".zh">Liverpool 学生公寓条件调研</span><span class=".en">Liverpool student apartment conditions survey</span></span>
<span class="prev-text nav-mobile">Prev</span>
</a>
<a class="next" href="/tech/words-api.html">
<span class="next-text nav-default"><span class=".zh">呓喵酱的一言API</span><span class=".en">IoTcat's Motto API</span></span>
<span class="prev-text nav-mobile">Next</span>
<i class="iconfont icon-right"></i>
</a>
</nav></footer>
</article><script>$(()=>{var p = window.location.pathname;setTimeout(()=>{if(window.location.pathname == p)tips.show({
title: 'tips',
position: 'topRight',
message: ((page.tran.getLang() == 'zh')?"此文章预计阅读 7 分钟哦~": "Read this page will spend around 15 minutes~")
})}, 6000)})</script>
</div><div class="comments" id="comments"><div id="vcomments"></div>
</div></div>
</main>
<footer id="footer" class="footer">
<script>
page_obj = {
layout: "post",
comments: "true"
};
</script><div class="social-links"><a href="mailto:i@iotcat.me" class="iconfont icon-email" title="email"></a>
<a href="https://github.com/iotcat" target="_blank" rel="noopener" class="iconfont icon-github" title="github"></a>
<a href="/atom.xml" class="iconfont icon-rss" title="rss"></a>
</div><div class="copyright"><span id="/tech/crown-place-erp.html" class="statistic leancloud_visitors">
<em>Visitors </em> <i class="leancloud-visitors-count">??</i>
<span class="division"> |</span>
<em>Reading </em> 15 min
</span>
<br>
<span class="power-by">
Powered by <a class="hexo-link" href="https://ushio.yimian.xyz/" target="_blank" rel="noopener">Ushio</a>
</span>
<span class="division">|</span>
<span class="theme-info">
Theme -
<a class="theme-link" href="https://github.com/iotcat/kayo" target="_blank" rel="noopener">Kayo</a>
</span>
<span class="copyright-year">&copy;2018 - 2021<span class="heart shaky">
<i class="iconfont icon-heart"></i>
</span>
<span class="author"><a href="https://iotcat.me/" target="_blank" rel="noopener">IoTcat</a></span>
</span>
</div>
</footer>
<div class="back-to-top" id="back-to-top">
<i class="iconfont icon-up"></i>
</div>
</div>
<script src="https://cdn.yimian.xyz/kayo/lib/valine/valine.min.js" data-pjax></script>
<style>
/* 背景图片 */
#veditor {
background-image: url(https://cdn.yimian.xyz/img/blog/comments_bg.webp);
background-size: contain;
background-repeat: no-repeat;
background-position: right;
background-color: rgba(255, 255, 255, 0);
resize: vertical
}
/* 头像旋转 */
img.vimg {
transition: all 1s /* 旋转时间为 1s */
}
img.vimg:hover {
transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
-ms-transform: rotate(360deg);
}
/* 盒子模式 */
#vcomments .vcards .vcard {
padding: 15px 20px 0 20px;
border-radius: 10px;
margin-bottom: 15px;
box-shadow: 0 0 4px 1px rgba(0, 0, 0, .12);
transition: all .3s
}
#vcomments .vcards .vcard:hover {
box-shadow: 0 0 8px 3px rgba(0, 0, 0, .12)
}
#vcomments .vcards .vcard .vh .vcard {
border: none;
box-shadow: none;
}
</style>
<script>
pjax_valine = () => {
$.get('https://auth.yimian.xyz/getEmailHash.php', function(res){
if(page.tran.getLang() == 'zh'){
var lan = 'zh-CN';
var metaPlaceholder = {"nick":"昵称/QQ号","mail":"邮箱(完全保密)"};
var tagMeta = ["博主","小伙伴","访客"];
var placeholder = "填写邮箱可以及时收到回复哦(●'◡'●)";
}else{
var lan = 'en';
var metaPlaceholder = {"nick":"Nickname/QQ","mail":"EMail"};
var tagMeta = ["Master","Friend","Visitor"];
var placeholder = "Leave some comments here (●'◡'●)";
}
new Valine({
el: '#vcomments',
appId: 'eVzpK7EyT6OafJvXWIRminWT-gzGzoHsz',
appKey: '2qjuEBgVE0BscTQnTmoS9roU',
master: '9b616ff4cd6c305e5970bee7b1bd9b1f', //博主邮箱md5
tagMeta: tagMeta, //标识字段名
friends: res, //["b6ddef7c7e1c647e7767afeacdfb7b64","46dd4e6fef4f9591736c4723a965ca2e","6132d77f9f0ae060bc733090991acecb","3e00e104b79d7c6e866c6b23c6ba6dfc"], //小伙伴邮箱Md5
metaPlaceholder: metaPlaceholder,
placeholder: placeholder,
lang: lan,
path: window.location.pathname,
enableQQ: true,
visitor: true,
emojiCDN: '//i0.hdslb.com/bfs/emote/',
emojiMaps: {
"tv_doge": "6ea59c827c414b4a2955fe79e0f6fd3dcd515e24.png",
"tv_亲亲": "a8111ad55953ef5e3be3327ef94eb4a39d535d06.png",
"tv_偷笑": "bb690d4107620f1c15cff29509db529a73aee261.png",
"tv_再见": "180129b8ea851044ce71caf55cc8ce44bd4a4fc8.png",
"tv_冷漠": "b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png",
"tv_发怒": "34ba3cd204d5b05fec70ce08fa9fa0dd612409ff.png",
"tv_发财": "34db290afd2963723c6eb3c4560667db7253a21a.png",
"tv_可爱": "9e55fd9b500ac4b96613539f1ce2f9499e314ed9.png",
"tv_吐血": "09dd16a7aa59b77baa1155d47484409624470c77.png",
"tv_呆": "fe1179ebaa191569b0d31cecafe7a2cd1c951c9d.png",
"tv_呕吐": "9f996894a39e282ccf5e66856af49483f81870f3.png",
"tv_困": "241ee304e44c0af029adceb294399391e4737ef2.png",
"tv_坏笑": "1f0b87f731a671079842116e0991c91c2c88645a.png",
"tv_大佬": "093c1e2c490161aca397afc45573c877cdead616.png",
"tv_大哭": "23269aeb35f99daee28dda129676f6e9ea87934f.png",
"tv_委屈": "d04dba7b5465779e9755d2ab6f0a897b9b33bb77.png",
"tv_害羞": "a37683fb5642fa3ddfc7f4e5525fd13e42a2bdb1.png",
"tv_尴尬": "7cfa62dafc59798a3d3fb262d421eeeff166cfa4.png",
"tv_微笑": "70dc5c7b56f93eb61bddba11e28fb1d18fddcd4c.png",
"tv_思考": "90cf159733e558137ed20aa04d09964436f618a1.png",
"tv_惊吓": "0d15c7e2ee58e935adc6a7193ee042388adc22af.png",
"tv_打脸": "56ab10b624063e966bfcb76ea5dc4794d87dfd47.png",
"tv_抓狂": "fe31c08edad661d63762b04e17b8d5ae3c71a757.png",
"tv_抠鼻": "c666f55e88d471e51bbd9fab9bb308110824a6eb.png",
"tv_斜眼笑": "911f987aa8bc1bee12d52aafe62bc41ef4474e6c.png",
"tv_无奈": "ea8ed89ee9878f2fece2dda0ea8a5dbfe21b5751.png",
"tv_晕": "5443c22b4d07fb1907ccc610c8e6db254f2461b7.png",
"tv_流汗": "cead1c351ab8d79e9f369605beb90148db0fbed3.png",
"tv_流泪": "7e71cde7858f0cd50d74b0264aa26db612a8a167.png",
"tv_流鼻血": "c32d39db2737f89b904ca32700d140a9241b0767.png",
"tv_点赞": "f85c354995bd99e28fc76c869bfe42ba6438eff4.png",
"tv_生气": "26702dcafdab5e8225b43ffd23c94ac1ff932654.png",
"tv_生病": "8b0ec90e6b86771092a498c54f09fc94621c1900.png",
"tv_疑问": "0793d949b18d7be716078349c202c15ff166f314.png",
"tv_白眼": "c1d59f439e379ee50eef488bcb5e5378e5044ea4.png",
"tv_皱眉": "72ccad6679fea0d14cce648b4d818e09b8ffea2d.png",
"tv_目瞪口呆": "0b8cb81a68de5d5365212c99375e7ace3e7891b7.png",
"tv_睡着": "8b196675b53af58264f383c50ad0945048290b33.png",
"tv_笑哭": "1abc628f6d4f4caf9d0e7800878f4697abbc8273.png",
"tv_腼腆": "89712c0d4af73e67f89e35cbc518420380a7f6f4.png",
"tv_色": "61822c7e9aae5da76475e7892534545336b23a6f.png",
"tv_调侃": "4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png",
"tv_调皮": "b9c41de8e82dd7a8515ae5e3cb63e898bf245186.png",
"tv_鄙视": "6e72339f346a692a495b123174b49e4e8e781303.png",
"tv_闭嘴": "c9e990da7f6e93975e25fd8b70e2e290aa4086ef.png",
"tv_难过": "87f46748d3f142ebc6586ff58860d0e2fc8263ba.png",
"tv_馋": "fc7e829b845c43c623c8b490ee3602b7f0e76a31.png",
"tv_鬼脸": "0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png",
"tv_黑人问号": "45821a01f51bc867da9edbaa2e070410819a95b2.png",
"tv_鼓掌": "1d21793f96ef4e6f48b23e53e3b9e42da833a0f6.png"
// ... 更多表情
}
});
});
};
</script><script type="text/javascript" src="https://cdn.yimian.xyz/ushio-js/ushio-footer.min.js"></script>
<script>
session.onload(function(){
if(session.get('group') != 'anonymous'){
function insertNick(){
if($('.vnick').length){
$('.vnick').val(session.get('nickname'));
}else{
setTimeout(insertNick, 500);
}
}
function insertMail(){
if($('.vmail').length){
$('.vmail').val(session.get('email'));
}else{
setTimeout(insertMail, 500);
}
}
if(session.get('nickname')){
insertNick();
}
if(session.get('email')){
insertMail();
}
}
});
</script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/lib/slideout/slideout.js"></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/lib/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/lib/iziToast/iziToast.min.js"></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/lib/iziModal/iziModal.min.js"></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/lib/mermaid/mermaid.min.js"></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/js/src/kayo.js?v=1.0.0" data-pjax></script>
<script type="text/javascript" src="https://cdn.yimian.xyz/kayo/js/src/kayo-no-pjax.js?v=1.0.0"></script>
<script src="https://cdn.yimian.xyz/kayo/lib/pjax/pjax.min.js"></script>
<script>window.pjax = new Pjax({
elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"])',
selectors: ["head title, #main", "#footer"],
});/* lazyload */
window.imageLazyLoadSetting = {
isSPA: false,
processImages: null,
};
window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});
/* 第一次载入页面加载的函数 */
pjax_ini = () => {
/* 关闭侧边栏 */
window.slideout.close();
if(page_obj.comments == "true"){pjax_valine();}pjax_google_analytics();mermaid.init(undefined, $(".mermaid"));/* lazy load */
!function(n){n.imageLazyLoadSetting.processImages=o;var i=n.imageLazyLoadSetting.isSPA,r=Array.prototype.slice.call(document.querySelectorAll("img[data-original]"));function o(){i&&(r=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")));for(var t,e,a=0;a<r.length;a++)t=r[a],e=void 0,0<=(e=t.getBoundingClientRect()).bottom&&0<=e.left&&e.top<=(n.innerHeight||document.documentElement.clientHeight)&&function(){var t,e,n,i,o=r[a];t=o,e=function(){r=r.filter(function(t){return o!==t})},n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,e&&e()},n.src=i}()}o(),n.addEventListener("scroll",function(){var t,e;t=o,e=n,clearTimeout(t.tId),t.tId=setTimeout(function(){t.call(e)},500)})}(this);
!function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})}();
};
/* 第一次 执行 */
pjax_ini();var loadingBar = document.querySelector(".loading-bar");
var progress = document.querySelector(".loading-bar .progress");
var timer = null;
// Pjax 开始时执行的函数
var loadingbarStart = function () {
// 进度条默认已经加载 20%
var loadingBarWidth = 20;
// 进度条的最大增加宽度
var MAX_LOADING_WIDTH = 95;
// 显示进度条
loadingBar.classList.add("loading");
// 初始化进度条的宽度
progress.style.width = loadingBarWidth + "%";
clearInterval(timer);
timer = setInterval(function () {
// 进度条的增加速度(可以改为一个随机值,显得更加真实)
loadingBarWidth += 3;
// 当进度条到达 95% 后停止增加
if (loadingBarWidth > MAX_LOADING_WIDTH) {
loadingBarWidth = MAX_LOADING_WIDTH;
}
progress.style.width = loadingBarWidth + "%";
}, 500);
};
// Pjax 完成之后执行的函数
var loadingbarStop = function () {
clearInterval(timer);
progress.style.width = "100%";
loadingBar.classList.remove("loading");
setTimeout(function () {
progress.style.width = 0;
}, 400);
};/* Pjax 开始时,重新加载的函数 */
document.addEventListener("pjax:send", function () {loadingbarStart();
});
/* Pjax 完成后,重新加载的函数 */
document.addEventListener("pjax:complete", function () {
/* 重载带data-pjax的script,或者.pjax-reload属性内容的script */
$("script[data-pjax], .pjax-reload script").each(function () {
$(this).parent().append($(this).remove());
});
pjax_ini();loadingbarStop();
page.tran.setLang();
});
/* Pjax 出错,执行的函数 */
document.addEventListener("pjax:error", function () {
});</script>
</body>
</html>