This commit is contained in:
boi 2025-06-14 15:52:13 +08:00
parent 0023c40636
commit 08109a34e6
14 changed files with 1522 additions and 1151 deletions

View File

@ -167,10 +167,10 @@ func setWebRoute_adm(web *c.CiyWebServer) {
"restorage": admin.Login_restorage,
},
"manage": {
"init": admin.Manage_init,
"favadd": admin.Manage_favadd,
"favdel": admin.Manage_favdel,
"setssh": admin.Manage_setssh,
"init": admin.Index_init,
"favadd": admin.Index_favadd,
"favdel": admin.Index_favdel,
"setssh": admin.Index_setssh,
},
"upload": {
"upload": admin.Upload_upload,

View File

@ -94,7 +94,7 @@
<script>
'use strict';
var Glob = {};
var ciy_vars = { "baseurl": "lab/cemap/" };
var ciy_vars = {};
var ce = new ciyearth();
Glob.dom_controltip = $5('.cecontrolpanel .tip');

View File

@ -1,7 +1,8 @@
var ciy_vars = {
"tokenfield":"ciyadm"
,"tokensalt":"ast34h$2"
,"baseurl":"admin/"
"tokenfield": "ciyadm"
, "tokensalt": "ast34h$2"
, "uploadurl": "admin/upload"
, "loginurl": "admin/login.html"
, "dupsec": 60
, "storselect": '/'
, "storlist": { '/': '/ud/', 'A': 'https://cf5.nyyzsoft.cn/ud/', 'Z': 'https://cf5.nyyzsoft.cn/ud/' }

View File

@ -7,7 +7,7 @@ import (
c "ciyon/zciyon"
)
func Manage_init(w http.ResponseWriter, r *http.Request) bool {
func Index_init(w http.ResponseWriter, r *http.Request) bool {
//menuurl: 普通链接~原型图 4378,key 普通链接~原型图 共存
//menupow: d=删除|e=修改 p[id]e 默认p[id]v 显示权限 角色权限menu url<>'' 可选择授权
post := c.NewCiyPost(w, r)
@ -54,7 +54,7 @@ func Manage_init(w http.ResponseWriter, r *http.Request) bool {
return c.SuccJSON(w, ret)
}
func Manage_favadd(w http.ResponseWriter, r *http.Request) bool {
func Index_favadd(w http.ResponseWriter, r *http.Request) bool {
post := c.NewCiyPost(w, r)
_, userid := Verifyfast(c.CiyDB, post)
if userid == 0 {
@ -80,7 +80,7 @@ func Manage_favadd(w http.ResponseWriter, r *http.Request) bool {
}
return c.SuccJSON(w)
}
func Manage_favdel(w http.ResponseWriter, r *http.Request) bool {
func Index_favdel(w http.ResponseWriter, r *http.Request) bool {
post := c.NewCiyPost(w, r)
_, userid := Verifyfast(c.CiyDB, post)
if userid == 0 {
@ -96,7 +96,7 @@ func Manage_favdel(w http.ResponseWriter, r *http.Request) bool {
return c.SuccJSON(w)
}
func Manage_setssh(w http.ResponseWriter, r *http.Request) bool {
func Index_setssh(w http.ResponseWriter, r *http.Request) bool {
post := c.NewCiyPost(w, r)
_, userid := Verifyfast(c.CiyDB, post)
if userid == 0 {

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
namespace web\admin;
class manage {
class index {
public static function json_init() {
global $db;
$rsuser = verifyfast();

179
web/admin/login.html Normal file
View File

@ -0,0 +1,179 @@
<!DOCTYPE html>
<html>
<head>
<title>管理员登录</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/jscss/theme.js"></script>
<script>ciy_chgtheme(true);</script>
<style>
body {
background: #04c1fb url(/ud/img/bglogin.png) no-repeat top;
}
h1 {
margin: 3em auto 0 auto;
text-align: center;
vertical-align: middle;
font-size: 2em;
line-height: 1.5em;
background: linear-gradient(180deg, #ffffff, #ffffff 30%, #ffffff40);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
letter-spacing: 0.2em;
font-weight: bolder;
}
.cmain {
display: flex;
justify-content: space-around;
max-width: 60em;
margin: 4em auto 3em;
padding: 0 2em;
}
fieldset.tips {
width: 22em;
background: rgba(255, 255, 255, 0.6);
border: 1px solid #ffffff;
margin: 0;
}
fieldset.tips>legend {
background: rgba(255, 255, 255, 0.9);
border: 1px solid #ffffff;
}
.chr {
max-width: 42em;
margin: auto;
height: 1px;
background-image: linear-gradient(90deg, transparent 0%, #ffffffaa 10%, #ffffffaa 90%, transparent 100%);
}
.ccopy {
text-align: center;
color: #ffffff;
text-shadow: 0 0 2px #000000;
margin-top: 0.7em;
padding-bottom: 1em;
}
.cselectlang {
text-align: right;
padding: 1em;
color: #ffffff;
}
@media (min-width: 576px) {
.cmain {
justify-content: flex-end;
}
}
#debug {
margin: auto;
max-width: 60em;
text-align: right;
}
#debug>div {
display: inline-block;
padding: 0 0.5em;
border: 1px solid #407fc6;
border-radius: 0.3em;
margin: 0.3em;
cursor: pointer;
background: #e0f4ff;
}
</style>
</head>
<body>
<div class="cselectlang">
<a class="btn-menu btn-menu-caret">
<span class="lang">选择语言</span>
<ul class="ciy-popmenu">
<li onclick="ciyfn.setlang()">简体中文</li>
<li onclick="ciyfn.setlang('en')">English</li>
<li onclick="ciyfn.setlang('ja')">日本語</li>
</ul>
</a>
</div>
<h1 class="ciy-title lang">CiyDAO 总控台</h1>
<div class="cmain">
<fieldset class="tips">
<legend class="lang">管理员登录</legend>
<div class="char5">
<form onsubmit="javascript:formsubmit(this);return false;">
<div class="ciy-form">
<label class="lang">手机号</label>
<div>
<input type="text" name="user" style="width: 10em;" />
</div>
</div>
<div class="ciy-form">
<label class="lang">&#x3000;</label>
<div>
<input type="password" name="pass" style="width: 10em;" />
</div>
</div>
<div class="ciy-form">
<label></label>
<div>
<button type="submit" class="lang btn lg">登录</button>
</div>
</div>
</form>
</div>
</fieldset>
</div>
<div id="debug"></div>
<div class="chr"></div>
<div class="ccopy">© 2024 众产<sup>®</sup></div>
<script type="text/javascript" src="/jscss/ciy.js"></script>
<script type="text/javascript" src="/jscss/md5.js"></script>
<script type="text/javascript" src="./common.js"></script>
<script type="text/javascript">
'use strict';
var Glob = {};
ciyfn.pageload(function () {
var debuguser = ciyfn.getstorage('_debuguser10');
if (isarray(debuguser)) {
for (var i in debuguser) {
$5('#debug').append('<div data-pass="' + debuguser[i].pass + '" data-user="' + debuguser[i].user + '">' + debuguser[i].name + '</div>');
}
$5('#debug').on('click', 'div', function (e) {
$5('[name=user]').val(e.currentTarget.getAttribute('data-user'));
$5('[name=pass]').val(e.currentTarget.getAttribute('data-pass'));
});
}
});
function formsubmit(dom) {
var postparam = ciyfn.getform(dom);
if (postparam.user == '')
return ciyfn.alert('请输入手机号');
if (postparam.pass == '')
return ciyfn.alert('请输入密码');
postparam.auth = (new Date()).getTime();
postparam.pass = hex_md5(hex_md5(postparam.pass + ciy_vars.tokensalt) + postparam.auth);
if (ciyfn.throttle(dom)) return;
ciyfn.callfunc("login", postparam, function (json) {
if (json.me)
ciyfn.setstorage(ciy_vars.tokenfield, json.me);
if (json.storage)
ciyfn.savedict(json.storage);
ciyfn.toast('登录成功', function () {
location.href = './';
});
});
}
</script>
</body>
</html>

View File

@ -1,998 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Ciyon</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<link href="/favicon.ico" rel="shortcut icon">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8" src="/jscss/theme.js"></script>
<style>
.ciy-menu-width {
width: 14em;
}
.ciy-shrink-min {
opacity: 0;
}
.ciy-body-main {
display: flex;
flex-flow: column;
position: fixed;
left: 14em;
top: 0;
right: 0;
bottom: 0;
transition: left var(--e-menusec);
-webkit-transition: left var(--e-menusec);
}
.ciy-navheader {
background: linear-gradient(166deg, var(--bg6), var(--bg1));
border-bottom: 1px solid var(--bg9);
position: relative;
}
.ciy-side {
position: fixed;
left: 0;
top: 0;
bottom: 0;
z-index: 1001;
overflow-x: hidden;
background-color: var(--bg5);
color: var(--txt5);
box-shadow: var(--e-dialog);
transition: transform var(--e-menusec), width var(--e-menusec), left var(--e-menusec);
-webkit-transition: transform var(--e-menusec), width var(--e-menusec), left var(--e-menusec);
}
.ciy-side-scroll {
position: relative;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
}
.ciy-side-scroll::-webkit-scrollbar {
display: none;
}
.ciy-body {
flex: 1;
width: auto;
overflow: hidden;
overflow-y: auto;
}
.ciy-body-item {
height: 100%;
display: none;
-webkit-overflow-scrolling: touch;
overflow: auto;
}
.ciy-body-show {
display: block;
}
.ciy-body-item>iframe {
width: 100%;
height: calc(100%);
display: none;
}
.ciy-body-item>iframe.active {
display: block;
}
.ciy-headertabs {
height: 2.5em;
/*页面标签高度*/
line-height: 2.5em;
background: var(--bg1);
border-bottom: 1px solid var(--bg6);
display: flex;
position: relative;
cursor: pointer;
}
.ciy-body-shade {
position: fixed;
display: none;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.ciy-menu-nav {
cursor: pointer;
color: var(--txt8);
}
.ciy-menu-nav li:hover {
color: var(--txt9);
}
.ciy-menu-nav>li>ul>li>a {
margin-left: 2.6em;
}
.ciy-menu-nav>li>ul>li>ul>li>a {
margin-left: 3.1em;
}
.ciy-menu-nav>li>ul>li>ul>li>ul>li>a {
margin-left: 3.6em;
}
.ciy-menu-nav>li>ul>li>ul>li>ul>li>ul>li>a {
margin-left: 4.1em;
}
.ciy-menu-nav>li,
.ciy-menu-nav>li>ul>li,
.ciy-menu-nav>li>ul>li>ul>li,
.ciy-menu-nav>li>ul>li>ul>li>ul>li,
.ciy-menu-nav>li>ul>li>ul>li>ul>li>ul>li {
display: block;
width: 100%;
line-height: 3em;
min-height: 3em;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
position: relative;
}
.ciy-menu-nav>li>ul {
display: none;
background: var(--bg4);
}
.ciy-menu-nav>li>ul>li>ul {
display: none;
background: var(--bg3);
}
.ciy-menu-nav>li>ul>li>ul>li>ul {
display: none;
background: var(--bg2);
}
.ciy-menu-nav>li>ul>li>ul>li>ul>li>ul {
display: none;
background: var(--bg1);
}
.ciy-menu-nav>li.show>ul,
.ciy-menu-nav>li>ul>li.show>ul,
.ciy-menu-nav>li>ul>li>ul>li.show>ul,
.ciy-menu-nav>li>ul>li>ul>li>ul>li.show>ul {
display: block;
}
.ciy-menu-more {
content: '';
width: 0;
height: 0;
border-style: solid dashed dashed;
border-color: var(--txt5) transparent transparent;
overflow: hidden;
position: absolute;
top: 1.4em;
left: 12em;
border-width: 6px;
border-top-color: var(--txt5);
transition: top .5s, border-color .5s;
-webkit-transition: top .5s, border-color .5s;
}
li.show>.ciy-menu-more {
top: 1em;
border-color: transparent transparent var(--txt5);
}
.ciy-nav-bar {
position: absolute;
left: 0;
top: 4em;
width: 5px;
height: 3em;
background-color: var(--succ5);
transition: top .5s;
-webkit-transition: top .5s;
}
@media (min-width:992px) {
/*电脑*/
.ciy-menu-shrink .ciy-side .ciy-menu-more,
.ciy-menu-shrink .ciy-nav-bar {
display: none;
}
.ciy-menu-shrink .ciy-side {
width: 3em;
}
.ciy-menu-shrink .ciy-body-main {
left: 3em;
/*缩小菜单宽度*/
}
.ciy-menu-shrink .ciy-menu-width {
width: 3em;
/*缩小菜单宽度*/
}
.ciy-menu-shrink .ciy-shrink-max {
opacity: 0;
}
.ciy-menu-shrink .ciy-shrink-min {
opacity: 1;
}
.ciy-menu-shrink .ciy-menu-nav>li>ul {
display: none !important;
}
}
@media (max-width:992px) {
/*平板和手机*/
.ciy-side {
transform: translate3d(-14em, 0, 0);
-webkit-transform: translate3d(-14em, 0, 0);
}
.ciy-nav-bar {
display: none;
}
.ciy-body-main {
left: 0;
}
.ciy-menu-shrink .ciy-side {
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
}
.ciy-menu-shrink .ciy-body-shade {
display: block;
}
}
.ciy-headertabs-btn {
display: flex;
align-items: center;
height: 100%;
padding: 0 0.8em;
background: var(--bg2);
}
.ciy-headertabs-nav::-webkit-scrollbar {
width: 0;
height: 0;
}
.ciy-headertabs-nav {
height: 2.5em;
overflow: hidden;
flex: 1;
border-left: 1px solid var(--bg6);
border-right: 1px solid var(--bg6);
}
.ciy-headertabs-nav li {
display: inline-block;
position: relative;
padding: 0.2em;
}
.ciy-headertabs-nav li>div {
color: var(--txt9);
padding: 0 1.5em;
line-height: 2em;
border-radius: 9px;
background: var(--bg4);
}
.ciy-headertabs-nav li.active>div {
background: linear-gradient(150deg, var(--man5) 0%, var(--man6) 100%);
color: var(--mant);
}
.ciy-headertabs-nav li.active .svgfill {
fill: var(--mant);
}
.ciy-headertabs-nav li>div>i {
position: absolute;
top: 0.2em;
right: 0.2em;
width: 1em;
height: 1em;
line-height: 1.2em;
display: none;
}
.ciy-headertabs-nav li:hover>div>i {
display: block;
}
.ciy-headertabs-nav li:after {
content: '';
background: var(--bg9);
position: absolute;
height: 2px;
left: 50%;
opacity: 0;
top: 0;
width: 0;
display: block;
transition: all .3s;
-webkit-transition: all .3s;
}
.ciy-headertabs-nav li:hover:after {
opacity: 1;
width: 100%;
left: 0;
}
.ciy-headertabs-nav>ul,
.ciy-headertabs-nav li {
white-space: nowrap;
}
@media (max-width:992px) {
/*平板和手机*/
.ciy-headertabs-nav {
overflow-x: scroll;
}
.ciy-headertabs-nav li>i {
display: block;
}
}
.menu {
position: fixed;
left: -3.5em;
top: 10.5em;
z-index: 1;
letter-spacing: 2px;
text-align: center;
padding-top: 0.3em;
color: var(--mant);
font-weight: 100;
font-size: 0.8em;
width: 7em;
border-radius: 1em;
height: 3em;
background: var(--man4);
border: 1px solid var(--man5);
transform: rotate(90deg);
cursor: pointer;
}
.ciy-menu-shrink>.menu {
display: none;
}
.ciy-nav {
position: relative;
padding-left: 0.5em;
display: flex;
align-items: center;
}
.ciy-logo {
flex: 1;
overflow: hidden;
cursor: default;
white-space: nowrap;
}
.ciy-nav>li {
position: relative;
color: var(--txt6);
line-height: 4em;
height: 4em;
cursor: pointer;
display: flex;
align-items: center;
}
.ciy-nav>li:hover {
color: var(--txt9);
}
.ciy-nav>li>a {
display: block;
padding: 0 1.5em;
}
@media (max-width: 767px) {
/*手机*/
.ciy-nav>li>a {
padding: 0 0.8em;
}
}
.ciy-nav>li:after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
height: 3px;
opacity: 0;
border-bottom: 2px solid var(--bg9);
width: 0%;
transition: all .3s;
-webkit-transition: all .3s;
}
.ciy-nav>li:hover:after,
.ciy-nav>li.show:after {
left: 0;
opacity: 1;
width: 100%;
}
.ciy-nav>li.show>ul.ciy-popmenu,
.btn-menu.show>.ciy-popmenu {
display: block;
}
.ciy-nav>li.show>a>.caret,
.btn-menu-caret.show:after {
transform: rotate(180deg);
}
</style>
</head>
<body>
<div id="id_body" oncontextmenu="return false;" onselectstart="return false">
<div class="menu" onclick="Glob.manage.page_shrink();">MENU</div>
<div class="ciy-layout">
<div class="ciy-navheader">
<ul class="ciy-nav" style="height:calc(4em - 1px);">
<div class="ciy-logo" style="line-height: 4em;" ondblclick="Glob.manage.page_shrink();">
<div class="ciy-title" style="margin-left:0.5em;font-size:1.6em;color:var(--man6);text-shadow: 1px 1px 3px var(--bg1),-1px -1px 3px var(--bg1);"></div>
</div>
<li>
<a onclick="chgthemesave()" style="width:2em;height:2em;position: relative;">
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path class="svgfill" d="M320 85.333333c-76.373333 49.066667-128 135.68-128 234.666667s51.626667 185.6 129.28 234.666667C190.293333 554.666667 85.333333 449.706667 85.333333 320S190.293333 85.333333 320 85.333333m493.653333 64l61.013334 61.013334L210.346667 874.666667 149.333333 813.653333 813.653333 149.333333m-263.68 103.68L486.826667 213.333333 425.386667 256l17.92-72.533333L384 138.24l74.666667-5.12 24.746666-70.4L512 132.266667l73.813333 1.28-57.6 48.213333 21.76 71.253333m-140.8 154.026667l-49.493333-31.146667-47.786667 33.28 14.506667-56.32-46.506667-35.413333 58.026667-3.84 19.2-55.04 21.76 54.186667 58.026667 1.28-44.8 37.12 17.066666 55.893333M810.666667 576c0 129.706667-104.96 234.666667-234.666667 234.666667-52.053333 0-100.266667-17.066667-139.093333-45.653334l328.106666-328.106666c28.586667 38.826667 45.653333 87.04 45.653334 139.093333m-187.733334 280.746667l118.186667-49.066667-10.24 142.933333-107.946667-93.866666m184.746667-115.2l49.066667-118.186667 93.866666 108.373333-142.933333 9.813334m49.066667-211.626667l-48.64-118.613333 142.506666 10.24-93.866666 108.373333M410.88 807.68l118.186667 49.066667-107.946667 93.44-10.24-142.506667z"></path>
</svg></a>
<!-- <span class="ciy-badge">9</span> -->
</li>
<li class="btn-menu"><a id="nav_user" style="white-space: nowrap;"></a>
<!-- <span class="ciy-badge-dot"></span> -->
<ul class="ciy-popmenu" style="top: 4em; right: 0.2em;" id="nav_userpopmenu"></ul>
</li>
</ul>
</div>
<!-- 侧边菜单 -->
<div class="ciy-side ciy-menu-width" style="top:4em;">
<div class="ciy-side-scroll">
<ul class="ciy-menu-nav" id="nav_menu"></ul>
<span class="ciy-nav-bar"></span>
</div>
</div>
<div class="ciy-body-main" style="top:4em;">
<!-- 页面标签 -->
<div class="ciy-headertabs">
<div class="ciy-headertabs-btn" onclick="Glob.manage.headertabscroll('left')">
<svg style="width: 1em; height: 1em;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#777777;" d="M559.356 129.195l83.722 83.394-390.725 389.153-83.722-83.394 390.726-389.153zM559.356 129.195z"></path>
<path style="fill:#777777;" d="M168.63 518.349l83.722-83.395 390.73 389.163-83.726 83.39-390.726-389.159zM168.63 518.349z"></path>
<path style="fill:#0073C1;" d="M598.819 459.383c32.702 0 59.206 26.399 59.206 58.966 0 32.562-26.503 58.961-59.206 58.961-32.692 0-59.204-26.399-59.204-58.961 0-32.567 26.513-58.966 59.204-58.966v0zM598.819 459.383z"></path>
<path style="fill:#8BC8EA;" d="M796.169 459.383c32.692 0 59.198 26.399 59.198 58.966 0 32.562-26.506 58.961-59.198 58.961-32.702 0-59.21-26.399-59.21-58.961 0-32.567 26.508-58.966 59.21-58.966v0zM796.169 459.383z"></path>
</svg>
</div>
<div class="ciy-headertabs-nav" id="id_headertabs">
<ul id="id_headertabs_ul">
</ul>
</div>
<div class="ciy-headertabs-btn right" onclick="Glob.manage.headertabscroll()">
<svg style="width: 1em; height: 1em;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#777777;" d="M464.644 894.805l-83.722-83.394 390.725-389.153 83.722 83.394-390.726 389.153zM464.644 894.805z"></path>
<path style="fill:#777777;" d="M855.37 505.651l-83.722 83.395-390.73-389.163 83.726-83.39 390.726 389.159zM855.37 505.651z"></path>
<path style="fill:#0073C1;" d="M425.181 564.617c-32.702 0-59.206-26.399-59.206-58.966 0-32.562 26.503-58.961 59.206-58.961 32.692 0 59.204 26.398 59.204 58.961 0 32.567-26.513 58.966-59.204 58.966v0zM425.181 564.617z"></path>
<path style="fill:#8BC8EA;" d="M227.831 564.617c-32.692 0-59.198-26.399-59.198-58.966 0-32.562 26.506-58.961 59.198-58.961 32.702 0 59.21 26.399 59.21 58.961 0 32.567-26.508 58.966-59.21 58.966v0zM227.831 564.617z"></path>
</svg>
</div>
</div>
<!-- 主体内容 -->
<div class="ciy-body">
<div class="ciy-body-item ciy-body-show" id="id_ifms">
</div>
</div>
</div>
<div class="ciy-body-shade" onclick="Glob.manage.page_shrink();"></div>
</div>
</div>
<script type="text/javascript" charset="utf-8" src="/jscss/ciy.js"></script>
<script type="text/javascript" charset="utf-8" src="/jscss/ciycmp.js"></script>
<script type="text/javascript" charset="utf-8" src="/jscss/ciycmp2.js"></script>
<script type="text/javascript" charset="utf-8" src="./common.js"></script>
<script type="text/javascript">
'use strict';
var Glob = {};
ciyclass.managepage = function (opn) {
var thos = this;
document.title = ciyfn.lang(opn.title);
$5('.ciy-title').html(document.title);
var html = '';
var me = ciyfn.getstorage(ciy_vars.tokenfield);
if (!me)
return location.href = '/' + ciy_vars.baseurl;
if (me.icon)
html += '<img src="' + ciyfn.file_stor(me.icon) + '" style="width: 2em;height: 2em;margin-right: 0.5em;border-radius: 50%;" onerror="this.onerror=null;this.src=\'/ud/img/face.png\'"/>';
html += ciyfn.lang(me.name) + '<span class="caret"></span>';
$5('#nav_user').html(html);
html = '';
for (var i in opn.menu) {
if (opn.menu[i].upid == 1)
html += '<li ' + createlipropurl(opn.menu[i].url) + '><a>' + ciyfn.lang(opn.menu[i].name) + '</a></li>';
}
html += '<li class="line"></li>';
html += '<li onclick="logout()"><a>' + ciyfn.lang('退出系统') + '</a></li>';
$5('#nav_userpopmenu').prepend(html);
html = '';
for (var i in opn.menu) {
if (opn.menu[i].upid == 2)
html += '<li ' + createlipropurl(opn.menu[i].url) + '><a>' + ciyfn.lang(opn.menu[i].name) + '</a></li>';
}
$5('.ciy-logo').after(html);
function logout() {
ciyfn.setstorage(ciy_vars.tokenfield, '');
location.href = '/' + ciy_vars.baseurl;
}
html = '';
if (opn.mnufav.length > 0) {
html += '<li id="id_favmenu"><i class="icon"></i><a>我的常用菜单</a><span class="ciy-menu-more"></span><ul>';
for (var i in opn.mnufav) {
var mnu = ciyfn.ccode(opn.menu, opn.mnufav[i].menuid, '_obj');
if (mnu)
html += '<li fav="' + opn.mnufav[i].menuid + '" data-href="' + mnu.url + '"><a>' + mnu.name + '</a></li>';
}
html += '</ul></li>';
}
var menus = ciyfn.arr_treemap(opn.menu, 0);
html += fillchild(me, menus, 0);
function fillchild(me, sub, deep) {
if (!sub)
return '';
var cldhtml = '';
for (var m in sub) {
var dbgshow = false;
if (sub[m].name.substring(0, 1) == '*') {
sub[m].name = sub[m].name.substring(1);
dbgshow = true;
}
if (dbgshow && ciyfn.getstorage('debug') != '1')
continue;
var hicon = '';
if (deep == 0) {
for (var i in opn.icon) {
if (opn.icon[i].id == sub[m].id) {
hicon = opn.icon[i].icon;
break;
}
}
if (hicon == '')
hicon = Glob.ciysvg;
hicon = '<i class="icon" style="margin:0 0.5em;">' + hicon + '</i>';
}
if (sub[m].child) {
var htmlchild = fillchild(me, sub[m].child, deep + 1);
if (htmlchild == '')
continue;
cldhtml += '<li>' + hicon + '<a>' + ciyfn.lang(sub[m].name) + '</a>';
if (sub[m].child) {
cldhtml += '<span class="ciy-menu-more"></span><ul>';
cldhtml += htmlchild;
cldhtml += '</ul>';
}
cldhtml += '</li>';
} else {
if (ciyfn.nopower(me.power, 'p' + sub[m].id + 'v'))
continue;
cldhtml += '<li data-id="' + sub[m].id + '" ' + createlipropurl(sub[m].url) + '>' + hicon + '<a>' + ciyfn.lang(sub[m].name) + '</a></li>';
}
}
return cldhtml;
}
function createlipropurl(url) {
if (!url)
return 'style="color:var(--txt1);"';
else if (url.indexOf('"') > -1)
return url;
else if (url.indexOf(')') > -1)
return 'onclick="' + url + '"';
else
return 'data-href="' + url + '"';
}
function ciy_ifrclose(domtab) {
var txt = domtab.attr('data-tit');
var domifm = $5("#id_ifms>iframe[data-tit='" + txt + "']");
domifm[0].src = 'about:blank';
domifm[0].contentWindow.close();
setTimeout(function () {
domifm.remove();
}, 100);
domtab.remove();
}
$5('#nav_menu').html(html);
var lmenuact = opn.act;
var tabsdom = $5('#id_headertabs');
var tabsuldom = $5('#id_headertabs_ul');
$5(document).on('click', '[data-href]', function (e) {
var adom = $5(e.currentTarget);
var hrefstr = adom.attr('data-href');
hrefstr = hrefstr.replace('{domain}', location.origin);
if (!hrefstr)
return;
var txt = adom.attr('data-title') || adom.text();
var hrefs = hrefstr.split('~');
var href = hrefs[0];
if (href == '') {
if (hrefs.length > 1) {
if (hrefs[1][0] == ':')
ciyfn.alert(hrefs[1].substring(1).replace(/\|/g, '<br/>'));
else
thos.page_ifropen(getdemourl(hrefs[1]), txt);
}
} else if (href.substring(0, 4) == 'http') {
window.open(href);
} else {
if (href.substring(0, 5) == '$http')
href = href.substring(1);
thos.page_ifropen(href, txt);
if (window.innerWidth < 992)
thos.page_shrink();
}
});
tabsuldom.on('dblclick', "li.active", ev => {
thos.page_refresh();
});
tabsuldom.on('click', "i", function (e) {
ciy_ifrclose($5(e.currentTarget).parent('li'));
});
ciyclass.dragdom({
dom: tabsuldom
, key: 'data-tit'
});
tabsuldom.on("click", 'li', function (ev) {
var lidom = $5(ev.currentTarget);
if (ev.currentTarget.parentNode == null) {//被删除
if (lidom.hasClass('active')) {
var domltab = tabsuldom.children(-1);//ciy_ifrclose前缓存next tit。
thos.page_ifropen('', domltab.attr('data-tit'));
}
return;
}
if (lidom.hasClass('active'))
return;
$5("li", tabsuldom).removeClass('active');
$5("#id_ifms>iframe").removeClass('active');
lidom.addClass('active');
$5("#id_ifms>iframe[data-tit='" + lidom.attr('data-tit') + "']").addClass('active');
});
tabsuldom.on('mousewheel', function (e) {
e.preventDefault();
var wheel = e.originalEvent.wheelDelta || -e.originalEvent.detail;
tabsdom.scroll({ left: tabsdom[0].scrollLeft - wheel * 2 });
});
function getdemourl(demostr) {
var demoparam = ciyfn.getstrparam('z=' + demostr, ',');
var acm = demoparam.z[0];
var str = 'menuid=' + demoparam.z.substring(1);
if (demoparam.key)
str += '&webkey=' + demoparam.key;
if (demoparam.tag)
str += '&tag=' + demoparam.tag;
var url = '';
if (acm == 'a')
url = '//i.qiboc.cn/app.goc?' + str + '&pc=1';
else if (acm == 'c')
url = '//i.qiboc.cn/chart.goc?' + str;
else if (acm == 'm')
url = '//i.qiboc.cn/menu.goc?' + str;
return url;
}
var navdom = $5('.ciy-menu-nav');
var bodydom = $5('#id_body');
navdom.on("contextmenu", "li", function (ev) {
var curra = $5(ev.currentTarget);
var hrefstr = curra.attr('data-href');
var menuid = curra.attr('data-id') || curra.attr('fav');
if (hrefstr == undefined)
return false;
var pops = [];
var hrefs = hrefstr.split('~');
var txt = curra.attr('data-title') || curra.text();
txt = ciyfn.lang(txt);
if (hrefs[0]) {
if (curra.hasattr('fav'))
pops.push({ act: 'delfav', id: menuid, title: ciyfn.lang('移除该菜单'), name: txt, url: hrefs[0] });
else
pops.push({ act: 'addfav', id: menuid, title: ciyfn.lang('加到常用菜单'), name: txt, url: hrefs[0] });
}
if (hrefs[1]) {
if (hrefs[1][0] == ':')
pops.push({ act: 'msg', title: ciyfn.lang('原型描述'), url: hrefs[1].substring(1) });
else
pops.push({ act: 'ifropen', title: ciyfn.lang('打开原型图'), name: txt + '-' + ciyfn.lang('原型图'), url: getdemourl(hrefs[1]) });
}
var popdom = ciyfn.popmenu(ev, pops);
popdom.on("click", "li", function (ev) {
var lidom = $5(ev.currentTarget);
var act = lidom.attr('data-act');
var menuid = lidom.attr('data-id');
var url = lidom.attr('data-url');
var name = lidom.attr('data-name');
ciygv.mask.hide();
popdom.remove();
if (act == 'addfav') {
thos.favadd(menuid, name, url);
} else if (act == 'delfav') {
thos.favdel(menuid, name, url);
} else if (act == 'msg') {
ciyfn.alert(url);
} else if (act == 'ifropen') {
thos.page_ifropen(url, name);
}
});
ev.preventDefault();
ev.stopPropagation();
return false;
});
var sidescrolldom = $5('.ciy-side-scroll');
navdom.on("click", "li", function (ev) {
var lidom = $5(ev.currentTarget);
if (bodydom.hasClass("ciy-menu-shrink") && window.innerWidth > 992) {
bodydom.removeClass("ciy-menu-shrink");
lidom.removeClass("show");
}
if (lidom.hasClass("show")) {
lidom.children('ul').hide('slide', 0.5);
lidom.removeClass("show");
} else {
lidom.children('ul').show('slide', 0.5);
lidom.addClass("show");
}
var navshows = new Array();
$5('li', navdom).each(function (dom) {
if (dom.querySelector(".ciy-menu-more") === null)
return;
if (dom.className != 'show')
return;
var atxt = dom.querySelector("a");
if (atxt === null)
return;
var navshow;
navshow = atxt.textContent;
navshows.push(navshow);
});
ciyfn.setstorage('menushow', navshows.join('||'));
});
navdom.on("mousemove", function (ev) {
var el = $5(ev.target);
if (el.node() != 'li')
el = el.parent('li');
if (bodydom.hasClass("ciy-menu-shrink")) {
var txt = el.find('a').text();
if (txt)
el.find('i').attr('title', txt);
} else {
var top = sidescrolldom[0].scrollTop - toint(sidescrolldom.parent().css().top) + el.rect().top;
$5(".ciy-nav-bar").css('top', top + 'px');
}
});
var menushow = localStorage.getItem('menushow');
if (menushow !== null) {
var navs = {};
$5('li', navdom).each(function (dom) {
if (dom.querySelector(".ciy-menu-more") === null)
return;
var atxt = dom.querySelector("a");
if (atxt === null)
return;
navs[atxt.textContent] = dom;
});
var menushows = menushow.split('||');
for (var i in menushows) {
if (navs[menushows[i]])
navs[menushows[i]].className = 'show';
}
}
this.page_ifropen = function (url, txt, ableclose, win) {
var elifmdoms = $5('#id_ifms');
var ind = txt.indexOf('#');
if (ind > 0) {
txt = ciyfn.lang(txt.substring(0, ind)) + '<span style="font-size:0.6em;">' + ciyfn.lang(txt.substring(ind + 1)) + '</span>';
}
var eletxt = txt.replace(/<[^>]+>/g, '');
var elifmdom = elifmdoms.find("[data-tit='" + eletxt + "']");
if (elifmdom.length == 0) {
if (!url)
return;
$5("li", tabsuldom).removeClass('active');
$5("#id_ifms>iframe").removeClass('active');
elifmdoms.append("<iframe class='active' src='" + url + "' data-tit='" + eletxt + "' frameborder='0'></iframe>");
if (ableclose)
ableclose = '';
else
ableclose = '<i><svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path class="svgfill" d="M512 0C229.216 0 0 229.216 0 512s229.216 512 512 512 512-229.216 512-512S794.784 0 512 0zM723.2 642.752c22.112 22.112 22.112 58.336 0 80.448s-58.336 22.112-80.448 0L512 592.448 381.248 723.2c-22.112 22.112-58.336 22.112-80.448 0s-22.112-58.336 0-80.448L431.552 512 300.8 381.248c-22.112-22.112-22.112-58.336 0-80.448s58.336-22.112 80.448 0L512 431.552 642.752 300.8c22.112-22.112 58.336-22.112 80.448 0s22.112 58.336 0 80.448L592.448 512 723.2 642.752z"></path></svg></i>';
if (url.indexOf('http') === 0)
url = '';
tabsuldom.append("<li draggable='true' class='active' data-tit='" + eletxt + "' title='" + url + "'><div><a>" + ciyfn.lang(txt) + "</a>" + ableclose + "</div></li>");
//滚动到最后
tabsdom[0].scrollLeft = tabsdom.width() * 2;
elifmdom = $5("#id_ifms>iframe[data-tit='" + eletxt + "']");
} else { //激活
var eltab = tabsuldom.find("[data-tit='" + eletxt + "']");
if (eltab.length == 0)
alert('eltab出现错误');
$5("li", tabsuldom).removeClass('active');
$5("#id_ifms>iframe").removeClass('active');
eltab.addClass('active');
elifmdom.addClass('active');
//自动滚动到能看到选中
var vsta = eltab.rect().left + tabsdom[0].scrollLeft - tabsdom.rect().left;
if (tabsdom[0].scrollLeft > vsta)
tabsdom.scroll({ left: vsta });
else {
var vend = vsta - tabsdom.width() + eltab.width() * 2;
if (tabsdom[0].scrollLeft < vend)
tabsdom.scroll({ left: vend });
}
//自动滚动到能看到选中 end
}
if (win)
elifmdom[0].win = win;
}
this.page_shrink = function () {
bodydom.toggleClass("ciy-menu-shrink");
}
this.page_refresh = function () {
var domifm = $5("#id_ifms>iframe.active");
if (domifm.length == 1)
domifm[0].contentWindow.location.reload(); //domifm.attr('src', domifm.attr('src'));
}
this.headertabscroll = function (act) {
var width = tabsdom.width() * 2 / 3;
var sl = tabsdom[0].scrollLeft;
if (act == 'left')
sl -= width;
else
sl += width;
tabsdom.scroll({ left: sl });
};
this.favadd = function (id, name, url) {
var favmenu = $5('#id_favmenu');
if (favmenu.length == 0) {
favmenu = $5('<li id="id_favmenu"><i class="icon"></i><a>我的常用菜单</a><span class="ciy-menu-more"></span><ul></ul></li>');
$5('#nav_menu').prepend(favmenu);
}
if (favmenu.find('ul li[data-href="' + url + '"]').length == 1)
return;
ciyfn.callfunc("favadd", { id: id }, function (json) {
favmenu.find('ul').append('<li fav="' + id + '" data-href="' + url + '"><a>' + name + '</a></li>');
});
}
this.favdel = function (id, name, url) {
ciyfn.callfunc("favdel", { id: id }, function (json) {
$5('#id_favmenu').find('ul li[fav="' + id + '"]').remove();
});
}
this.page_ifropen(opn.welcome.url, opn.welcome.name, true);
// Glob.manage.page_ifropen('rigger/admin.html', '管理员');
// Glob.manage.page_ifropen('rigger/urole.html', '权限审核');
// Glob.manage.page_ifropen('rigger/cataindex.html', '字典<code>启停状态</code>');
// Glob.manage.page_ifropen('rigger/paper.html', '单页');
// Glob.manage.page_ifropen('rigger/color.html', '配色');
return this;
};
ciyfn.pageload(function () {
if (!ciyfn) return setTimeout(function () { location.reload(); }, 1000);
Glob.ciysvg = '<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path class="svgfill" d="M987.136 384.512C919.552 131.584 668.16-22.528 415.232 27.136c219.648-41.984 434.176 79.36 488.96 283.136 57.344 214.016-82.944 437.76-313.344 499.2-49.664 13.312-78.848 64-65.536 113.152 13.312 49.664 64 78.848 113.152 65.536 263.168-70.144 418.816-340.48 348.672-603.648zM116.224 713.216C58.88 499.2 199.68 275.456 430.08 214.016c49.664-13.312 78.848-64 65.536-113.152C482.816 51.2 432.128 21.504 382.464 34.816c-263.68 70.656-419.84 340.992-349.184 604.16 67.584 252.928 319.488 407.04 571.392 356.864-219.648 42.496-433.664-78.848-488.448-282.624z m93.184-203.776L291.84 449.536c44.544-32.256 90.112-32.256 133.12-0.512l83.456 60.928-149.504-230.4-149.504 229.888z m516.096-60.416L808.96 509.952l-149.504-229.888-149.504 229.376 82.432-59.904c44.544-32.256 90.112-32.256 133.12-0.512z m-366.08 291.84L441.856 680.96c44.544-32.256 90.112-32.256 133.12-0.512l83.456 60.928-149.504-230.4-149.504 229.888z"></path></svg>';
ciyfn.callfunc("init", {}, function (json) {
Glob.manage = new ciyclass.managepage(json);
});
});
window.addEventListener('message', function (event) {
if (!event.data.func)
return;
if (event.data.func == 'restorage') {
restorage(event.data.show);
}
if (event.data.func == 'manage_refresh') {
Glob.manage.page_refresh();
}
if (event.data.func == 'manage_ifropen') {
Glob.manage.page_ifropen(event.data.url, event.data.name, event.data.ableclose, event.source);
}
if (event.data.func == 'manage_fulldiv') {
if (event.data.full) {
$5('.ciy-body-main').css({ zIndex: null });
$5('.ciy-body').css({ position: null, top: null, left: null, right: null, bottom: null, zIndex: null });
} else {
$5('.ciy-body-main').css({ zIndex: 1004 });
$5('.ciy-body').css({ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, zIndex: 9 });
}
}
});
var ideb = 0;
window.addEventListener('keydown', function (e) {
if (e.ctrlKey && e.keyCode == 83) {//Ctrl+S
e.preventDefault();
var save_s = $5('.ctrl_s');
if(save_s.length == 1)
save_s.trigger('click');
}
if (e.ctrlKey && e.keyCode == 69) {//Ctrl+E
e.preventDefault();
ideb++;
if (ideb == 5) {
if (ciyfn.getstorage('debug') == '1')
ciyfn.removestorage('debug');
else
ciyfn.setstorage('debug', '1');
location.reload();
}
}
});
function setssh(able) {
//if (ciyfn.throttle()) return;
ciyfn.callfunc("setssh", { able: able }, function (json) {
ciyfn.toast('设置完成');
});
}
function restorage(show) {
ciyfn.callfunc("login.restorage", { bshow: show }, function (json) {
if (json.me)
ciyfn.setstorage(ciy_vars.tokenfield, json.me);
if (json.storage)
ciyfn.savedict(json.storage);
if (show === true)
ciyfn.toast('已刷新缓存');
}, { showload: false });
}
function logout() {
ciyfn.callfunc("login.logout", {}, function (json) {
ciyfn.removestorage(ciy_vars.tokenfield);
ciyfn.removestorage('_' + ciy_vars.tokenfield);
location.href = '/' + ciy_vars.baseurl;
});
}
function chgthemesave() {
var val = (ciyfn.getstorage('theme') == 'dark');
ciy_chgtheme(val);
ciyfn.setstorage('theme', val ? 'light' : 'dark');
var ifms = document.getElementsByTagName("iframe");
for (var i = 0; i < ifms.length; i++) {
ciyfn.sendsignal(ifms[i].contentWindow, 'chgtheme', { data: val });
}
}
</script>
</body>
</html>

View File

@ -28,7 +28,7 @@ class upload {
return errjson('没有文件上传');
$file = reset($_FILES);
if ($file['error'] > 0)
return errjson('上传参数出错:' . $file['error']);
return errjson(\ciy\upload::UploadError($file['error']));
list($name, $extfile) = \ciy\upload::Fileext($path);
if ($uploadcfg['checkext'] == 'exts') {
if (!in_array($extfile, $uploadcfg['exts']))

View File

@ -1049,10 +1049,8 @@ ciyfn.callfunc = function (funcname, post, successfunc, opn) { //opn showload,m
if (typeof (successfunc) == 'function')
successfunc(json, xhr);
} else if (json.code == 2) {
if (top.ciy_vars.baseurl)
top.location.href = '/' + top.ciy_vars.baseurl;
else
top.location.href = '/';
if (top.ciy_vars.loginurl)
top.location.href = '/' + top.ciy_vars.loginurl;
} else if (json.code == 3) {
document.body.innerHTML = '<h1 style="text-align: center;margin-top: 0.5em;color: #ff0000;font-size: 2em;">' + json.errmsg + '</h1>';
} else {

View File

@ -112,7 +112,7 @@ ciyfn.file_uploads = function (maxcount, files, opn, fn) {
var postdata = new FormData();
postdata.append('file', gfile, gfile.name);
var xhr = new XMLHttpRequest();
xhr.open("POST", opn.action + "upload.upload&pathfile=" + pathfile, true);
xhr.open("POST", opn.action + ".upload&pathfile=" + pathfile, true);
xhr.setRequestHeader(ciy_vars.tokenfield, ciyfn.getstorage('_' + ciy_vars.tokenfield));
xhr.setRequestHeader("X-Custom-Header", "CustomValue");
xhr.onload = function () {
@ -145,7 +145,7 @@ ciyfn.file_uploads = function (maxcount, files, opn, fn) {
};
xhr.send(postdata);
} else {
ciyfn.callfunc(opn.action + "upload.s3&pathfile=" + pathfile + "&storselect=" + opn.stor, {}, function (json) {
ciyfn.callfunc(opn.action + ".s3&pathfile=" + pathfile + "&storselect=" + opn.stor, {}, function (json) {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function (N) {
if (N.lengthComputable) {
@ -1133,7 +1133,7 @@ ciycmpfunc.ciyupload = function (opn) { // v2
opn.showwh = opn.showwh || opn.dom.attr('showwh') || '100px'; //显示宽高
opn.action = opn.action || opn.dom.attr('action');
if (!opn.action) {
opn.action = "/z/?func=" + ciy_vars.baseurl;
opn.action = "/z/?func=" + ciy_vars.uploadurl;
}
var now = new Date();
opn.path = opn.path || opn.dom.attr('path') || 'nopath';

View File

@ -810,7 +810,7 @@ ciycmpfunc.ciymarkdown = function (opn) {
opn.watertext = opn.watertext || opn.dom.attr('watertext') || '';
opn.action = opn.action || opn.dom.attr('action');
if (!opn.action) {
opn.action = "/z/?func=" + ciy_vars.baseurl;
opn.action = "/z/?func=" + ciy_vars.uploadurl;
}
var now = new Date();
opn.path = opn.path || opn.dom.attr('path') || 'nopath';

View File

@ -57,7 +57,7 @@
* file_down URL文件下载保存
* fileext 获取文件扩展名如jpg
*/
if(isset($_SERVER['HTTP_CIY_TIMEOUT']))
if (isset($_SERVER['HTTP_CIY_TIMEOUT']))
set_time_limit((int)$_SERVER['HTTP_CIY_TIMEOUT'] + 10);
error_reporting(E_ALL); //0禁用错误输出E_ALL打开错误输出
date_default_timezone_set('Asia/Shanghai');
@ -217,6 +217,17 @@ function isweixin() {
return true;
return false;
}
function getcciycheck($num) {
$checksum = 0;
for ($i = 15; $i > 0; $i--) {
$nibble = ($num >> (4 * $i)) & 0xF;
$checksum ^= $nibble;
}
return $checksum;
}
function iscciy($num) {
return getcciycheck($num) == ($num & 0xf);
}
function idcard($str) {
$str = strtoupper(trim($str));
if (empty($str))

369
zciyphp/dbmongo.php Normal file
View File

@ -0,0 +1,369 @@
<?php
/* =================================================================================
* License: GPL-2.0 license
* Author: 众产® https://ciy.cn/code
* Version: 0.1.3
* =================================================================================*/
/**
* getone 获取一条数据。 无数据返回null 出错返回false 判断is_array确认数据有效
* get 获取数据集合。 无数据返回array() 出错返回false
* insert 新增数据。 成功返回影响行数 出错返回false
* update 更新数据。 成功返回影响行数 出错返回false
* delete 删除及备份数据。 成功返回影响行数 出错返回false
* begin 开始事务 成功返回true 出错返回false
* commit 事务提交 成功返回true 出错返回false
* rollback 事务回滚 成功返回true 出错返回false
* tran 事务回调 成功返回true 出错返回false
* insert_id 获取刚新增数据的id
*
*
$mongo = new \ciy\dbmongo();
$cmd = new \stdClass();
$cmd->collection = 'movies';
$cmd->pageno = 1;
$count = -1;
$rows = $mongo->get($cmd, $count);
if ($rows === false)
return clog($mongo->error);
clog($count);
foreach ($rows as $row) {
clog($row);
}
return;
*
*/
namespace ciy;
class dbmongo {
private $dbpst;
private $linkdb;
private $session;
private $database;
private $lastinsertid;
private $isTransaction;
public $error;
function __construct($dbpst = '') {
$this->linkdb = false;
$this->dbpst = $dbpst;
$this->isTransaction = false;
$this->error = '';
}
private function errdata($errmsg, $ret = false) {
$this->error = $errmsg;
return $ret;
}
private function connect() {
if ($this->linkdb !== false)
return $this->linkdb;
$cfg = webini('mongodb' . $this->dbpst);
if (is_string($cfg))
return $cfg;
try {
$uriOptions = [];
$driverOptions = [];
$this->linkdb = new \MongoDB\Driver\Manager(
$cfg['uri'],
$uriOptions,
$driverOptions
);
$pingCommand = new \MongoDB\Driver\Command(['ping' => 1]);
$this->linkdb->executeCommand('admin', $pingCommand);
$this->database = $cfg['name'];
return $this->linkdb;
} catch (\Exception $e) {
return 'MongoDB connection failed: ' . $e->getMessage();
}
}
private function getTransactionOptions($defaultOptions = null): array {
if ($this->isTransaction && $this->session) {
return ['session' => $this->session];
}
return $defaultOptions ? ['writeConcern' => $defaultOptions] : [];
}
/**
* 获取查询的第一条数据
*
* @param \stdClass $params 查询参数
* - collection: string 集合名
* - filter: array 查询条件 (可选)
* - options: array 查询选项 (可选)
* @return array|false 查询结果或false表示失败
*/
public function getone(\stdClass $params) {
try {
$link = $this->connect();
if (is_string($link))
return $link;
$params->options = $params->options ?? [];
$params->options['limit'] = 1;
$params->filter = $params->filter ?? [];
$query = new \MongoDB\Driver\Query($params->filter, $params->options);
$cursor = $link->executeQuery(
"{$this->database}.{$params->collection}",
$query,
$this->getTransactionOptions()
);
foreach ($cursor as $document) {
return $document;
}
return null;
} catch (\Exception $e) {
return $this->errdata('Query getone failed: ' . $e->getMessage());
}
}
/**
* 获取查询的多条数据(带分页)
*
* @param \stdClass $params 查询参数
* - collection: string 集合名
* - filter: array 查询条件 (可选)
* - options: array 查询选项 (可选)
* - pageno: int 页码 (默认1)
* - pagecount: int 每页数量 (默认10)
* @return \stdClass|false 包含数据和总数量的对象或false表示失败
*/
public function get(\stdClass $params, &$rowcount = -1) {
try {
$link = $this->connect();
if (is_string($link))
return $link;
$params->filter = $params->filter ?? new \stdClass();
$params->options = $params->options ?? [];
$params->pageno = $params->pageno ?? 1;
$params->pagecount = $params->pagecount ?? 10;
if ($rowcount == -1) {
$countCommand = new \MongoDB\Driver\Command([
'count' => $params->collection,
'query' => $params->filter
]);
$countResult = $link->executeCommand($this->database, $countCommand, $this->getTransactionOptions());
$rowcount = $countResult->toArray()[0]->n ?? 0;
}
$params->options['skip'] = ($params->pageno - 1) * $params->pagecount;
$params->options['limit'] = $params->pagecount;
// 执行查询
$query = new \MongoDB\Driver\Query($params->filter, $params->options);
$cursor = $link->executeQuery(
"{$this->database}.{$params->collection}",
$query,
$this->getTransactionOptions()
);
return $cursor;
} catch (\Exception $e) {
return $this->errdata('Query get failed: ' . $e->getMessage());
}
}
/**
* 插入数据
*
* @param \stdClass $params 插入参数
* - collection: string 集合名
* - document: array 要插入的文档
* - options: array 插入选项 (可选)
* @return int|false 插入数量或false表示失败
*/
public function insert(\stdClass $params) {
if (empty($params->document) || !is_array($params->document)) {
return $this->errdata('Document must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$this->lastinsertid = $bulk->insert($params->document);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getInsertedCount();
} catch (\Exception $e) {
return $this->errdata('Insert operation failed: ' . $e->getMessage());
}
}
public function insert_id() {
return $this->lastinsertid;
}
/**
* 更新数据
*
* @param \stdClass $params 更新参数
* - collection: string 集合名
* - filter: array 查询条件
* - update: array 更新操作
* - options: array 更新选项 (可选)
* @return int|false 更新的文档数量或false表示失败
*/
public function update(\stdClass $params) {
if (empty($params->filter) || !is_array($params->filter)) {
return $this->errdata('Filter must be provided and must be an array');
}
if (empty($params->update) || !is_array($params->update)) {
return $this->errdata('Update must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$params->options = $params->options ?? [];
if (!isset($params->options['multi'])) {
$params->options['multi'] = false;
}
$bulk->update($params->filter, $params->update, $params->options);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getModifiedCount();
} catch (\Exception $e) {
return $this->errdata('Update operation failed: ' . $e->getMessage());
}
}
/**
* 删除数据
*
* @param \stdClass $params 删除参数
* - collection: string 集合名
* - filter: array 查询条件
* - options: array 删除选项 (可选)
* @return int|false 删除的文档数量或false表示失败
*/
public function delete(\stdClass $params) {
if (empty($params->filter) || !is_array($params->filter)) {
return $this->errdata('Filter must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$params->options = $params->options ?? [];
if (!isset($params->options['limit'])) {
$params->options['limit'] = false;
}
$bulk->delete($params->filter, $params->options);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getDeletedCount();
} catch (\Exception $e) {
return $this->errdata('Delete operation failed: ' . $e->getMessage());
}
}
/**
* 开始事务
* @return bool 是否成功
*/
public function begin() {
if ($this->isTransaction) {
return $this->errdata('Transaction already started');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$this->session = $link->startSession();
$this->session->startTransaction();
$this->isTransaction = true;
return true;
} catch (\Exception $e) {
return $this->errdata('Failed to start transaction: ' . $e->getMessage());
}
}
/**
* 提交事务
* @return bool 是否成功
*/
public function commit() {
if (!$this->isTransaction) {
return $this->errdata('No active transaction to commit');
}
try {
$this->session->commitTransaction();
$this->session->endSession();
$this->isTransaction = false;
return true;
} catch (\Exception $e) {
$this->isTransaction = false;
return $this->errdata('Failed to commit transaction: ' . $e->getMessage());
}
}
/**
* 回滚事务
* @return bool 是否成功
*/
public function rollback() {
if (!$this->isTransaction) {
return $this->errdata('No active transaction to rollback');
}
try {
$this->session->abortTransaction();
$this->session->endSession();
$this->isTransaction = false;
return true;
} catch (\Exception $e) {
$this->isTransaction = false;
return $this->errdata('Failed to rollback transaction: ' . $e->getMessage());
}
}
public function tran($func) {
if (!($func instanceof \Closure)) {
$this->error = '没有传递正确的闭包函数';
return false;
}
$this->begin();
$ret = false;
try {
$ret = $func();
} catch (\Exception $ex) {
$ret = false;
$this->error = $ex->getMessage();
}
if ($ret === false)
$this->rollback();
else
$this->commit();
return $ret;
}
}