From 0cb58627366ab1b298649202f2c0768f545d1bf4 Mon Sep 17 00:00:00 2001 From: Karson Date: Tue, 8 Aug 2017 23:36:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8F=92=E4=BB=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20=E6=96=B0=E5=A2=9E=E5=90=8E=E5=8F=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=A3=80=E6=B5=8B=E5=8A=9F=E8=83=BD=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=8F=92=E4=BB=B6=E5=91=BD=E4=BB=A4=E8=A1=8C=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=20=E6=96=B0=E5=A2=9Ecitypicker=E5=9F=8E=E5=B8=82?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E6=8F=92=E4=BB=B6=20=E6=96=B0=E5=A2=9EBacken?= =?UTF-8?q?d.api.open=E7=9A=84callback=E5=8A=9F=E8=83=BD=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9EBackend.api.close=E6=96=B9=E6=B3=95=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=20=E6=96=B0=E5=A2=9EMenu=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E7=B1=BB=20=E6=96=B0=E5=A2=9EVersion=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=B1=BB=20=E6=96=B0=E5=A2=9Ermdirs=E5=92=8Ccopydirs=E5=87=BD?= =?UTF-8?q?=E6=95=B0=20=E6=96=B0=E5=A2=9Ebtn-ajax=E7=B1=BB=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=8F=91=E9=80=81AJAX=E8=AF=B7=E6=B1=82=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20=E6=96=B0=E5=A2=9E$this->assignconfig=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E6=95=B0=E6=8D=AE=E5=88=B0JS=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20=E5=90=AF=E7=94=A8=E5=85=A8=E6=96=B0?= =?UTF-8?q?=E7=BD=91=E7=AB=99=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 变更上传和表单的接口参数 变更菜单栏折叠时的展现方式 修复在包含下线划表的关联模型下的搜索错误 移除auth_rule表中name的admin前缀 移除从DOM中绑定上传和表单的事件 移除插件化后的模块及数据库 移除使用$this->code和$this->data功能 移除前台冗余的控制器和类 --- README.md | 3 +- application/admin/command/Addon.php | 226 +++ .../admin/command/Addon/stubs/addon.stub | 45 + .../admin/command/Addon/stubs/config.stub | 40 + .../admin/command/Addon/stubs/info.stub | 7 + application/admin/command/Crud.php | 35 +- .../admin/command/Install/fastadmin.sql | 305 +-- application/admin/command/Menu.php | 12 +- application/admin/command/Min.php | 8 +- application/admin/common.php | 84 + application/admin/controller/Addon.php | 293 +++ application/admin/controller/Ajax.php | 54 +- application/admin/controller/Category.php | 4 +- application/admin/controller/Index.php | 14 +- application/admin/controller/Page.php | 51 - application/admin/controller/User.php | 27 - application/admin/controller/Version.php | 26 - application/admin/controller/auth/Admin.php | 20 +- .../admin/controller/auth/Adminlog.php | 14 +- application/admin/controller/auth/Group.php | 46 +- application/admin/controller/auth/Rule.php | 24 +- .../controller/example/Bootstraptable.php | 70 - .../admin/controller/example/Colorbadge.php | 24 - .../controller/example/Controllerjump.php | 24 - .../admin/controller/example/Cxselect.php | 23 - .../admin/controller/example/Multitable.php | 33 - .../controller/example/Relationmodel.php | 52 - .../controller/example/Tabletemplate.php | 60 - .../admin/controller/general/Attachment.php | 16 +- .../admin/controller/general/Config.php | 33 +- .../admin/controller/general/Crontab.php | 100 - .../admin/controller/general/Database.php | 211 --- .../admin/controller/general/Profile.php | 4 +- .../admin/controller/wechat/Autoreply.php | 74 - .../admin/controller/wechat/Config.php | 164 -- application/admin/controller/wechat/Menu.php | 111 -- .../admin/controller/wechat/Response.php | 86 - application/admin/lang/zh-cn/addon.php | 9 + .../admin/lang/zh-cn/general/crontab.php | 16 - .../admin/lang/zh-cn/general/database.php | 30 - application/admin/lang/zh-cn/index.php | 4 + application/admin/lang/zh-cn/page.php | 17 - application/admin/lang/zh-cn/version.php | 15 - .../admin/lang/zh-cn/wechat/autoreply.php | 8 - .../admin/lang/zh-cn/wechat/config.php | 10 - .../admin/lang/zh-cn/wechat/response.php | 8 - application/admin/library/Auth.php | 15 +- application/admin/model/Config.php | 55 - application/admin/view/add.html | 203 -- application/admin/view/addon/add.html | 22 + application/admin/view/addon/config.html | 102 + application/admin/view/addon/index.html | 120 ++ application/admin/view/auth/admin/index.html | 2 +- application/admin/view/auth/group/add.html | 2 +- application/admin/view/auth/group/edit.html | 2 +- application/admin/view/auth/group/index.html | 2 +- application/admin/view/category/add.html | 16 +- application/admin/view/category/edit.html | 16 +- application/admin/view/common/header.html | 32 +- application/admin/view/common/menu.html | 4 + application/admin/view/edit.html | 203 -- .../view/example/bootstraptable/detail.html | 22 - .../view/example/bootstraptable/index.html | 31 - .../admin/view/example/colorbadge/index.html | 21 - .../view/example/controllerjump/index.html | 21 - .../admin/view/example/cxselect/index.html | 160 -- .../admin/view/example/multitable/index.html | 43 - .../view/example/relationmodel/index.html | 21 - .../view/example/tabletemplate/index.html | 67 - .../admin/view/general/configvalue/add.html | 52 - .../admin/view/general/configvalue/edit.html | 53 - .../admin/view/general/configvalue/index.html | 25 - .../admin/view/general/crontab/add.html | 81 - .../admin/view/general/crontab/edit.html | 81 - .../admin/view/general/crontab/index.html | 25 - .../admin/view/general/database/index.html | 81 - application/admin/view/index.html | 25 - application/admin/view/index/login.html | 12 +- application/admin/view/page/add.html | 80 - application/admin/view/page/edit.html | 81 - application/admin/view/page/index.html | 25 - application/admin/view/user/third/add.phtml | 64 - application/admin/view/user/third/edit.phtml | 64 - application/admin/view/user/third/index.phtml | 25 - application/admin/view/user/user/add.phtml | 193 -- application/admin/view/user/user/edit.phtml | 187 -- application/admin/view/user/user/index.phtml | 25 - application/admin/view/version/add.html | 64 - application/admin/view/version/edit.html | 58 - application/admin/view/version/index.html | 25 - .../admin/view/wechat/autoreply/add.html | 51 - .../admin/view/wechat/autoreply/edit.html | 51 - .../admin/view/wechat/autoreply/index.html | 25 - application/admin/view/wechat/config/add.html | 45 - .../admin/view/wechat/config/edit.html | 47 - .../admin/view/wechat/config/index.html | 25 - application/admin/view/wechat/menu/index.html | 84 - .../admin/view/wechat/response/add.html | 48 - .../admin/view/wechat/response/edit.html | 52 - .../admin/view/wechat/response/index.html | 19 - .../admin/view/wechat/response/select.html | 16 - application/api/controller/Index.php | 15 - application/command.php | 1 + application/common.php | 36 +- application/common/behavior/Common.php | 1 + application/common/controller/Backend.php | 92 +- application/common/controller/Frontend.php | 49 +- application/common/controller/Uc.php | 162 -- application/common/library/Auth.php | 650 ------- application/common/library/Menu.php | 77 + application/common/library/Token.php | 66 - application/common/model/Config.php | 57 +- application/common/model/Configvalue.php | 76 - application/common/model/Crontab.php | 54 - application/common/model/Page.php | 20 - application/common/model/User.php | 16 - application/common/model/UserSignin.php | 16 - application/common/model/UserThird.php | 16 - application/common/model/WechatAutoreply.php | 16 - application/common/model/WechatConfig.php | 32 - application/common/model/WechatContext.php | 16 - application/common/model/WechatResponse.php | 16 - application/config.php | 6 + application/constants.php | 23 - application/extra/addons.php | 8 + application/extra/payment.php | 48 - application/extra/service.php | 42 - application/extra/third.php | 28 - application/extra/upload.php | 28 +- application/extra/wechat.php | 64 - application/index/controller/Ajax.php | 14 +- application/index/controller/Autotask.php | 135 -- application/index/controller/Common.php | 18 - application/index/controller/Demo.php | 108 -- application/index/controller/Index.php | 2 +- application/index/controller/Sms.php | 168 -- application/index/controller/Ucenter.php | 363 ---- application/index/controller/Upyun.php | 58 - application/index/controller/User.php | 222 --- application/index/controller/Wechat.php | 192 -- application/index/lang/zh-cn.php | 187 +- application/index/lang/zh-cn/sms.php | 9 - application/index/view/demo/bootstrap.html | 1646 ----------------- application/index/view/demo/index.html | 7 - application/index/view/demo/qrcode.html | 149 -- application/index/view/index/index.html | 261 ++- application/index/view/layout/bootstrap.html | 117 -- application/index/view/layout/user.html | 31 - application/index/view/user/changepwd.html | 34 - application/index/view/user/index.html | 44 - application/index/view/user/login.html | 48 - application/index/view/user/register.html | 62 - application/uc.php | 24 - bower.json | 10 +- composer.json | 3 +- extend/fast/Auth.php | 3 +- .../common/model => extend/fast}/Version.php | 229 +-- extend/fast/payment/Alipay.php | 447 ----- extend/fast/payment/Wechat.php | 440 ----- extend/fast/service/Alisms.php | 167 -- extend/fast/service/Easemob.php | 307 --- extend/fast/service/Qiniu.php | 187 -- extend/fast/service/Upyun.php | 572 ------ extend/fast/service/Wechat.php | 213 --- extend/fast/third/Application.php | 76 - extend/fast/third/Qq.php | 145 -- extend/fast/third/Wechat.php | 124 -- extend/fast/third/Weibo.php | 124 -- extend/fast/ucenter/client/Client.php | 31 - .../fast/ucenter/client/uc_client/client.php | 840 --------- .../ucenter/client/uc_client/control/app.php | 63 - .../client/uc_client/control/cache.php | 30 - .../client/uc_client/control/client.php | 817 -------- .../client/uc_client/control/domain.php | 31 - .../ucenter/client/uc_client/control/feed.php | 114 -- .../client/uc_client/control/friend.php | 64 - .../client/uc_client/control/index.htm | 1 - .../ucenter/client/uc_client/control/mail.php | 42 - .../ucenter/client/uc_client/control/pm.php | 463 ----- .../ucenter/client/uc_client/control/tag.php | 102 - .../ucenter/client/uc_client/control/user.php | 443 ----- .../client/uc_client/data/cache/apps.php | 40 - .../client/uc_client/data/cache/badwords.php | 5 - .../client/uc_client/data/cache/index.htm | 0 .../client/uc_client/data/cache/settings.php | 32 - .../ucenter/client/uc_client/data/index.htm | 0 .../fast/ucenter/client/uc_client/index.htm | 1 - .../ucenter/client/uc_client/lib/db.class.php | 210 --- .../client/uc_client/lib/dbi.class.php | 200 -- .../ucenter/client/uc_client/lib/index.htm | 1 - .../client/uc_client/lib/sendmail.inc.php | 159 -- .../client/uc_client/lib/uccode.class.php | 174 -- .../client/uc_client/lib/xml.class.php | 129 -- .../ucenter/client/uc_client/model/app.php | 40 - .../ucenter/client/uc_client/model/base.php | 347 ---- .../ucenter/client/uc_client/model/cache.php | 119 -- .../ucenter/client/uc_client/model/domain.php | 63 - .../ucenter/client/uc_client/model/friend.php | 148 -- .../ucenter/client/uc_client/model/index.htm | 1 - .../ucenter/client/uc_client/model/mail.php | 181 -- .../ucenter/client/uc_client/model/misc.php | 198 -- .../ucenter/client/uc_client/model/note.php | 230 --- .../ucenter/client/uc_client/model/pm.php | 1261 ------------- .../ucenter/client/uc_client/model/tag.php | 84 - .../ucenter/client/uc_client/model/user.php | 439 ----- extend/fast/ucenter/common/Functions.php | 98 - extend/fast/ucenter/common/XML.php | 129 -- public/assets/css/backend.css | 8 + public/assets/css/index.css | 422 +++++ public/assets/img/bg-middle.jpg | Bin 0 -> 44976 bytes public/assets/img/bg-pattern.png | Bin 0 -> 633 bytes public/assets/img/bootstrap.jpg | Bin 46466 -> 0 bytes public/assets/img/loginbg.jpg | Bin 0 -> 70837 bytes public/assets/img/qrcode.jpg | Bin 36360 -> 0 bytes public/assets/img/third.jpg | Bin 47784 -> 0 bytes public/assets/img/ucenter.jpg | Bin 24340 -> 0 bytes public/assets/js/addons.js | 3 + public/assets/js/adminlte.js | 44 +- public/assets/js/backend.js | 23 +- public/assets/js/backend/addon.js | 213 +++ public/assets/js/backend/auth/admin.js | 7 +- public/assets/js/backend/auth/group.js | 19 +- public/assets/js/backend/category.js | 16 +- .../js/backend/example/bootstraptable.js | 162 -- .../assets/js/backend/example/colorbadge.js | 55 - .../js/backend/example/controllerjump.js | 62 - public/assets/js/backend/example/cxselect.js | 14 - .../assets/js/backend/example/multitable.js | 86 - .../js/backend/example/relationmodel.js | 50 - .../js/backend/example/tabletemplate.js | 128 -- .../assets/js/backend/general/attachment.js | 12 +- public/assets/js/backend/general/crontab.js | 74 - public/assets/js/backend/general/database.js | 39 - public/assets/js/backend/general/profile.js | 2 +- public/assets/js/backend/index.js | 105 +- public/assets/js/backend/page.js | 61 - public/assets/js/backend/user/third.js | 57 - public/assets/js/backend/user/user.js | 65 - public/assets/js/backend/version.js | 58 - public/assets/js/backend/wechat/autoreply.js | 77 - public/assets/js/backend/wechat/config.js | 97 - public/assets/js/backend/wechat/menu.js | 289 --- public/assets/js/backend/wechat/response.js | 187 -- public/assets/js/fast.js | 126 +- public/assets/js/frontend/demo.js | 152 -- public/assets/js/require-backend.js | 9 +- public/assets/js/require-backend.min.js | 3 +- public/assets/js/require-form.js | 285 ++- public/assets/js/require-table.js | 5 +- public/assets/js/require-upload.js | 186 +- public/assets/less/backend.less | 9 + 251 files changed, 2817 insertions(+), 21911 deletions(-) create mode 100644 application/admin/command/Addon.php create mode 100644 application/admin/command/Addon/stubs/addon.stub create mode 100644 application/admin/command/Addon/stubs/config.stub create mode 100644 application/admin/command/Addon/stubs/info.stub create mode 100644 application/admin/controller/Addon.php delete mode 100644 application/admin/controller/Page.php delete mode 100644 application/admin/controller/User.php delete mode 100644 application/admin/controller/Version.php delete mode 100644 application/admin/controller/example/Bootstraptable.php delete mode 100644 application/admin/controller/example/Colorbadge.php delete mode 100644 application/admin/controller/example/Controllerjump.php delete mode 100644 application/admin/controller/example/Cxselect.php delete mode 100644 application/admin/controller/example/Multitable.php delete mode 100644 application/admin/controller/example/Relationmodel.php delete mode 100644 application/admin/controller/example/Tabletemplate.php delete mode 100644 application/admin/controller/general/Crontab.php delete mode 100644 application/admin/controller/general/Database.php delete mode 100644 application/admin/controller/wechat/Autoreply.php delete mode 100644 application/admin/controller/wechat/Config.php delete mode 100644 application/admin/controller/wechat/Menu.php delete mode 100644 application/admin/controller/wechat/Response.php create mode 100644 application/admin/lang/zh-cn/addon.php delete mode 100644 application/admin/lang/zh-cn/general/crontab.php delete mode 100644 application/admin/lang/zh-cn/general/database.php delete mode 100644 application/admin/lang/zh-cn/page.php delete mode 100644 application/admin/lang/zh-cn/version.php delete mode 100644 application/admin/lang/zh-cn/wechat/autoreply.php delete mode 100644 application/admin/lang/zh-cn/wechat/config.php delete mode 100644 application/admin/lang/zh-cn/wechat/response.php delete mode 100644 application/admin/model/Config.php delete mode 100644 application/admin/view/add.html create mode 100644 application/admin/view/addon/add.html create mode 100644 application/admin/view/addon/config.html create mode 100644 application/admin/view/addon/index.html delete mode 100644 application/admin/view/edit.html delete mode 100644 application/admin/view/example/bootstraptable/detail.html delete mode 100644 application/admin/view/example/bootstraptable/index.html delete mode 100644 application/admin/view/example/colorbadge/index.html delete mode 100644 application/admin/view/example/controllerjump/index.html delete mode 100644 application/admin/view/example/cxselect/index.html delete mode 100644 application/admin/view/example/multitable/index.html delete mode 100644 application/admin/view/example/relationmodel/index.html delete mode 100644 application/admin/view/example/tabletemplate/index.html delete mode 100644 application/admin/view/general/configvalue/add.html delete mode 100644 application/admin/view/general/configvalue/edit.html delete mode 100644 application/admin/view/general/configvalue/index.html delete mode 100644 application/admin/view/general/crontab/add.html delete mode 100644 application/admin/view/general/crontab/edit.html delete mode 100644 application/admin/view/general/crontab/index.html delete mode 100644 application/admin/view/general/database/index.html delete mode 100644 application/admin/view/index.html delete mode 100644 application/admin/view/page/add.html delete mode 100644 application/admin/view/page/edit.html delete mode 100644 application/admin/view/page/index.html delete mode 100644 application/admin/view/user/third/add.phtml delete mode 100644 application/admin/view/user/third/edit.phtml delete mode 100644 application/admin/view/user/third/index.phtml delete mode 100644 application/admin/view/user/user/add.phtml delete mode 100644 application/admin/view/user/user/edit.phtml delete mode 100644 application/admin/view/user/user/index.phtml delete mode 100644 application/admin/view/version/add.html delete mode 100644 application/admin/view/version/edit.html delete mode 100644 application/admin/view/version/index.html delete mode 100644 application/admin/view/wechat/autoreply/add.html delete mode 100644 application/admin/view/wechat/autoreply/edit.html delete mode 100644 application/admin/view/wechat/autoreply/index.html delete mode 100644 application/admin/view/wechat/config/add.html delete mode 100644 application/admin/view/wechat/config/edit.html delete mode 100644 application/admin/view/wechat/config/index.html delete mode 100644 application/admin/view/wechat/menu/index.html delete mode 100644 application/admin/view/wechat/response/add.html delete mode 100644 application/admin/view/wechat/response/edit.html delete mode 100644 application/admin/view/wechat/response/index.html delete mode 100644 application/admin/view/wechat/response/select.html delete mode 100644 application/api/controller/Index.php delete mode 100644 application/common/controller/Uc.php delete mode 100644 application/common/library/Auth.php create mode 100644 application/common/library/Menu.php delete mode 100644 application/common/library/Token.php delete mode 100644 application/common/model/Configvalue.php delete mode 100644 application/common/model/Crontab.php delete mode 100644 application/common/model/Page.php delete mode 100644 application/common/model/User.php delete mode 100644 application/common/model/UserSignin.php delete mode 100644 application/common/model/UserThird.php delete mode 100644 application/common/model/WechatAutoreply.php delete mode 100644 application/common/model/WechatConfig.php delete mode 100644 application/common/model/WechatContext.php delete mode 100644 application/common/model/WechatResponse.php delete mode 100644 application/constants.php create mode 100644 application/extra/addons.php delete mode 100644 application/extra/payment.php delete mode 100644 application/extra/service.php delete mode 100644 application/extra/third.php delete mode 100644 application/extra/wechat.php delete mode 100644 application/index/controller/Autotask.php delete mode 100644 application/index/controller/Common.php delete mode 100644 application/index/controller/Demo.php delete mode 100644 application/index/controller/Sms.php delete mode 100644 application/index/controller/Ucenter.php delete mode 100644 application/index/controller/Upyun.php delete mode 100644 application/index/controller/User.php delete mode 100644 application/index/controller/Wechat.php delete mode 100644 application/index/lang/zh-cn/sms.php delete mode 100644 application/index/view/demo/bootstrap.html delete mode 100644 application/index/view/demo/index.html delete mode 100644 application/index/view/demo/qrcode.html delete mode 100644 application/index/view/layout/bootstrap.html delete mode 100644 application/index/view/layout/user.html delete mode 100644 application/index/view/user/changepwd.html delete mode 100644 application/index/view/user/index.html delete mode 100644 application/index/view/user/login.html delete mode 100644 application/index/view/user/register.html delete mode 100644 application/uc.php rename {application/common/model => extend/fast}/Version.php (50%) delete mode 100644 extend/fast/payment/Alipay.php delete mode 100644 extend/fast/payment/Wechat.php delete mode 100644 extend/fast/service/Alisms.php delete mode 100644 extend/fast/service/Easemob.php delete mode 100644 extend/fast/service/Qiniu.php delete mode 100644 extend/fast/service/Upyun.php delete mode 100644 extend/fast/service/Wechat.php delete mode 100644 extend/fast/third/Application.php delete mode 100644 extend/fast/third/Qq.php delete mode 100644 extend/fast/third/Wechat.php delete mode 100644 extend/fast/third/Weibo.php delete mode 100644 extend/fast/ucenter/client/Client.php delete mode 100644 extend/fast/ucenter/client/uc_client/client.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/app.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/cache.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/client.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/domain.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/feed.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/friend.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/control/mail.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/pm.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/tag.php delete mode 100644 extend/fast/ucenter/client/uc_client/control/user.php delete mode 100644 extend/fast/ucenter/client/uc_client/data/cache/apps.php delete mode 100644 extend/fast/ucenter/client/uc_client/data/cache/badwords.php delete mode 100644 extend/fast/ucenter/client/uc_client/data/cache/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/data/cache/settings.php delete mode 100644 extend/fast/ucenter/client/uc_client/data/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/lib/db.class.php delete mode 100644 extend/fast/ucenter/client/uc_client/lib/dbi.class.php delete mode 100644 extend/fast/ucenter/client/uc_client/lib/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php delete mode 100644 extend/fast/ucenter/client/uc_client/lib/uccode.class.php delete mode 100644 extend/fast/ucenter/client/uc_client/lib/xml.class.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/app.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/base.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/cache.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/domain.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/friend.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/index.htm delete mode 100644 extend/fast/ucenter/client/uc_client/model/mail.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/misc.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/note.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/pm.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/tag.php delete mode 100644 extend/fast/ucenter/client/uc_client/model/user.php delete mode 100644 extend/fast/ucenter/common/Functions.php delete mode 100644 extend/fast/ucenter/common/XML.php create mode 100644 public/assets/css/index.css create mode 100755 public/assets/img/bg-middle.jpg create mode 100644 public/assets/img/bg-pattern.png delete mode 100644 public/assets/img/bootstrap.jpg create mode 100755 public/assets/img/loginbg.jpg delete mode 100644 public/assets/img/qrcode.jpg delete mode 100644 public/assets/img/third.jpg delete mode 100644 public/assets/img/ucenter.jpg create mode 100644 public/assets/js/addons.js create mode 100644 public/assets/js/backend/addon.js delete mode 100644 public/assets/js/backend/example/bootstraptable.js delete mode 100644 public/assets/js/backend/example/colorbadge.js delete mode 100644 public/assets/js/backend/example/controllerjump.js delete mode 100644 public/assets/js/backend/example/cxselect.js delete mode 100644 public/assets/js/backend/example/multitable.js delete mode 100644 public/assets/js/backend/example/relationmodel.js delete mode 100644 public/assets/js/backend/example/tabletemplate.js delete mode 100644 public/assets/js/backend/general/crontab.js delete mode 100755 public/assets/js/backend/general/database.js delete mode 100644 public/assets/js/backend/page.js delete mode 100644 public/assets/js/backend/user/third.js delete mode 100644 public/assets/js/backend/user/user.js delete mode 100644 public/assets/js/backend/version.js delete mode 100644 public/assets/js/backend/wechat/autoreply.js delete mode 100644 public/assets/js/backend/wechat/config.js delete mode 100644 public/assets/js/backend/wechat/menu.js delete mode 100644 public/assets/js/backend/wechat/response.js delete mode 100644 public/assets/js/frontend/demo.js diff --git a/README.md b/README.md index 10802d1c..55061464 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,9 @@ FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。 * 基于`Bower`进行前端组件包管理 * 数据库表一键生成`CRUD`,包括控制器、模型、视图、JS、语言包 * 一键压缩打包JS和CSS文件 +* 强大的插件扩展功能,在线安装卸载插件 * 多语言支持,服务端及客户端支持 -* 无缝整合又拍云上传功能 +* 无缝整合又拍云、七牛上传等云存储功能 * 第三方登录(QQ、微信、微博)整合 * Ucenter整合 diff --git a/application/admin/command/Addon.php b/application/admin/command/Addon.php new file mode 100644 index 00000000..240606f4 --- /dev/null +++ b/application/admin/command/Addon.php @@ -0,0 +1,226 @@ +setName('addon') + ->addOption('name', 'a', Option::VALUE_REQUIRED, 'addon name', null) + ->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/install/uninstall/refresh)', 'create') + ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null) + ->setDescription('Addon manager'); + } + + protected function execute(Input $input, Output $output) + { + $name = $input->getOption('name') ?: ''; + $action = $input->getOption('action') ?: ''; + //强制覆盖 + $force = $input->getOption('force'); + + include dirname(__DIR__) . DS . 'common.php'; + + if (!$name) + { + throw new Exception('Addon name could not be empty'); + } + if (!$action || !in_array($action, ['create', 'disable', 'enable', 'install', 'uninstall', 'refresh'])) + { + throw new Exception('Please input correct action name'); + } + + $addonDir = ADDON_PATH . $name; + switch ($action) + { + case 'create': + //非覆盖模式时如果存在则报错 + if (is_dir($addonDir) && !$force) + { + throw new Exception("addon already exists!\nIf you need to create again, use the parameter --force=true "); + } + //如果存在先移除 + if (is_dir($addonDir)) + { + rmdirs($addonDir); + } + mkdir($addonDir); + $data = [ + 'name' => $name, + 'addon' => $name, + 'addonClassName' => ucfirst($name) + ]; + $this->writeToFile("addon", $data, $addonDir . DS . ucfirst($name) . '.php'); + $this->writeToFile("config", $data, $addonDir . DS . 'config.php'); + $this->writeToFile("info", $data, $addonDir . DS . 'info.ini'); + $output->info("Create Successed!"); + break; + case 'disable': + case 'enable': + try + { + //调用启用、禁用的方法 + Service::$action($name, 0); + } + catch (AddonException $e) + { + if ($e->getCode() != -3) + { + throw new Exception($e->getMessage()); + } + //如果有冲突文件则提醒 + $data = $e->getData(); + foreach ($data['conflictlist'] as $k => $v) + { + $output->warning($v); + } + $output->info("Are you sure you want to " . ($action == 'enable' ? 'override' : 'delete') . " all those files? Type 'yes' to continue: "); + $line = fgets(STDIN); + if (trim($line) != 'yes') + { + throw new Exception("Operation is aborted!"); + } + //调用启用、禁用的方法 + Service::$action($name, 1); + } + catch (Exception $e) + { + throw new Exception($e->getMessage()); + } + $output->info(ucfirst($action) . " Successed!"); + break; + case 'install': + //非覆盖模式时如果存在则报错 + if (is_dir($addonDir) && !$force) + { + throw new Exception("addon already exists!\nIf you need to install again, use the parameter --force=true "); + } + //如果存在先移除 + if (is_dir($addonDir)) + { + rmdirs($addonDir); + } + try + { + Service::install($name, 0); + } + catch (AddonException $e) + { + if ($e->getCode() != -3) + { + throw new Exception($e->getMessage()); + } + //如果有冲突文件则提醒 + $data = $e->getData(); + foreach ($data['conflictlist'] as $k => $v) + { + $output->warning($v); + } + $output->info("Are you sure you want to override all those files? Type 'yes' to continue: "); + $line = fgets(STDIN); + if (trim($line) != 'yes') + { + throw new Exception("Operation is aborted!"); + } + Service::install($name, 1); + } + catch (Exception $e) + { + throw new Exception($e->getMessage()); + } + + $output->info("Install Successed!"); + break; + case 'uninstall': + //非覆盖模式时如果存在则报错 + if (!$force) + { + throw new Exception("If you need to uninstall addon, use the parameter --force=true "); + } + try + { + Service::uninstall($name, 0); + } + catch (AddonException $e) + { + if ($e->getCode() != -3) + { + throw new Exception($e->getMessage()); + } + //如果有冲突文件则提醒 + $data = $e->getData(); + foreach ($data['conflictlist'] as $k => $v) + { + $output->warning($v); + } + $output->info("Are you sure you want to delete all those files? Type 'yes' to continue: "); + $line = fgets(STDIN); + if (trim($line) != 'yes') + { + throw new Exception("Operation is aborted!"); + } + Service::uninstall($name, 1); + } + catch (Exception $e) + { + throw new Exception($e->getMessage()); + } + + $output->info("Uninstall Successed!"); + break; + case 'refresh': + Service::refresh(); + $output->info("Refresh Successed!"); + break; + default : + break; + } + } + + /** + * 写入到文件 + * @param string $name + * @param array $data + * @param string $pathname + * @return mixed + */ + protected function writeToFile($name, $data, $pathname) + { + $search = $replace = []; + foreach ($data as $k => $v) + { + $search[] = "{%{$k}%}"; + $replace[] = $v; + } + $stub = file_get_contents($this->getStub($name)); + $content = str_replace($search, $replace, $stub); + + if (!is_dir(dirname($pathname))) + { + mkdir(strtolower(dirname($pathname)), 0755, true); + } + return file_put_contents($pathname, $content); + } + + /** + * 获取基础模板 + * @param string $name + * @return string + */ + protected function getStub($name) + { + return __DIR__ . '/Addon/stubs/' . $name . '.stub'; + } + +} diff --git a/application/admin/command/Addon/stubs/addon.stub b/application/admin/command/Addon/stubs/addon.stub new file mode 100644 index 00000000..22567a43 --- /dev/null +++ b/application/admin/command/Addon/stubs/addon.stub @@ -0,0 +1,45 @@ +getConfig()); + // 可以返回模板,模板文件默认读取的为插件目录中的文件。模板名不能为空! + //return $this->fetch('view/info'); + } + +} diff --git a/application/admin/command/Addon/stubs/config.stub b/application/admin/command/Addon/stubs/config.stub new file mode 100644 index 00000000..4ad20dcc --- /dev/null +++ b/application/admin/command/Addon/stubs/config.stub @@ -0,0 +1,40 @@ + 'usernmae', + //显示的标题 + 'title' => '用户名', + //类型 + 'type' => 'string', + //数据字典 + 'content' => [ + ], + //值 + 'value' => '', + //验证规则 + 'rule' => 'required', + //错误消息 + 'msg' => '', + //提示消息 + 'tip' => '', + //成功消息 + 'ok' => '', + //扩展信息 + 'extend' => '' + ], + [ + 'name' => 'password', + 'title' => '密码', + 'type' => 'string', + 'content' => [ + ], + 'value' => '', + 'rule' => 'required', + 'msg' => '', + 'tip' => '', + 'ok' => '', + 'extend' => '' + ], +]; diff --git a/application/admin/command/Addon/stubs/info.stub b/application/admin/command/Addon/stubs/info.stub new file mode 100644 index 00000000..27570c3c --- /dev/null +++ b/application/admin/command/Addon/stubs/info.stub @@ -0,0 +1,7 @@ +name = {%name%} +title = 插件名称 +intro = FastAdmin插件 +author = yourname +website = http://www.fastadmin.net +version = 1.0.0 +state = 1 \ No newline at end of file diff --git a/application/admin/command/Crud.php b/application/admin/command/Crud.php index 7f81d964..3b96bde9 100644 --- a/application/admin/command/Crud.php +++ b/application/admin/command/Crud.php @@ -44,6 +44,11 @@ class Crud extends Command */ protected $switchSuffix = ['switch']; + /** + * 城市后缀 + */ + protected $citySuffix = ['city']; + /** * Selectpage对应的后缀 */ @@ -114,6 +119,7 @@ class Crud extends Command ->addOption('filefield', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate file component with suffix', null) ->addOption('intdatesuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate date component with suffix', null) ->addOption('switchsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate switch component with suffix', null) + ->addOption('citysuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate citypicker component with suffix', null) ->addOption('selectpagesuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate selectpage component with suffix', null) ->addOption('selectpagessuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate multiple selectpage component with suffix', null) ->addOption('sortfield', null, Option::VALUE_OPTIONAL, 'sort field', null) @@ -162,6 +168,8 @@ class Crud extends Command $intdatesuffix = $input->getOption('intdatesuffix'); //开关后缀 $switchsuffix = $input->getOption('switchsuffix'); + //城市后缀 + $citysuffix = $input->getOption('citysuffix'); //selectpage后缀 $selectpagesuffix = $input->getOption('selectpagesuffix'); //selectpage多选后缀 @@ -182,6 +190,8 @@ class Crud extends Command $this->intDateSuffix = $intdatesuffix; if ($switchsuffix) $this->switchSuffix = $switchsuffix; + if ($citysuffix) + $this->citySuffix = $citysuffix; if ($selectpagesuffix) $this->selectpageSuffix = $selectpagesuffix; if ($selectpagessuffix) @@ -447,7 +457,7 @@ class Crud extends Command $defaultValue = $v['COLUMN_DEFAULT']; $editValue = "{\$row.{$field}}"; // 如果默认值非null,则是一个必选项 - if (!is_null($v['COLUMN_DEFAULT'])) + if ($v['IS_NULLABLE'] == 'NO') { $attrArr['data-rule'] = 'required'; } @@ -556,6 +566,13 @@ class Crud extends Command $formEditElement .= sprintf(Form::label("{$attrArr['id']}", "%s abcdefg"), Form::checkbox($fieldName, $yes, 0, $attrArr)); $formEditElement = str_replace('type="checkbox"', 'type="checkbox" {in name="' . "\$row.{$field}" . '" value="' . $yes . '"}checked{/in}', $formEditElement); } + else if ($inputType == 'citypicker') + { + $attrArr['class'] = implode(' ', $cssClassArr); + $attrArr['data-toggle'] = "city-picker"; + $formAddElement = sprintf("
%s
", Form::input('text', $fieldName, $defaultValue, $attrArr)); + $formEditElement = sprintf("
%s
", Form::input('text', $fieldName, $editValue, $attrArr)); + } else { $search = $replace = ''; @@ -1077,6 +1094,11 @@ EOD; { $inputType = "switch"; } + // 指定后缀结尾城市选择框 + if ($this->isMatchSuffix($fieldsName, $this->citySuffix) && ($v['DATA_TYPE'] == 'varchar' || $v['DATA_TYPE'] == 'char')) + { + $inputType = "citypicker"; + } return $inputType; } @@ -1126,19 +1148,20 @@ EOD; */ protected function getImageUpload($field, $content) { - $filter = ''; + $uploadfilter = $selectfilter = ''; if ($this->isMatchSuffix($field, $this->imageField)) { - $filter = ' data-mimetype="image/*"'; + $uploadfilter = ' data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp"'; + $selectfilter = ' data-mimetype="image/*"'; } $multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"'; - $preview = $filter ? ' data-preview-id="p-' . $field . '"' : ''; + $preview = $uploadfilter ? ' data-preview-id="p-' . $field . '"' : ''; $previewcontainer = $preview ? '' : ''; return << {$content} - - + + {$previewcontainer} EOD; diff --git a/application/admin/command/Install/fastadmin.sql b/application/admin/command/Install/fastadmin.sql index 5823a760..99711b17 100755 --- a/application/admin/command/Install/fastadmin.sql +++ b/application/admin/command/Install/fastadmin.sql @@ -4,7 +4,7 @@ 官网: http://www.fastadmin.net 演示: http://demo.fastadmin.net - Date: 07/11/2017 23:52:44 PM + Date: 08/08/2017 23:19:44 PM */ SET FOREIGN_KEY_CHECKS = 0; @@ -35,7 +35,7 @@ CREATE TABLE `fa_admin` ( -- Records of `fa_admin` -- ---------------------------- BEGIN; -INSERT INTO `fa_admin` VALUES ('1', 'admin', 'Admin', '075eaec83636846f51c152f29b98a2fd', 's4f3', '/assets/img/avatar.png', 'admin@fastadmin.net', '0', '1497070325', '1492186163', '1497070325', 'c586728f-0687-4e1a-84c0-c3b9f9003850', 'normal'), ('2', 'admin2', 'admin2', '9a28ce07ce875fbd14172a9ca5357d3c', '2dHDmj', '/assets/img/avatar.png', 'admin2@fastadmin.net', '0', '0', '1492186163', '1492186163', '', 'normal'), ('3', 'admin3', 'admin3', '1c11f945dfcd808a130a8c2a8753fe62', 'WOKJEn', '/assets/img/avatar.png', 'admin3@fastadmin.net', '0', '0', '1492186201', '1492186201', '', 'normal'), ('4', 'admin22', 'admin22', '1c1a0aa0c3c56a8c1a908aab94519648', 'Aybcn5', '/assets/img/avatar.png', 'admin22@fastadmin.net', '0', '0', '1492186240', '1492186240', '', 'normal'), ('5', 'admin32', 'admin32', 'ade94d5d7a7033afa7d84ac3066d0a02', 'FvYK0u', '/assets/img/avatar.png', 'admin32@fastadmin.net', '0', '0', '1492186263', '1492186263', '', 'normal'), ('6', 'test123', 'test', '2a9020e6ef15245399f00d5cda5fb1e6', 'unbBZH', '', 'test@163.com', '0', '1497062737', '1497062728', '1497070313', '', 'normal'); +INSERT INTO `fa_admin` VALUES ('1', 'admin', 'Admin', '075eaec83636846f51c152f29b98a2fd', 's4f3', '/assets/img/avatar.png', 'admin@fastadmin.net', '0', '1502029281', '1492186163', '1502029281', 'd3992c3b-5ecc-4ecb-9dc2-8997780fcadc', 'normal'), ('2', 'admin2', 'admin2', '9a28ce07ce875fbd14172a9ca5357d3c', '2dHDmj', '/assets/img/avatar.png', 'admin2@fastadmin.net', '0', '1502015003', '1492186163', '1502029266', '', 'normal'), ('3', 'admin3', 'admin3', '1c11f945dfcd808a130a8c2a8753fe62', 'WOKJEn', '/assets/img/avatar.png', 'admin3@fastadmin.net', '0', '1501980868', '1492186201', '1501982377', '', 'normal'), ('4', 'admin22', 'admin22', '1c1a0aa0c3c56a8c1a908aab94519648', 'Aybcn5', '/assets/img/avatar.png', 'admin22@fastadmin.net', '0', '0', '1492186240', '1492186240', '', 'normal'), ('5', 'admin32', 'admin32', 'ade94d5d7a7033afa7d84ac3066d0a02', 'FvYK0u', '/assets/img/avatar.png', 'admin32@fastadmin.net', '0', '0', '1492186263', '1492186263', '', 'normal'); COMMIT; -- ---------------------------- @@ -54,36 +54,7 @@ CREATE TABLE `fa_admin_log` ( `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '操作时间', PRIMARY KEY (`id`), KEY `name` (`username`) -) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='管理员日志表'; - --- ---------------------------- --- Records of `fa_admin_log` --- ---------------------------- -BEGIN; -INSERT INTO `fa_admin_log` VALUES ('1', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"phone-bg.png\",\"signature\":\"e6afb5fb65947ba639810670d67535f2\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499768230\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499681848'), ('2', '1', 'admin', '/public/admin.php/category/edit/ids/5?dialog=1', '分类管理 编辑', '{\"dialog\":\"1\",\"row\":{\"type\":\"page\",\"pid\":\"0\",\"name\":\"\\u8f6f\\u4ef6\\u4ea7\\u54c1\",\"nickname\":\"software\",\"flag\":[\"recommend\"],\"image\":\"\\/uploads\\/20170710\\/52ecad420fc9bb113e588de3b3593b90.png\",\"keywords\":\"\",\"description\":\"\",\"weigh\":\"0\",\"status\":\"normal\"},\"ids\":\"5\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499681850'), ('3', '1', 'admin', '/public/admin.php/test/add/ids?dialog=1', '测试管理 添加', '{\"dialog\":\"1\",\"row_category_id_text\":\"\\u6d4b\\u8bd51\",\"row\":{\"category_id\":\"12\",\"category_ids\":\"12,13\",\"user_id\":\"3\",\"user_ids\":\"3\",\"week\":\"monday\",\"flag\":[\"hot\",\"index\"],\"genderdata\":\"male\",\"hobbydata\":[\"music\",\"reading\"],\"title\":\"\\u6211\\u662f\\u4e00\\u7bc7\\u6d4b\\u8bd5\\u6587\\u7ae0\",\"content\":\"

\\u6211\\u662f\\u6d4b\\u8bd5\\u5185\\u5bb9<\\/p>\",\"image\":\"\\/assets\\/img\\/avatar.png\",\"images\":\"\\/assets\\/img\\/avatar.png,\\/assets\\/img\\/qrcode.png\",\"attachfile\":\"\\/assets\\/img\\/avatar.png\",\"keywords\":\"\\u5173\\u952e\\u5b57\",\"description\":\"\\u63cf\\u8ff0\",\"price\":\"0.00\",\"views\":\"0\",\"startdate\":\"2017-07-10\",\"activitytime\":\"2017-07-10 18:24:45\",\"year\":\"2017\",\"times\":\"18:24:45\",\"refreshtime\":\"2017-07-10 18:24:45\",\"weigh\":\"0\",\"status\":\"normal\",\"state\":\"1\"},\"row_category_ids_text\":\"\",\"row_user_id_text\":\"admin\",\"row_user_ids_text\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499682526'), ('4', '1', 'admin', '/public/admin/test/add/ids?dialog=1', '测试管理 添加', '{\"dialog\":\"1\",\"row_category_id_text\":\"\\u6d4b\\u8bd52\",\"row\":{\"category_id\":\"13\",\"category_ids\":\"13\",\"user_id\":\"3\",\"user_ids\":\"3\",\"week\":\"monday\",\"flag\":[\"hot\",\"index\"],\"genderdata\":\"male\",\"hobbydata\":[\"music\",\"reading\"],\"title\":\"tes\",\"content\":\"

test<\\/p>\",\"image\":\"a\",\"images\":\"b\",\"attachfile\":\"c\",\"keywords\":\"a\",\"description\":\"a\",\"price\":\"0.00\",\"views\":\"0\",\"startdate\":\"2017-07-11\",\"activitytime\":\"2017-07-11 16:12:03\",\"year\":\"2017\",\"times\":\"16:12:03\",\"refreshtime\":\"2017-07-11 16:12:03\",\"weigh\":\"0\",\"status\":\"normal\",\"state\":\"1\"},\"row_category_ids_text\":\"\",\"row_user_id_text\":\"admin\",\"row_user_ids_text\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499760748'), ('5', '1', 'admin', '/public/admin/ajax/upload', '', '{\"name\":\"qrcode.png\",\"signature\":\"45fd8c9bd10632cabd23ba0ce7070533\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499847826\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499761445'), ('6', '1', 'admin', '/public/admin/auth/rule/edit/ids/11291?dialog=1', '权限管理 规则管理 编辑', '{\"dialog\":\"1\",\"row\":{\"ismenu\":\"1\",\"pid\":\"11290\",\"name\":\"\\/admin\\/wechat\\/autoreply\",\"title\":\"\\u5fae\\u4fe1\\u81ea\\u52a8\\u56de\\u590d\\u7ba1\\u7406\",\"icon\":\"fa fa-reply-all\",\"weigh\":\"26\",\"condition\":\"\\u7528\\u6237\\u5728\\u5fae\\u4fe1\\u516c\\u4f17\\u53f7\\u4e2d\\u8f93\\u5165\\u7279\\u5b9a\\u7684\\u6587\\u5b57\\u540e\\uff0c\\u670d\\u52a1\\u5668\\u54cd\\u5e94\\u4e0d\\u540c\\u7684\\u4e8b\\u4ef6\",\"remark\":\"\",\"status\":\"normal\"},\"ids\":\"11291\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499761628'), ('7', '1', 'admin', '/public/admin/auth/group/del/ids/1', '权限管理 角色组 删除', '{\"action\":\"del\",\"ids\":\"1\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499762290'), ('8', '1', 'admin', '/public/admin/auth/group/del/ids/1', '权限管理 角色组 删除', '{\"action\":\"del\",\"ids\":\"1\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499762464'), ('9', '1', 'admin', '/public/admin/auth/group/del/ids/1', '权限管理 角色组 删除', '{\"action\":\"del\",\"ids\":\"1\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499762761'), ('10', '1', 'admin', '/public/admin/auth/group/del/ids/1', '权限管理 角色组 删除', '{\"action\":\"del\",\"ids\":\"1\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499762770'), ('11', '1', 'admin', '/public/admin/auth/group/del/ids/1', '权限管理 角色组 删除', '{\"action\":\"del\",\"ids\":\"1\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499762943'), ('12', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795288.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764194'), ('13', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795290.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764194'), ('14', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795282.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764194'), ('15', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795283.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764194'), ('16', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795292.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764194'), ('17', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795286.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764195'), ('18', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795293.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764245'), ('19', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795277.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764259'), ('20', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795284.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764270'), ('21', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795287.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764281'), ('22', '1', 'admin', '/public/admin.php/ajax/upload', '', '{\"name\":\"14558668_1350878795289.jpg\",\"signature\":\"99d25cbae44dab9ed570f7db53ef28fb\",\"bucket\":\"yourbucketname\",\"save-key\":\"\\/uploads\\/{year}{mon}{day}\\/{filemd5}{.suffix}\",\"expiration\":\"1499850578\",\"notify-url\":\"http:\\/\\/www.yoursite.com\\/upyun\\/notify\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499764291'), ('23', '1', 'admin', '/public/admin.php/general/crontab/get_schedule_future', '', '{\"schedule\":\"* * * * *\",\"days\":\"7\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765449'), ('24', '1', 'admin', '/public/admin.php/general/crontab/check_schedule', '', '{\"row\":{\"schedule\":\"* * * * *\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765451'), ('25', '1', 'admin', '/public/admin.php/general/crontab/get_schedule_future', '', '{\"schedule\":\"* * * * *\",\"days\":\"7\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765451'), ('26', '1', 'admin', '/public/admin.php/general/crontab/edit/ids/1?dialog=1', '常规管理 定时任务 编辑', '{\"dialog\":\"1\",\"row\":{\"title\":\"\\u8bf7\\u6c42FastAdmin\",\"type\":\"url\",\"content\":\"http:\\/\\/www.fastadmin.net\",\"schedule\":\"* * * * *\",\"maximums\":\"0\",\"begintime\":\"2017-01-01 00:00:00\",\"endtime\":\"2019-01-01 00:00:00\",\"weigh\":\"1\",\"status\":\"normal\"},\"ids\":\"1\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765451'), ('27', '1', 'admin', '/public/admin.php/general/crontab/get_schedule_future', '', '{\"schedule\":\"* * * * *\",\"days\":\"7\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765453'), ('28', '1', 'admin', '/public/admin.php/general/crontab/check_schedule', '', '{\"row\":{\"schedule\":\"* * * * *\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765456'), ('29', '1', 'admin', '/public/admin.php/general/crontab/get_schedule_future', '', '{\"schedule\":\"* * * * *\",\"days\":\"7\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765456'), ('30', '1', 'admin', '/public/admin.php/general/crontab/edit/ids/2?dialog=1', '常规管理 定时任务 编辑', '{\"dialog\":\"1\",\"row\":{\"title\":\"\\u67e5\\u8be2\\u4e00\\u6761SQL\",\"type\":\"sql\",\"content\":\"SELECT 1;\",\"schedule\":\"* * * * *\",\"maximums\":\"0\",\"begintime\":\"2017-01-01 00:00:00\",\"endtime\":\"2019-01-01 00:00:00\",\"weigh\":\"2\",\"status\":\"normal\"},\"ids\":\"2\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765456'), ('31', '1', 'admin', '/public/admin.php/general/crontab/get_schedule_future', '', '{\"schedule\":\"* * * * *\",\"days\":\"7\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499765460'), ('32', '1', 'admin', '/public/admin.php/page/add/ids?dialog=1', '单页管理 添加', '{\"dialog\":\"1\",\"row_category_id_text\":\"Android\\u5f00\\u53d1\",\"row\":{\"category_id\":\"4\",\"title\":\"test\",\"keywords\":\"test\",\"flag\":\"recommend\",\"image\":\"\\/assets\\/img\\/qrcode.png\",\"content\":\"

test<\\/p>\",\"icon\":\"\",\"views\":\"0\",\"comments\":\"0\",\"weigh\":\"0\",\"status\":\"normal\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499769482'), ('33', '1', 'admin', '/public/admin.php/example/bootstraptable/change/ids/31', '', '{\"action\":\"\",\"ids\":\"31\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499769813'), ('34', '1', 'admin', '/public/admin.php/example/bootstraptable/change/ids/31', '', '{\"action\":\"\",\"ids\":\"31\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499769814'), ('35', '1', 'admin', '/public/admin.php/example/bootstraptable/change/ids/33', '', '{\"action\":\"\",\"ids\":\"33\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499769815'), ('36', '1', 'admin', '/public/admin.php/example/bootstraptable/change/ids/35', '', '{\"action\":\"\",\"ids\":\"35\",\"params\":\"\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', '1499769816'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_article` --- ---------------------------- -DROP TABLE IF EXISTS `fa_article`; -CREATE TABLE `fa_article` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `category_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '分类ID', - `flag` set('h','i','r') NOT NULL DEFAULT '' COMMENT '标志', - `title` varchar(50) NOT NULL DEFAULT '' COMMENT '标题', - `content` text NOT NULL COMMENT '内容', - `image` varchar(100) NOT NULL DEFAULT '' COMMENT '图片', - `keywords` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字', - `description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述', - `views` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '点击', - `comments` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '评论数', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', - `status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='文章表'; +) ENGINE=InnoDB AUTO_INCREMENT=1218 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='管理员日志表'; -- ---------------------------- -- Table structure for `fa_attachment` @@ -104,9 +75,8 @@ CREATE TABLE `fa_attachment` ( `uploadtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '上传时间', `storage` enum('local','upyun') NOT NULL DEFAULT 'local' COMMENT '存储位置', `sha1` varchar(40) NOT NULL DEFAULT '' COMMENT '文件 sha1编码', - PRIMARY KEY (`id`), - UNIQUE KEY `sha1` (`sha1`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='附件表'; + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='附件表'; -- ---------------------------- -- Records of `fa_attachment` @@ -134,7 +104,7 @@ CREATE TABLE `fa_auth_group` ( -- Records of `fa_auth_group` -- ---------------------------- BEGIN; -INSERT INTO `fa_auth_group` VALUES ('1', '0', '超级管理员', '*', '1490883540', '1490883540', 'normal'), ('2', '1', '二级管理员', '11180,11181,11182,11183,11184,11185,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288,11289', '1490883540', '1497431170', 'normal'), ('3', '2', '三级管理员', '11180,11181,11182,11183,11184,11185,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,11214,11215,11216,11217', '1490883540', '1497431183', 'normal'), ('4', '1', '二级管理员2', '11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,11311,11312,11313,11314,11315,11316', '1490883540', '1497431177', 'normal'), ('5', '2', '三级管理员2', '11180,11181,11182,11183,11184,11185,11218,11219,11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288,11289', '1490883540', '1497431190', 'normal'); +INSERT INTO `fa_auth_group` VALUES ('1', '0', '超级管理员', '*', '1490883540', '149088354', 'normal'), ('2', '1', '二级管理员', '1,2,4,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,5', '1490883540', '1502205308', 'normal'), ('3', '2', '三级管理员', '1,4,9,10,11,13,14,15,16,17,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,5', '1490883540', '1502205322', 'normal'), ('4', '1', '二级管理员2', '1,4,13,14,15,16,17,55,56,57,58,59,60,61,62,63,64,65', '1490883540', '1502205350', 'normal'), ('5', '2', '三级管理员2', '1,2,6,7,8,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34', '1490883540', '1502205344', 'normal'); COMMIT; -- ---------------------------- @@ -153,7 +123,7 @@ CREATE TABLE `fa_auth_group_access` ( -- Records of `fa_auth_group_access` -- ---------------------------- BEGIN; -INSERT INTO `fa_auth_group_access` VALUES ('1', '1'), ('2', '2'), ('3', '3'), ('4', '5'), ('5', '5'), ('6', '2'); +INSERT INTO `fa_auth_group_access` VALUES ('1', '1'), ('2', '2'), ('3', '3'), ('4', '5'), ('5', '5'); COMMIT; -- ---------------------------- @@ -178,13 +148,13 @@ CREATE TABLE `fa_auth_rule` ( UNIQUE KEY `name` (`name`) USING BTREE, KEY `pid` (`pid`), KEY `weigh` (`weigh`) -) ENGINE=InnoDB AUTO_INCREMENT=11324 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点表'; +) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点表'; -- ---------------------------- -- Records of `fa_auth_rule` -- ---------------------------- BEGIN; -INSERT INTO `fa_auth_rule` VALUES ('11174', 'file', '0', '/admin/category', '分类管理', 'fa fa-list\r', '', '用于统一管理网站的所有分类,分类可进行无限级分类\r', '1', '1497429920', '1497429920', '119', 'normal'), ('11175', 'file', '11174', '/admin/category/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '142', 'normal'), ('11176', 'file', '11174', '/admin/category/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '141', 'normal'), ('11177', 'file', '11174', '/admin/category/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '140', 'normal'), ('11178', 'file', '11174', '/admin/category/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '139', 'normal'), ('11179', 'file', '11174', '/admin/category/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '138', 'normal'), ('11180', 'file', '0', '/admin/dashboard', '控制台', 'fa fa-dashboard\r', '', '用于展示当前系统中的统计数据、统计报表及重要实时数据\r', '1', '1497429920', '1497429920', '143', 'normal'), ('11181', 'file', '11180', '/admin/dashboard/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '136', 'normal'), ('11182', 'file', '11180', '/admin/dashboard/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '135', 'normal'), ('11183', 'file', '11180', '/admin/dashboard/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '134', 'normal'), ('11184', 'file', '11180', '/admin/dashboard/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '133', 'normal'), ('11185', 'file', '11180', '/admin/dashboard/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '132', 'normal'), ('11186', 'file', '0', '/admin/page', '单页管理', 'fa fa-tags', '', '用于管理普通的单页面,通常用于关于我们、联系我们、商务合作等单一页面\r\n', '1', '1497429920', '1497430149', '125', 'normal'), ('11187', 'file', '11186', '/admin/page/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '130', 'normal'), ('11188', 'file', '11186', '/admin/page/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '129', 'normal'), ('11189', 'file', '11186', '/admin/page/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '128', 'normal'), ('11190', 'file', '11186', '/admin/page/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '127', 'normal'), ('11191', 'file', '11186', '/admin/page/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '126', 'normal'), ('11192', 'file', '0', '/admin/version', '版本管理', 'fa fa-file-text-o', '', '', '1', '1497429920', '1497430600', '27', 'normal'), ('11193', 'file', '11192', '/admin/version/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '124', 'normal'), ('11194', 'file', '11192', '/admin/version/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '123', 'normal'), ('11195', 'file', '11192', '/admin/version/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '122', 'normal'), ('11196', 'file', '11192', '/admin/version/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '121', 'normal'), ('11197', 'file', '11192', '/admin/version/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '120', 'normal'), ('11198', 'file', '0', '/admin/auth', '权限管理', 'fa fa-group', '', '', '1', '1497429920', '1497430092', '99', 'normal'), ('11199', 'file', '11198', '/admin/auth/admin', '管理员管理', 'fa fa-user', '', '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成', '1', '1497429920', '1497430320', '118', 'normal'), ('11200', 'file', '11199', '/admin/auth/admin/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '117', 'normal'), ('11201', 'file', '11199', '/admin/auth/admin/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '116', 'normal'), ('11202', 'file', '11199', '/admin/auth/admin/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '115', 'normal'), ('11203', 'file', '11199', '/admin/auth/admin/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '114', 'normal'), ('11204', 'file', '11198', '/admin/auth/adminlog', '管理员日志', 'fa fa-list-alt', '', '管理员可以查看自己所拥有的权限的管理员日志', '1', '1497429920', '1497430307', '113', 'normal'), ('11205', 'file', '11204', '/admin/auth/adminlog/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '112', 'normal'), ('11206', 'file', '11204', '/admin/auth/adminlog/detail', '详情', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '111', 'normal'), ('11207', 'file', '11204', '/admin/auth/adminlog/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '110', 'normal'), ('11208', 'file', '11198', '/admin/auth/group', '角色组', 'fa fa-group', '', '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别下级的角色组或管理员', '1', '1497429920', '1497429920', '109', 'normal'), ('11209', 'file', '11208', '/admin/auth/group/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '108', 'normal'), ('11210', 'file', '11208', '/admin/auth/group/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '107', 'normal'), ('11211', 'file', '11208', '/admin/auth/group/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '106', 'normal'), ('11212', 'file', '11208', '/admin/auth/group/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '105', 'normal'), ('11213', 'file', '11198', '/admin/auth/rule', '规则管理', 'fa fa-bars', '', '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过控制台进行生成规则节点', '1', '1497429920', '1497430581', '104', 'normal'), ('11214', 'file', '11213', '/admin/auth/rule/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '103', 'normal'), ('11215', 'file', '11213', '/admin/auth/rule/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '102', 'normal'), ('11216', 'file', '11213', '/admin/auth/rule/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '101', 'normal'), ('11217', 'file', '11213', '/admin/auth/rule/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '100', 'normal'), ('11218', 'file', '0', '/admin/example', '示例管理', 'fa fa-magic', '', '', '1', '1497429920', '1497430123', '131', 'normal'), ('11219', 'file', '11218', '/admin/example/bootstraptable', '表格完整示例', 'fa fa-table', '', '在使用Bootstrap-table中的常用方式,更多使用方式可查看:http://bootstrap-table.wenzhixin.net.cn/zh-cn/', '1', '1497429920', '1497429920', '98', 'normal'), ('11220', 'file', '11219', '/admin/example/bootstraptable/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '97', 'normal'), ('11221', 'file', '11219', '/admin/example/bootstraptable/detail', '详情', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '96', 'normal'), ('11222', 'file', '11219', '/admin/example/bootstraptable/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '95', 'normal'), ('11223', 'file', '11219', '/admin/example/bootstraptable/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '94', 'normal'), ('11224', 'file', '11219', '/admin/example/bootstraptable/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '93', 'normal'), ('11225', 'file', '11219', '/admin/example/bootstraptable/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '92', 'normal'), ('11226', 'file', '11218', '/admin/example/colorbadge', '彩色角标', 'fa fa-table', '', '在JS端控制角标的显示与隐藏,请注意左侧菜单栏角标的数值变化', '1', '1497429920', '1497429920', '91', 'normal'), ('11227', 'file', '11226', '/admin/example/colorbadge/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '90', 'normal'), ('11228', 'file', '11226', '/admin/example/colorbadge/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '89', 'normal'), ('11229', 'file', '11226', '/admin/example/colorbadge/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '88', 'normal'), ('11230', 'file', '11226', '/admin/example/colorbadge/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '87', 'normal'), ('11231', 'file', '11226', '/admin/example/colorbadge/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '86', 'normal'), ('11232', 'file', '11218', '/admin/example/controllerjump', '控制器间跳转', 'fa fa-table', '', 'FastAdmin支持在控制器间跳转,点击后将切换到另外一个TAB中,无需刷新当前页面', '1', '1497429920', '1497429920', '85', 'normal'), ('11233', 'file', '11232', '/admin/example/controllerjump/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '84', 'normal'), ('11234', 'file', '11232', '/admin/example/controllerjump/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '83', 'normal'), ('11235', 'file', '11232', '/admin/example/controllerjump/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '82', 'normal'), ('11236', 'file', '11232', '/admin/example/controllerjump/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '81', 'normal'), ('11237', 'file', '11232', '/admin/example/controllerjump/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '80', 'normal'), ('11238', 'file', '11218', '/admin/example/cxselect', '多级联动', 'fa fa-table', '', 'FastAdmin使用了jQuery-cxselect实现多级联动,更多文档请参考https://github.com/karsonzhang/cxSelect', '1', '1497429920', '1497429920', '79', 'normal'), ('11239', 'file', '11238', '/admin/example/cxselect/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '78', 'normal'), ('11240', 'file', '11238', '/admin/example/cxselect/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '77', 'normal'), ('11241', 'file', '11238', '/admin/example/cxselect/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '76', 'normal'), ('11242', 'file', '11238', '/admin/example/cxselect/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '75', 'normal'), ('11243', 'file', '11238', '/admin/example/cxselect/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '74', 'normal'), ('11244', 'file', '11218', '/admin/example/multitable', '多表格示例', 'fa fa-table', '', '当一个页面上存在多个Bootstrap-table时该如何控制按钮和表格', '1', '1497429920', '1497429920', '73', 'normal'), ('11245', 'file', '11244', '/admin/example/multitable/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '72', 'normal'), ('11246', 'file', '11244', '/admin/example/multitable/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '71', 'normal'), ('11247', 'file', '11244', '/admin/example/multitable/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '70', 'normal'), ('11248', 'file', '11244', '/admin/example/multitable/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '69', 'normal'), ('11249', 'file', '11244', '/admin/example/multitable/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '68', 'normal'), ('11250', 'file', '11218', '/admin/example/relationmodel', '多模型关联', 'fa fa-table', '', '当使用到关联模型时需要重载index方法', '1', '1497429920', '1497429920', '67', 'normal'), ('11251', 'file', '11250', '/admin/example/relationmodel/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '66', 'normal'), ('11252', 'file', '11250', '/admin/example/relationmodel/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '65', 'normal'), ('11253', 'file', '11250', '/admin/example/relationmodel/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '64', 'normal'), ('11254', 'file', '11250', '/admin/example/relationmodel/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '63', 'normal'), ('11255', 'file', '11250', '/admin/example/relationmodel/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '62', 'normal'), ('11256', 'file', '0', '/admin/general', '常规管理', 'fa fa-cogs', '', '', '1', '1497429920', '1497430169', '137', 'normal'), ('11257', 'file', '11256', '/admin/general/attachment', '附件管理', 'fa fa-file-image-o', '', '主要用于管理上传到又拍云的数据或上传至本服务的上传数据\r\n', '1', '1497429920', '1497430699', '53', 'normal'), ('11258', 'file', '11257', '/admin/general/attachment/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '59', 'normal'), ('11259', 'file', '11257', '/admin/general/attachment/select', '选择附件', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '58', 'normal'), ('11260', 'file', '11257', '/admin/general/attachment/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '57', 'normal'), ('11261', 'file', '11257', '/admin/general/attachment/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '56', 'normal'), ('11262', 'file', '11257', '/admin/general/attachment/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '55', 'normal'), ('11263', 'file', '11257', '/admin/general/attachment/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '54', 'normal'), ('11264', 'file', '11256', '/admin/general/config', '系统配置', 'fa fa-cog', '', '', '1', '1497429920', '1497430683', '60', 'normal'), ('11265', 'file', '11264', '/admin/general/config/index', 'index', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '52', 'normal'), ('11266', 'file', '11264', '/admin/general/config/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '51', 'normal'), ('11267', 'file', '11264', '/admin/general/config/edit', 'edit', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '50', 'normal'), ('11268', 'file', '11264', '/admin/general/config/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '49', 'normal'), ('11269', 'file', '11264', '/admin/general/config/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '48', 'normal'), ('11270', 'file', '11256', '/admin/general/crontab', '定时任务', 'fa fa-tasks', '', '类似于Linux的Crontab定时任务,可以按照设定的时间进行任务的执行,目前仅支持三种任务:请求URL、执行SQL、执行Shell', '1', '1497429920', '1497429920', '47', 'normal'), ('11271', 'file', '11270', '/admin/general/crontab/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '46', 'normal'), ('11272', 'file', '11270', '/admin/general/crontab/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '45', 'normal'), ('11273', 'file', '11270', '/admin/general/crontab/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '44', 'normal'), ('11274', 'file', '11270', '/admin/general/crontab/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '43', 'normal'), ('11275', 'file', '11270', '/admin/general/crontab/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '42', 'normal'), ('11276', 'file', '11256', '/admin/general/database', '数据库管理', 'fa fa-database', '', '可在线进行一些简单的数据库表优化或修复,查看表结构和数据。也可以进行SQL语句的操作', '1', '1497429920', '1497429920', '41', 'normal'), ('11277', 'file', '11276', '/admin/general/database/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '40', 'normal'), ('11278', 'file', '11276', '/admin/general/database/query', 'SQL查询', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '39', 'normal'), ('11279', 'file', '11276', '/admin/general/database/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '38', 'normal'), ('11280', 'file', '11276', '/admin/general/database/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '37', 'normal'), ('11281', 'file', '11276', '/admin/general/database/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '36', 'normal'), ('11282', 'file', '11276', '/admin/general/database/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '35', 'normal'), ('11283', 'file', '11256', '/admin/general/profile', '个人配置', 'fa fa-user\r', '', '', '1', '1497429920', '1497429920', '34', 'normal'), ('11284', 'file', '11283', '/admin/general/profile/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '33', 'normal'), ('11285', 'file', '11283', '/admin/general/profile/update', '更新个人信息', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '32', 'normal'), ('11286', 'file', '11283', '/admin/general/profile/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '31', 'normal'), ('11287', 'file', '11283', '/admin/general/profile/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '30', 'normal'), ('11288', 'file', '11283', '/admin/general/profile/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '29', 'normal'), ('11289', 'file', '11283', '/admin/general/profile/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '28', 'normal'), ('11290', 'file', '0', '/admin/wechat', '微信管理', 'fa fa-wechat', '', '', '1', '1497429920', '1497430064', '61', 'normal'), ('11291', 'file', '11290', '/admin/wechat/autoreply', '微信自动回复管理', 'fa fa-reply-all', '用户在微信公众号中输入特定的文字后,服务器响应不同的事件', '', '1', '1497429920', '1499761628', '26', 'normal'), ('11292', 'file', '11291', '/admin/wechat/autoreply/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '25', 'normal'), ('11293', 'file', '11291', '/admin/wechat/autoreply/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '24', 'normal'), ('11294', 'file', '11291', '/admin/wechat/autoreply/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '23', 'normal'), ('11295', 'file', '11291', '/admin/wechat/autoreply/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '22', 'normal'), ('11296', 'file', '11291', '/admin/wechat/autoreply/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '21', 'normal'), ('11297', 'file', '11290', '/admin/wechat/config', '微信配置管理', 'fa fa-cog', '', '', '1', '1497429920', '1497430632', '20', 'normal'), ('11298', 'file', '11297', '/admin/wechat/config/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '19', 'normal'), ('11299', 'file', '11297', '/admin/wechat/config/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '18', 'normal'), ('11300', 'file', '11297', '/admin/wechat/config/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '17', 'normal'), ('11301', 'file', '11297', '/admin/wechat/config/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '16', 'normal'), ('11302', 'file', '11297', '/admin/wechat/config/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '15', 'normal'), ('11303', 'file', '11290', '/admin/wechat/menu', '菜单管理', 'fa fa-bars', '', '', '1', '1497429920', '1497430652', '14', 'normal'), ('11304', 'file', '11303', '/admin/wechat/menu/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '13', 'normal'), ('11305', 'file', '11303', '/admin/wechat/menu/edit', '修改', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '12', 'normal'), ('11306', 'file', '11303', '/admin/wechat/menu/sync', '同步', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '11', 'normal'), ('11307', 'file', '11303', '/admin/wechat/menu/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '10', 'normal'), ('11308', 'file', '11303', '/admin/wechat/menu/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '9', 'normal'), ('11309', 'file', '11303', '/admin/wechat/menu/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '8', 'normal'), ('11310', 'file', '11290', '/admin/wechat/response', '资源管理', 'fa fa-list-alt', '', '', '1', '1497429920', '1497429920', '7', 'normal'), ('11311', 'file', '11310', '/admin/wechat/response/select', '选择素材', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '6', 'normal'), ('11312', 'file', '11310', '/admin/wechat/response/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '5', 'normal'), ('11313', 'file', '11310', '/admin/wechat/response/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '4', 'normal'), ('11314', 'file', '11310', '/admin/wechat/response/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '3', 'normal'), ('11315', 'file', '11310', '/admin/wechat/response/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '2', 'normal'), ('11316', 'file', '11310', '/admin/wechat/response/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '1', 'normal'), ('11317', 'file', '11218', '/admin/example/tabletemplate', '表格模板示例', 'fa fa-table', '', '可以通过使用表格模板将表格中的行渲染成一样的展现方式,基于此功能可以任意定制自己想要的展示列表', '1', '1497968508', '1497968508', '0', 'normal'), ('11318', 'file', '11317', '/admin/example/tabletemplate/index', '查看', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'), ('11319', 'file', '11317', '/admin/example/tabletemplate/detail', '详情', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'), ('11320', 'file', '11317', '/admin/example/tabletemplate/add', '添加', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'), ('11321', 'file', '11317', '/admin/example/tabletemplate/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'), ('11322', 'file', '11317', '/admin/example/tabletemplate/del', '删除', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'), ('11323', 'file', '11317', '/admin/example/tabletemplate/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497968508', '1497968508', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('1', 'file', '0', 'dashboard', '控制台', 'fa fa-dashboard\r', '', '用于展示当前系统中的统计数据、统计报表及重要实时数据\r', '1', '1497429920', '1497429920', '143', 'normal'), ('2', 'file', '0', 'general', '常规管理', 'fa fa-cogs', '', '', '1', '1497429920', '1497430169', '137', 'normal'), ('3', 'file', '0', 'category', '分类管理', 'fa fa-list\r', '', '用于统一管理网站的所有分类,分类可进行无限级分类\r', '1', '1497429920', '1497429920', '119', 'normal'), ('4', 'file', '0', 'addon', '插件管理', 'fa fa-rocket', '', '可在线安装、卸载、禁用、启用插件,同时支持添加本地插件', '1', '1502035509', '1502035509', '0', 'normal'), ('5', 'file', '0', 'auth', '权限管理', 'fa fa-group', '', '', '1', '1497429920', '1497430092', '99', 'normal'), ('6', 'file', '2', 'general/config', '系统配置', 'fa fa-cog', '', '', '1', '1497429920', '1497430683', '60', 'normal'), ('7', 'file', '2', 'general/attachment', '附件管理', 'fa fa-file-image-o', '', '主要用于管理上传到又拍云的数据或上传至本服务的上传数据\r\n', '1', '1497429920', '1497430699', '53', 'normal'), ('8', 'file', '2', 'general/profile', '个人配置', 'fa fa-user\r', '', '', '1', '1497429920', '1497429920', '34', 'normal'), ('9', 'file', '5', 'auth/admin', '管理员管理', 'fa fa-user', '', '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成', '1', '1497429920', '1497430320', '118', 'normal'), ('10', 'file', '5', 'auth/adminlog', '管理员日志', 'fa fa-list-alt', '', '管理员可以查看自己所拥有的权限的管理员日志', '1', '1497429920', '1497430307', '113', 'normal'), ('11', 'file', '5', 'auth/group', '角色组', 'fa fa-group', '', '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别下级的角色组或管理员', '1', '1497429920', '1497429920', '109', 'normal'), ('12', 'file', '5', 'auth/rule', '规则管理', 'fa fa-bars', '', '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过控制台进行生成规则节点', '1', '1497429920', '1497430581', '104', 'normal'), ('13', 'file', '1', 'dashboard/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '136', 'normal'), ('14', 'file', '1', 'dashboard/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '135', 'normal'), ('15', 'file', '1', 'dashboard/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '133', 'normal'), ('16', 'file', '1', 'dashboard/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '134', 'normal'), ('17', 'file', '1', 'dashboard/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '132', 'normal'), ('18', 'file', '6', 'general/config/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '52', 'normal'), ('19', 'file', '6', 'general/config/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '51', 'normal'), ('20', 'file', '6', 'general/config/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '50', 'normal'), ('21', 'file', '6', 'general/config/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '49', 'normal'), ('22', 'file', '6', 'general/config/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '48', 'normal'), ('23', 'file', '7', 'general/attachment/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '59', 'normal'), ('24', 'file', '7', 'general/attachment/select', '选择附件', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '58', 'normal'), ('25', 'file', '7', 'general/attachment/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '57', 'normal'), ('26', 'file', '7', 'general/attachment/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '56', 'normal'), ('27', 'file', '7', 'general/attachment/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '55', 'normal'), ('28', 'file', '7', 'general/attachment/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '54', 'normal'), ('29', 'file', '8', 'general/profile/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '33', 'normal'), ('30', 'file', '8', 'general/profile/update', '更新个人信息', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '32', 'normal'), ('31', 'file', '8', 'general/profile/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '31', 'normal'), ('32', 'file', '8', 'general/profile/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '30', 'normal'), ('33', 'file', '8', 'general/profile/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '29', 'normal'), ('34', 'file', '8', 'general/profile/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '28', 'normal'), ('35', 'file', '3', 'category/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '142', 'normal'), ('36', 'file', '3', 'category/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '141', 'normal'), ('37', 'file', '3', 'category/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '140', 'normal'), ('38', 'file', '3', 'category/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '139', 'normal'), ('39', 'file', '3', 'category/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '138', 'normal'), ('40', 'file', '9', 'auth/admin/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '117', 'normal'), ('41', 'file', '9', 'auth/admin/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '116', 'normal'), ('42', 'file', '9', 'auth/admin/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '115', 'normal'), ('43', 'file', '9', 'auth/admin/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '114', 'normal'), ('44', 'file', '10', 'auth/adminlog/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '112', 'normal'), ('45', 'file', '10', 'auth/adminlog/detail', '详情', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '111', 'normal'), ('46', 'file', '10', 'auth/adminlog/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '110', 'normal'), ('47', 'file', '11', 'auth/group/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '108', 'normal'), ('48', 'file', '11', 'auth/group/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '107', 'normal'), ('49', 'file', '11', 'auth/group/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '106', 'normal'), ('50', 'file', '11', 'auth/group/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '105', 'normal'), ('51', 'file', '12', 'auth/rule/index', '查看', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '103', 'normal'), ('52', 'file', '12', 'auth/rule/add', '添加', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '102', 'normal'), ('53', 'file', '12', 'auth/rule/edit', '编辑', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '101', 'normal'), ('54', 'file', '12', 'auth/rule/del', '删除', 'fa fa-circle-o', '', '', '0', '1497429920', '1497429920', '100', 'normal'), ('55', 'file', '4', 'addon/index', '查看', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('56', 'file', '4', 'addon/add', '添加', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('57', 'file', '4', 'addon/edit', '修改', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('58', 'file', '4', 'addon/del', '删除', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('59', 'file', '4', 'addon/local', '本地安装', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('60', 'file', '4', 'addon/state', '禁用启用', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('61', 'file', '4', 'addon/install', '安装', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('62', 'file', '4', 'addon/uninstall', '卸载', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('63', 'file', '4', 'addon/config', '配置', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('64', 'file', '4', 'addon/refresh', '刷新', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'), ('65', 'file', '4', 'addon/multi', '批量更新', 'fa fa-circle-o', '', '', '0', '1502035509', '1502035509', '0', 'normal'); COMMIT; -- ---------------------------- @@ -209,13 +179,13 @@ CREATE TABLE `fa_category` ( PRIMARY KEY (`id`), KEY `weigh` (`weigh`,`id`), KEY `pid` (`pid`) -) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='分类表'; +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='分类表'; -- ---------------------------- -- Records of `fa_category` -- ---------------------------- BEGIN; -INSERT INTO `fa_category` VALUES ('1', '0', 'page', '官方新闻', 'news', 'recommend', '/assets/img/qrcode.png', '', '', 'news', '1495262190', '1495262190', '1', 'normal'), ('2', '0', 'page', '移动应用', 'mobileapp', 'hot', '/assets/img/qrcode.png', '', '', 'mobileapp', '1495262244', '1495262244', '2', 'normal'), ('3', '2', 'page', '微信公众号', 'wechatpublic', 'index', '/assets/img/qrcode.png', '', '', 'wechatpublic', '1495262288', '1495262288', '3', 'normal'), ('4', '2', 'page', 'Android开发', 'android', 'recommend', '/assets/img/qrcode.png', '', '', 'android', '1495262317', '1495262317', '4', 'normal'), ('5', '0', 'page', '软件产品', 'software', 'recommend', '/assets/img/qrcode.png', '', '', 'software', '1495262336', '1499681850', '5', 'normal'), ('6', '5', 'page', '网站建站', 'website', 'recommend', '/assets/img/qrcode.png', '', '', 'website', '1495262357', '1495262357', '6', 'normal'), ('7', '5', 'page', '企业管理软件', 'company', 'index', '/assets/img/qrcode.png', '', '', 'company', '1495262391', '1495262391', '7', 'normal'), ('8', '6', 'page', 'PC端', 'website-pc', 'recommend', '/assets/img/qrcode.png', '', '', 'website-pc', '1495262424', '1495262424', '8', 'normal'), ('9', '6', 'page', '移动端', 'website-mobile', 'recommend', '/assets/img/qrcode.png', '', '', 'website-mobile', '1495262456', '1495262456', '9', 'normal'), ('10', '7', 'page', 'CRM系统 ', 'company-crm', 'recommend', '/assets/img/qrcode.png', '', '', 'company-crm', '1495262487', '1495262487', '10', 'normal'), ('11', '7', 'page', 'SASS平台软件', 'company-sass', 'recommend', '/assets/img/qrcode.png', '', '', 'company-sass', '1495262515', '1495262515', '11', 'normal'), ('12', '0', 'test', '测试1', 'test1', 'recommend', '/assets/img/qrcode.png', '', '', 'test1', '1497015727', '1497015727', '12', 'normal'), ('13', '0', 'test', '测试2', 'test2', 'recommend', '/assets/img/qrcode.png', '', '', 'test2', '1497015738', '1497015738', '13', 'normal'); +INSERT INTO `fa_category` VALUES ('1', '0', 'page', '官方新闻', 'news', 'recommend', '/assets/img/qrcode.png', '', '', 'news', '1495262190', '1495262190', '1', 'normal'), ('2', '0', 'page', '移动应用', 'mobileapp', 'hot', '/assets/img/qrcode.png', '', '', 'mobileapp', '1495262244', '1495262244', '2', 'normal'), ('3', '2', 'page', '微信公众号', 'wechatpublic', 'index', '/assets/img/qrcode.png', '', '', 'wechatpublic', '1495262288', '1495262288', '3', 'normal'), ('4', '2', 'page', 'Android开发', 'android', 'recommend', '/assets/img/qrcode.png', '', '', 'android', '1495262317', '1495262317', '4', 'normal'), ('5', '0', 'page', '软件产品', 'software', 'recommend', '/assets/img/qrcode.png', '', '', 'software', '1495262336', '1499681850', '5', 'normal'), ('6', '5', 'page', '网站建站', 'website', 'recommend', '/assets/img/qrcode.png', '', '', 'website', '1495262357', '1495262357', '6', 'normal'), ('7', '5', 'page', '企业管理软件', 'company', 'index', '/assets/img/qrcode.png', '', '', 'company', '1495262391', '1495262391', '7', 'normal'), ('8', '6', 'page', 'PC端', 'website-pc', 'recommend', '/assets/img/qrcode.png', '', '', 'website-pc', '1495262424', '1495262424', '8', 'normal'), ('9', '6', 'page', '移动端', 'website-mobile', 'recommend', '/assets/img/qrcode.png', '', '', 'website-mobile', '1495262456', '1495262456', '9', 'normal'), ('10', '7', 'page', 'CRM系统 ', 'company-crm', 'recommend', '/assets/img/qrcode.png', '', '', 'company-crm', '1495262487', '1495262487', '10', 'normal'), ('11', '7', 'page', 'SASS平台软件', 'company-sass', 'recommend', '/assets/img/qrcode.png', '', '', 'company-sass', '1495262515', '1495262515', '11', 'normal'), ('12', '0', 'test', '测试1', 'test1', 'recommend', '/assets/img/qrcode.png', '', '', 'test1', '1497015727', '1497015727', '12', 'normal'), ('13', '0', 'test', '测试2', 'test2', 'recommend', '/assets/img/qrcode.png', '', '', 'test2', '1497015738', '1497015738', '13', 'normal'), ('14', '0', 'page', '官方新闻', 'news', 'recommend', '/assets/img/qrcode.png', '', '', 'news', '1495262190', '1495262190', '1', 'normal'), ('15', '0', 'page', '移动应用', 'mobileapp', 'hot', '/assets/img/qrcode.png', '', '', 'mobileapp', '1495262244', '1495262244', '2', 'normal'), ('16', '2', 'page', '微信公众号', 'wechatpublic', 'index', '/assets/img/qrcode.png', '', '', 'wechatpublic', '1495262288', '1495262288', '3', 'normal'), ('17', '2', 'page', 'Android开发', 'android', 'recommend', '/assets/img/qrcode.png', '', '', 'android', '1495262317', '1495262317', '4', 'normal'), ('18', '0', 'page', '软件产品', 'software', 'recommend', '/assets/img/qrcode.png', '', '', 'software', '1495262336', '1499681850', '5', 'normal'), ('19', '5', 'page', '网站建站', 'website', 'recommend', '/assets/img/qrcode.png', '', '', 'website', '1495262357', '1495262357', '6', 'normal'), ('20', '5', 'page', '企业管理软件', 'company', 'index', '/assets/img/qrcode.png', '', '', 'company', '1495262391', '1495262391', '7', 'normal'), ('21', '6', 'page', 'PC端', 'website-pc', 'recommend', '/assets/img/qrcode.png', '', '', 'website-pc', '1495262424', '1495262424', '8', 'normal'), ('22', '6', 'page', '移动端', 'website-mobile', 'recommend', '/assets/img/qrcode.png', '', '', 'website-mobile', '1495262456', '1495262456', '9', 'normal'), ('23', '7', 'page', 'CRM系统 ', 'company-crm', 'recommend', '/assets/img/qrcode.png', '', '', 'company-crm', '1495262487', '1495262487', '10', 'normal'), ('24', '7', 'page', 'SASS平台软件', 'company-sass', 'recommend', '/assets/img/qrcode.png', '', '', 'company-sass', '1495262515', '1495262515', '11', 'normal'), ('25', '0', 'test', '测试1', 'test1', 'recommend', '/assets/img/qrcode.png', '', '', 'test1', '1497015727', '1497015727', '12', 'normal'), ('26', '0', 'test', '测试2', 'test2', 'recommend', '/assets/img/qrcode.png', '', '', 'test2', '1497015738', '1497015738', '13', 'normal'); COMMIT; -- ---------------------------- @@ -244,65 +214,6 @@ BEGIN; INSERT INTO `fa_config` VALUES ('1', 'name', 'basic', '站点名称', '请填写站点名称', 'string', 'FastAdmin', '', 'required', ''), ('2', 'beian', 'basic', '备案号', '粤ICP备15054802号-4', 'string', '', '', '', ''), ('3', 'cdnurl', 'basic', 'CDN地址', '如果使用CDN云储存请配置该值', 'string', '', '', '', ''), ('4', 'version', 'basic', '版本号', '如果静态资源有变动请重新配置该值', 'string', '1.0.1', '', 'required', ''), ('5', 'timezone', 'basic', '时区', '', 'string', 'Asia/Shanghai', '', 'required', ''), ('6', 'forbiddenip', 'basic', '禁止访问IP', '一行一条记录', 'text', '', '', '', ''), ('7', 'languages', 'basic', '模块语言', '', 'array', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', ''), ('8', 'fixedpage', 'basic', '后台默认页', '请尽量输入左侧菜单栏存在的链接', 'string', 'dashboard', '', 'required', ''), ('9', 'categorytype', 'dictionary', '分类类型', '', 'array', '{\"default\":\"默认\",\"page\":\"单页\",\"article\":\"文章\",\"test\":\"测试\"}', '', '', ''), ('10', 'configgroup', 'dictionary', '配置分组', '', 'array', '{\"basic\":\"基础配置\",\"email\":\"邮件配置\",\"dictionary\":\"字典配置\",\"user\":\"会员配置\",\"example\":\"示例分组\"}', '', '', ''), ('11', 'mail_type', 'email', '邮件发送方式', '选择邮件发送方式', 'select', '1', '[\"请选择\",\"SMTP\",\"mail()函数\"]', '', ''), ('12', 'mail_smtp_host', 'email', 'SMTP[服务器]', '错误的配置发送邮件会导致服务器超时', 'string', 'smtp.qq.com', '', '', ''), ('13', 'mail_smtp_port', 'email', 'SMTP[端口]', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '465', '', '', ''), ('14', 'mail_smtp_user', 'email', 'SMTP[用户名]', '(填写完整用户名)', 'string', '10000', '', '', ''), ('15', 'mail_smtp_pass', 'email', 'SMTP[密码]', '(填写您的密码)', 'string', 'password', '', '', ''), ('16', 'mail_verify_type', 'email', 'SMTP验证方式', '(SMTP验证方式[推荐SSL])', 'select', '2', '[\"无\",\"TLS\",\"SSL\"]', '', ''), ('17', 'mail_from', 'email', '发件人邮箱', '', 'string', '10000@qq.com', '', '', ''); COMMIT; --- ---------------------------- --- Table structure for `fa_crontab` --- ---------------------------- -DROP TABLE IF EXISTS `fa_crontab`; -CREATE TABLE `fa_crontab` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `type` varchar(10) NOT NULL DEFAULT '' COMMENT '事件类型', - `title` varchar(100) NOT NULL DEFAULT '' COMMENT '事件标题', - `content` text NOT NULL COMMENT '事件内容', - `schedule` varchar(100) NOT NULL DEFAULT '' COMMENT 'Crontab格式', - `sleep` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '延迟秒数执行', - `maximums` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大执行次数 0为不限', - `executes` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '已经执行的次数', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `begintime` int(10) NOT NULL DEFAULT '0' COMMENT '开始时间', - `endtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '结束时间', - `executetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后执行时间', - `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', - `status` enum('completed','expired','hidden','normal') NOT NULL DEFAULT 'normal' COMMENT '状态', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='定时任务表'; - --- ---------------------------- --- Records of `fa_crontab` --- ---------------------------- -BEGIN; -INSERT INTO `fa_crontab` VALUES ('1', 'url', '请求FastAdmin', 'http://www.fastadmin.net', '* * * * *', '0', '0', '1063', '1497070825', '1499788320', '1483200000', '1546272000', '1499788320', '1', 'normal'), ('2', 'sql', '查询一条SQL', 'SELECT 1;', '* * * * *', '0', '0', '1063', '1497071095', '1499788320', '1483200000', '1546272000', '1499788320', '2', 'normal'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_page` --- ---------------------------- -DROP TABLE IF EXISTS `fa_page`; -CREATE TABLE `fa_page` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `category_id` int(10) NOT NULL DEFAULT '0' COMMENT '分类ID', - `title` varchar(50) NOT NULL DEFAULT '' COMMENT '标题', - `keywords` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字', - `flag` set('hot','index','recommend') NOT NULL DEFAULT '' COMMENT '标志', - `image` varchar(255) NOT NULL DEFAULT '' COMMENT '头像', - `content` text NOT NULL COMMENT '内容', - `icon` varchar(50) NOT NULL DEFAULT '' COMMENT '图标', - `views` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '点击', - `comments` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '评论', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', - `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='单页表'; - --- ---------------------------- --- Records of `fa_page` --- ---------------------------- -BEGIN; -INSERT INTO `fa_page` VALUES ('1', '4', 'test', 'test', 'recommend', '/assets/img/qrcode.png', '

test

', '', '0', '0', '1499769482', '1499769482', '0', 'normal'); -COMMIT; - -- ---------------------------- -- Table structure for `fa_test` -- ---------------------------- @@ -311,8 +222,6 @@ CREATE TABLE `fa_test` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `category_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '分类ID(单选)', `category_ids` varchar(100) NOT NULL COMMENT '分类ID(多选)', - `user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID', - `user_ids` varchar(100) NOT NULL DEFAULT '' COMMENT '多会员ID', `week` enum('monday','tuesday','wednesday') NOT NULL COMMENT '星期(单选):monday=星期一,tuesday=星期二,wednesday=星期三', `flag` set('hot','index','recommend') NOT NULL DEFAULT '' COMMENT '标志(多选):hot=热门,index=首页,recommend=推荐', `genderdata` enum('male','female') NOT NULL DEFAULT 'male' COMMENT '性别(单选):male=男,female=女', @@ -324,6 +233,7 @@ CREATE TABLE `fa_test` ( `attachfile` varchar(100) NOT NULL DEFAULT '' COMMENT '附件', `keywords` varchar(100) NOT NULL DEFAULT '' COMMENT '关键字', `description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述', + `city` varchar(100) NOT NULL DEFAULT '' COMMENT '省市', `price` float(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '价格', `views` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '点击', `startdate` date DEFAULT NULL COMMENT '开始日期', @@ -334,6 +244,7 @@ CREATE TABLE `fa_test` ( `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', + `switch` tinyint(1) NOT NULL DEFAULT '0' COMMENT '开关', `status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态', `state` enum('0','1','2') NOT NULL DEFAULT '1' COMMENT '状态值:0=禁用,1=正常,2=推荐', PRIMARY KEY (`id`) @@ -343,193 +254,7 @@ CREATE TABLE `fa_test` ( -- Records of `fa_test` -- ---------------------------- BEGIN; -INSERT INTO `fa_test` VALUES ('1', '12', '12,13', '3', '3', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '

我是测试内容

', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '描述', '0.00', '0', '2017-07-10', '2017-07-10 18:24:45', '2017', '18:24:45', '1499682285', '1499682526', '1499682526', '0', 'normal', '1'); +INSERT INTO `fa_test` VALUES ('1', '12', '12,13', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '

我是测试内容

', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '描述', '广西壮族自治区/百色市/平果县', '0.00', '0', '2017-07-10', '2017-07-10 18:24:45', '2017', '18:24:45', '1499682285', '1499682526', '1499682526', '0', '1', 'normal', '1'); COMMIT; --- ---------------------------- --- Table structure for `fa_user` --- ---------------------------- -DROP TABLE IF EXISTS `fa_user`; -CREATE TABLE `fa_user` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名', - `nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '昵称', - `password` varchar(32) NOT NULL DEFAULT '' COMMENT '密码', - `salt` varchar(30) NOT NULL DEFAULT '' COMMENT '密码盐', - `email` varchar(100) NOT NULL DEFAULT '' COMMENT '电子邮箱', - `mobile` varchar(11) NOT NULL DEFAULT '' COMMENT '手机号', - `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '头像', - `level` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '等级', - `gender` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '性别', - `birthday` date NOT NULL COMMENT '生日', - `score` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '积分', - `prevtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '上次登录时间', - `loginfailure` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '失败次数', - `logintime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登录时间', - `loginip` varchar(50) NOT NULL DEFAULT '' COMMENT '登录IP', - `joinip` varchar(50) NOT NULL DEFAULT '' COMMENT '加入时间', - `jointime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '加入时间', - `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', - PRIMARY KEY (`id`), - KEY `username` (`username`), - KEY `email` (`email`), - KEY `mobile` (`mobile`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='会员表'; - --- ---------------------------- --- Records of `fa_user` --- ---------------------------- -BEGIN; -INSERT INTO `fa_user` VALUES ('3', 'admin', 'admin', 'c13f62012fd6a8fdf06b3452a94430e5', 'rpR6Bv', 'admin@163.com', '13888888888', '/assets/img/avatar.png', '0', '0', '2017-04-15', '0', '1491822015', '0', '1491822038', '127.0.0.1', '127.0.0.1', '1491461418', 'normal'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_user_signin` --- ---------------------------- -DROP TABLE IF EXISTS `fa_user_signin`; -CREATE TABLE `fa_user_signin` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID', - `successions` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '连续签到次数', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - PRIMARY KEY (`id`), - KEY `user_id` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='会员签到表'; - --- ---------------------------- --- Table structure for `fa_user_third` --- ---------------------------- -DROP TABLE IF EXISTS `fa_user_third`; -CREATE TABLE `fa_user_third` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', - `user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID', - `platform` enum('weibo','wechat','qq') NOT NULL COMMENT '第三方应用', - `openid` varchar(50) NOT NULL DEFAULT '' COMMENT '第三方唯一ID', - `openname` varchar(50) NOT NULL DEFAULT '' COMMENT '第三方会员昵称', - `access_token` varchar(100) NOT NULL DEFAULT '', - `refresh_token` varchar(100) NOT NULL DEFAULT '', - `expires_in` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '有效期', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `logintime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登录时间', - `expiretime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '过期时间', - PRIMARY KEY (`id`), - UNIQUE KEY `platform` (`platform`,`openid`), - KEY `user_id` (`user_id`,`platform`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='会员连接表'; - --- ---------------------------- --- Table structure for `fa_version` --- ---------------------------- -DROP TABLE IF EXISTS `fa_version`; -CREATE TABLE `fa_version` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', - `oldversion` varchar(30) NOT NULL DEFAULT '' COMMENT '旧版本号', - `newversion` varchar(30) NOT NULL DEFAULT '' COMMENT '新版本号', - `packagesize` varchar(30) NOT NULL DEFAULT '' COMMENT '包大小', - `content` varchar(500) NOT NULL DEFAULT '' COMMENT '升级内容', - `downloadurl` varchar(255) NOT NULL DEFAULT '' COMMENT '下载地址', - `enforce` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '强制更新', - `createtime` int(10) NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重', - `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='版本表'; - --- ---------------------------- --- Records of `fa_version` --- ---------------------------- -BEGIN; -INSERT INTO `fa_version` VALUES ('1', '1.1.1,2', '1.2.1', '20M', '更新内容', 'http://www.downloadurl.com', '1', '1400000000', '0', '0', 'normal'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_wechat_autoreply` --- ---------------------------- -DROP TABLE IF EXISTS `fa_wechat_autoreply`; -CREATE TABLE `fa_wechat_autoreply` ( - `id` int(10) NOT NULL AUTO_INCREMENT, - `title` varchar(100) NOT NULL DEFAULT '' COMMENT '标题', - `text` varchar(100) NOT NULL DEFAULT '' COMMENT '触发文本', - `eventkey` varchar(50) NOT NULL DEFAULT '' COMMENT '响应事件', - `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '添加时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='微信自动回复表'; - --- ---------------------------- --- Records of `fa_wechat_autoreply` --- ---------------------------- -BEGIN; -INSERT INTO `fa_wechat_autoreply` VALUES ('1', '输入hello', 'hello', '58c7d908c4570', '123', '1493366855', '1493366855', 'normal'), ('2', '输入你好', '你好', '58fdfaa9e1965', 'sad', '1493704976', '1493704976', 'normal'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_wechat_config` --- ---------------------------- -DROP TABLE IF EXISTS `fa_wechat_config`; -CREATE TABLE `fa_wechat_config` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT '' COMMENT '配置名称', - `title` varchar(50) NOT NULL DEFAULT '' COMMENT '配置标题', - `value` text NOT NULL COMMENT '配置值', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='微信配置表'; - --- ---------------------------- --- Records of `fa_wechat_config` --- ---------------------------- -BEGIN; -INSERT INTO `fa_wechat_config` VALUES ('1', 'menu', '微信菜单', '[{\"name\":\"FastAdmin\",\"sub_button\":[{\"name\":\"官网\",\"type\":\"view\",\"url\":\"http:\\/\\/www.fastadmin.net\"},{\"name\":\"在线演示\",\"type\":\"view\",\"url\":\"http:\\/\\/demo.fastadmin.net\"},{\"name\":\"文档\",\"type\":\"view\",\"url\":\"http:\\/\\/doc.fastadmin.net\"}]},{\"name\":\"在线客服\",\"type\":\"click\",\"key\":\"58cb852984970\"},{\"name\":\"关于我们\",\"type\":\"click\",\"key\":\"58bf944aa0777\"}]', '1497398820', '1497422985'), ('2', 'service', '客服配置', '{\"onlinetime\":\"09:00-18:00\",\"offlinemsg\":\"请在工作时间联系客服!\",\"nosessionmsg\":\"当前没有客服在线!请稍后重试!\",\"waitformsg\":\"请问有什么可以帮到您?\"}', '1497429674', '1497429674'), ('3', 'signin', '连续登录配置', '{\"s1\":\"100\",\"s2\":\"200\",\"s3\":\"300\",\"sn\":\"500\"}', '1497429711', '1497429711'); -COMMIT; - --- ---------------------------- --- Table structure for `fa_wechat_context` --- ---------------------------- -DROP TABLE IF EXISTS `fa_wechat_context`; -CREATE TABLE `fa_wechat_context` ( - `id` int(10) NOT NULL AUTO_INCREMENT, - `openid` varchar(64) NOT NULL DEFAULT '', - `type` varchar(30) NOT NULL DEFAULT '' COMMENT '类型', - `eventkey` varchar(64) NOT NULL DEFAULT '', - `command` varchar(64) NOT NULL DEFAULT '', - `message` varchar(255) NOT NULL DEFAULT '' COMMENT '内容', - `refreshtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后刷新时间', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - PRIMARY KEY (`id`), - KEY `openid` (`openid`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='微信上下文表'; - --- ---------------------------- --- Table structure for `fa_wechat_response` --- ---------------------------- -DROP TABLE IF EXISTS `fa_wechat_response`; -CREATE TABLE `fa_wechat_response` ( - `id` int(10) NOT NULL AUTO_INCREMENT, - `title` varchar(100) NOT NULL DEFAULT '' COMMENT '资源名', - `eventkey` varchar(128) NOT NULL DEFAULT '' COMMENT '事件', - `type` enum('text','image','news','voice','video','music','link','app') NOT NULL DEFAULT 'text' COMMENT '类型', - `content` text NOT NULL COMMENT '内容', - `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', - `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态', - PRIMARY KEY (`id`), - UNIQUE KEY `event` (`eventkey`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='微信资源表'; - --- ---------------------------- --- Records of `fa_wechat_response` --- ---------------------------- -BEGIN; -INSERT INTO `fa_wechat_response` VALUES ('1', '签到送积分', '58adaf7876aab', 'app', '{\"app\":\"signin\"}', '', '1487777656', '1487777656', 'normal'), ('2', '关于我们', '58bf944aa0777', 'app', '{\"app\":\"page\",\"id\":\"1\"}', '', '1488950346', '1488950346', 'normal'), ('3', '自动回复1', '58c7d908c4570', 'text', '{\"content\":\"world\"}', '', '1489492232', '1489492232', 'normal'), ('4', '联系客服', '58cb852984970', 'app', '{\"app\":\"service\"}', '', '1489732905', '1489732905', 'normal'), ('5', '自动回复2', '58fdfaa9e1965', 'text', '{\"content\":\"我是FastAdmin!\"}', '', '1493039785', '1493039785', 'normal'); -COMMIT; - -SET FOREIGN_KEY_CHECKS = 1; +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/application/admin/command/Menu.php b/application/admin/command/Menu.php index 751abadf..04164673 100644 --- a/application/admin/command/Menu.php +++ b/application/admin/command/Menu.php @@ -219,13 +219,13 @@ class Menu extends Command //先定入菜单的数据 $pid = 0; - $name = "/admin"; - foreach (explode('/', $controller) as $k => $v) + foreach ($controllerArr as $k => $v) { - $name .= '/' . strtolower($v); - $title = (!isset($controllerArr[$k + 1]) ? $controllerTitle : ''); - $icon = (!isset($controllerArr[$k + 1]) ? $controllerIcon : 'fa fa-list'); - $remark = (!isset($controllerArr[$k + 1]) ? $controllerRemark : ''); + $key = $k + 1; + $name = strtolower(implode('/', array_slice($controllerArr, 0, $key))); + $title = (!isset($controllerArr[$key]) ? $controllerTitle : ''); + $icon = (!isset($controllerArr[$key]) ? $controllerIcon : 'fa fa-list'); + $remark = (!isset($controllerArr[$key]) ? $controllerRemark : ''); $title = $title ? $title : __(ucfirst($v) . ' manager'); $rulemodel = $this->model->get(['name' => $name]); if (!$rulemodel) diff --git a/application/admin/command/Min.php b/application/admin/command/Min.php index 8f8a458c..e3385346 100644 --- a/application/admin/command/Min.php +++ b/application/admin/command/Min.php @@ -32,8 +32,8 @@ class Min extends Command protected function execute(Input $input, Output $output) { - $module = $input->getOption('module') ? : ''; - $resource = $input->getOption('resource') ? : ''; + $module = $input->getOption('module') ?: ''; + $resource = $input->getOption('resource') ?: ''; if (!$module || !in_array($module, ['frontend', 'backend', 'all'])) { @@ -85,8 +85,8 @@ class Min extends Command 'jsBaseUrl' => $this->options['jsBaseUrl'], 'cssBaseName' => str_replace('{module}', $mod, $this->options['cssBaseName']), 'cssBaseUrl' => $this->options['cssBaseUrl'], - 'jsBasePath' => ROOT_PATH . $this->options['jsBaseUrl'], - 'cssBasePath' => ROOT_PATH . $this->options['cssBaseUrl'], + 'jsBasePath' => str_replace('\\', '/', ROOT_PATH) . $this->options['jsBaseUrl'], + 'cssBasePath' => str_replace('\\', '/', ROOT_PATH) . $this->options['cssBaseUrl'], 'ds' => DS, ]; diff --git a/application/admin/common.php b/application/admin/common.php index 86800c8d..00c2f315 100644 --- a/application/admin/common.php +++ b/application/admin/common.php @@ -135,3 +135,87 @@ function build_heading($title = NULL, $content = NULL) return ''; return '
' . $title . '' . $content . '
'; } + +/** + * 判断文件或文件夹是否可写 + * @param string + * @return bool + */ +function is_really_writable($file) +{ + if (DIRECTORY_SEPARATOR === '/') + { + return is_writable($file); + } + if (is_dir($file)) + { + $file = rtrim($file, '/') . '/' . md5(mt_rand()); + if (($fp = @fopen($file, 'ab')) === FALSE) + { + return FALSE; + } + fclose($fp); + @chmod($file, 0777); + @unlink($file); + return TRUE; + } + elseif (!is_file($file) OR ( $fp = @fopen($file, 'ab')) === FALSE) + { + return FALSE; + } + fclose($fp); + return TRUE; +} + +/** + * 删除文件夹 + * @param string $dirname + * @return boolean + */ +function rmdirs($dirname) +{ + if (!is_dir($dirname)) + return false; + $files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($files as $fileinfo) + { + $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); + $todo($fileinfo->getRealPath()); + } + @rmdir($dirname); + return true; +} + +/** + * 复制文件夹 + * @param string $source 源文件夹 + * @param string $dest 目标文件夹 + */ +function copydirs($source, $dest) +{ + if (!is_dir($dest)) + { + mkdir($dest, 0755); + } + foreach ( + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST) as $item + ) + { + if ($item->isDir()) + { + $sontDir = $dest . DS . $iterator->getSubPathName(); + if (!is_dir($sontDir)) + { + mkdir($sontDir); + } + } + else + { + copy($item, $dest . DS . $iterator->getSubPathName()); + } + } +} diff --git a/application/admin/controller/Addon.php b/application/admin/controller/Addon.php new file mode 100644 index 00000000..0526109b --- /dev/null +++ b/application/admin/controller/Addon.php @@ -0,0 +1,293 @@ + &$v) + { + $config = get_addon_config($v['name']); + $v['config'] = $config ? 1 : 0; + } + $this->assignconfig(['addons' => $addons]); + return $this->view->fetch(); + } + + /** + * 配置 + */ + public function config($ids = NULL) + { + $name = $this->request->get("name"); + if (!$name) + { + $this->error(__('Parameter %s can not be empty', $id ? 'id' : 'name')); + } + if (!is_dir(ADDON_PATH . $name)) + { + $this->error(__('Directory not found')); + } + $info = get_addon_info($name); + $config = get_addon_fullconfig($name); + if (!$info) + $this->error(__('No Results were found')); + if ($this->request->isPost()) + { + $params = $this->request->post("row/a"); + if ($params) + { + $configList = []; + foreach ($config as $k => &$v) + { + if (isset($params[$v['name']])) + { + if ($v['type'] == 'array') + { + $fieldarr = $valuearr = []; + $field = $params[$v['name']]['field']; + $value = $params[$v['name']]['value']; + + foreach ($field as $m => $n) + { + if ($n != '') + { + $fieldarr[] = $field[$m]; + $valuearr[] = $value[$m]; + } + } + $params[$v['name']] = array_combine($fieldarr, $valuearr); + $value = $params[$v['name']]; + } + else + { + $value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']]; + } + + $v['value'] = $value; + } + } + try + { + //更新配置文件 + set_addon_fullconfig($name, $config); + $this->success(); + } + catch (Exception $e) + { + $this->error($e->getMessage()); + } + } + $this->error(__('Parameter %s can not be empty', '')); + } + $this->view->assign("addon", ['info' => $info, 'config' => $config]); + return $this->view->fetch(); + } + + /** + * 安装 + */ + public function install() + { + $name = $this->request->post("name"); + $force = (int) $this->request->post("force"); + if (!$name) + { + $this->error(__('Parameter %s can not be empty', 'name')); + } + try + { + Service::install($name, $force); + $this->success("安装成功", null, ['addon' => get_addon_info($name)]); + } + catch (AddonException $e) + { + $this->result($e->getData(), $e->getCode(), $e->getMessage()); + } + catch (Exception $e) + { + $this->error($e->getMessage(), $e->getCode()); + } + } + + /** + * 卸载 + */ + public function uninstall() + { + $name = $this->request->post("name"); + $force = (int) $this->request->post("force"); + if (!$name) + { + $this->error(__('Parameter %s can not be empty', 'name')); + } + try + { + Service::uninstall($name, $force); + $this->success("卸载成功"); + } + catch (AddonException $e) + { + $this->result($e->getData(), $e->getCode(), $e->getMessage()); + } + catch (Exception $e) + { + $this->error($e->getMessage()); + } + } + + /** + * 禁用启用 + */ + public function state() + { + $name = $this->request->post("name"); + $action = $this->request->post("action"); + $force = (int) $this->request->post("force"); + if (!$name) + { + $this->error(__('Parameter %s can not be empty', 'name')); + } + try + { + $action = $action == 'enable' ? $action : 'disable'; + //调用启用、禁用的方法 + Service::$action($name, $force); + $this->success("操作成功"); + } + catch (AddonException $e) + { + $this->result($e->getData(), $e->getCode(), $e->getMessage()); + } + catch (Exception $e) + { + $this->error($e->getMessage()); + } + } + + /** + * 本地上传 + */ + public function local() + { + $file = $this->request->file('file'); + $addonTmpDir = RUNTIME_PATH . 'addons' . DS; + if (!is_dir($addonTmpDir)) + { + @mkdir($addonTmpDir, 0755, true); + } + $info = $file->rule('uniqid')->validate(['size' => 10240000, 'ext' => 'zip'])->move($addonTmpDir); + if ($info) + { + $tmpName = substr($info->getFilename(), 0, stripos($info->getFilename(), '.')); + $tmpAddonDir = ADDON_PATH . $tmpName . DS; + $tmpFile = $addonTmpDir . $info->getSaveName(); + try + { + Service::unzip($tmpName); + @unlink($tmpFile); + $infoFile = $tmpAddonDir . 'info.ini'; + if (!is_file($infoFile)) + { + throw new Exception("插件配置文件未找到"); + } + + $config = Config::parse($infoFile, '', $tmpName); + $name = isset($config['name']) ? $config['name'] : ''; + if (!$name) + { + throw new Exception("插件配置信息不正确"); + } + + $newAddonDir = ADDON_PATH . $name . DS; + if (is_dir($newAddonDir)) + { + throw new Exception("上传的插件已经存在"); + } + + //重命名插件文件夹 + rename($tmpAddonDir, $newAddonDir); + try + { + //默认禁用该插件 + $info = get_addon_info($name); + if ($info['state']) + { + $info['state'] = 0; + set_addon_info($name, $info); + } + + //执行插件的安装方法 + $class = get_addon_class($name); + if (class_exists($class)) + { + $addon = new $class(); + $addon->install(); + } + + //导入SQL + Service::importsql($name); + + $this->success("插件安装成功,你需要手动启用该插件,使之生效", null, ['addon' => $info]); + } + catch (Exception $e) + { + @rmdirs($newAddonDir); + throw new Exception($e->getMessage()); + } + } + catch (Exception $e) + { + @unlink($tmpFile); + @rmdirs($tmpAddonDir); + $this->error($e->getMessage()); + } + } + else + { + // 上传失败获取错误信息 + $this->error($file->getError()); + } + } + + /** + * 刷新缓存 + */ + public function refresh() + { + try + { + Service::refresh(); + $this->success("操作成功"); + } + catch (Exception $e) + { + $this->error($e->getMessage()); + } + } + +} diff --git a/application/admin/controller/Ajax.php b/application/admin/controller/Ajax.php index 8a1ac5f5..0bf244ab 100644 --- a/application/admin/controller/Ajax.php +++ b/application/admin/controller/Ajax.php @@ -4,8 +4,6 @@ namespace app\admin\controller; use app\common\controller\Backend; use fast\Random; -use RecursiveDirectoryIterator; -use RecursiveIteratorIterator; use think\Cache; use think\Config; use think\Db; @@ -38,6 +36,7 @@ class Ajax extends Backend header('Content-Type: application/javascript'); $callback = $this->request->get('callback'); $controllername = input("controllername"); + //默认只加载了控制器对应的语言名,你还根据控制器名来加载额外的语言包 $this->loadlang($controllername); //强制输出JSON Object $result = 'define(' . json_encode(Lang::get(), JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE) . ');'; @@ -49,25 +48,14 @@ class Ajax extends Backend */ public function upload() { - $this->code = -1; $file = $this->request->file('file'); if (empty($file)) { - $this->msg = "未上传文件或超出服务器上传限制"; - return; + $this->error("未上传文件或超出服务器上传限制"); } //判断是否已经存在附件 $sha1 = $file->hash(); - $uploaded = model("attachment")->where('sha1', $sha1)->find(); - if ($uploaded) - { - $this->code = 1; - $this->data = [ - 'url' => $uploaded['url'] - ]; - return; - } $upload = Config::get('upload'); @@ -120,16 +108,17 @@ class Ajax extends Backend 'storage' => 'local', 'sha1' => $sha1, ); - model("attachment")->create(array_filter($params)); - $this->code = 1; - $this->data = [ + $attachment = model("attachment"); + $attachment->create(array_filter($params)); + \think\Hook::listen("upload_after", $attachment); + $this->success('上传成功', null, [ 'url' => $uploadDir . $splInfo->getSaveName() - ]; + ]); } else { // 上传失败获取错误信息 - $this->data = $file->getError(); + $this->error($file->getError()); } } @@ -177,7 +166,7 @@ class Ajax extends Backend { Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]); } - $this->code = 1; + $this->success(); } else { @@ -216,7 +205,7 @@ class Ajax extends Backend $weighids[$n] = $weighdata[$offset]; Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]); } - $this->code = 1; + $this->success(); } } @@ -231,20 +220,11 @@ class Ajax extends Backend $dir = constant($item); if (!is_dir($dir)) continue; - $files = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST - ); - - foreach ($files as $fileinfo) - { - $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); - $todo($fileinfo->getRealPath()); - } - - //rmdir($dir); + rmdirs($dir); } Cache::clear(); - $this->code = 1; + \think\Hook::listen("wipecache_after"); + $this->success(); } /** @@ -269,9 +249,7 @@ class Ajax extends Backend $categorylist = Db::name('category')->where($where)->field('id as value,name')->order('weigh desc,id desc')->select(); } - $this->code = 1; - $this->data = $categorylist; - return; + $this->success('', null, $categorylist); } /** @@ -300,9 +278,7 @@ class Ajax extends Backend $provincelist = Db::name('area')->where($where)->field('id as value,name')->select(); } } - $this->code = 1; - $this->data = $provincelist; - return; + $this->success('', null, $provincelist); } } diff --git a/application/admin/controller/Category.php b/application/admin/controller/Category.php index c1cb54d2..8336e3e5 100644 --- a/application/admin/controller/Category.php +++ b/application/admin/controller/Category.php @@ -28,10 +28,10 @@ class Category extends Backend $tree = Tree::instance(); $tree->init($this->model->order('weigh desc,id desc')->select(), 'pid'); $this->categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name'); - $categorydata = [0 => __('None')]; + $categorydata = [0 => ['type'=>'all', 'name'=>__('None')]]; foreach ($this->categorylist as $k => $v) { - $categorydata[$v['id']] = $v['name']; + $categorydata[$v['id']] = $v; } $this->view->assign("flagList", $this->model->getFlagList()); $this->view->assign("typeList", CategoryModel::getTypeList()); diff --git a/application/admin/controller/Index.php b/application/admin/controller/Index.php index b2f2048f..b624f4ef 100644 --- a/application/admin/controller/Index.php +++ b/application/admin/controller/Index.php @@ -29,9 +29,8 @@ class Index extends Backend // $menulist = $this->auth->getSidebar([ 'dashboard' => 'hot', - 'auth' => ['new', 'red', 'badge'], - 'auth/admin' => 12, - 'auth/rule' => 4, + 'addon' => ['new', 'red', 'badge'], + 'auth/rule' => 'side', 'general' => ['18', 'purple'], ], $this->view->site['fixedpage']); $this->view->assign('menulist', $menulist); @@ -48,7 +47,6 @@ class Index extends Backend if ($this->auth->isLogin()) { $this->error(__("You've logged in, do not login again"), $url); - return; } if ($this->request->isPost()) { @@ -71,20 +69,17 @@ class Index extends Backend if (!$result) { $this->error($validate->getError(), $url, ['token' => $this->request->token()]); - return; } \app\admin\model\AdminLog::setTitle(__('Login')); $result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0); if ($result === true) { $this->success(__('Login successful'), $url, ['url' => $url, 'id' => $this->auth->id, 'username' => $username, 'avatar' => $this->auth->avatar]); - return; } else { $this->error(__('Username or password is incorrect'), $url, ['token' => $this->request->token()]); } - return; } // 根据客户端的cookie,判断是否可以自动登录 @@ -92,7 +87,9 @@ class Index extends Backend { $this->redirect($url); } - $this->view->assign('title', __('Login')); + $background = cdnurl("/assets/img/loginbg.jpg"); + $this->view->assign('background', $background); + \think\Hook::listen("login_init", $this->request); return $this->view->fetch(); } @@ -103,7 +100,6 @@ class Index extends Backend { $this->auth->logout(); $this->success(__('Logout successful'), 'index/login'); - return; } } diff --git a/application/admin/controller/Page.php b/application/admin/controller/Page.php deleted file mode 100644 index aeacb90b..00000000 --- a/application/admin/controller/Page.php +++ /dev/null @@ -1,51 +0,0 @@ -model = model('Page'); - } - - /** - * 查看 - */ - public function index() - { - if ($this->request->isAjax()) - { - list($where, $sort, $order, $offset, $limit) = $this->buildparams(); - $total = $this->model - ->with("category") - ->where($where) - ->order($sort, $order) - ->count(); - $list = $this->model - ->with("category") - ->where($where) - ->order($sort, $order) - ->limit($offset, $limit) - ->select(); - $result = array("total" => $total, "rows" => $list); - - return json($result); - } - return $this->view->fetch(); - } - -} diff --git a/application/admin/controller/User.php b/application/admin/controller/User.php deleted file mode 100644 index cd7748a2..00000000 --- a/application/admin/controller/User.php +++ /dev/null @@ -1,27 +0,0 @@ -model = model('User'); - } - -} diff --git a/application/admin/controller/Version.php b/application/admin/controller/Version.php deleted file mode 100644 index e0360f7c..00000000 --- a/application/admin/controller/Version.php +++ /dev/null @@ -1,26 +0,0 @@ -model = model('Version'); - } - -} diff --git a/application/admin/controller/auth/Admin.php b/application/admin/controller/auth/Admin.php index f4a54872..06c7177d 100644 --- a/application/admin/controller/auth/Admin.php +++ b/application/admin/controller/auth/Admin.php @@ -101,7 +101,6 @@ class Admin extends Backend { if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a"); if ($params) { @@ -120,10 +119,9 @@ class Admin extends Backend $dataset[] = ['uid' => $admin->id, 'group_id' => $value]; } model('AuthGroupAccess')->saveAll($dataset); - $this->code = 1; + $this->success(); } - - return; + $this->error(); } return $this->view->fetch(); } @@ -138,7 +136,6 @@ class Admin extends Backend $this->error(__('No Results were found')); if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a"); if ($params) { @@ -167,10 +164,9 @@ class Admin extends Backend $dataset[] = ['uid' => $row->id, 'group_id' => $value]; } model('AuthGroupAccess')->saveAll($dataset); - $this->code = 1; + $this->success(); } - - return; + $this->error(); } $grouplist = $this->auth->getGroups($row['id']); $groupids = []; @@ -188,7 +184,6 @@ class Admin extends Backend */ public function del($ids = "") { - $this->code = -1; if ($ids) { // 避免越权删除管理员 @@ -208,12 +203,11 @@ class Admin extends Backend { $this->model->destroy($deleteIds); model('AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete(); - $this->code = 1; + $this->success(); } } } - - return; + $this->error(); } /** @@ -223,7 +217,7 @@ class Admin extends Backend public function multi($ids = "") { // 管理员禁止批量操作 - $this->code = -1; + $this->error(); } } diff --git a/application/admin/controller/auth/Adminlog.php b/application/admin/controller/auth/Adminlog.php index d33cff88..a8898466 100644 --- a/application/admin/controller/auth/Adminlog.php +++ b/application/admin/controller/auth/Adminlog.php @@ -74,7 +74,7 @@ class Adminlog extends Backend } return $this->view->fetch(); } - + /** * 详情 */ @@ -93,7 +93,7 @@ class Adminlog extends Backend */ public function add() { - $this->code = -1; + $this->error(); } /** @@ -102,7 +102,7 @@ class Adminlog extends Backend */ public function edit($ids = NULL) { - $this->code = -1; + $this->error(); } /** @@ -110,7 +110,6 @@ class Adminlog extends Backend */ public function del($ids = "") { - $this->code = -1; if ($ids) { $childrenGroupIds = $this->childrenIds; @@ -127,12 +126,11 @@ class Adminlog extends Backend if ($deleteIds) { $this->model->destroy($deleteIds); - $this->code = 1; + $this->success(); } } } - - return; + $this->error(); } /** @@ -142,7 +140,7 @@ class Adminlog extends Backend public function multi($ids = "") { // 管理员禁止批量操作 - $this->code = -1; + $this->error(); } } diff --git a/application/admin/controller/auth/Group.php b/application/admin/controller/auth/Group.php index 744f8ced..e1b78900 100644 --- a/application/admin/controller/auth/Group.php +++ b/application/admin/controller/auth/Group.php @@ -79,26 +79,21 @@ class Group extends Backend { if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a", [], 'strip_tags'); $params['rules'] = explode(',', $params['rules']); if (!in_array($params['pid'], $this->childrenIds)) { - $this->code = -1; - $this->msg = __(''); - return; + $this->error(__('The parent group can not be its own child')); } $parentmodel = model("AuthGroup")->get($params['pid']); if (!$parentmodel) { - $this->msg = __('The parent group can not found'); - return; + $this->error(__('The parent group can not found')); } // 父级别的规则节点 $parentrules = explode(',', $parentmodel->rules); // 当前组别的规则节点 $currentrules = $this->auth->getRuleIds(); - $rules = $params['rules']; // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限 $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules); // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限 @@ -107,10 +102,9 @@ class Group extends Backend if ($params) { $this->model->create($params); - $this->code = 1; + $this->success(); } - - return; + $this->error(); } return $this->view->fetch(); } @@ -125,27 +119,25 @@ class Group extends Backend $this->error(__('No Results were found')); if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a", [], 'strip_tags'); // 父节点不能是它自身的子节点 if (!in_array($params['pid'], $this->childrenIds)) { - $this->msg = __('The parent group can not be its own child'); - return; + $this->error(__('The parent group can not be its own child')); } $params['rules'] = explode(',', $params['rules']); $parentmodel = model("AuthGroup")->get($params['pid']); if (!$parentmodel) { - $this->msg = __('The parent group can not found'); - return; + $this->error(__('The parent group can not found')); } // 父级别的规则节点 $parentrules = explode(',', $parentmodel->rules); // 当前组别的规则节点 $currentrules = $this->auth->getRuleIds(); $rules = $params['rules']; + $rules = $params['rules']; // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限 $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules); // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限 @@ -154,9 +146,9 @@ class Group extends Backend if ($params) { $row->save($params); - $this->code = 1; + $this->success(); } - + $this->error(); return; } $this->view->assign("row", $row); @@ -168,7 +160,6 @@ class Group extends Backend */ public function del($ids = "") { - $this->code = -1; if ($ids) { $ids = explode(',', $ids); @@ -201,16 +192,15 @@ class Group extends Backend } if (!$ids) { - $this->msg = __('You can not delete group that contain child group and administrators'); - return; + $this->error(__('You can not delete group that contain child group and administrators')); } $count = $this->model->where('id', 'in', $ids)->delete(); if ($count) { - $this->code = 1; + $this->success(); } } - return; + $this->error(); } /** @@ -220,8 +210,7 @@ class Group extends Backend public function multi($ids = "") { // 组别禁止批量操作 - $this->code = -1; - return; + $this->error(); } /** @@ -291,19 +280,16 @@ class Group extends Backend $state = array('selected' => in_array($v['id'], $current_rule_ids) && !in_array($v['id'], $hasChildrens)); $nodelist[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state); } - $this->code = 1; - $this->data = $nodelist; + $this->success('',null,$nodelist); } else { - $this->code = -1; - $this->data = __('Can not change the parent to child'); + $this->error(__('Can not change the parent to child')); } } else { - $this->code = -1; - $this->data = __('Group not found'); + $this->error(__('Group not found')); } } diff --git a/application/admin/controller/auth/Rule.php b/application/admin/controller/auth/Rule.php index a77c9c97..48a51ace 100644 --- a/application/admin/controller/auth/Rule.php +++ b/application/admin/controller/auth/Rule.php @@ -60,21 +60,18 @@ class Rule extends Backend { if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a", [], 'strip_tags'); if ($params) { if (!$params['ismenu'] && !$params['pid']) { - $this->msg = __('The non-menu rule must have parent'); - return; + $this->error(__('The non-menu rule must have parent')); } $this->model->create($params); Cache::rm('__menu__'); - $this->code = 1; + $this->success(); } - - return; + $this->error(); } return $this->view->fetch(); } @@ -89,21 +86,18 @@ class Rule extends Backend $this->error(__('No Results were found')); if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a", [], 'strip_tags'); if ($params) { if (!$params['ismenu'] && !$params['pid']) { - $this->msg = __('The non-menu rule must have parent'); - return; + $this->error(__('The non-menu rule must have parent')); } $row->save($params); Cache::rm('__menu__'); - $this->code = 1; + $this->success(); } - - return; + $this->error(); } $this->view->assign("row", $row); return $this->view->fetch(); @@ -114,7 +108,6 @@ class Rule extends Backend */ public function del($ids = "") { - $this->code = -1; if ($ids) { $delIds = []; @@ -127,11 +120,10 @@ class Rule extends Backend if ($count) { Cache::rm('__menu__'); - $this->code = 1; + $this->success(); } } - - return; + $this->error(); } } diff --git a/application/admin/controller/example/Bootstraptable.php b/application/admin/controller/example/Bootstraptable.php deleted file mode 100644 index 914c84e1..00000000 --- a/application/admin/controller/example/Bootstraptable.php +++ /dev/null @@ -1,70 +0,0 @@ -model = model('AdminLog'); - } - - /** - * 查看 - */ - public function index() - { - if ($this->request->isAjax()) - { - list($where, $sort, $order, $offset, $limit) = $this->buildparams(NULL); - $total = $this->model - ->where($where) - ->order($sort, $order) - ->count(); - $list = $this->model - ->where($where) - ->order($sort, $order) - ->limit($offset, $limit) - ->select(); - $result = array("total" => $total, "rows" => $list); - - return json($result); - } - return $this->view->fetch(); - } - - /** - * 详情 - */ - public function detail($ids) - { - $row = $this->model->get(['id' => $ids]); - if (!$row) - $this->error(__('No Results were found')); - $this->view->assign("row", $row->toArray()); - return $this->view->fetch(); - } - - /** - * 变更 - * @internal - */ - public function change() - { - $this->code = 1; - } - -} diff --git a/application/admin/controller/example/Colorbadge.php b/application/admin/controller/example/Colorbadge.php deleted file mode 100644 index 4d0bc213..00000000 --- a/application/admin/controller/example/Colorbadge.php +++ /dev/null @@ -1,24 +0,0 @@ -model = model('AdminLog'); - } - -} diff --git a/application/admin/controller/example/Controllerjump.php b/application/admin/controller/example/Controllerjump.php deleted file mode 100644 index 2bd1540e..00000000 --- a/application/admin/controller/example/Controllerjump.php +++ /dev/null @@ -1,24 +0,0 @@ -model = model('AdminLog'); - } - -} diff --git a/application/admin/controller/example/Cxselect.php b/application/admin/controller/example/Cxselect.php deleted file mode 100644 index 391c0977..00000000 --- a/application/admin/controller/example/Cxselect.php +++ /dev/null @@ -1,23 +0,0 @@ -loadlang('general/attachment'); - $this->loadlang('general/crontab'); - return $this->view->fetch(); - } - -} diff --git a/application/admin/controller/example/Relationmodel.php b/application/admin/controller/example/Relationmodel.php deleted file mode 100644 index ae42b769..00000000 --- a/application/admin/controller/example/Relationmodel.php +++ /dev/null @@ -1,52 +0,0 @@ -model = model('AdminLog'); - } - - /** - * 查看 - */ - public function index() - { - $this->relationSearch = true; - $this->searchFields = "admin.username,id"; - if ($this->request->isAjax()) - { - list($where, $sort, $order, $offset, $limit) = $this->buildparams(); - $total = $this->model - ->with("admin") - ->where($where) - ->order($sort, $order) - ->count(); - $list = $this->model - ->with("admin") - ->where($where) - ->order($sort, $order) - ->limit($offset, $limit) - ->select(); - $result = array("total" => $total, "rows" => $list); - - return json($result); - } - return $this->view->fetch(); - } - -} diff --git a/application/admin/controller/example/Tabletemplate.php b/application/admin/controller/example/Tabletemplate.php deleted file mode 100644 index fcc5c35f..00000000 --- a/application/admin/controller/example/Tabletemplate.php +++ /dev/null @@ -1,60 +0,0 @@ -model = model('AdminLog'); - } - - /** - * 查看 - */ - public function index() - { - if ($this->request->isAjax()) - { - list($where, $sort, $order, $offset, $limit) = $this->buildparams(NULL); - $total = $this->model - ->where($where) - ->order($sort, $order) - ->count(); - $list = $this->model - ->where($where) - ->order($sort, $order) - ->limit($offset, $limit) - ->select(); - $result = array("total" => $total, "rows" => $list); - - return json($result); - } - return $this->view->fetch(); - } - - /** - * 详情 - */ - public function detail($ids) - { - $row = $this->model->get(['id' => $ids]); - if (!$row) - $this->error(__('No Results were found')); - $this->view->assign("row", $row->toArray()); - return $this->view->fetch(); - } - -} diff --git a/application/admin/controller/general/Attachment.php b/application/admin/controller/general/Attachment.php index cb549ffd..6f5a1696 100644 --- a/application/admin/controller/general/Attachment.php +++ b/application/admin/controller/general/Attachment.php @@ -71,9 +71,23 @@ class Attachment extends Backend { if ($this->request->isAjax()) { - $this->code = -1; + $this->error(); } return $this->view->fetch(); } + public function del($ids = "") + { + if ($ids) + { + $count = $this->model->destroy($ids); + if ($count) + { + \think\Hook::listen("upload_after", $this); + $this->success(); + } + } + $this->error(__('Parameter %s can not be empty', 'ids')); + } + } diff --git a/application/admin/controller/general/Config.php b/application/admin/controller/general/Config.php index ef634058..16c367d3 100644 --- a/application/admin/controller/general/Config.php +++ b/application/admin/controller/general/Config.php @@ -72,7 +72,6 @@ class Config extends Backend { if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a"); if ($params) { @@ -106,36 +105,30 @@ class Config extends Backend try { $this->refreshFile(); - $this->code = 1; + $this->success(); } catch (Exception $e) { - $this->msg = $e->getMessage(); + $this->error($e->getMessage()); } } else { - $this->msg = $this->model->getError(); + $this->error($this->model->getError()); } } catch (Exception $e) { - $this->msg = $e->getMessage(); + $this->error($e->getMessage()); } } - else - { - $this->msg = __('Parameter %s can not be empty', ''); - } - - return; + $this->error(__('Parameter %s can not be empty', '')); } return $this->view->fetch(); } public function edit($ids = NULL) { - $this->code = -1; if ($this->request->isPost()) { $params = $this->request->post("row/a"); @@ -175,19 +168,14 @@ class Config extends Backend try { $this->refreshFile(); - $this->code = 1; + $this->success(); } catch (Exception $e) { - $this->msg = $e->getMessage(); + $this->error($e->getMessage()); } } - else - { - $this->msg = __('Parameter %s can not be empty', ''); - } - - return; + $this->error(__('Parameter %s can not be empty', '')); } } @@ -251,12 +239,11 @@ class Config extends Backend ->send(); if ($result) { - $this->code = 1; + $this->success(); } else { - $this->code = -1; - $this->msg = $email->getError(); + $this->error($email->getError()); } } diff --git a/application/admin/controller/general/Crontab.php b/application/admin/controller/general/Crontab.php deleted file mode 100644 index 73dfdd08..00000000 --- a/application/admin/controller/general/Crontab.php +++ /dev/null @@ -1,100 +0,0 @@ -model = model('Crontab'); - $this->view->assign('typedata', \app\common\model\Crontab::getTypeList()); - } - - /** - * 查看 - */ - public function index() - { - if ($this->request->isAjax()) - { - list($where, $sort, $order, $offset, $limit) = $this->buildparams(); - $total = $this->model - ->where($where) - ->order($sort, $order) - ->count(); - - $list = $this->model - ->where($where) - ->order($sort, $order) - ->limit($offset, $limit) - ->select(); - foreach ($list as $k => &$v) - { - $cron = CronExpression::factory($v['schedule']); - $v['nexttime'] = $cron->getNextRunDate()->getTimestamp(); - } - $result = array("total" => $total, "rows" => $list); - - return json($result); - } - return $this->view->fetch(); - } - - /** - * 判断Crontab格式是否正确 - * @internal - */ - public function check_schedule() - { - $row = $this->request->post("row/a"); - $schedule = isset($row['schedule']) ? $row['schedule'] : ''; - if (CronExpression::isValidExpression($schedule)) - { - return json(['ok' => '']); - } - else - { - return json(['error' => __('Crontab format invalid')]); - } - } - - /** - * 根据Crontab表达式读取未来七次的时间 - * @internal - */ - public function get_schedule_future() - { - $time = []; - $schedule = $this->request->post('schedule'); - $days = (int) $this->request->post('days'); - try - { - $cron = CronExpression::factory($schedule); - for ($i = 0; $i < $days; $i++) - { - $time[] = $cron->getNextRunDate(null, $i)->format('Y-m-d H:i:s'); - } - } - catch (\Exception $e) - { - - } - - return json(['futuretime' => $time]); - } - -} diff --git a/application/admin/controller/general/Database.php b/application/admin/controller/general/Database.php deleted file mode 100644 index 2d31a014..00000000 --- a/application/admin/controller/general/Database.php +++ /dev/null @@ -1,211 +0,0 @@ - $row) - { - $tables[] = ['name' => reset($row), 'rows' => 0]; - } - $data['tables'] = $tables; - $data['saved_sql'] = []; - $this->view->assign($data); - return $this->view->fetch(); - } - - /** - * SQL查询 - */ - public function query() - { - $do_action = $this->request->post('do_action'); - - echo ''; - if ($do_action == '') - exit(__('Invalid parameters')); - - $tablename = $this->request->post("tablename/a"); - - if (in_array($do_action, array('doquery', 'optimizeall', 'repairall'))) - { - $this->$do_action(); - } - else if (count($tablename) == 0) - { - exit(__('Invalid parameters')); - } - else - { - foreach ($tablename as $table) - { - $this->$do_action($table); - echo "
"; - } - } - } - - private function viewinfo($name) - { - $row = Db::query("SHOW CREATE TABLE `{$name}`"); - $row = array_values($row[0]); - $info = $row[1]; - echo "{$info};"; - } - - private function viewdata($name = '') - { - $sqlquery = "SELECT * FROM `{$name}`"; - $this->doquery($sqlquery); - } - - private function optimize($name = '') - { - if (Db::execute("OPTIMIZE TABLE `{$name}`")) - { - echo __('Optimize table %s done', $name); - } - else - { - echo __('Optimize table %s fail', $name); - } - } - - private function optimizeall($name = '') - { - $list = Db::query("SHOW TABLES"); - foreach ($list as $key => $row) - { - $name = reset($row); - if (Db::execute("OPTIMIZE TABLE {$name}")) - { - echo __('Optimize table %s done', $name); - } - else - { - echo __('Optimize table %s fail', $name); - } - echo "
"; - } - } - - private function repair($name = '') - { - if (Db::execute("REPAIR TABLE `{$name}`")) - { - echo __('Repair table %s done', $name); - } - else - { - echo __('Repair table %s fail', $name); - } - } - - private function repairall($name = '') - { - $list = Db::query("SHOW TABLES"); - foreach ($list as $key => $row) - { - $name = reset($row); - if (Db::execute("REPAIR TABLE {$name}")) - { - echo __('Repair table %s done', $name); - } - else - { - echo __('Repair table %s fail', $name); - } - echo "
"; - } - } - - private function doquery($sql = null) - { - $sqlquery = $sql ? $sql : $this->request->post('sqlquery'); - if ($sqlquery == '') - exit(__('SQL can not be empty')); - $sqlquery = str_replace("\r", "", $sqlquery); - $sqls = preg_split("/;[ \t]{0,}\n/i", $sqlquery); - $maxreturn = 100; - $r = ''; - foreach ($sqls as $key => $val) - { - if (trim($val) == '') - continue; - $val = rtrim($val, ';'); - $r .= "SQL:{$val} "; - if (preg_match("/^(select|explain)(.*)/i ", $val)) - { - Debug::remark("begin"); - $limit = stripos(strtolower($val), "limit") !== false ? true : false; - $count = Db::execute($val); - if ($count > 0) - { - $resultlist = Db::query($val . (!$limit && $count > $maxreturn ? ' LIMIT ' . $maxreturn : '')); - } - else - { - $resultlist = []; - } - Debug::remark("end"); - $time = Debug::getRangeTime('begin', 'end', 4); - - $usedseconds = __('Query took %s seconds', $time) . "
"; - if ($count <= 0) - { - $r .= __('Query returned an empty result'); - } - else - { - $r .= (__('Total:%s', $count) . (!$limit && $count > $maxreturn ? ',' . __('Max output:%s', $maxreturn) : "")); - } - $r = $r . ',' . $usedseconds; - $j = 0; - foreach ($resultlist as $m => $n) - { - $j++; - if (!$limit && $j > $maxreturn) - break; - $r .= "
"; - $r .= "" . __('Row:%s', $j) . "
"; - foreach ($n as $k => $v) - { - $r .= "{$k}:{$v}
\r\n"; - } - } - } - else - { - Debug::remark("begin"); - $count = Db::execute($val); - Debug::remark("end"); - $time = Debug::getRangeTime('begin', 'end', 4); - $r .= __('Query affected %s rows and took %s seconds', $count, $time) . "
"; - } - } - echo $r; - } - -} diff --git a/application/admin/controller/general/Profile.php b/application/admin/controller/general/Profile.php index 39344b19..3189d7c8 100644 --- a/application/admin/controller/general/Profile.php +++ b/application/admin/controller/general/Profile.php @@ -52,7 +52,6 @@ class Profile extends Backend { if ($this->request->isPost()) { - $this->code = -1; $params = $this->request->post("row/a"); $params = array_filter(array_intersect_key($params, array_flip(array('email', 'nickname', 'password', 'avatar')))); unset($v); @@ -71,8 +70,9 @@ class Profile extends Backend $admin = model('admin')->get(['id' => $admin_id]); Session::set("admin", $admin); } - $this->code = 1; + $this->success(); } + $this->error(); } return; } diff --git a/application/admin/controller/wechat/Autoreply.php b/application/admin/controller/wechat/Autoreply.php deleted file mode 100644 index 0de21275..00000000 --- a/application/admin/controller/wechat/Autoreply.php +++ /dev/null @@ -1,74 +0,0 @@ -model = model('WechatAutoreply'); - } - - /** - * 编辑 - */ - public function edit($ids = NULL) - { - $row = $this->model->get(['id' => $ids]); - if (!$row) - $this->error(__('No Results were found')); - if ($this->request->isPost()) - { - $this->code = -1; - $params = $this->request->post("row/a"); - if ($params) - { - $row->save($params); - $this->code = 1; - } - return; - } - $response = WechatResponse::get(['eventkey' => $row['eventkey']]); - $this->view->assign("response", $response); - $this->view->assign("row", $row); - return $this->view->fetch(); - } - - /** - * 判断文本是否唯一 - * @internal - */ - public function check_text_unique() - { - $row = $this->request->post("row/a"); - $except = $this->request->post("except"); - $text = isset($row['text']) ? $row['text'] : ''; - if ($this->model->where('text', $text)->where(function($query) use($except) { - if ($except) - { - $query->where('text', '<>', $except); - } - })->count() == 0) - { - return json(['ok' => '']); - } - else - { - return json(['error' => __('Text already exists')]); - } - } - -} diff --git a/application/admin/controller/wechat/Config.php b/application/admin/controller/wechat/Config.php deleted file mode 100644 index bf9af55d..00000000 --- a/application/admin/controller/wechat/Config.php +++ /dev/null @@ -1,164 +0,0 @@ -model = model('WechatConfig'); - } - - /** - * 添加 - */ - public function add() - { - if ($this->request->isPost()) - { - $this->code = -1; - $params = $this->request->post("row/a"); - if ($params) - { - foreach ($params as $k => &$v) - { - $v = is_array($v) ? implode(',', $v) : $v; - } - - if ($params['mode'] == 'json') - { - //JSON字段 - $fieldarr = $valuearr = []; - $field = $this->request->post('field/a'); - $value = $this->request->post('value/a'); - foreach ($field as $k => $v) - { - if ($v != '') - { - $fieldarr[] = $field[$k]; - $valuearr[] = $value[$k]; - } - } - $params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE); - } - unset($params['mode']); - try - { - //是否采用模型验证 - if ($this->modelValidate) - { - $name = basename(str_replace('\\', '/', get_class($this->model))); - $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; - $this->model->validate($validate); - } - $result = $this->model->save($params); - if ($result !== false) - { - $this->code = 1; - } - else - { - $this->msg = $this->model->getError(); - } - } - catch (\think\exception\PDOException $e) - { - $this->msg = $e->getMessage(); - } - } - else - { - $this->msg = __('Parameter %s can not be empty', ''); - } - - return; - } - return $this->view->fetch(); - } - - /** - * 编辑 - */ - public function edit($ids = NULL) - { - $row = $this->model->get($ids); - if (!$row) - $this->error(__('No Results were found')); - if ($this->request->isPost()) - { - $this->code = -1; - $params = $this->request->post("row/a"); - if ($params) - { - foreach ($params as $k => &$v) - { - $v = is_array($v) ? implode(',', $v) : $v; - } - - if ($params['mode'] == 'json') - { - //JSON字段 - $fieldarr = $valuearr = []; - $field = $this->request->post('field/a'); - $value = $this->request->post('value/a'); - foreach ($field as $k => $v) - { - if ($v != '') - { - $fieldarr[] = $field[$k]; - $valuearr[] = $value[$k]; - } - } - $params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE); - } - unset($params['mode']); - try - { - //是否采用模型验证 - if ($this->modelValidate) - { - $name = basename(str_replace('\\', '/', get_class($this->model))); - $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; - $row->validate($validate); - } - $result = $row->save($params); - if ($result !== false) - { - $this->code = 1; - } - else - { - $this->msg = $row->getError(); - } - } - catch (think\exception\PDOException $e) - { - $this->msg = $e->getMessage(); - } - } - else - { - $this->msg = __('Parameter %s can not be empty', ''); - } - - return; - } - $this->view->assign("row", $row); - $this->view->assign("value", (array) json_decode($row->value, true)); - return $this->view->fetch(); - } - -} diff --git a/application/admin/controller/wechat/Menu.php b/application/admin/controller/wechat/Menu.php deleted file mode 100644 index 1a1b7132..00000000 --- a/application/admin/controller/wechat/Menu.php +++ /dev/null @@ -1,111 +0,0 @@ -wechatcfg = \app\common\model\WechatConfig::get(['name' => 'menu']); - } - - /** - * 查看 - */ - public function index() - { - $responselist = array(); - $all = WechatResponse::all(); - foreach ($all as $k => $v) - { - $responselist[$v['eventkey']] = $v['title']; - } - $this->view->assign('responselist', $responselist); - $this->view->assign('menu', (array) json_decode($this->wechatcfg->value, TRUE)); - return $this->view->fetch(); - } - - /** - * 修改 - */ - public function edit($ids = NULL) - { - $menu = $this->request->post("menu"); - $menu = (array) json_decode($menu, TRUE); - $this->wechatcfg->value = json_encode($menu, JSON_UNESCAPED_UNICODE); - $this->wechatcfg->save(); - $this->code = 1; - return; - } - - /** - * 同步 - */ - public function sync($ids = NULL) - { - $this->code = -1; - $app = new Application(Config::get('wechat')); - - try - { - $hasError = false; - $menu = json_decode($this->wechatcfg->value, TRUE); - foreach ($menu as $k => $v) - { - if (isset($v['sub_button'])) - { - foreach ($v['sub_button'] as $m => $n) - { - if (isset($n['key']) && !$n['key']) - { - $hasError = true; - break 2; - } - } - } - else if (isset($v['key']) && !$v['key']) - { - $hasError = true; - break; - } - } - if (!$hasError) - { - $ret = $app->menu->add($menu); - if ($ret->errcode == 0) - { - $this->code = 1; - } - else - { - $this->msg = $ret->errmsg; - } - } - else - { - $this->msg = __('Invalid parameters'); - } - } - catch (Exception $e) - { - $this->msg = $e->getMessage(); - } - return; - } - -} diff --git a/application/admin/controller/wechat/Response.php b/application/admin/controller/wechat/Response.php deleted file mode 100644 index d1bbb1a7..00000000 --- a/application/admin/controller/wechat/Response.php +++ /dev/null @@ -1,86 +0,0 @@ -model = model('WechatResponse'); - } - - /** - * 选择素材 - */ - public function select() - { - return $this->view->fetch(); - } - - /** - * 添加 - */ - public function add() - { - if ($this->request->isPost()) - { - $this->code = -1; - $params = $this->request->post("row/a"); - $params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid(); - $params['content'] = json_encode($params['content']); - $params['createtime'] = time(); - if ($params) - { - $this->model->save($params); - $this->code = 1; - $this->content = $params; - } - - return; - } - $appConfig = Wechat::appConfig(); - $this->view->applist = $appConfig; - return $this->view->fetch(); - } - - /** - * 编辑 - */ - public function edit($ids = NULL) - { - $row = $this->model->get($ids); - if (!$row) - $this->error(__('No Results were found')); - if ($this->request->isPost()) - { - $this->code = -1; - $params = $this->request->post("row/a"); - $params['eventkey'] = isset($params['eventkey']) && $params['eventkey'] ? $params['eventkey'] : uniqid(); - $params['content'] = json_encode($params['content']); - if ($params) - { - $row->save($params); - $this->code = 1; - } - return; - } - $this->view->assign("row", $row); - $appConfig = Wechat::appConfig(); - $this->view->applist = $appConfig; - return $this->view->fetch(); - } - -} diff --git a/application/admin/lang/zh-cn/addon.php b/application/admin/lang/zh-cn/addon.php new file mode 100644 index 00000000..8a438075 --- /dev/null +++ b/application/admin/lang/zh-cn/addon.php @@ -0,0 +1,9 @@ + 'ID', + 'Title' => '标题', + 'Value' => '配置值', + 'Array key' => '键', + 'Array value' => '值', +]; diff --git a/application/admin/lang/zh-cn/general/crontab.php b/application/admin/lang/zh-cn/general/crontab.php deleted file mode 100644 index 041aab78..00000000 --- a/application/admin/lang/zh-cn/general/crontab.php +++ /dev/null @@ -1,16 +0,0 @@ - '任务标题', - 'Maximums' => '最多执行', - 'Sleep' => '延迟秒数', - 'Schedule' => '执行周期', - 'Executes' => '执行次数', - 'Execute time' => '最后执行时间', - 'Request Url' => '请求URL', - 'Execute Sql Script' => '执行SQL', - 'Execute Shell' => '执行Shell', - 'Crontab format invalid' => 'Crontab格式错误', - 'Next execute time' => '下次预计时间', - 'The next %s times the execution time' => '接下来 %s 次的执行时间', -]; diff --git a/application/admin/lang/zh-cn/general/database.php b/application/admin/lang/zh-cn/general/database.php deleted file mode 100644 index 1defa653..00000000 --- a/application/admin/lang/zh-cn/general/database.php +++ /dev/null @@ -1,30 +0,0 @@ - '查询结果', - 'Basic query' => '基础查询', - 'View structure' => '查看表结构', - 'View data' => '查看表数据', - 'Optimize' => '优化表', - 'Repair' => '修复表', - 'Optimize all' => '优化全部表', - 'Repair all' => '修复全部表', - 'Table:%s' => '总计:%s个表', - 'Record:%s' => '记录:%s条', - 'Data:%s' => '占用:%s', - 'Index:%s' => '索引:%s', - 'SQL Result:' => '查询结果:', - 'SQL can not be empty' => 'SQL语句不能为空', - 'Max output:%s' => '最大返回%s条', - 'Total:%s' => '共有%s条记录! ', - 'Row:%s' => '记录:%s', - 'Executes one or multiple queries which are concatenated by a semicolon' => '请输入SQL语句,支持批量查询,多条SQL以分号(;)分格', - 'Query affected %s rows and took %s seconds' => '共影响%s条记录! 耗时:%s秒!', - 'Query returned an empty result' => '返回结果为空!', - 'Query took %s seconds' => '耗时%s秒!', - 'Optimize table %s done' => '优化表[%s]成功', - 'Repair table %s done' => '修复表[%s]成功', - 'Optimize table %s fail' => '优化表[%s]失败', - 'Repair table %s fail' => '修复表[%s]失败' -]; - diff --git a/application/admin/lang/zh-cn/index.php b/application/admin/lang/zh-cn/index.php index c4b76fd9..9bba7d10 100644 --- a/application/admin/lang/zh-cn/index.php +++ b/application/admin/lang/zh-cn/index.php @@ -31,4 +31,8 @@ return [ 'Verification code is incorrect' => '验证码不正确', 'Wipe cache completed' => '清除缓存成功', 'Wipe cache failed' => '清除缓存失败', + 'Wipe cache' => '清空缓存', + 'Check for updates' => '检测更新', + 'Latest news' => '最新消息', + 'View more' => '查看更多', ]; diff --git a/application/admin/lang/zh-cn/page.php b/application/admin/lang/zh-cn/page.php deleted file mode 100644 index 852303d0..00000000 --- a/application/admin/lang/zh-cn/page.php +++ /dev/null @@ -1,17 +0,0 @@ - 'ID', - 'category_id' => '分类ID', - 'category' => '分类', - 'title' => '标题', - 'keywords' => '关键字', - 'flag' => '标志', - 'image' => '头像', - 'content' => '内容', - 'icon' => '图标', - 'views' => '点击', - 'comments' => '评论', - 'weigh' => '权重', - 'status' => '状态' -]; diff --git a/application/admin/lang/zh-cn/version.php b/application/admin/lang/zh-cn/version.php deleted file mode 100644 index ce752693..00000000 --- a/application/admin/lang/zh-cn/version.php +++ /dev/null @@ -1,15 +0,0 @@ - 'ID', - 'oldversion' => '旧版本号', - 'newversion' => '新版本号', - 'packagesize' => '包大小', - 'content' => '升级内容', - 'downloadurl' => '下载地址', - 'enforce' => '强制更新', - 'createtime' => '创建时间', - 'updatetime' => '更新时间', - 'weigh' => '权重', - 'status' => '状态' -]; diff --git a/application/admin/lang/zh-cn/wechat/autoreply.php b/application/admin/lang/zh-cn/wechat/autoreply.php deleted file mode 100644 index 6ba7061c..00000000 --- a/application/admin/lang/zh-cn/wechat/autoreply.php +++ /dev/null @@ -1,8 +0,0 @@ - '文本', - 'Event key' => '响应标识', - 'Remark' => '备注', - 'Text already exists' => '文本已经存在', -]; diff --git a/application/admin/lang/zh-cn/wechat/config.php b/application/admin/lang/zh-cn/wechat/config.php deleted file mode 100644 index fbbd04a1..00000000 --- a/application/admin/lang/zh-cn/wechat/config.php +++ /dev/null @@ -1,10 +0,0 @@ - '配置名称', - 'value' => '配置值', - 'Json key' => '键', - 'Json value' => '值', - 'createtime' => '创建时间', - 'updatetime' => '更新时间' -]; diff --git a/application/admin/lang/zh-cn/wechat/response.php b/application/admin/lang/zh-cn/wechat/response.php deleted file mode 100644 index 37bb3bd7..00000000 --- a/application/admin/lang/zh-cn/wechat/response.php +++ /dev/null @@ -1,8 +0,0 @@ - '资源标题', - 'Event key' => '事件标识', - 'Text' => '文本', - 'App' => '应用', -]; diff --git a/application/admin/library/Auth.php b/application/admin/library/Auth.php index 145298fc..0b1b299d 100644 --- a/application/admin/library/Auth.php +++ b/application/admin/library/Auth.php @@ -244,14 +244,8 @@ class Auth extends \fast\Auth // 生成菜单的badge foreach ($params as $k => $v) { - if (stripos($k, '/') === false) - { - $url = '/' . $module . '/' . $k; - } - else - { - $url = url($k); - } + + $url = $k; if (is_array($v)) { @@ -275,7 +269,6 @@ class Auth extends \fast\Auth // 读取管理员当前拥有的权限节点 $userRule = $this->getRuleList(); $select_id = 0; - $activeUrl = '/' . $module . '/' . $fixedPage; // 必须将结果集转换为数组 $ruleList = collection(model('AuthRule')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray(); foreach ($ruleList as $k => &$v) @@ -285,8 +278,8 @@ class Auth extends \fast\Auth unset($ruleList[$k]); continue; } - $select_id = $v['name'] == $activeUrl ? $v['id'] : $select_id; - $v['url'] = $v['name']; + $select_id = $v['name'] == $fixedPage ? $v['id'] : $select_id; + $v['url'] = '/' . $module . '/' . $v['name']; $v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : ''; $v['py'] = \fast\Pinyin::get($v['title'], true); $v['pinyin'] = \fast\Pinyin::get($v['title']); diff --git a/application/admin/model/Config.php b/application/admin/model/Config.php deleted file mode 100644 index cec8a769..00000000 --- a/application/admin/model/Config.php +++ /dev/null @@ -1,55 +0,0 @@ - __('String'), - 'text' => __('Text'), - 'number' => __('Number'), - 'datetime' => __('Datetime'), - 'select' => __('Select'), - 'selects' => __('Selects'), - 'image' => __('Image'), - 'images' => __('Images'), - 'file' => __('File'), - 'files' => __('Files'), - 'checkbox' => __('Checkbox'), - 'radio' => __('Radio'), - 'array' => __('Array'), - ]; - return $typeList; - } - - /** - * 读取分类分组列表 - * @return array - */ - public static function getGroupList() - { - $groupList = config('site.configgroup'); - return $groupList; - } - -} diff --git a/application/admin/view/add.html b/application/admin/view/add.html deleted file mode 100644 index 746d0090..00000000 --- a/application/admin/view/add.html +++ /dev/null @@ -1,203 +0,0 @@ -
- -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- - - -
-
-
- -
- - - -
-
-
- -
- - {foreach name="genderdataList" item="vo"} - - {/foreach} - -
-
-
- -
- - {foreach name="hobbydataList" item="vo"} - - {/foreach} - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
- - - -
    -
    -
    -
    -
    - -
    -
    - - - -
      -
      -
      -
      -
      - -
      -
      - - - - -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - - {foreach name="statusList" item="vo"} - - {/foreach} - -
      -
      -
      - -
      - - {foreach name="stateList" item="vo"} - - {/foreach} - -
      -
      - -
      diff --git a/application/admin/view/addon/add.html b/application/admin/view/addon/add.html new file mode 100644 index 00000000..6900e4fb --- /dev/null +++ b/application/admin/view/addon/add.html @@ -0,0 +1,22 @@ +
      + +
      + +
      + +
      +
      +
      + +
      + +
      +
      + +
      diff --git a/application/admin/view/addon/config.html b/application/admin/view/addon/config.html new file mode 100644 index 00000000..e780dc8a --- /dev/null +++ b/application/admin/view/addon/config.html @@ -0,0 +1,102 @@ +
      + + + + + + + + + {foreach $addon.config as $item} + + + + + {/foreach} + +
      {:__('Title')}{:__('Value')}
      {$item.title} +
      +
      + {switch $item.type} + {case string} + + {/case} + {case text} + + {/case} + {case array} +
      +
      + {:__('Array key')} + {:__('Array value')} +
      + {foreach $item.value as $key => $vo} +
      + + + + +
      + {/foreach} +
      {:__('Append')}
      +
      + {/case} + {case datetime} + + {/case} + {case number} + + {/case} + {case checkbox} + {foreach name="item.content" item="vo"} + + {/foreach} + {/case} + {case radio} + {foreach name="item.content" item="vo"} + + {/foreach} + {/case} + {case value="select" break="0"}{/case} + {case value="selects"} + + {/case} + {case value="image" break="0"}{/case} + {case value="images"} +
      + + + +
        +
        + {/case} + {case value="file" break="0"}{/case} + {case value="files"} +
        + + + +
        + {/case} + {case bool} + + + {/case} + {/switch} +
        +
        +
        + +
        + +
        \ No newline at end of file diff --git a/application/admin/view/addon/index.html b/application/admin/view/addon/index.html new file mode 100644 index 00000000..a4712ea7 --- /dev/null +++ b/application/admin/view/addon/index.html @@ -0,0 +1,120 @@ + +
        + {:build_heading()} + +
        +
        +
        +
        +
        + {:build_toolbar('refresh')} + + {:__('刷新插件缓存')} +
        + + +
        + +
        +
        + +
        +
        +
        + + + \ No newline at end of file diff --git a/application/admin/view/auth/admin/index.html b/application/admin/view/auth/admin/index.html index a44c5627..9e3f7940 100644 --- a/application/admin/view/auth/admin/index.html +++ b/application/admin/view/auth/admin/index.html @@ -6,7 +6,7 @@
        - {:build_toolbar()} + {:build_toolbar('refresh,add,delete')}
        diff --git a/application/admin/view/auth/group/add.html b/application/admin/view/auth/group/add.html index 5e2aa8b2..406a5b93 100644 --- a/application/admin/view/auth/group/add.html +++ b/application/admin/view/auth/group/add.html @@ -1,4 +1,4 @@ - +
        diff --git a/application/admin/view/auth/group/edit.html b/application/admin/view/auth/group/edit.html index e7b433b2..fbd76fe1 100644 --- a/application/admin/view/auth/group/edit.html +++ b/application/admin/view/auth/group/edit.html @@ -1,4 +1,4 @@ - +
        diff --git a/application/admin/view/auth/group/index.html b/application/admin/view/auth/group/index.html index 8832095f..327313d8 100644 --- a/application/admin/view/auth/group/index.html +++ b/application/admin/view/auth/group/index.html @@ -6,7 +6,7 @@
        - {:build_toolbar()} + {:build_toolbar('refresh,add,delete')}
        diff --git a/application/admin/view/category/add.html b/application/admin/view/category/add.html index 7ab24afa..f8ca6c42 100644 --- a/application/admin/view/category/add.html +++ b/application/admin/view/category/add.html @@ -3,10 +3,10 @@
        - - {foreach name="typeList" item="vo"} - + {/foreach} @@ -15,10 +15,10 @@
        - - {foreach name="parentList" item="vo"} - + {/foreach} @@ -39,10 +39,10 @@
        - + diff --git a/application/admin/view/category/edit.html b/application/admin/view/category/edit.html index eb9403e1..d0ae2750 100644 --- a/application/admin/view/category/edit.html +++ b/application/admin/view/category/edit.html @@ -3,10 +3,10 @@
        - - {foreach name="typeList" item="vo"} - + {/foreach} @@ -15,10 +15,10 @@
        - - {foreach name="parentList" item="vo"} - + {/foreach} @@ -39,10 +39,10 @@
        - + diff --git a/application/admin/view/common/header.html b/application/admin/view/common/header.html index da3e9dd8..49f8cebe 100644 --- a/application/admin/view/common/header.html +++ b/application/admin/view/common/header.html @@ -38,28 +38,18 @@ - + - - - +
      • - + + + +
      • + +
      • +
      • @@ -113,10 +103,10 @@ diff --git a/application/admin/view/common/menu.html b/application/admin/view/common/menu.html index 5874fb10..9f8b109f 100644 --- a/application/admin/view/common/menu.html +++ b/application/admin/view/common/menu.html @@ -29,6 +29,10 @@ \ No newline at end of file diff --git a/application/admin/view/edit.html b/application/admin/view/edit.html deleted file mode 100644 index 6e00ce6c..00000000 --- a/application/admin/view/edit.html +++ /dev/null @@ -1,203 +0,0 @@ - - -
        - -
        - -
        -
        -
        - -
        - -
        -
        -
        - -
        - -
        -
        -
        - -
        - -
        -
        -
        - -
        - - - -
        -
        -
        - -
        - - - -
        -
        -
        - -
        - - {foreach name="genderdataList" item="vo"} - - {/foreach} - -
        -
        -
        - -
        - - {foreach name="hobbydataList" item="vo"} - - {/foreach} - -
        -
        -
        - -
        - -
        -
        -
        - -
        - -
        -
        -
        - -
        -
        - - - -
          -
          -
          -
          -
          - -
          -
          - - - -
            -
            -
            -
            -
            - -
            -
            - - - - -
            -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - - {foreach name="statusList" item="vo"} - - {/foreach} - -
            -
            -
            - -
            - - {foreach name="stateList" item="vo"} - - {/foreach} - -
            -
            - - diff --git a/application/admin/view/example/bootstraptable/detail.html b/application/admin/view/example/bootstraptable/detail.html deleted file mode 100644 index 07c0ee51..00000000 --- a/application/admin/view/example/bootstraptable/detail.html +++ /dev/null @@ -1,22 +0,0 @@ -
            - - - - - - - - {volist name="row" id="vo" } - - - - - {/volist} - -
            {:__('Title')}{:__('Content')}
            {$key}{$vo}
            - \ No newline at end of file diff --git a/application/admin/view/example/bootstraptable/index.html b/application/admin/view/example/bootstraptable/index.html deleted file mode 100644 index 81e78ec6..00000000 --- a/application/admin/view/example/bootstraptable/index.html +++ /dev/null @@ -1,31 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            - - - -
            - -
            -
            - -
            -
            -
            \ No newline at end of file diff --git a/application/admin/view/example/colorbadge/index.html b/application/admin/view/example/colorbadge/index.html deleted file mode 100644 index 8d61a3a5..00000000 --- a/application/admin/view/example/colorbadge/index.html +++ /dev/null @@ -1,21 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            -
            - {:build_toolbar('refresh,delete')} -
            - - -
            - - -
            -
            - -
            -
            -
            \ No newline at end of file diff --git a/application/admin/view/example/controllerjump/index.html b/application/admin/view/example/controllerjump/index.html deleted file mode 100644 index 8d61a3a5..00000000 --- a/application/admin/view/example/controllerjump/index.html +++ /dev/null @@ -1,21 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            -
            - {:build_toolbar('refresh,delete')} -
            - - -
            - - -
            -
            - -
            -
            -
            \ No newline at end of file diff --git a/application/admin/view/example/cxselect/index.html b/application/admin/view/example/cxselect/index.html deleted file mode 100644 index 478bf5a0..00000000 --- a/application/admin/view/example/cxselect/index.html +++ /dev/null @@ -1,160 +0,0 @@ - -
            - {:build_heading()} - -
            -
            -
            -
            -
            -
            -
            - -
            -
            省市区联动(通过AJAX读取数据)
            -
            -
            -
            -
            - - - -
            -
            -
            -
            -
            -
            - -
            -
            -
            -
            -
            - - - -
            -
            -
            -
            -
            -
            - -
            -
            -
            - -
            -
            -
            -
            -
            类别联动(Ajax读取数据)
            -
            -
            -
            -
            - - -
            -
            -
            -
            -
            -
            - -
            -
            -
            -
            -
            - - -
            -
            -
            -
            -
            -
            - -
            -
            - -
            -
            -
            -
            -
            -
            省市区联动(通过JSON渲染数据)
            -
            -
            -
            - -
            - - - -
            -
            -
            -
            -
            -
            - -
            -
            -
            -
            - -
            - - - -
            -
            -
            -
            -
            -
            - -
            -
            -
            - -
            -
            -
            -
            -
            -
            - -
            -
            -
            \ No newline at end of file diff --git a/application/admin/view/example/multitable/index.html b/application/admin/view/example/multitable/index.html deleted file mode 100644 index 3ada81e4..00000000 --- a/application/admin/view/example/multitable/index.html +++ /dev/null @@ -1,43 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            -
            -
            - - -
            -
            -
            - - -
            -
            -
            -
            -
            - -
            -
            -
            diff --git a/application/admin/view/example/relationmodel/index.html b/application/admin/view/example/relationmodel/index.html deleted file mode 100644 index c1f4483c..00000000 --- a/application/admin/view/example/relationmodel/index.html +++ /dev/null @@ -1,21 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            -
            - {:build_toolbar('delete')} -
            - - -
            - - -
            -
            - -
            -
            -
            \ No newline at end of file diff --git a/application/admin/view/example/tabletemplate/index.html b/application/admin/view/example/tabletemplate/index.html deleted file mode 100644 index 4d470e67..00000000 --- a/application/admin/view/example/tabletemplate/index.html +++ /dev/null @@ -1,67 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            -
            - {:build_toolbar('refresh,delete')} - 获取选中项 - 切换视图 -
            - - -
            - -
            -
            - -
            -
            -
            - - - \ No newline at end of file diff --git a/application/admin/view/general/configvalue/add.html b/application/admin/view/general/configvalue/add.html deleted file mode 100644 index 095a60e1..00000000 --- a/application/admin/view/general/configvalue/add.html +++ /dev/null @@ -1,52 +0,0 @@ -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            -
            -
            - {:__('Key')} - {:__('Value')} -
            -
            - - - - -
            -
            {:__('Append')}
            -
            -
            -
            -
            - -
            - -
            -
            -
            - -
            - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
            -
            - - -
            diff --git a/application/admin/view/general/configvalue/edit.html b/application/admin/view/general/configvalue/edit.html deleted file mode 100644 index dfd1e289..00000000 --- a/application/admin/view/general/configvalue/edit.html +++ /dev/null @@ -1,53 +0,0 @@ -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            -
            -
            - {:__('Key')} - {:__('Value')} -
            - {foreach $row.content as $key => $vo} -
            - - - - -
            - {/foreach} -
            {:__('Append')}
            -
            -
            -
            -
            - -
            - -
            -
            -
            - -
            - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
            -
            - -
            diff --git a/application/admin/view/general/configvalue/index.html b/application/admin/view/general/configvalue/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/general/configvalue/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            - - -
            -
            -
            - -
            -
            -
            diff --git a/application/admin/view/general/crontab/add.html b/application/admin/view/general/crontab/add.html deleted file mode 100644 index 826e56b2..00000000 --- a/application/admin/view/general/crontab/add.html +++ /dev/null @@ -1,81 +0,0 @@ - -
            -
            - -
            - -
            -
            -
            - -
            - {:build_select('row[type]', $typedata, null, ['class'=>'form-control', 'data-rule'=>'required'])} -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            *    *    *    *    *
            --    -    -    -    -
            -|    |    |    |    +--- day of week (0 - 7) (Sunday=0 or 7)
            -|    |    |    +-------- month (1 - 12)
            -|    |    +------------- day of month (1 - 31)
            -|    +------------------ hour (0 - 23)
            -+----------------------- min (0 - 59)
            -
            {:__('The next %s times the execution time', '')}
            -
              -
            -
            -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
            -
            - - -
            diff --git a/application/admin/view/general/crontab/edit.html b/application/admin/view/general/crontab/edit.html deleted file mode 100644 index caa2aea4..00000000 --- a/application/admin/view/general/crontab/edit.html +++ /dev/null @@ -1,81 +0,0 @@ - -
            -
            - -
            - -
            -
            -
            - -
            - {:build_select('row[type]', $typedata, $row['type'], ['class'=>'form-control', 'data-rule'=>'required'])} -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            *    *    *    *    *
            --    -    -    -    -
            -|    |    |    |    +--- day of week (0 - 7) (Sunday=0 or 7)
            -|    |    |    +-------- month (1 - 12)
            -|    |    +------------- day of month (1 - 31)
            -|    +------------------ hour (0 - 23)
            -+----------------------- min (0 - 59)
            -
            {:__('The next %s times the execution time', '')}
            -
              -
            -
            -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
            -
            - - -
            diff --git a/application/admin/view/general/crontab/index.html b/application/admin/view/general/crontab/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/general/crontab/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            - - -
            -
            -
            - -
            -
            -
            diff --git a/application/admin/view/general/database/index.html b/application/admin/view/general/database/index.html deleted file mode 100644 index aaabdd5a..00000000 --- a/application/admin/view/general/database/index.html +++ /dev/null @@ -1,81 +0,0 @@ - -
            - {:build_heading()} - -
            -
            -
            -
            - -
            -
            -

            {:__('SQL Result')}:

            -
            -
            -
            - - -
            - - - -
            -
            -
            - -
            -
            - -
            -
            - -
            - -
            - - - -
            -
            -
            - -
            -
            -
            diff --git a/application/admin/view/index.html b/application/admin/view/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
            - {:build_heading()} - -
            -
            -
            -
            - - -
            -
            -
            - -
            -
            -
            diff --git a/application/admin/view/index/login.html b/application/admin/view/index/login.html index d985f909..d0f2cc69 100644 --- a/application/admin/view/index/login.html +++ b/application/admin/view/index/login.html @@ -6,7 +6,7 @@ -
            diff --git a/application/admin/view/page/add.html b/application/admin/view/page/add.html deleted file mode 100644 index 3304c708..00000000 --- a/application/admin/view/page/add.html +++ /dev/null @@ -1,80 +0,0 @@ -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - -
            -
            -
            - -
            - {:build_select('row[flag]', ['recommend'=>__('Recommend'), 'index'=>__('Index'), 'hot'=>__('Hot')], null, ['id'=>'c-flag','class'=>'form-control selectpicker','data-rule'=>'required'])} -
            -
            -
            - -
            -
            - - - -
              -
              -
              -
              -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
              -
              - -
              diff --git a/application/admin/view/page/edit.html b/application/admin/view/page/edit.html deleted file mode 100644 index abb2647e..00000000 --- a/application/admin/view/page/edit.html +++ /dev/null @@ -1,81 +0,0 @@ -
              - -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - -
              -
              -
              - -
              - {:build_select('row[flag]', ['recommend'=>__('Recommend'), 'index'=>__('Index'), 'hot'=>__('Hot')], $row['flag'], ['id'=>'c-flag','class'=>'form-control selectpicker','data-rule'=>'required'])} -
              -
              -
              - -
              -
              - - - -
                -
                -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
                -
                - -
                diff --git a/application/admin/view/page/index.html b/application/admin/view/page/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/page/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/user/third/add.phtml b/application/admin/view/user/third/add.phtml deleted file mode 100644 index b0b61890..00000000 --- a/application/admin/view/user/third/add.phtml +++ /dev/null @@ -1,64 +0,0 @@ -
                -
                - -
                - -
                -
                -
                - -
                - {:build_select("row[{'platform'}]", 'weibo,wechat,qq', "", ['id' => 'c-platform', 'class' => 'form-control selectpicker', 'multiple', 'required'])} -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                - - -
                diff --git a/application/admin/view/user/third/edit.phtml b/application/admin/view/user/third/edit.phtml deleted file mode 100644 index c89ccded..00000000 --- a/application/admin/view/user/third/edit.phtml +++ /dev/null @@ -1,64 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - {:build_select("row[platform]", 'weibo,wechat,qq', $row['platform'], ['id' => 'c-platform', 'class' => 'form-control selectpicker', 'multiple', 'required']);} -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                - -
                diff --git a/application/admin/view/user/third/index.phtml b/application/admin/view/user/third/index.phtml deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/user/third/index.phtml +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/user/user/add.phtml b/application/admin/view/user/user/add.phtml deleted file mode 100644 index a9803459..00000000 --- a/application/admin/view/user/user/add.phtml +++ /dev/null @@ -1,193 +0,0 @@ -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                -
                - - -
                -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
                -
                - - -
                diff --git a/application/admin/view/user/user/edit.phtml b/application/admin/view/user/user/edit.phtml deleted file mode 100644 index b4579aa1..00000000 --- a/application/admin/view/user/user/edit.phtml +++ /dev/null @@ -1,187 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                -
                - - -
                -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
                -
                - -
                diff --git a/application/admin/view/user/user/index.phtml b/application/admin/view/user/user/index.phtml deleted file mode 100644 index 43c6636e..00000000 --- a/application/admin/view/user/user/index.phtml +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/version/add.html b/application/admin/view/version/add.html deleted file mode 100644 index 6887392c..00000000 --- a/application/admin/view/version/add.html +++ /dev/null @@ -1,64 +0,0 @@ - - -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[enforce]', [1=>__('Yes'), 0=>__('No')], 1)} -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
                -
                - -
                diff --git a/application/admin/view/version/edit.html b/application/admin/view/version/edit.html deleted file mode 100644 index 34b1b73b..00000000 --- a/application/admin/view/version/edit.html +++ /dev/null @@ -1,58 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[enforce]', [1=>__('Yes'), 0=>__('No')], $row['enforce'])} -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
                -
                - -
                diff --git a/application/admin/view/version/index.html b/application/admin/view/version/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/version/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/wechat/autoreply/add.html b/application/admin/view/wechat/autoreply/add.html deleted file mode 100644 index bd31f5cd..00000000 --- a/application/admin/view/wechat/autoreply/add.html +++ /dev/null @@ -1,51 +0,0 @@ - - -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - - -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
                -
                - - -
                diff --git a/application/admin/view/wechat/autoreply/edit.html b/application/admin/view/wechat/autoreply/edit.html deleted file mode 100644 index 9c74994e..00000000 --- a/application/admin/view/wechat/autoreply/edit.html +++ /dev/null @@ -1,51 +0,0 @@ - - -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                -
                - - 选择现有资源
                资源名:{:$response['title'] ?>
                - 添加新资源 -
                -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
                -
                - -
                diff --git a/application/admin/view/wechat/autoreply/index.html b/application/admin/view/wechat/autoreply/index.html deleted file mode 100644 index f1bdef1f..00000000 --- a/application/admin/view/wechat/autoreply/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                -
                - {:build_toolbar()} - -
                - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/wechat/config/add.html b/application/admin/view/wechat/config/add.html deleted file mode 100644 index 015f524f..00000000 --- a/application/admin/view/wechat/config/add.html +++ /dev/null @@ -1,45 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                -

                - {:__('Json editor')} - {:__('Insert link')} -

                - -
                -
                - {:__('Json key')} - {:__('Json value')} -
                -
                - - - - -
                -
                {:__('Append')}
                -
                -
                -
                - -
                diff --git a/application/admin/view/wechat/config/edit.html b/application/admin/view/wechat/config/edit.html deleted file mode 100644 index 334731cf..00000000 --- a/application/admin/view/wechat/config/edit.html +++ /dev/null @@ -1,47 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                -

                - {:__('Json editor')} - {:__('Insert link')} -

                - -
                -
                - {:__('Json key')} - {:__('Json value')} -
                - {foreach $value as $key => $vo} -
                - - - - -
                - {/foreach} -
                {:__('Append')}
                -
                -
                -
                - -
                diff --git a/application/admin/view/wechat/config/index.html b/application/admin/view/wechat/config/index.html deleted file mode 100644 index d3eefa4f..00000000 --- a/application/admin/view/wechat/config/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/wechat/menu/index.html b/application/admin/view/wechat/menu/index.html deleted file mode 100644 index ebc1fdfb..00000000 --- a/application/admin/view/wechat/menu/index.html +++ /dev/null @@ -1,84 +0,0 @@ - -
                - {:build_heading()} - -
                -
                -
                -
                -
                -
                -
                {$site.name}
                - -
                -
                - -
                - 点击左侧菜单进行编辑操作 -
                -
                -
                -
                -
                - 可直接拖动菜单排序 -
                - -
                -
                -
                - -
                -
                -
                - diff --git a/application/admin/view/wechat/response/add.html b/application/admin/view/wechat/response/add.html deleted file mode 100644 index 6d718a5d..00000000 --- a/application/admin/view/wechat/response/add.html +++ /dev/null @@ -1,48 +0,0 @@ -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - - - - -
                -
                -
                - -
                -
                - -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} -
                -
                -
                -
                -
                - - -
                -
                - -
                - \ No newline at end of file diff --git a/application/admin/view/wechat/response/edit.html b/application/admin/view/wechat/response/edit.html deleted file mode 100644 index 9ee6d32a..00000000 --- a/application/admin/view/wechat/response/edit.html +++ /dev/null @@ -1,52 +0,0 @@ -
                - -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - -
                -
                -
                - -
                - {:build_radios('row[type]', ['text' => __('Text'), 'app' => __('App')], $row['type'])} -
                -
                -
                - -
                -
                -
                -
                - {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} -
                -
                - - -
                - \ No newline at end of file diff --git a/application/admin/view/wechat/response/index.html b/application/admin/view/wechat/response/index.html deleted file mode 100644 index ca4b5492..00000000 --- a/application/admin/view/wechat/response/index.html +++ /dev/null @@ -1,19 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                -
                - {:build_toolbar();} -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/admin/view/wechat/response/select.html b/application/admin/view/wechat/response/select.html deleted file mode 100644 index 6139835a..00000000 --- a/application/admin/view/wechat/response/select.html +++ /dev/null @@ -1,16 +0,0 @@ -
                - {:build_heading()} - -
                -
                -
                -
                - - -
                -
                -
                - -
                -
                -
                diff --git a/application/api/controller/Index.php b/application/api/controller/Index.php deleted file mode 100644 index 52bd44c4..00000000 --- a/application/api/controller/Index.php +++ /dev/null @@ -1,15 +0,0 @@ - 0]); - } - -} diff --git a/application/command.php b/application/command.php index da724a9c..062fa2e8 100755 --- a/application/command.php +++ b/application/command.php @@ -15,4 +15,5 @@ return [ 'app\admin\command\Menu', 'app\admin\command\Install', 'app\admin\command\Min', + 'app\admin\command\Addon', ]; diff --git a/application/common.php b/application/common.php index 95d30fc6..7189c997 100755 --- a/application/common.php +++ b/application/common.php @@ -1,7 +1,5 @@ root()); // 如果未设置__CDN__则自动匹配得出 if (!Config::get('view_replace_str.__CDN__')) diff --git a/application/common/controller/Backend.php b/application/common/controller/Backend.php index 94868ff9..09c66120 100644 --- a/application/common/controller/Backend.php +++ b/application/common/controller/Backend.php @@ -5,35 +5,16 @@ namespace app\common\controller; use app\admin\library\Auth; use think\Config; use think\Controller; +use think\Hook; use think\Lang; use think\Session; -load_trait('library/traits/Backend'); - /** * 后台控制器基类 */ class Backend extends Controller { - /** - * 返回码,默认为null,当设置了该值后将输出json数据 - * @var int - */ - protected $code = null; - - /** - * 返回内容,默认为null,当设置了该值后将输出json数据 - * @var mixed - */ - protected $data = null; - - /** - * 返回文本,默认为空 - * @var mixed - */ - protected $msg = ''; - /** * 无需登录的方法,同时也就不需要鉴权了 * @var array @@ -94,7 +75,7 @@ class Backend extends Controller $controllername = strtolower($this->request->controller()); $actionname = strtolower($this->request->action()); - $path = '/' . $modulename . '/' . str_replace('.', '/', $controllername) . '/' . $actionname; + $path = str_replace('.', '/', $controllername) . '/' . $actionname; // 定义是否Addtabs请求 !defined('IS_ADDTABS') && define('IS_ADDTABS', input("addtabs") ? TRUE : FALSE); @@ -115,6 +96,7 @@ class Backend extends Controller //检测是否登录 if (!$this->auth->isLogin()) { + Hook::listen('admin_nologin', $this); $url = Session::get('referer'); $url = $url ? $url : $this->request->url(); $this->error(__('Please login first'), url('index/login', ['url' => $url])); @@ -125,7 +107,8 @@ class Backend extends Controller // 判断控制器和方法判断是否有对应权限 if (!$this->auth->check($path)) { - $this->error(__('You have no permission'), NULL); + Hook::listen('admin_nopermission', $this); + $this->error(__('You have no permission'), ''); } } } @@ -156,24 +139,33 @@ class Backend extends Controller $site = Config::get("site"); + $upload = \app\common\model\Config::upload(); + + // 上传信息配置后 + Hook::listen("upload_config_init", $upload); + // 配置信息 $config = [ 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])), - 'upload' => \app\common\model\Config::upload(), + 'upload' => $upload, 'modulename' => $modulename, 'controllername' => $controllername, 'actionname' => $actionname, 'jsname' => 'backend/' . str_replace('.', '/', $controllername), 'moduleurl' => rtrim(url("/{$modulename}", '', false), '/'), 'language' => $lang, + 'fastadmin' => Config::get('fastadmin'), 'referer' => Session::get("referer") ]; - + // 配置信息后 + Hook::listen("config_init", $config); + //加载当前控制器语言包 $this->loadlang($controllername); - + //渲染站点配置 $this->assign('site', $site); + //渲染配置信息 $this->assign('config', $config); - + //渲染管理员对象 $this->assign('admin', Session::get('admin')); } @@ -186,6 +178,16 @@ class Backend extends Controller Lang::load(APP_PATH . $this->request->module() . '/lang/' . Lang::detect() . '/' . str_replace('.', '/', $name) . '.php'); } + /** + * 渲染配置信息 + * @param mixed $name 键名或数组 + * @param mixed $value 值 + */ + protected function assignconfig($name, $value = '') + { + $this->view->config = array_merge($this->view->config ? $this->view->config : [], is_array($name) ? $name : [$name => $value]); + } + /** * 生成查询所需要的条件,排序方式 * @param mixed $searchfields 查询条件 @@ -207,37 +209,36 @@ class Backend extends Controller $op = json_decode($op, TRUE); $filter = $filter ? $filter : []; $where = []; - $modelName = ''; + $tableName = ''; if ($relationSearch) { if (!empty($this->model)) { $class = get_class($this->model); $name = basename(str_replace('\\', '/', $class)); - $name = strtolower(preg_replace('/(?model->getQuery()->getTable($name) . "."; } if (stripos($sort, ".") === false) { - $sort = $modelName . $sort; + $sort = $tableName . $sort; } } if ($search) { $searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields); - $searchlist = []; - foreach ($searcharr as $k => $v) + foreach ($searcharr as $k => &$v) { - $searchlist[] = (stripos($v, ".") !== false ? $v : "{$modelName}`{$v}`") . " LIKE '%{$search}%'"; + $v = $tableName . $v; } - $where[] = "(" . implode(' OR ', $searchlist) . ")"; + unset($v); + $where[] = [implode("|", $searcharr), "LIKE", "%{$search}%"]; } foreach ($filter as $k => $v) { $sym = isset($op[$k]) ? $op[$k] : '='; if (stripos($k, ".") === false) { - $k = $modelName . $k; + $k = $tableName . $k; } $sym = isset($op[$k]) ? $op[$k] : $sym; switch ($sym) @@ -306,7 +307,7 @@ class Backend extends Controller //当前页 $page = $this->request->request("page"); //分页大小 - $pagesize = $this->request->request("page_size"); + $pagesize = $this->request->request("per_page"); //搜索条件 $andor = $this->request->request("and_or"); //排序方式 @@ -368,23 +369,4 @@ class Backend extends Controller return json(['list' => $list, 'total' => $total]); } - /** - * 析构方法 - * - */ - public function __destruct() - { - //判断是否设置code值,如果有则变动response对象的正文 - if (!is_null($this->code)) - { - $result = [ - 'code' => $this->code, - 'msg' => $this->msg, - 'time' => $_SERVER['REQUEST_TIME'], - 'data' => $this->data, - ]; - echo json_encode($result); - } - } - } diff --git a/application/common/controller/Frontend.php b/application/common/controller/Frontend.php index 8366b013..fe9dde0b 100644 --- a/application/common/controller/Frontend.php +++ b/application/common/controller/Frontend.php @@ -11,24 +11,6 @@ use think\Session; class Frontend extends Controller { - /** - * 返回码,默认为null,当设置了该值后将输出json数据 - * @var int - */ - protected $code = null; - - /** - * 返回内容,默认为null,当设置了该值后将输出json数据 - * @var mixed - */ - protected $data = null; - - /** - * 返回文本,默认为空 - * @var mixed - */ - protected $msg = ''; - /** * * @var Auth @@ -57,22 +39,6 @@ class Frontend extends Controller $path = '/' . $modulename . '/' . str_replace('.', '/', $controllername) . '/' . $actionname; - $this->user = Auth::instance(); - - // 设置当前请求的URI - $this->user->setRequestUri($path); - - // 检测当前是否登录并进行初始化 - $this->user->init(); - - // 检测是否需要验证登录 - if (!$this->user->match($this->noNeedLogin)) - { - $this->checkLogin(); - } - - // 将auth对象渲染至视图 - $this->view->assign("user", $this->user); // 如果有使用模板布局 if ($this->layout) { @@ -119,18 +85,15 @@ class Frontend extends Controller { Lang::load(APP_PATH . $this->request->module() . '/lang/' . Lang::detect() . '/' . str_replace('.', '/', $name) . '.php'); } - + /** - * 析构方法 - * + * 渲染配置信息 + * @param mixed $name 键名或数组 + * @param mixed $value 值 */ - public function __destruct() + protected function assignconfig($name, $value = '') { - //判断是否设置code值,如果有则变动response对象的正文 - if (!is_null($this->code)) - { - $this->result($this->data, $this->code, $this->msg, 'json'); - } + $this->view->config = array_merge($this->view->config ? $this->view->config : [], is_array($name) ? $name : [$name => $value]); } } diff --git a/application/common/controller/Uc.php b/application/common/controller/Uc.php deleted file mode 100644 index fb51f352..00000000 --- a/application/common/controller/Uc.php +++ /dev/null @@ -1,162 +0,0 @@ -request->module(); - $controllername = strtolower($this->request->controller()); - $actionname = strtolower($this->request->action()); - - $path = '/' . $modulename . '/' . str_replace('.', '/', $controllername) . '/' . $actionname; - - $this->user = Auth::instance(); - - // 设置当前请求的URI - $this->user->setRequestUri($path); - - // 检测当前是否登录并进行初始化 - //$this->user->init(); - // - //加载UC函数库 - //加载UC XML类库 - Loader::import('fast.ucenter.common.Functions'); - Loader::import('fast.ucenter.common.XML'); - $this->initConfig(); //初始化UC应用配置 - $this->initRequest(); //初始化请求 - } - - function initConfig() - { - if (!defined('UC_API')) - { - $this->error('未发现uc常量配置信息'); - } - } - - function _serialize($arr, $htmlon = 0) - { - return xml_serialize($arr, $htmlon); - } - - /** - * 解析请求 - * @return boolean - */ - public function initRequest() - { - $code = $this->request->get('code'); - parse_str(_uc_authcode($code, 'DECODE', UC_KEY), $get); - if (get_magic_quotes_gpc()) - { - $get = _uc_stripslashes($get); - } - if (empty($get) || !isset($get['time']) || !isset($get['action'])) - { - $this->error = '非法请求'; - return false; - } - $timestamp = time(); - if ($timestamp - $get['time'] > 3600) - { - $this->error = '请求有效期已过'; - return false; - } - - $requestdata = file_get_contents('php://input'); - $this->code = $code; - $this->action = strtolower(parse_name($get['action'], '1')); - $this->get = $get; - $this->post = @xml_unserialize($requestdata); - $this->appdir = EXTEND_PATH . 'fast/ucenter/client/'; - // 定义允许请求的接口 - $allowaction = ['test', 'adduser', 'deleteuser', 'gettag', 'synregister', 'synlogin', 'synlogout', 'updateinfo', 'updatebadwords', 'updatehosts', 'updateapps', 'updateclient', 'updatecredit', 'getcreditsettings', 'updatecreditsettings']; - if (!in_array($this->action, $allowaction)) - { - $this->error = '请求不允许'; - return false; - } - } - - /** - * 响应ucserver的通信请求,调用相应方法,输出最终结果并结束整个流程 - */ - public function response() - { - if ($this->_before_response()) - { - if ($this->error !== NULL) - { - exit($this->error); - } - $response = call_user_func(array($this, $this->action)); - } - if ($this->_after_response($response)) - { - exit($response); - } - exit('-1'); - } - - protected function _before_response() - { - return true; - } - - protected function _after_response($response = "") - { - return true; - } - - public function test() - { - return API_RETURN_SUCCEED; - } - -} diff --git a/application/common/library/Auth.php b/application/common/library/Auth.php deleted file mode 100644 index 8cf8661d..00000000 --- a/application/common/library/Auth.php +++ /dev/null @@ -1,650 +0,0 @@ -user = new User; - } - - /** - * 初始化 - * @param array $options 参数 - * @return Auth - */ - public static function instance($options = []) - { - if (is_null(self::$instance)) - { - self::$instance = new static($options); - } - - return self::$instance; - } - - /** - * - * @return User - */ - public function getModel() - { - return $this->user; - } - - public function __get($name) - { - return $this->check() ? $this->user->$name : NULL; - } - - public function __call($name, $arguments) - { - return call_user_func_array([$this->user, $name], $arguments); - } - - /** - * 注册用户 - * - * @param string $username 用户名 - * @param string $password 密码 - * @param string $email 邮箱 - * @param string $mobile 手机号 - * @param string $extend 扩展参数 - * @return boolean - */ - public function register($username, $password, $email = '', $mobile = '', $extend = [], $keeptime = 0, $sync = TRUE) - { - $rule = [ - 'username' => 'require|length:6,30', - 'password' => 'require|length:6,30', - 'email' => 'email', - 'mobile' => 'regex:/^1\d{10}$/', - ]; - - $msg = [ - 'username.require' => __('Username can not be empty'), - 'username.length' => __('Username must be 6 to 30 characters'), - 'password.require' => __('Password can not be empty'), - 'password.length' => __('Password must be 6 to 30 characters'), - 'email' => __('Email is incorrect'), - 'mobile' => __('Mobile is incorrect'), - ]; - $data = [ - 'username' => $username, - 'password' => $password, - 'email' => $email, - 'mobile' => $mobile, - ]; - $validate = new Validate($rule, $msg); - $result = $validate->check($data); - if (!$result) - { - $this->setError($validate->getError()); - return FALSE; - } - - // 检测用户名或邮箱、手机号是否存在 - if (User::getByUsername($username)) - { - $this->setError(__('Username already exist')); - return FALSE; - } - if ($email && User::getByEmail($email)) - { - $this->setError(__('Email already exist')); - return FALSE; - } - if ($mobile && User::getByMobile($mobile)) - { - $this->setError(__('Mobile already exist')); - return FALSE; - } - - $ip = request()->ip(); - $time = time(); - $params = array_merge($data, [ - 'nickname' => $username, - 'salt' => Random::alnum(), - 'jointime' => $time, - 'joinip' => $ip, - 'logintime' => $time, - 'loginip' => $ip, - 'prevtime' => $time, - 'status' => 'normal' - ]); - $params['password'] = $this->getEncryptPassword($password, $params['salt']); - $params = array_merge($params, $extend); - - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS && $sync) - { - $uc = new Client(); - $user_id = $uc->uc_user_register($username, $password, $email); - // 如果小于0则说明发生错误 - if ($user_id <= 0) - { - $this->setError($user_id > -4 ? self::ERR_USERNAME_IS_INCORRECT : self::ERR_EMAIL_IS_INCORRECT); - return FALSE; - } - else - { - $params['id'] = $user_id; - } - } - - //账号注册时需要开启事务,避免出现垃圾数据 - Db::startTrans(); - try - { - $ret = $this->user->save($params); - Db::commit(); - - // 此时的Model中只包含部分数据 - $this->user = $this->user->get($this->user->id); - - $this->keeptime($keeptime); - return $this->syncLogin(); - } - catch (Exception $e) - { - Db::rollback(); - return FALSE; - } - } - - /** - * 用户登录 - * - * @param string $account 账号,用户名、邮箱、手机号 - * @param string $password 密码 - * @param int $keeptime 有效时长,默认为浏览器关闭 - * @return array - */ - public function login($account, $password, $keeptime = 0, $sync = TRUE) - { - $field = Validate::is($account, 'email') ? 'email' : (Validate::regex($account, '/^1\d{10}$/') ? 'mobile' : 'username'); - $user = $this->user->get([$field => $account]); - if ($user) - { - if ($user->status != 'normal') - { - $this->setError(self::ERR_ACCOUNT_IS_LOCKED); - return FALSE; - } - if ($user->password != $this->getEncryptPassword($password, $user->salt)) - { - $this->setError(self::ERR_PASSWORD_IS_INCORRECT); - return FALSE; - } - - $this->user = $user; - - // 设置登录有效时长 - $this->keeptime($keeptime); - - return $this->syncLogin($sync); - } - else - { - $this->setError(self::ERR_ACCOUNT_IS_INCORRECT); - return FALSE; - } - } - - /** - * 注销登录退出 - * @return bool - */ - public function logout($token = NULL) - { - //设置登录标识 - $this->_logined = FALSE; - $token = is_null($token) ? Cookie::get('token') : $token; - Token::delete($token); - Cookie::delete('user_id'); - //Cookie::del('username'); - Cookie::delete('token'); - return TRUE; - } - - /** - * 生成Token - * @return string - */ - public function token() - { - //$token = Encrypt::aesEncode($this->keeptime . '|' . $expiretime, Config::get('encrypt', 'aes_key'), TRUE); - $token = Random::uuid(); - Token::set($token, $this->user->id, $this->keeptime); - return $token; - } - - /** - * 初始化 - * - * @param int $user_id 会员ID,默认从Cookie中取 - * @param string $token 会员Token,默认从Cookie中取 - * - * @return boolean - */ - public function init($user_id = NULL, $token = NULL) - { - $user_id = $user_id ? $user_id : Cookie::get('user_id'); - $user_id = intval($user_id); - if ($user_id > 0) - { - if ($this->_error) - return FALSE; - $user = $this->get($user_id); - if (!$user) - { - $this->setError(self::ERR_ACCOUNT_NOT_EXIST); - return FALSE; - } - if ($user['status'] != 'normal') - { - $this->setError(self::ERR_ACCOUNT_IS_LOCKED); - return FALSE; - } - $token = $token ? $token : Cookie::get('token'); - if (!Token::check($token)) - { - return FALSE; - } - if (Token::identity($token) != $user['id']) - { - return FALSE; - } - $this->user = $user; - $this->_logined = TRUE; - return TRUE; - } - else - { - $this->setError(self::ERR_YOU_ARE_NOT_LOGGED_IN); - return FALSE; - } - } - - /** - * 检测是否登录 - * - * @return boolean - */ - public function check() - { - return $this->_logined; - } - - /** - * 检测是否登录 - * - * @return boolean - */ - public function isLogin() - { - return $this->check(); - } - - /** - * 获取当前请求的URI - * @return string - */ - public function getRequestUri() - { - return $this->requestUri; - } - - /** - * 设置当前请求的URI - * @param string $uri - */ - public function setRequestUri($uri) - { - $this->requestUri = $uri; - } - - /** - * 第三方登录 - * @param string $platform - * @param array $params - * @param int $keeptime - * @return boolean - */ - public function connect($platform, $params = [], $keeptime = 0) - { - $time = time(); - $values = [ - 'platform' => $platform, - 'openid' => $params['openid'], - 'openname' => isset($params['userinfo']['nickname']) ? $params['userinfo']['nickname'] : '', - 'access_token' => $params['access_token'], - 'refresh_token' => $params['refresh_token'], - 'expires_in' => $params['expires_in'], - 'logintime' => $time, - 'expiretime' => $time + $params['expires_in'], - ]; - - $this->keeptime($keeptime); - $userthird = UserThird::get(['platform' => $platform, 'openid' => $params['openid']]); - if ($userthird) - { - $this->user = $this->user->get($userthird['user_id']); - if (!$this->user) - { - return FALSE; - } - $userthird->save($values); - return $this->syncLogin(); - } - else - { - // 先随机一个用户名,随后再变更为u+数字id - $username = Random::alnum(20); - $password = Random::alnum(6); - // 默认注册一个会员 - $result = $this->register($username, $password, '', '', [], $keeptime); - if (!$result) - { - return FALSE; - } - $userarr = ['username' => 'u' . $this->user->id]; - if (isset($params['userinfo']['nickname'])) - $userarr['nickname'] = $params['userinfo']['nickname']; - if (isset($params['userinfo']['avatar'])) - $userarr['avatar'] = $params['userinfo']['avatar']; - - // 更新会员资料 - $this->user->save($userarr); - - // 保存第三方信息 - $values['user_id'] = $this->user->id; - UserThird::create($values); - - // 写入登录Cookies和Token - $this->writeStatus(); - return TRUE; - } - } - - /** - * 删除一个指定会员 - * @param int $user_id - * @param bool $sync 是否同步删除 - */ - public function delete($user_id, $sync = TRUE) - { - $user = $this->user->get($user_id); - if (!$user) - { - return FALSE; - } - - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS && $sync) - { - $uc = new Client(); - $re = $uc->uc_user_delete($user['id']); - // 如果小于0则说明发生错误 - if ($re <= 0) - { - $this->setError(self::ERR_ACCOUNT_IS_LOCKED); - return FALSE; - } - } - // 调用事务删除账号 - $result = Db::transaction(function($db) use($user_id) { - // 删除会员 - User::destroy($user_id); - - // 删除会员第三方登录 - UserThird::destroy($user_id); - }); - - return $result ? TRUE : FALSE; - } - - /** - * 直接登录账号 - * @param int $user_id - * @param boolean $sync - * @return boolean - */ - public function direct($user_id, $sync = TRUE) - { - $this->user = $this->user->get($user_id); - if ($this->user) - { - $this->syncLogin($sync); - return TRUE; - } - else - { - return FALSE; - } - } - - /** - * 获取密码加密方式 - * @param string $password - * @param string $salt - * @return string - */ - public function getEncryptPassword($password, $salt = '') - { - return md5(md5($password) . $salt); - } - - - - /** - * 检测当前控制器和方法是否匹配传递的数组 - * - * @param array $arr 需要验证权限的数组 - */ - public function match($arr = []) - { - $request = Request::instance(); - $arr = is_array($arr) ? $arr : explode(',', $arr); - if (!$arr) - { - return FALSE; - } - // 是否存在 - if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) - { - return TRUE; - } - - // 没找到匹配 - return FALSE; - } - - /** - * 同步登录信息 - * @param int $sync 是否同步登录到UC - * @return boolean - */ - protected function syncLogin($sync = TRUE) - { - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS && $sync) - { - $uc = new Client(); - $re = $uc->uc_user_login($this->user->id, $this->user->password . '#split#' . $this->user->salt, 3); - // 如果小于0则说明发生错误 - if ($re <= 0) - { - $this->setError(self::ERR_USERNAME_OR_PASSWORD_IS_INCORRECT); - return FALSE; - } - } - - //增加登录次数和设置最后登录时间 - $this->user->save([ - 'prevtime' => $this->user->logintime, - 'logintime' => time(), - 'loginip' => request()->ip(), - ]); - - // 写入登录Cookies和Token - $this->writeStatus(); - return TRUE; - } - - /** - * 写入登录态和Cookie - * - * @param int $keeptime - */ - protected function writeStatus() - { - //设置登录标识 - $this->_logined = TRUE; - - $token = $this->token(); - Cookie::set('user_id', $this->user->id, $this->keeptime); - Cookie::set('username', $this->user->username, 86400 * 365); - //加密安全字符 - Cookie::set('token', $token, $this->keeptime); - $this->setError(''); - } - - /** - * 设置会话有效时间 - * @param int $keeptime 默认为永久 - */ - public function keeptime($keeptime = 0) - { - $this->keeptime = $keeptime; - } - - /** - * 渲染用户数据 - * @param array $datalist - * @param array $fields - * @param string $fieldkey - * @param string $renderkey - * @return array - */ - public function render(&$datalist, $fields = [], $fieldkey = 'user_id', $renderkey = 'userinfo') - { - $fields = !$fields ? ['id', 'nickname', 'level', 'avatar'] : (is_array($fields) ? $fields : explode(',', $fields)); - $ids = []; - foreach ($datalist as $k => $v) - { - if (!isset($v[$fieldkey])) - continue; - $ids[] = $v[$fieldkey]; - } - $list = []; - if ($ids) - { - if (!in_array('id', $fields)) - { - $fields[] = 'id'; - } - $ids = array_unique($ids); - $selectlist = User::where('id', 'in', $ids)->column($fields); - foreach ($selectlist as $k => $v) - { - $list[$v['id']] = $v; - } - } - foreach ($datalist as $k => &$v) - { - $v[$renderkey] = isset($list[$v[$fieldkey]]) ? $list[$v[$fieldkey]] : NULL; - } - unset($v); - return $datalist; - } - - /** - * 设置错误信息 - * - * @param $error - */ - public function setError($error) - { - $this->_error = $error; - return $this; - } - - /** - * 获取错误信息 - * @return string - */ - public function getError() - { - return __($this->_error); - } - - public function __toString() - { - return $this->user->toJson(); - } - - // JsonSerializable - public function jsonSerialize() - { - return $this->user->toArray(); - } - - // ArrayAccess - public function offsetSet($name, $value) - { - $this->user->setAttr($name, $value); - } - - public function offsetExists($name) - { - return $this->user->__isset($name); - } - - public function offsetUnset($name) - { - $this->user->__unset($name); - } - - public function offsetGet($name) - { - return $this->user->getAttr($name); - } - -} diff --git a/application/common/library/Menu.php b/application/common/library/Menu.php new file mode 100644 index 00000000..fb63ab5d --- /dev/null +++ b/application/common/library/Menu.php @@ -0,0 +1,77 @@ + $v) + { + $hasChild = isset($v['sublist']) && $v['sublist'] ? true : false; + + $data = array_intersect_key($v, $allow); + + $data['ismenu'] = isset($data['ismenu']) ? $data['ismenu'] : ($hasChild ? 1 : 0); + $data['icon'] = isset($data['icon']) ? $data['icon'] : ($hasChild ? 'fa fa-list' : 'fa fa-circle-o'); + $data['pid'] = $pid; + $data['status'] = 'normal'; + try + { + $menu = AuthRule::create($data); + if ($hasChild) + { + self::create($v['sublist'], $menu->id); + } + } + catch (PDOException $e) + { + print_r($e); + } + } + } + + /** + * 删除菜单 + * @param string $name 规则name + * @return boolean + */ + public static function delete($name) + { + $menu = AuthRule::getByName($name); + if ($menu) + { + // 必须将结果集转换为数组 + $ruleList = collection(model('AuthRule')->order('weigh', 'desc')->field('id,pid,name')->select())->toArray(); + // 构造菜单数据 + $ids = Tree::instance()->init($ruleList)->getChildrenIds($menu['id'], true); + if ($ids) + { + AuthRule::destroy($ids); + } + return true; + } + return false; + } + +} diff --git a/application/common/library/Token.php b/application/common/library/Token.php deleted file mode 100644 index 268790cc..00000000 --- a/application/common/library/Token.php +++ /dev/null @@ -1,66 +0,0 @@ - - * 更多字段可参考http://docs.upyun.com/api/form_api/#_2 - * + * 本地上传配置信息 * @return array */ - public static function upload($params = []) + public static function upload() { $uploadcfg = config('upload'); - $uploadcfg = $uploadcfg ? $uploadcfg : []; - $uploadcfg = array_merge($uploadcfg, $params); - $uploadcfg['bucket'] = isset($uploadcfg['bucket']) ? $uploadcfg['bucket'] : ''; - $multiple = isset($uploadcfg['multiple']) ? $uploadcfg['multiple'] : false; - $savekey = isset($uploadcfg['savekey']) ? $uploadcfg['savekey'] : ''; - $uploadcfg['save-key'] = isset($uploadcfg['save-key']) ? $uploadcfg['save-key'] : $savekey; - $expiration = time() + (isset($uploadcfg['expire']) ? $uploadcfg['expire'] : 600); - $uploadcfg['expiration'] = isset($uploadcfg['expiration']) ? $uploadcfg['expiration'] : $expiration; - $notifyurl = isset($uploadcfg['notifyurl']) ? $uploadcfg['notifyurl'] : ''; - $returnurl = isset($uploadcfg['returnurl']) ? $uploadcfg['returnurl'] : ''; - if ($notifyurl) - $uploadcfg['notify-url'] = $notifyurl; - else - unset($uploadcfg['notify-url']); - if ($returnurl) - $uploadcfg['return-url'] = $returnurl; - else - unset($uploadcfg['return-url']); - //设置允许的附加字段 - $allowfields = [ - 'bucket', 'save-key', 'expiration', 'date', 'content-md5', 'notify-url', 'return-url', 'content-secret', 'content-type', 'allow-file-type', 'content-length-range', - 'image-width-range', 'image-height-range', 'x-gmkerl-thumb', 'x-gmkerl-type', 'apps', 'b64encoded', 'ext-param' - ]; - $params = array_intersect_key($uploadcfg, array_flip($allowfields)); - $policy = base64_encode(json_encode($params)); - $signature = md5($policy . '&' . (isset($uploadcfg['formkey']) ? $uploadcfg['formkey'] : '')); - $multipart = [ - 'policy' => $policy, - 'signature' => $signature, - ]; - - $multipart = array_merge($multipart, $params); - return [ - 'cdnurl' => isset($uploadcfg['cdnurl']) ? $uploadcfg['cdnurl'] : '', - 'uploadurl' => isset($uploadcfg['uploadurl']) ? $uploadcfg['uploadurl'] : url('ajax/upload'), - 'bucket' => $uploadcfg['bucket'], - 'maxsize' => isset($uploadcfg['maxsize']) ? $uploadcfg['maxsize'] : '', - 'mimetype' => isset($uploadcfg['mimetype']) ? $uploadcfg['mimetype'] : '', - 'multipart' => $multipart, - 'multiple' => $multiple, + $upload = [ + 'cdnurl' => $uploadcfg['cdnurl'], + 'uploadurl' => $uploadcfg['uploadurl'], + 'bucket' => 'local', + 'maxsize' => $uploadcfg['maxsize'], + 'mimetype' => $uploadcfg['mimetype'], + 'multipart' => [], + 'multiple' => $uploadcfg['multiple'], ]; + return $upload; } } diff --git a/application/common/model/Configvalue.php b/application/common/model/Configvalue.php deleted file mode 100644 index dfbbec63..00000000 --- a/application/common/model/Configvalue.php +++ /dev/null @@ -1,76 +0,0 @@ - 'json', - ]; - - /** - * 加载上传配置 - * - * @param array $params 扩展参数,常用字段savekey,mimetype,maxsize,ext-param,notify-url,return-url
                - * 更多字段可参考http://docs.upyun.com/api/form_api/#_2 - * - * @return array - */ - public static function upload($params = []) - { - $uploadcfg = Config::get('upload'); - $uploadcfg = $uploadcfg ? $uploadcfg : []; - $uploadcfg = array_merge($uploadcfg, $params); - $uploadcfg['bucket'] = isset($uploadcfg['bucket']) ? $uploadcfg['bucket'] : ''; - $multiple = isset($uploadcfg['multiple']) ? $uploadcfg['multiple'] : false; - $savekey = isset($uploadcfg['savekey']) ? $uploadcfg['savekey'] : ''; - $uploadcfg['save-key'] = isset($uploadcfg['save-key']) ? $uploadcfg['save-key'] : $savekey; - $expiration = time() + (isset($uploadcfg['expire']) ? $uploadcfg['expire'] : 600); - $uploadcfg['expiration'] = isset($uploadcfg['expiration']) ? $uploadcfg['expiration'] : $expiration; - $notifyurl = isset($uploadcfg['notifyurl']) ? $uploadcfg['notifyurl'] : ''; - $returnurl = isset($uploadcfg['returnurl']) ? $uploadcfg['returnurl'] : ''; - if ($notifyurl) - $uploadcfg['notify-url'] = $notifyurl; - else - unset($uploadcfg['notify-url']); - if ($returnurl) - $uploadcfg['return-url'] = $returnurl; - else - unset($uploadcfg['return-url']); - - //设置允许的附加字段 - $allowfields = [ - 'bucket', 'save-key', 'expiration', 'date', 'content-md5', 'notify-url', 'return-url', 'content-secret', 'content-type', 'allow-file-type', 'content-length-range', - 'image-width-range', 'image-height-range', 'x-gmkerl-thumb', 'x-gmkerl-type', 'apps', 'b64encoded', 'ext-param' - ]; - $params = array_intersect_key($uploadcfg, array_flip($allowfields)); - $policy = base64_encode(json_encode($params)); - $signature = md5($policy . '&' . (isset($uploadcfg['formkey']) ? $uploadcfg['formkey'] : '')); - $multipart = [ - 'policy' => $policy, - 'signature' => $signature, - ]; - - $multipart = array_merge($multipart, $params); - return [ - 'cdnurl' => isset($uploadcfg['cdnurl']) ? $uploadcfg['cdnurl'] : '', - 'uploadurl' => isset($uploadcfg['uploadurl']) ? $uploadcfg['uploadurl'] : url('ajax/upload'), - 'bucket' => $uploadcfg['bucket'], - 'maxsize' => isset($uploadcfg['maxsize']) ? $uploadcfg['maxsize'] : '', - 'mimetype' => isset($uploadcfg['mimetype']) ? $uploadcfg['mimetype'] : '', - 'multipart' => $multipart, - 'multiple' => $multiple, - ]; - } - -} diff --git a/application/common/model/Crontab.php b/application/common/model/Crontab.php deleted file mode 100644 index f0681dd3..00000000 --- a/application/common/model/Crontab.php +++ /dev/null @@ -1,54 +0,0 @@ - __('Request Url'), - 'sql' => __('Execute Sql Script'), - 'shell' => __('Execute Shell'), - ]; - } - - public function getTypeTextAttr($value, $data) - { - $typelist = self::getTypeList(); - $value = $value ? $value : $data['type']; - return $value && isset($typelist[$value]) ? $typelist[$value] : $value; - } - - protected function setBegintimeAttr($value) - { - return $value && !is_numeric($value) ? strtotime($value) : $value; - } - - protected function setEndtimeAttr($value) - { - return $value && !is_numeric($value) ? strtotime($value) : $value; - } - - protected function setExecutetimeAttr($value) - { - return $value && !is_numeric($value) ? strtotime($value) : $value; - } - -} diff --git a/application/common/model/Page.php b/application/common/model/Page.php deleted file mode 100644 index 18cd2f86..00000000 --- a/application/common/model/Page.php +++ /dev/null @@ -1,20 +0,0 @@ -belongsTo('Category', 'category_id')->setEagerlyType(0); - } -} diff --git a/application/common/model/User.php b/application/common/model/User.php deleted file mode 100644 index b81500e3..00000000 --- a/application/common/model/User.php +++ /dev/null @@ -1,16 +0,0 @@ - $name]); - return $item ? $item->value : ''; - } - -} diff --git a/application/common/model/WechatContext.php b/application/common/model/WechatContext.php deleted file mode 100644 index c51aee09..00000000 --- a/application/common/model/WechatContext.php +++ /dev/null @@ -1,16 +0,0 @@ - 'page', 'list_rows' => 15, ], + //验证码配置 'captcha' => [ // 验证码字符集合 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY', @@ -239,4 +240,9 @@ return [ // 验证成功后是否重置 'reset' => true ], + //FastAdmin配置 + 'fastadmin' => [ + 'version' => '1.0.0.20170808_beta', + 'api_url' => 'http://api.fastadmin.net', + ], ]; diff --git a/application/constants.php b/application/constants.php deleted file mode 100644 index c670814c..00000000 --- a/application/constants.php +++ /dev/null @@ -1,23 +0,0 @@ - false, + 'hooks' => + array ( + ), +); \ No newline at end of file diff --git a/application/extra/payment.php b/application/extra/payment.php deleted file mode 100644 index eeb49b10..00000000 --- a/application/extra/payment.php +++ /dev/null @@ -1,48 +0,0 @@ - [ - // 即时到账方式 - 'payment_type' => 1, - // 传输协议 - 'transport' => 'http', - // 编码方式 - 'input_charset' => 'utf-8', - // 签名方法 - 'sign_type' => 'MD5', - // 证书路径 - 'cacert' => './cacert.pem', - //验签公钥地址 - 'public_key_path' => './alipay_public_key.pem', - 'private_key_path' => '', - // 支付完成异步通知调用地址 - 'notify_url' => '/order/callback_alipay/notify', - // 支付完成同步返回地址 - 'return_url' => '/order/callback_alipay/return', - // 支付宝商家 ID - 'partner' => '2088xxxxxxxx', - // // 支付宝商家 KEY - 'key' => 'xxxxxxxxxxxx', - // // 支付宝商家注册邮箱 - 'seller_email' => 'email@domain.com' - ], - 'wechat' => [ - //微信支付配置数组 - // 公众账号appid - 'appid' => '', - // 商户号 - 'mch_id' => '', - // 加密key - 'apikey' => '', - // 公众号appsecret - 'appsecret' => '', - // 证书路径(apiclient_cert.pem) - 'sslcertPath' => '', - // 密钥路径(apiclient_key.pem) - 'sslkeyPath' => '', - // 支付完成异步通知调用地址 - 'notify_url' => '' - ] -]; diff --git a/application/extra/service.php b/application/extra/service.php deleted file mode 100644 index 4c7c64ff..00000000 --- a/application/extra/service.php +++ /dev/null @@ -1,42 +0,0 @@ - [ - 'key' => '', - 'secret' => '' - ], - // 环信配置 - 'easemob' => [ - 'org_name' => '', - 'app_name' => '', - 'client_id' => '', - 'client_secret' => '', - ], - // 七牛上传配置 - 'qiniu' => [ - 'secretkey' => '', - 'accesskey' => '', - //超时时间 - 'expire' => 86400, - //bucket配置 - 'file' => 'uploadbucket', - 'task' => 'taskbucket', - 'share' => 'sharebucket', - //bucket对应域名 - 'domain' => [ - 'uploadbucket' => 'http://1.qiniudn.com/', - 'taskbucket' => 'http://1.qiniudn.com/', - 'sharebucket' => 'http://1.qiniudn.com/', - ] - ], - // 又拍云配置 - 'upyun' => [ - 'bucketname' => '', - 'username' => '', - 'password' => '', - 'endpoint' => 'v0.api.upyun.com', - ] -]; diff --git a/application/extra/third.php b/application/extra/third.php deleted file mode 100644 index 9001c58b..00000000 --- a/application/extra/third.php +++ /dev/null @@ -1,28 +0,0 @@ - [ - 'app_id' => '', - 'app_secret' => '', - 'callback' => '', - ], - // 微信 - // 申请请到https://open.weixin.qq.com - 'wechat' => [ - 'app_id' => '', - 'app_secret' => '', - 'callback' => '', - 'scope' => 'snsapi_userinfo', - ], - // QQ - // 申请请到https://connect.qq.com - 'qq' => [ - 'app_id' => '', - 'app_secret' => '', - 'scope' => 'get_user_info', - 'callback' => '', - ], -]; diff --git a/application/extra/upload.php b/application/extra/upload.php index d461c3b5..e04fd0ca 100644 --- a/application/extra/upload.php +++ b/application/extra/upload.php @@ -3,29 +3,13 @@ //上传配置 return [ /** - * 上传地址,默认是本地上传,如果需要使用又拍云则改为http://v0.api.upyun.com/yourbucketname + * 上传地址,默认是本地上传 */ 'uploadurl' => 'ajax/upload', /** - * 本机的CDN地址或又拍云http://yourbucketname.b0.upaiyun.com + * CDN地址 */ 'cdnurl' => '', - /** - * 上传成功后的通知地址 - */ - 'notifyurl' => 'http://www.yoursite.com/upyun/notify', - /** - * 又拍云Bucket - */ - 'bucket' => 'yourbucketname', - /** - * 生成的policy有效时间 - */ - 'expire' => '86400', - /** - * 又拍云formkey - */ - 'formkey' => '', /** * 文件保存格式 */ @@ -42,12 +26,4 @@ return [ * 是否支持批量上传 */ 'multiple' => false, - /** - * 又拍云操作员用户名 - */ - 'username' => '', - /** - * 又拍云操作员密码 - */ - 'password' => '', ]; diff --git a/application/extra/wechat.php b/application/extra/wechat.php deleted file mode 100644 index e8fdfe74..00000000 --- a/application/extra/wechat.php +++ /dev/null @@ -1,64 +0,0 @@ - true, - /** - * 账号基本信息,请从微信公众平台/开放平台获取 - */ - 'app_id' => 'your-app-id', // AppID - 'secret' => 'your-app-secret', // AppSecret - 'token' => 'your-token', // Token - 'aes_key' => '', // EncodingAESKey,安全模式下请一定要填写!!! - /** - * 日志配置 - * - * level: 日志级别, 可选为: - * debug/info/notice/warning/error/critical/alert/emergency - * permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644) - * file:日志文件位置(绝对路径!!!),要求可写权限 - */ - 'log' => [ - 'level' => 'debug', - 'permission' => 0777, - 'file' => '/runtime/log/easywechat.log', - ], - /** - * OAuth 配置 - * - * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login - * callback:OAuth授权完成后的回调页地址 - */ - 'oauth' => [ - 'scopes' => ['snsapi_userinfo'], - 'callback' => 'http://www.yoursite.com/callback', - ], - /** - * 微信支付 - */ - 'payment' => [ - 'merchant_id' => 'your-mch-id', - 'key' => 'key-for-signature', - 'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径!!!! - 'key_path' => 'path/to/your/key', // XXX: 绝对路径!!!! - // 'device_info' => '013467007045764', - // 'sub_app_id' => '', - // 'sub_merchant_id' => '', - // ... - ], - /** - * Guzzle 全局设置 - * - * 更多请参考: http://docs.guzzlephp.org/en/latest/request-options.html - */ - 'guzzle' => [ - 'timeout' => 3.0, // 超时时间(秒) - //'verify' => false, // 关掉 SSL 认证(强烈不建议!!!) - ], -]; diff --git a/application/index/controller/Ajax.php b/application/index/controller/Ajax.php index 738f0a7a..26ee7a96 100644 --- a/application/index/controller/Ajax.php +++ b/application/index/controller/Ajax.php @@ -38,7 +38,6 @@ class Ajax extends Frontend public function upload() { $this->checkLogin(); - $this->code = -1; $file = $this->request->file('file'); //判断是否已经存在附件 @@ -46,11 +45,9 @@ class Ajax extends Frontend $uploaded = model("attachment")->where('sha1', $sha1)->find(); if ($uploaded) { - $this->code = 1; - $this->data = [ + $this->success('', null, [ 'url' => $uploaded['url'] - ]; - return; + ]); } $upload = Config::get('upload'); @@ -104,15 +101,14 @@ class Ajax extends Frontend 'sha1' => $sha1, ); model("attachment")->create(array_filter($params)); - $this->code = 1; - $this->data = [ + $this->success('', null, [ 'url' => $uploadDir . $splInfo->getSaveName() - ]; + ]); } else { // 上传失败获取错误信息 - $this->data = $file->getError(); + $this->error($file->getError()); } } diff --git a/application/index/controller/Autotask.php b/application/index/controller/Autotask.php deleted file mode 100644 index 03f75372..00000000 --- a/application/index/controller/Autotask.php +++ /dev/null @@ -1,135 +0,0 @@ -request->isCli()) - $this->error('Autotask script only work at client!'); - - parent::_initialize(); - - // 清除错误 - error_reporting(0); - - // 设置永不超时 - set_time_limit(0); - } - - /** - * 执行定时任务 - */ - public function crontab() - { - $time = time(); - $logDir = LOG_PATH . 'crontab/'; - if (!is_dir($logDir)) - { - mkdir($logDir); - } - //筛选未过期且未完成的任务 - $crontabList = Crontab::where('status', '=', 'normal')->order('weigh desc,id desc')->select(); - foreach ($crontabList as $crontab) - { - $update = []; - $execute = FALSE; - if ($time < $crontab['begintime']) - { - //任务未开始 - continue; - } - if ($crontab['maximums'] && $crontab['executes'] > $crontab['maximums']) - { - //任务已超过最大执行次数 - $update['status'] = 'completed'; - } - else if ($crontab['endtime'] > 0 && $time > $crontab['endtime']) - { - //任务已过期 - $update['status'] = 'expired'; - } - else - { - //重复执行 - //如果未到执行时间则继续循环 - if (!Date::cron($crontab['schedule'])) - continue; - $execute = TRUE; - } - - // 如果允许执行 - if ($execute) - { - $update['executetime'] = $time; - $update['executes'] = $crontab['executes'] + 1; - $update['status'] = ($crontab['maximums'] > 0 && $update['executes'] >= $crontab['maximums']) ? 'completed' : 'normal'; - } - - // 如果需要更新状态 - if (!$update) - continue; - // 更新状态 - $crontab->save($update); - - // 将执行放在后面是为了避免超时导致多次执行 - if (!$execute) - continue; - try - { - if ($crontab['type'] == 'url') - { - if (substr($crontab['content'], 0, 1) == "/") - { - // 本地项目URL - exec('nohup php ' . ROOT_PATH . 'public/index.php ' . $crontab['content'] . ' >> ' . $logDir . date("Y-m-d") . '.log 2>&1 &'); - } - else - { - // 远程异步调用URL - Http::sendAsyncRequest($crontab['content']); - } - } - else if ($crontab['type'] == 'sql') - { - //这里需要强制重连数据库,使用已有的连接会报2014错误 - $connect = Db::connect([], true); - $connect->execute("select 1"); - // 执行SQL - $connect->getPdo()->exec($crontab['content']); - } - else if ($crontab['type'] == 'shell') - { - // 执行Shell - exec($crontab['content'] . ' >> ' . $logDir . date("Y-m-d") . '.log 2>&1 &'); - } - } - catch (Exception $e) - { - Log::record($e->getMessage()); - } - } - return 'Execute completed!'; - } - -} diff --git a/application/index/controller/Common.php b/application/index/controller/Common.php deleted file mode 100644 index 3dab595d..00000000 --- a/application/index/controller/Common.php +++ /dev/null @@ -1,18 +0,0 @@ -view->fetch(); - } - - /** - * 二维码生成 - */ - public function qrcode() - { - if ($this->request->get("issubmit")) - { - $text = $this->request->get('text'); - $size = $this->request->get('size'); - $padding = $this->request->get('padding'); - $errorcorrection = $this->request->get('errorcorrection'); - $foreground = $this->request->get('foreground', "#fff"); - $background = $this->request->get('background', "#000"); - $logo = $this->request->get('logo'); - $logosize = $this->request->get('logosize'); - $label = $this->request->get('label'); - $labelfontsize = $this->request->get('labelfontsize'); - $labelhalign = $this->request->get('labelhalign'); - $labelvalign = $this->request->get('labelvalign'); - - - // 前景色 - list($r, $g, $b) = sscanf($foreground, "#%02x%02x%02x"); - $foregroundcolor = ['r' => $r, 'g' => $g, 'b' => $b]; - - // 背景色 - list($r, $g, $b) = sscanf($background, "#%02x%02x%02x"); - $backgroundcolor = ['r' => $r, 'g' => $g, 'b' => $b]; - - $qrCode = new QrCode(); - $qrCode - ->setText($text) - ->setSize($size) - ->setPadding($padding) - ->setErrorCorrection($errorcorrection) - ->setForegroundColor($foregroundcolor) - ->setBackgroundColor($backgroundcolor) - ->setLogoSize($logosize) - ->setLabelFontPath(ROOT_PATH . 'public/assets/fonts/fzltxh.ttf') - ->setLabel($label) - ->setLabelFontSize($labelfontsize) - ->setLabelHalign($labelhalign) - ->setLabelValign($labelvalign) - ->setImageType(QrCode::IMAGE_TYPE_PNG); - if ($logo) - { - $qrCode->setLogo(ROOT_PATH . 'public/assets/img/qrcode.png'); - } - //也可以直接使用render方法输出结果 - //$qrCode->render(); - return new Response($qrCode->get(), 200, ['Content-Type' => $qrCode->getContentType()]); - } - else - { - return $this->view->fetch(); - } - } - - /** - * Bootstrap组件 - */ - public function bootstrap() - { - return $this->view->fetch(); - } - - /** - * 阿里大于短信发送 - */ - public function alisms() - { - $alisms = new \fast\service\Alisms(); - $ret = $alisms->mobile('your mobile') - ->template('your sms template') - ->sign('your sign') - ->param(['code' => '8647']) - ->send(); - dump($ret); - } - -} diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php index aa611de7..598385fb 100755 --- a/application/index/controller/Index.php +++ b/application/index/controller/Index.php @@ -7,7 +7,7 @@ use app\common\controller\Frontend; class Index extends Frontend { - protected $layout = 'bootstrap'; + protected $layout = ''; public function _initialize() { diff --git a/application/index/controller/Sms.php b/application/index/controller/Sms.php deleted file mode 100644 index 3dc4bbb1..00000000 --- a/application/index/controller/Sms.php +++ /dev/null @@ -1,168 +0,0 @@ - - * 可选参数:无 - */ - public function send() - { - $this->code = -1; - $mobile = $this->request->post("mobile"); - $type = $this->request->post("type"); - $type = $type ? $type : 'register'; - - $last = Smslib::get($mobile, $type); - if ($last && time() - $last['createtime'] < 60) - { - //发送频繁 - $this->msg = __('SMS sent frequently'); - return; - } - if ($type) - { - $userinfo = User::getByMobile($mobile); - if ($type == 'register' && $userinfo) - { - //注册账号 - $this->msg = __('The phone number already exists'); - return; - } - else if ($type == 'changepwd' && !$userinfo) - { - //修改密码 - $this->msg = __('The phone number not exists'); - return; - } - else if (in_array($type, ['changemobile', 'bindmobile']) && $userinfo) - { - //修改手机号 - $this->msg = __('The phone number already exists'); - return; - } - } - $ret = Smslib::send($mobile, '', $type); - if ($ret) - { - $this->code = 1; - $this->msg = "发送成功"; - } - else - { - $this->msg = __('Send failed, please try again later'); - } - return; - } - - /** - * 检测验证码 - * - * 必选参数:mobile,type,captchacode
                - * 可选参数:无 - */ - public function check() - { - $this->code = -1; - $mobile = $this->request->post("mobile"); - $type = $this->request->post("type"); - $type = $type ? $type : 'register'; - $captchacode = $this->request->post("captchacode"); - - if ($type) - { - $userinfo = User::getByMobile($mobile); - if ($type == 'register' && $userinfo) - { - //注册账号 - $this->msg = __('The phone number already exists'); - return; - } - else if ($type == 'changepwd' && !$userinfo) - { - //修改密码 - $this->msg = __('The phone number note exists'); - return; - } - else if (in_array($type, ['changemobile', 'bindmobile']) && $userinfo) - { - //修改手机号 - $this->msg = __('The phone number already exists'); - return; - } - } - $ret = Smslib::check($mobile, $captchacode, $type); - if ($ret) - { - $this->code = 1; - } - else - { - $this->msg = __('The captcha code not correct'); - } - return; - } - - public function sendemail() - { - $this->code = -1; - $email = $this->request->post("email"); - $type = $this->request->post("type"); - $type = $type ? $type : 'register'; - - $name = "email{$type}"; - $session = session($name); - - if (!$session) - { - if (time() - $session['time'] < 120) - { - $this->msg = "发送邮箱验证码过于频繁"; - return; - } - } - - if (Smslib::sendemail($email, '', $type)) - { - $this->code = 1; - $this->msg = "发送成功"; - } - else - { - $this->msg = "发送邮件失败!请稍后重试!"; - } - } - - public function checkemail() - { - $this->code = -1; - $email = $this->request->post("email"); - $type = $this->request->post("type"); - $type = $type ? $type : 'register'; - - $ret = Smslib::checkemail($email, $captchacode, $type); - if ($ret) - { - $this->code = 1; - } - else - { - $this->msg = __('The captcha code not correct'); - } - } - -} diff --git a/application/index/controller/Ucenter.php b/application/index/controller/Ucenter.php deleted file mode 100644 index 6ea13180..00000000 --- a/application/index/controller/Ucenter.php +++ /dev/null @@ -1,363 +0,0 @@ -response(); - return; - } - - public function index() - { - $this->redirect('/'); - return; - } - - /** - * 删除用户 - */ - protected function deleteuser() - { - $uids = $this->get['ids']; - $uids = is_array($uids) ? $uids : explode(',', $uids); - !API_DELETEUSER && exit(API_RETURN_FORBIDDEN); - User::destroy($uids); - UserThird::destroy($uids); - $result = TRUE; - return $result ? API_RETURN_SUCCEED : API_RETURN_FAILED; - } - - /** - * 获取标签 - */ - protected function gettag() - { - $name = $this->get['id']; - if (!API_GETTAG) - { - return API_RETURN_FORBIDDEN; - } - $datalist = []; - if ($name == 'get_recently_list') - { - for ($i = 0; $i < 9; $i++) - { - $datalist[] = array( - 'name' => 'name' . $i, - 'uid' => 1, - 'username' => 'username' . $i, - 'dateline' => '2021', - 'url' => 'http://www.yourwebsite.com/thread.php?id=', - 'image' => 'http://www.yourwebsite.com/threadimage.php?id=', - ); - } - } - return $this->_serialize([$name, $datalist], 1); - } - - /** - * 同步注册 - */ - protected function synregister() - { - $uid = $this->get['uid']; - $username = $this->get['username']; - $password = $this->get['password']; - $email = isset($this->get['email']) ? $this->get['email'] : ''; - $mobile = isset($this->get['mobile']) ? $this->get['mobile'] : ''; - if (!API_SYNLOGIN) - { - return API_RETURN_FORBIDDEN; - } - // 同步注册接口 - header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); - $this->user->register($username, $password, $email, $mobile, [], 0, FALSE); - echo 'signup ok'; - } - - /** - * 同步登录 - */ - protected function synlogin() - { - $uid = $this->get['uid']; - $username = $this->get['username']; - if (!API_SYNLOGIN) - { - return API_RETURN_FORBIDDEN; - } - // 同步登录接口 - header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); - $this->user->direct($uid, FALSE); - echo 'login ok'; - } - - /** - * 同步退出 - */ - protected function synlogout() - { - if (!API_SYNLOGOUT) - { - return API_RETURN_FORBIDDEN; - } - - //同步登出接口 - header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); - $this->user->logout(); - echo 'logout ok'; - } - - /** - * 添加用户 - */ - protected function adduser() - { - $uid = $this->get['uid']; - $username = $this->get['username']; - $password = $this->get['password']; - $email = isset($this->get['email']) ? $this->get['email'] : ''; - $mobile = isset($this->get['mobile']) ? $this->get['mobile'] : ''; - if (!API_ADDUSER) - { - return API_RETURN_FORBIDDEN; - } - $time = time(); - $salt = Random::alnum(); - $password = $this->user->getEncryptPassword($password, $salt); - $ip = $this->request->ip(); - $userarr = [ - 'id' => $uid, - 'username' => $username, - 'password' => $password, - 'salt' => $salt, - 'email' => $email, - 'mobile' => $mobile, - 'jointime' => $time, - 'joinip' => $ip - ]; - User::save($userarr); - return API_RETURN_SUCCEED; - } - - /** - * 更新用户信息,包含用户名,密码,邮箱,手机号和其它扩展信息 - */ - protected function updateinfo() - { - if (!API_UPDATEINFO) - { - return API_RETURN_FORBIDDEN; - } - $uid = isset($this->get['uid']) ? $this->get['uid'] : 0; - $username = isset($this->get['username']) ? $this->get['username'] : ''; - $password = isset($this->get['password']) ? $this->get['password'] : ''; - $email = isset($this->get['email']) ? $this->get['email'] : ''; - $mobile = isset($this->get['mobile']) ? $this->get['mobile'] : ''; - print_r($this->get); - $userinfo = User::get($uid); - if (!$userinfo) - { - return API_RETURN_FAILED; - } - $values = []; - if ($username) - { - $values['username'] = $username; - } - if ($password) - { - $salt = Random::alnum(); - $password = $this->user->getEncryptPassword($password, $salt); - $values['password'] = $password; - $values['salt'] = $salt; - } - if ($email) - { - $values['email'] = $email; - } - if ($mobile) - { - $values['mobile'] = $mobile; - } - $userinfo->save($values); - return API_RETURN_SUCCEED; - } - - /** - * 更新禁言文字 - */ - protected function updatebadwords() - { - if (!API_UPDATEBADWORDS) - { - return API_RETURN_FORBIDDEN; - } - $cachefile = $this->appdir . './uc_client/data/cache/badwords.php'; - $fp = fopen($cachefile, 'w'); - $data = array(); - if (is_array($this->post)) - { - foreach ($this->post as $k => $v) - { - $data['findpattern'][$k] = $v['findpattern']; - $data['replace'][$k] = $v['replacement']; - } - } - $s = "appdir . './uc_client/data/cache/hosts.php'; - $fp = fopen($cachefile, 'w'); - $s = "post, TRUE) . ";\r\n"; - fwrite($fp, $s); - fclose($fp); - return API_RETURN_SUCCEED; - } - - /** - * 更新App信息 - */ - protected function updateapps() - { - if (!API_UPDATEAPPS) - { - return API_RETURN_FORBIDDEN; - } - $UC_API = $this->post['UC_API']; - - //note 写 app 缓存文件 - $cachefile = $this->appdir . './uc_client/data/cache/apps.php'; - $fp = fopen($cachefile, 'w'); - $s = "post, TRUE) . ";\r\n"; - fwrite($fp, $s); - fclose($fp); - - //note 写配置文件 - if (is_writeable($this->appdir . './config.inc.php')) - { - $configfile = trim(file_get_contents($this->appdir . './config.inc.php')); - $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile; - $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '$UC_API');", $configfile); - if ($fp = @fopen($this->appdir . './config.inc.php', 'w')) - { - @fwrite($fp, trim($configfile)); - @fclose($fp); - } - } - - return API_RETURN_SUCCEED; - } - - /** - * 更新客户端配置文件 - */ - protected function updateclient() - { - if (!API_UPDATECLIENT) - { - return API_RETURN_FORBIDDEN; - } - $cachefile = $this->appdir . './uc_client/data/cache/settings.php'; - $fp = fopen($cachefile, 'w'); - $s = "post, TRUE) . ";\r\n"; - fwrite($fp, $s); - fclose($fp); - return API_RETURN_SUCCEED; - } - - /** - * 更新积分 - */ - protected function updatecredit() - { - if (!API_UPDATECREDIT) - { - return API_RETURN_FORBIDDEN; - } - $credit = $this->get['credit']; - $amount = $this->get['amount']; - $uid = $this->get['uid']; - return API_RETURN_SUCCEED; - } - - /** - * 获取积分 - */ - protected function getcredit() - { - if (!API_GETCREDIT) - { - return API_RETURN_FORBIDDEN; - } - } - - /** - * 获取积分配置 - */ - protected function getcreditsettings() - { - if (!API_GETCREDITSETTINGS) - { - return API_RETURN_FORBIDDEN; - } - $credits = [ - '1' => array('威望', ''), - '2' => array('金钱', '枚'), - ]; - return $this->_serialize($credits); - } - - /** - * 更新积分配置 - */ - protected function updatecreditsettings() - { - if (!API_UPDATECREDITSETTINGS) - { - return API_RETURN_FORBIDDEN; - } - return API_RETURN_SUCCEED; - } - -} diff --git a/application/index/controller/Upyun.php b/application/index/controller/Upyun.php deleted file mode 100644 index d84eaba4..00000000 --- a/application/index/controller/Upyun.php +++ /dev/null @@ -1,58 +0,0 @@ -request->post("url"); - $code = $this->request->post("code"); - $message = $this->request->post("message"); - $sign = $this->request->post("sign"); - $time = $this->request->post("time"); - $extparam = $this->request->post("ext-param"); - if ($url && $code && $message && $time && $sign) - { - $arr = [$code, $message, $url, $time, Config::get('upload.formkey')]; - if ($extparam) - { - $arr[] = $extparam; - } - if ($sign == md5(implode('&', $arr))) - { - $params = array( - 'filesize' => $this->request->param("file_size"), - 'imagewidth' => $this->request->param("image-width"), - 'imageheight' => $this->request->param("image-height"), - 'imagetype' => $this->request->param("image-type"), - 'imageframes' => $this->request->param("image-frames"), - 'mimetype' => $this->request->param("mimetype"), - 'extparam' => $extparam, - 'url' => $url, - 'uploadtime' => $time, - 'storage' => 'upyun' - ); - model("attachment")->create(array_filter($params)); - echo "success"; - } - else - { - echo "failure"; - } - } - else - { - echo "failure"; - } - return; - } - -} diff --git a/application/index/controller/User.php b/application/index/controller/User.php deleted file mode 100644 index eb545e4b..00000000 --- a/application/index/controller/User.php +++ /dev/null @@ -1,222 +0,0 @@ -view->fetch(); - } - - /** - * 注册会员 - */ - public function register() - { - $url = $this->request->get('url', '/'); - if ($this->user->check()) - $this->error(__('You\'ve logged in, do not login again'), $url); - if ($this->request->isPost()) - { - $username = $this->request->post('username'); - $password = $this->request->post('password'); - $repassword = $password; - $email = $this->request->post('email'); - $captcha = $this->request->post('captcha'); - if (!captcha_check($captcha)) - { - $this->error(__('Captcha is incorrect')); - } - if ($this->user->register($username, $password, $email)) - { - $synchtml = ''; - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $synchtml = $uc->uc_user_synregister($this->user->id, $password); - } - $referer = Cookie::get('referer_url'); - $this->success(__('Sign up successful') . $synchtml, $url); - } - else - { - $this->error($this->user->getError()); - } - } - return $this->view->fetch(); - } - - /** - * 会员登录 - */ - public function login() - { - $url = $this->request->get('url', '/'); - if ($this->user->check()) - $this->error(__('You\'ve logged in, do not login again'), $url); - if ($this->request->isPost()) - { - $account = $this->request->post('account'); - $password = $this->request->post('password'); -// $captcha = $this->request->post('captcha'); -// if (!captcha_check($captcha)) -// { -// $this->error(__('Captcha is incorrect')); -// } - if ($this->user->login($account, $password)) - { - $synchtml = ''; - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $synchtml = $uc->uc_user_synlogin($this->user->id); - } - $this->success(__('Logged in successful') . $synchtml, $url); - } - else - { - $this->error($this->user->getError()); - } - } - return $this->view->fetch(); - } - - /** - * 注销登录 - */ - function logout() - { - //注销本站 - $this->user->logout(); - $synchtml = ''; - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $synchtml = $uc->uc_user_synlogout(); - } - $this->success(__('Logout successful') . $synchtml, '/'); - } - - /** - * 第三方登录跳转和回调处理 - */ - public function third() - { - $action = $this->request->param('action'); - $platform = $this->request->param('platform'); - $config = Config::get('third'); - if (!isset($config[$platform])) - { - $this->error(__('Invalid parameters')); - return; - } - $thirdapp = new Application(); - if ($action == 'redirect') - { - // 跳转到登录授权页面 - $this->redirect($thirdapp->{$platform}->getAuthorizeUrl()); - } - else if ($action == 'callback') - { - // 授权成功后的回调 - $result = $thirdapp->{$platform}->getUserInfo(); - if ($result) - { - $loginret = $this->user->connect($platform, $result); - if ($loginret) - { - $synchtml = ''; - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $synchtml = $uc->uc_user_synlogin($this->user->id); - } - $this->success(__('Logged in successful') . $synchtml, '/'); - return; - } - } - $this->error(__('Operation failed'), 'user/login'); - } - else - { - $this->error(__('Invalid parameters')); - } - - return; - } - - /** - * 修改密码 - */ - public function changepwd() - { - if ($this->request->isPost()) - { - $oldpassword = $this->request->post("oldpassword"); - $newpassword = $this->request->post("newpassword"); - //判断旧密码是否正确 - if ($this->user->password == $this->user->getEncryptPassword($oldpassword, $this->user->salt)) - { - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $ret = $uc->uc_user_edit($this->user->id, $this->user->username, $newpassword, $this->user->email, $this->user->mobile); - // 如果小于0则说明发生错误 - if ($ret < 0) - { - $this->error(__('Change password failure')); - } - } - - $salt = Random::alnum(); - $newpassword = $this->user->getEncryptPassword($newpassword, $salt); - $this->user->save(['password' => $newpassword, 'salt' => $salt]); - $this->user->logout(); - $synchtml = ''; - ////////////////同步到Ucenter//////////////// - if (defined('UC_STATUS') && UC_STATUS) - { - $uc = new Client(); - $synchtml = $uc->uc_user_synlogout(); - } - $this->success(__('Change password successful') . $synchtml, "user/login"); - } - else - { - //旧密码不正确 - $this->error(__('Password is incorrect')); - } - } - return $this->view->fetch(); - } - -} diff --git a/application/index/controller/Wechat.php b/application/index/controller/Wechat.php deleted file mode 100644 index eca68468..00000000 --- a/application/index/controller/Wechat.php +++ /dev/null @@ -1,192 +0,0 @@ -app = new Application(Config::get('wechat')); - } - - /** - * 微信API对接接口 - */ - public function api() - { - $this->app->server->setMessageHandler(function ($message) { - - $WechatService = new WechatService; - $WechatContext = new WechatContext; - $WechatResponse = new WechatResponse; - - $openid = $message->FromUserName; - $to_openid = $message->ToUserName; - $event = $message->Event; - $eventkey = $message->EventKey ? $message->EventKey : $message->Event; - - $unknownmessage = WechatConfig::value('default.unknown.message'); - $unknownmessage = $unknownmessage ? $unknownmessage : "对找到对应指令!"; - - switch ($message->MsgType) - { - case 'event': //事件消息 - switch ($event) - { - case 'subscribe'://添加关注 - $subscribemessage = WechatConfig::value('default.subscribe.message'); - $subscribemessage = $subscribemessage ? $subscribemessage : "欢迎关注我们!"; - return $subscribemessage; - case 'unsubscribe'://取消关注 - return ''; - case 'LOCATION'://获取地理位置 - return ''; - case 'VIEW': //跳转链接,eventkey为链接 - return ''; - default: - break; - } - - $response = $WechatResponse->where(["eventkey" => $eventkey, 'status' => 'normal'])->find(); - if ($response) - { - $content = (array) json_decode($response['content'], TRUE); - $context = $WechatContext->where(['openid' => $openid])->find(); - $data = ['eventkey' => $eventkey, 'command' => '', 'refreshtime' => time(), 'openid' => $openid]; - if ($context) - { - $WechatContext->data($data)->where('id', $context['id'])->update(); - $data['id'] = $context['id']; - } - else - { - $id = $WechatContext->data($data)->save(); - $data['id'] = $id; - } - $result = $WechatService->response($this, $openid, $content, $data); - if ($result) - { - return $result; - } - } - return $unknownmessage; - case 'text': //文字消息 - case 'image': //图片消息 - case 'voice': //语音消息 - case 'video': //视频消息 - case 'location': //坐标消息 - case 'link': //链接消息 - default: //其它消息 - //上下文事件处理 - $context = $WechatContext->where(['openid' => ['=', $openid], 'refreshtime' => ['>=', time() - 1800]])->find(); - if ($context && $context['eventkey']) - { - $response = $WechatResponse->where(['eventkey' => $context['eventkey'], 'status' => 'normal'])->find(); - if ($response) - { - $WechatContext->data(array('refreshtime' => time()))->where('id', $context['id'])->update(); - $content = (array) json_decode($response['content'], TRUE); - $result = $WechatService->command($this, $openid, $content, $context); - if ($result) - { - return $result; - } - } - } - //自动回复处理 - if ($message->MsgType == 'text') - { - $wechat_autoreply = new WechatAutoreply(); - $autoreply = $wechat_autoreply->where(['text' => $message->Content, 'status' => 'normal'])->find(); - if ($autoreply) - { - $response = $WechatResponse->where(["eventkey" => $autoreply['eventkey'], 'status' => 'normal'])->find(); - if ($response) - { - $content = (array) json_decode($response['content'], TRUE); - $context = $WechatContext->where(['openid' => $openid])->find(); - $result = $WechatService->response($this, $openid, $content, $context); - if ($result) - { - return $result; - } - } - } - } - return $unknownmessage; - } - return ""; //SUCCESS - }); - $response = $this->app->server->serve(); - // 将响应输出 - $response->send(); - } - - /** - * 登录回调 - */ - public function callback() - { - - } - - /** - * 支付回调 - */ - public function notify() - { - Log::record(file_get_contents('php://input'), "notify"); - $response = $this->app->payment->handleNotify(function($notify, $successful) { - // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单 - $orderinfo = Order::findByTransactionId($notify->transaction_id); - if ($orderinfo) - { - //订单已处理 - return true; - } - $orderinfo = Order::get($notify->out_trade_no); - if (!$orderinfo) - { // 如果订单不存在 - return 'Order not exist.'; // 告诉微信,我已经处理完了,订单没找到,别再通知我了 - } - // 如果订单存在 - // 检查订单是否已经更新过支付状态,已经支付成功了就不再更新了 - if ($orderinfo['paytime']) - { - return true; - } - // 用户是否支付成功 - if ($successful) - { - // 请在这里编写处理成功的处理逻辑 - - return true; // 返回处理完成 - } - else - { // 用户支付失败 - return true; - } - }); - - $response->send(); - } - -} diff --git a/application/index/lang/zh-cn.php b/application/index/lang/zh-cn.php index 840dfe4c..69ff6cf1 100644 --- a/application/index/lang/zh-cn.php +++ b/application/index/lang/zh-cn.php @@ -1,105 +1,90 @@ '保持会话', - 'Sign in' => '登入', - 'Username' => '用户名', - 'User id' => '会员ID', - 'Username' => '用户名', - 'Nickname' => '昵称', - 'Password' => '密码', - 'Sign up' => '注 册', - 'Sign in' => '登 录', - 'Sign out' => '注 销', - 'Keep login' => '保持会话', - 'Guest' => '游客', - 'Welcome' => '%s,你好!', - 'Add' => '添加', - 'Edit' => '编辑', - 'Delete' => '删除', - 'Move' => '移动', - 'Name' => '名称', - 'Status' => '状态', - 'Weigh' => '权重', - 'Operate' => '操作', - 'Warning' => '温馨提示', - 'Default' => '默认', - 'Article' => '文章', - 'Page' => '单页', - 'OK' => '确定', - 'Cancel' => '取消', - 'Loading' => '加载中', - 'More' => '更多', - 'Normal' => '正常', - 'Hidden' => '隐藏', - 'Submit' => '提交', - 'Reset' => '重置', - 'Execute' => '执行', - 'Close' => '关闭', - 'Search' => '搜索', - 'Refresh' => '刷新', - 'First' => '首页', - 'Previous' => '上一页', - 'Next' => '下一页', - 'Last' => '末页', - 'None' => '无', - 'Home' => '主页', - 'Online' => '在线', - 'Logout' => '注销', - 'Profile' => '个人资料', - 'Index' => '首页', - 'Hot' => '热门', - 'Recommend' => '推荐', - 'Dashboard' => '控制台', - 'Code' => '编号', - 'Message' => '内容', - 'Line' => '行号', - 'File' => '文件', - 'Menu' => '菜单', - 'Name' => '名称', - 'Weigh' => '权重', - 'Type' => '类型', - 'Title' => '标题', - 'Content' => '内容', - 'Status' => '状态', - 'Operate' => '操作', - 'Append' => '追加', - 'Memo' => '备注', - 'Parent' => '父级', - 'Params' => '参数', - 'Permission' => '权限', - 'Advance search' => '高级搜索', - 'Check all' => '选中全部', - 'Expand all' => '展开全部', - 'Begin time' => '开始时间', - 'End time' => '结束时间', - 'Create time' => '创建时间', - 'Flag' => '标志', - 'Redirect now' => '立即跳转', - 'Operation completed' => '操作成功!', - 'Operation failed' => '操作失败!', - 'Unknown data format' => '未知的数据格式!', - 'Network error' => '网络错误!', - 'Issues & Wiki' => '问题交流', - 'Advanced search' => '高级搜索', - 'Invalid parameters' => '未知参数', - 'No results were found' => '记录未找到', - 'Parameter %s can not be empty' => '参数%s不能为空', - 'Are you sure you want to delete the %s selected item?' => '确定删除选中的 %s 项?', - 'Are you sure you want to delete this item?' => '确定删除此项?', - 'Are you sure you want to delete or turncate?' => '确定删除或清空?', - 'You have no permission' => '你没有权限访问', - 'Please enter your username' => '请输入你的用户名', - 'Please enter your password' => '请输入你的密码', - 'Please login first' => '请登录后操作', - 'Sign up successful' => '注册成功', - 'Logged in successful' => '登录成功', - 'Logout successful' => '注销成功', - 'You\'ve logged in, do not login again' => '你已经登录,无需重复登录', - 'Username or password can not be empty' => '用户名密码不能为空', - 'Username is incorrect' => '用户名不正确', - 'Password is incorrect' => '密码不正确', - 'Verification code is incorrect' => '验证码不正确', - 'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中', - 'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转', + 'Keep login' => '保持会话', + 'Sign in' => '登入', + 'Username' => '用户名', + 'User id' => '会员ID', + 'Username' => '用户名', + 'Nickname' => '昵称', + 'Password' => '密码', + 'Sign up' => '注 册', + 'Sign in' => '登 录', + 'Sign out' => '注 销', + 'Keep login' => '保持会话', + 'Guest' => '游客', + 'Welcome' => '%s,你好!', + 'Add' => '添加', + 'Edit' => '编辑', + 'Delete' => '删除', + 'Move' => '移动', + 'Name' => '名称', + 'Status' => '状态', + 'Weigh' => '权重', + 'Operate' => '操作', + 'Warning' => '温馨提示', + 'Default' => '默认', + 'Article' => '文章', + 'Page' => '单页', + 'OK' => '确定', + 'Cancel' => '取消', + 'Loading' => '加载中', + 'More' => '更多', + 'Normal' => '正常', + 'Hidden' => '隐藏', + 'Submit' => '提交', + 'Reset' => '重置', + 'Execute' => '执行', + 'Close' => '关闭', + 'Search' => '搜索', + 'Refresh' => '刷新', + 'First' => '首页', + 'Previous' => '上一页', + 'Next' => '下一页', + 'Last' => '末页', + 'None' => '无', + 'Home' => '主页', + 'Online' => '在线', + 'Logout' => '注销', + 'Profile' => '个人资料', + 'Index' => '首页', + 'Hot' => '热门', + 'Recommend' => '推荐', + 'Dashboard' => '控制台', + 'Code' => '编号', + 'Message' => '内容', + 'Line' => '行号', + 'File' => '文件', + 'Menu' => '菜单', + 'Name' => '名称', + 'Weigh' => '权重', + 'Type' => '类型', + 'Title' => '标题', + 'Content' => '内容', + 'Status' => '状态', + 'Operate' => '操作', + 'Append' => '追加', + 'Memo' => '备注', + 'Parent' => '父级', + 'Params' => '参数', + 'Permission' => '权限', + 'Advance search' => '高级搜索', + 'Check all' => '选中全部', + 'Expand all' => '展开全部', + 'Begin time' => '开始时间', + 'End time' => '结束时间', + 'Create time' => '创建时间', + 'Flag' => '标志', + 'Redirect now' => '立即跳转', + 'Operation completed' => '操作成功!', + 'Operation failed' => '操作失败!', + 'Unknown data format' => '未知的数据格式!', + 'Network error' => '网络错误!', + 'Advanced search' => '高级搜索', + 'Invalid parameters' => '未知参数', + 'No results were found' => '记录未找到', + 'Parameter %s can not be empty' => '参数%s不能为空', + 'You have no permission' => '你没有权限访问', + 'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中', + 'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转', ]; diff --git a/application/index/lang/zh-cn/sms.php b/application/index/lang/zh-cn/sms.php deleted file mode 100644 index 1e1459f7..00000000 --- a/application/index/lang/zh-cn/sms.php +++ /dev/null @@ -1,9 +0,0 @@ - '短信发送频繁', - 'The phone number already exists' => '手机号已经存在', - 'The phone number note exists' => '手机号不存在', - 'The captcha code not correct' => '验证码不正确', - 'Send failed, please try again later' => '发送失败,请稍后重试', -]; diff --git a/application/index/view/demo/bootstrap.html b/application/index/view/demo/bootstrap.html deleted file mode 100644 index 51a645db..00000000 --- a/application/index/view/demo/bootstrap.html +++ /dev/null @@ -1,1646 +0,0 @@ -
                - - -
                -
                -
                - - -
                - -
                - -
                - -
                - -
                -
                -
                - - - -
                - - -
                -
                - -

                - - - - - - - -

                - -

                - - - - - - - -

                - - -
                -
                - - - - - - - - - -
                -
                - -

                - - - - -

                - -

                - - Delete - - Settings -

                -

                - - Font Awesome
                Version 4.4.0
                -

                -

                -

                - - - - -
                -

                -

                -

                - - -
                -

                -

                -

                - - -
                -

                -

                -

                -

                -

                -

                -

                -
                -
                - -

                - -

                - - -
                -
                - Left - Middle - Right -
                -
                - -
                -
                -
                - - - - -
                - -
                - - - -
                - -
                - -
                - - -
                -
                -
                -
                - -
                -
                - - - - -
                -
                - -
                -
                -
                - - -
                -
                -
                - -
                -
                - - - -
                -
                -
                -

                Heading 1

                -

                Heading 2

                -

                Heading 3

                -

                Heading 4

                -
                Heading 5
                -
                Heading 6
                -

                Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

                -
                -
                -
                -
                -

                Example body text

                -

                Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.

                -

                This line of text is meant to be treated as fine print.

                -

                The following snippet of text is rendered as bold text.

                -

                The following snippet of text is rendered as italicized text.

                -

                The following snippet of text is rendered as code.

                -

                An abbreviation of the word attribute is attr.

                -
                - -
                -
                -
                -

                Emphasis classes

                -

                Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

                -

                Nullam id dolor id nibh ultricies vehicula ut id elit.

                -

                Etiam porta sem malesuada magna mollis euismod.

                -

                Donec ullamcorper nulla non metus auctor fringilla.

                -

                Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

                -

                Maecenas sed diam eget risus varius blandit sit amet non magna.

                -
                - -
                -
                - - - -
                -
                -

                Blockquotes

                -
                -
                -
                -
                -
                -
                -

                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

                - Someone famous in Source Title -
                -
                -
                -
                -
                -
                -

                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

                - Someone famous in Source Title -
                -
                -
                -
                -
                - - - -
                - -
                - - -
                - -
                -
                - -

                Bordered table && Hover rows

                -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                ID Name PhoneCompany ZipCity Date
                1Jennifer1-342-463-8341Et Rutrum Non Associates35728Fogo03/04/14
                2Clark1-516-859-1120Nam Ac Inc.7162Machelen03/23/13
                3Brendan1-724-406-2487Enim Commodo Limited98611Norman02/13/14
                4Warren1-412-485-9725Odio Etiam Institute10312Sautin01/01/13
                5Rajah1-849-642-8777Neque Ltd29131Glovertown02/16/13
                -
                -

                Striped rows

                -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                #First NameLast NameUsername
                1MarkOtto@mdo
                2JacobThornton@fat
                3Larrythe Bird@twitter
                -
                -

                Contextual classes

                -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                #Column headingColumn headingColumn heading
                1Column contentColumn contentColumn content
                2Column contentColumn contentColumn content
                3Column contentColumn contentColumn content
                4Column contentColumn contentColumn content
                5Column contentColumn contentColumn content
                6Column contentColumn contentColumn content
                7Column contentColumn contentColumn content
                -
                -
                -
                -
                - -
                -
                -

                Thumbnails

                -
                -
                -
                -
                -
                - - 100%x180 - -
                -
                - - 100%x180 - -
                -
                - - 100%x180 - -
                -
                - - 100%x180 - -
                -
                -
                -
                -
                -

                Custom content

                -
                -
                -
                -
                -
                -
                - 100%x200 -
                -

                Thumbnail label

                -

                Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

                -

                Button Button

                -
                -
                -
                -
                -
                - 100%x200 -
                -

                Thumbnail label

                -

                Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

                -

                Button Button

                -
                -
                -
                -
                -
                - 100%x200 -
                -

                Thumbnail label

                -

                Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

                -

                Button Button

                -
                -
                -
                -
                -
                - -
                -
                -

                Default media

                -
                -
                -
                -
                -
                - - 64x64 - -
                -
                -

                Media heading

                - Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. -
                -
                -
                -
                - - 64x64 - -
                -
                -

                Media heading

                - Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. -
                -
                - - 64x64 - -
                -
                -

                Nested media heading

                - Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. -
                -
                -
                -
                -
                -
                -

                Media heading

                - Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. -
                -
                - - 64x64 - -
                -
                -
                -
                - - 64x64 - -
                -
                -

                Media heading

                - Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. -
                -
                - - 64x64 - -
                -
                -
                - - -
                -
                -
                - -
                -
                - -
                -
                -
                -
                -
                - Legend -
                - -
                - -
                -
                -
                - -
                - -
                - -
                -
                -
                -
                - -
                - - A longer block of help text that breaks onto a new line and may extend beyond one line. -
                -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                -
                - -
                - -
                - -
                -
                -
                -
                - - -
                -
                -
                -
                -
                -
                -
                - -
                -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - - -
                - -
                - -
                - $ - - - - -
                -
                -
                - -
                -
                -
                - - -
                - -
                -
                - -
                -
                - -
                -
                - -
                - -
                -
                -

                Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

                -
                -
                -

                Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit.

                -
                - - -
                -
                -
                - -
                - -
                - - - - - -
                - -
                -
                - - -
                -
                -

                Pagination

                -
                - - - - - -
                -
                -
                -

                Pager

                -
                - - - -
                -
                -
                - -
                -
                -
                - - - -
                - -
                - - -
                - -
                -
                - - -
                -
                -
                - -
                -
                -

                Alerts

                -
                -
                - -

                Warning!

                -

                Best check yo self, you're not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

                -
                -
                -
                -
                -
                -
                -
                -
                - - Oh snap! Change a few things up and try submitting again. -
                -
                -
                -
                -
                -
                - - Well done! You successfully read this important alert message. -
                -
                -
                -
                -
                -
                - - Heads up! This alert needs your attention, but it's not super important. -
                -
                -
                -
                -
                -
                -

                Labels

                -
                - Default - Primary - Success - Warning - Danger - Info -
                -
                -
                -

                Badges

                - -
                -
                - - -
                - -
                -
                - - -

                Basic

                -
                -
                -
                -
                -
                - -

                Contextual alternatives

                -
                -
                -
                -
                - -
                -
                -
                - -
                -
                -
                - -
                -
                -
                -
                - -

                Striped

                -
                -
                -
                -
                - -
                -
                -
                - -
                -
                -
                - -
                -
                -
                -
                - -

                Animated

                -
                -
                -
                -
                -
                - -

                Stacked

                -
                -
                -
                -
                -
                -
                -
                -
                -
                -
                - - -
                - -
                -
                - -
                -
                -

                Jumbotron

                -

                This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

                -

                Learn more

                -
                -
                -
                -
                - - -
                -
                -

                List groups

                -
                -
                - - - -
                -
                -

                Panels

                -
                -
                -
                -
                -
                -
                -
                - Basic panel -
                -
                - -
                -
                Panel heading
                -
                - Panel content -
                -
                - -
                -
                - Panel content -
                - -
                -
                -
                -
                -
                -
                -
                -

                Panel primary

                -
                -
                - Panel content -
                -
                - -
                -
                -

                Panel success

                -
                -
                - Panel content -
                -
                - -
                -
                -

                Panel warning

                -
                -
                - Panel content -
                -
                -
                -
                -
                -
                -
                -
                -

                Panel danger

                -
                -
                - Panel content -
                -
                - -
                -
                -

                Panel info

                -
                -
                - Panel content -
                -
                -
                -
                -
                - -
                -
                -

                Wells

                -
                -
                -
                -
                -
                -
                - Look, I'm in a well! -
                -
                -
                -
                -
                -
                - Look, I'm in a small well! -
                -
                -
                -
                -
                -
                - Look, I'm in a large well! -
                -
                -
                -
                -
                - - -
                - -
                -
                - -
                -
                -
                -
                -

                Modals

                -
                - Show modal dialog - -
                -

                Bootstrap3-Dialog Plugin

                - -
                -
                -

                Popovers

                -
                - - - - - - - -
                -

                Tooltips

                -
                - - - - - - - -
                -
                -
                -
                - -
                -

                Toastr

                -
                -
                -
                -
                - - -
                -
                - - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                - -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                - -
                -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                -
                - -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                -
                -
                - -
                -
                - - - -
                -
                - -
                -
                -
                
                -            
                -
                -
                - -
                \ No newline at end of file diff --git a/application/index/view/demo/index.html b/application/index/view/demo/index.html deleted file mode 100644 index d6fd4405..00000000 --- a/application/index/view/demo/index.html +++ /dev/null @@ -1,7 +0,0 @@ -
                -
                -
                - Demo -
                -
                -
                \ No newline at end of file diff --git a/application/index/view/demo/qrcode.html b/application/index/view/demo/qrcode.html deleted file mode 100644 index 3e85d000..00000000 --- a/application/index/view/demo/qrcode.html +++ /dev/null @@ -1,149 +0,0 @@ -
                -

                二维码生成

                -
                -
                - -
                -
                -
                - - -
                -
                - - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                -
                - - -
                -
                - -
                -
                - -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                - -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                - -
                -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                -
                - -
                -
                - - -
                -
                - - -
                -
                -
                - -
                - -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                -
                -
                -
                -
                - -
                \ No newline at end of file diff --git a/application/index/view/index/index.html b/application/index/view/index/index.html index 207946b3..ce236ac7 100644 --- a/application/index/view/index/index.html +++ b/application/index/view/index/index.html @@ -1,55 +1,224 @@ -
                - - + -
                -
                -
                - -
                -

                第三方登录

                -

                FastAdmin中自带第三方登录扩展组件,包括微博登录、QQ登录、微信登录,可极速进行第三方登录的融合,同时系统中已提供注册登录的代码

                -

                预览 下载

                + + + + + + + FastAdmin - 基于ThinkPHP5和Bootstrap的极速后台开发框架 + + + + + + + + + + + + + + + + + + + + + + +
                +
                +
                +
                +
                +
                +

                FastAdmin

                +

                基于ThinkPHP5和Bootstrap的极速后台开发框架

                + 登录后台 +
                +
                +
                -
                -
                -
                - -
                -

                Ucenter整合登录

                -

                FastAdmin中基于Ucenter融合一套账号同步登录注册退出的方案,同时提供修改版Ucenter和Discuz论坛代码下载,同时适应于PHP7,此版本改动较大,建议适用于新系统的开发

                -

                预览 下载

                + + +
                +
                +
                +
                +
                +

                功能特性

                +
                +
                +
                +
                +
                +
                +
                +
                +
                + +

                权限管理

                +

                基于完善的Auth权限控制管理、无限父子级权限分组、可自由分配子级权限、一个管理员可同时属于多个组别

                +
                +
                +
                +
                + +

                响应式开发

                +

                基于Bootstrap和AdminLTE进行二次开发,手机、平板、PC均自动适配,无需要担心兼容性问题

                +
                +
                +
                +
                + +

                多语言

                +

                不仅仅后台开发支持多语言,同时视图部分和JS部分仍然共享同一个语言包,语法相同且自动加载

                +
                +
                +
                +
                + +

                模块化开发

                +

                控制器、模型、视图、JS一一对应,使用RequireJS进行JS模块化管理,采用Bower进行前端包组件管理

                +
                +
                +
                +
                + +

                CRUD

                +

                控制台进行一键生成控制器、模型、视图和JS文件,同时可一键生成后台权限节点和菜单栏

                +
                +
                +
                +
                + +

                自由可扩展

                +

                FastAdmin提供强大的扩展中心,可直接在线安装和卸载插件,同时支持命令行一键操作

                +
                +
                +
                +
                +
                -
                -
                -
                - -
                -

                二维码生成

                -

                基于第三方组件增加了一个二维码的生成示例,可快速的调整文字、标签、Logo的大小、颜色、字体等等。此外还可对标签位置、容错率等进行相关设置。

                -

                预览 下载

                + + +
                +
                +
                +

                不要犹豫
                开始行动

                + 为FastAdmin贡献代码!
                -
                -
                -
                - -
                -

                Bootstrap组件

                -

                由于FastAdmin对Bootstrap进行了大量的二次开发,对Bootstrap的组件样式有许多更改,你可以直接在这里预览到Bootstrap的部分组件

                -

                预览 下载

                -
                +
                + + +
                +
                +

                © 2017 FastAdmin. All Rights Reserved.

                +
                -
                -
                -
                \ No newline at end of file + + + + + + + + + + + + + + + + + + + diff --git a/application/index/view/layout/bootstrap.html b/application/index/view/layout/bootstrap.html deleted file mode 100644 index ee325811..00000000 --- a/application/index/view/layout/bootstrap.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - FastAdmin - - - - - - - - - - - - - - - - - - - {__CONTENT__} - - - - - - \ No newline at end of file diff --git a/application/index/view/layout/user.html b/application/index/view/layout/user.html deleted file mode 100644 index 309c2fe2..00000000 --- a/application/index/view/layout/user.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - 会员中心 - - - - - - - - - - - - - -
                -
                -
                -
                - {__CONTENT__} -
                -
                -
                -
                - - \ No newline at end of file diff --git a/application/index/view/user/changepwd.html b/application/index/view/user/changepwd.html deleted file mode 100644 index 5c8a71a9..00000000 --- a/application/index/view/user/changepwd.html +++ /dev/null @@ -1,34 +0,0 @@ -
                -
                -
                - -
                -
                -
                -
                -
                - - - -
                -
                - - - -
                -
                - - - -
                - - 返回 -
                -
                -
                -
                -
                -
                -
                \ No newline at end of file diff --git a/application/index/view/user/index.html b/application/index/view/user/index.html deleted file mode 100644 index 1c866400..00000000 --- a/application/index/view/user/index.html +++ /dev/null @@ -1,44 +0,0 @@ -
                -
                -
                - -
                -
                - {if $user->check()} -
                -
                -
                -

                - {:__('Welcome', $user->nickname)}
                - Lv:{$user->level} -

                -
                -
                - - - 立即注销 - {else/} - 立即注册 - 立即登录 - {/if} -
                -
                -
                -
                -
                \ No newline at end of file diff --git a/application/index/view/user/login.html b/application/index/view/user/login.html deleted file mode 100644 index 06f74d37..00000000 --- a/application/index/view/user/login.html +++ /dev/null @@ -1,48 +0,0 @@ -
                -
                -
                - -
                -
                -
                -
                -
                - - - -
                -
                - - - -
                -
                Wrong username og password
                -
                - -
                - - 注册一个新账号 -
                -
                -
                -
                -

                会员权益

                -
                  -
                • 最新代码推送
                • -
                • 发布评论
                • -
                • 个性化头像
                • -
                • 定制专属页面
                • -
                • 发现更多
                • -
                - 微博登录 - 微信登录 - QQ登录 -
                -
                -
                -
                -
                \ No newline at end of file diff --git a/application/index/view/user/register.html b/application/index/view/user/register.html deleted file mode 100644 index 01af6d5c..00000000 --- a/application/index/view/user/register.html +++ /dev/null @@ -1,62 +0,0 @@ -
                -
                -
                - -
                -
                -
                -
                -
                - - - -
                -
                - - - -
                -
                - - - -
                -
                - - - -
                -
                - -
                - - - - -
                - -
                - - 已经账号,立即登录 -
                -
                -
                -
                -

                会员权益

                -
                  -
                • 最新代码推送
                • -
                • 发布评论
                • -
                • 个性化头像
                • -
                • 定制专属页面
                • -
                • 发现更多
                • -
                - 微博登录 - 微信登录 - QQ登录 -
                -
                -
                -
                -
                \ No newline at end of file diff --git a/application/uc.php b/application/uc.php deleted file mode 100644 index 17976ba4..00000000 --- a/application/uc.php +++ /dev/null @@ -1,24 +0,0 @@ -rules = Db::name($this->config['auth_rule'])->where($where)->field('id,pid,condition,icon,name,title,ismenu')->select(); - + //循环规则,判断结果。 $rulelist = []; // if (in_array('*', $ids)) @@ -248,7 +248,6 @@ class Auth } } $_rulelist[$uid] = $rulelist; - //登录验证则需要保存规则列表 if (2 == $this->config['auth_type']) { diff --git a/application/common/model/Version.php b/extend/fast/Version.php similarity index 50% rename from application/common/model/Version.php rename to extend/fast/Version.php index 31864bad..fb50a2d0 100644 --- a/application/common/model/Version.php +++ b/extend/fast/Version.php @@ -1,136 +1,93 @@ - 'normal'], [], TRUE); - foreach ($versionlist as $k => $v) - { - // 版本正常且新版本号不等于验证的版本号且找到匹配的旧版本 - if ($v['status'] == 'normal' && $v['newversion'] !== $version && self::inversion($version, $v['oldversion'])) - { - $updateversion = $v; - break; - } - } - if (isset($updateversion)) - { - $search = ['{version}', '{newversion}', '{downloadurl}', '{url}', '{packagesize}']; - $replace = [$version, $updateversion['newversion'], $updateversion['downloadurl'], $updateversion['downloadurl'], $updateversion['packagesize']]; - $upgradetext = str_replace($search, $replace, $updateversion['content']); - return [ - "enforce" => $updateversion['enforce'], - "version" => $version, - "newversion" => $updateversion['newversion'], - "downloadurl" => $updateversion['downloadurl'], - "packagesize" => $updateversion['packagesize'], - "upgradetext" => $upgradetext - ]; - } - return NULL; - } - - /** - * 检测版本是否的版本要求的数据中 - * - * @param string $version - * @param array $data - */ - public static function inversion($version, $data = []) - { - //版本号以.分隔 - $data = is_array($data) ? $data : [$data]; - if ($data) - { - if (in_array("*", $data) || in_array($version, $data)) - { - return TRUE; - } - $ver = explode('.', $version); - if ($ver) - { - $versize = count($ver); - //验证允许的版本 - foreach ($data as $m) - { - $c = explode('.', $m); - if (!$c || $versize != count($c)) - continue; - $i = 0; - foreach ($c as $a => $k) - { - if (!self::compare($ver[$a], $k)) - { - continue 2; - } - else - { - $i++; - } - } - if ($i == $versize) - return TRUE; - } - } - } - return FALSE; - } - - /** - * 比较两个版本号 - * - * @param string $v1 - * @param string $v2 - * @return boolean - */ - public static function compare($v1, $v2) - { - if ($v2 == "*" || $v1 == $v2) - { - return TRUE; - } - else - { - $values = []; - $k = explode(',', $v2); - foreach ($k as $v) - { - if (strpos($v, '-') !== FALSE) - { - list($start, $stop) = explode('-', $v); - for ($i = $start; $i <= $stop; $i++) - { - $values[] = $i; - } - } - else - { - $values[] = $v; - } - } - return in_array($v1, $values) ? TRUE : FALSE; - } - } - -} + $k) + { + if (!self::compare($ver[$a], $k)) + { + continue 2; + } + else + { + $i++; + } + } + if ($i == $versize) + return TRUE; + } + } + } + return FALSE; + } + + /** + * 比较两个版本号 + * + * @param string $v1 + * @param string $v2 + * @return boolean + */ + public static function compare($v1, $v2) + { + if ($v2 == "*" || $v1 == $v2) + { + return TRUE; + } + else + { + $values = []; + $k = explode(',', $v2); + foreach ($k as $v) + { + if (strpos($v, '-') !== FALSE) + { + list($start, $stop) = explode('-', $v); + for ($i = $start; $i <= $stop; $i++) + { + $values[] = $i; + } + } + else + { + $values[] = $v; + } + } + return in_array($v1, $values) ? TRUE : FALSE; + } + } + +} diff --git a/extend/fast/payment/Alipay.php b/extend/fast/payment/Alipay.php deleted file mode 100644 index 97d4e522..00000000 --- a/extend/fast/payment/Alipay.php +++ /dev/null @@ -1,447 +0,0 @@ - 1, - // 传输协议 - 'transport' => 'http', - // 编码方式 - 'input_charset' => 'utf-8', - // 签名方法 - 'sign_type' => 'MD5', - // 证书路径 - 'cacert' => './cacert.pem', - //验签公钥地址 - 'public_key_path' => './alipay_public_key.pem', - 'private_key_path' => '', - // 支付完成异步通知调用地址 - // 'notify_url' => 'http://'.$_SERVER['HTTP_HOST'].'/order/callback_alipay/notify', - // 支付完成同步返回地址 - // 'return_url' => 'http://'.$_SERVER['HTTP_HOST'].'/order/callback_alipay/return', - // 支付宝商家 ID - 'partner' => '2088xxxxxxxx', - // // 支付宝商家 KEY - 'key' => 'xxxxxxxxxxxx', - // // 支付宝商家注册邮箱 - 'seller_email' => 'email@domain.com' - ); - private $is_mobile = FALSE; - public $service = self::SERVICE; - public $gateway = self::GATEWAY; - - /** - * 配置 - * @param $options array 配置信息 - * @param null $type string 类型 wap app - */ - public function __construct($options = [], $type = null) - { - if ($config = Config::get('payment.alipay')) - { - $this->config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - $this->is_mobile = (($type == 'wap' || $type === true) ? true : false); - if ($this->is_mobile) - { - $this->gateway = self::GATEWAY_MOBILE; - } - - if ($type == 'wap' || $type === true) - { - $this->service = self::SERVICE_WAP; - } - elseif ($type == 'app') - { - $this->service = self::SERVICE_APP; - } - } - - /** - * 生成请求参数的签名 - * - * @param $params - * @return - * - */ - function signParameters($params) - { - // 支付宝的签名串必须是未经过 urlencode 的字符串 - // 不清楚为何 PHP 5.5 里没有 http_build_str() 方法 - $paramStr = urldecode(http_build_query($params)); - switch (strtoupper(trim($this->config['sign_type']))) - { - case "MD5" : - $result = md5($paramStr . $this->config['key']); - break; - case "RSA" : - case "0001" : - $priKey = file_get_contents($this->config['private_key_path']); - $res = openssl_get_privatekey($priKey); - openssl_sign($paramStr, $sign, $res); - openssl_free_key($res); - //base64编码 - $result = base64_encode($sign); - break; - default : - $result = ""; - } - return $result; - } - - /** - * 准备签名参数 - * - * @param $params - * $params['out_trade_no'] 唯一订单编号 - * $params['subject'] - * $params['total_fee'] - * $params['body'] - * $params['show_url'] - * $params['anti_phishing_key'] - * $params['exter_invoke_ip'] - * $params['it_b_pay'] - * $params['_input_charset'] - * @return - */ - function prepareParameters($params) - { - $default = array( - 'service' => $this->service, - 'partner' => $this->config['partner'], - '_input_charset' => trim(strtolower($this->config['input_charset'])) - ); - if (!$this->is_mobile) - { - $default = array_merge($default, array( - 'payment_type' => $this->config['payment_type'], - 'seller_id' => $this->config['partner'], - 'notify_url' => $this->config['notify_url'], - )); - if (isset($this->config['return_url'])) - { - $default['return_url'] = $this->config['return_url']; - } - } - - $params = $this->filterSignParameter(array_merge($default, (array) $params)); - ksort($params); - reset($params); - return $params; - } - - /** - * 生成签名后的请求参数 - * - */ - function buildSignedParameters($params) - { - $params = $this->prepareParameters($params); - $params['sign'] = $this->signParameters($params); - if ($params['service'] != self::SERVICE_WAP && $params['service'] != self::SERVICE_WAP_AUTH) - { - $params['sign_type'] = strtoupper(trim($this->config['sign_type'])); - } - return $params; - } - - /** - * https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.NgdeQA&treeId=59&articleId=103663&docType=1 - * 服务端生成app支付使用的参数以及签名 - * @param $params - * @return - */ - function buildSignedParametersForApp($params) - { - $params = $this->prepareParameters($params); - $params['sign'] = urlencode($this->signParameters($params)); - $params['sign_type'] = 'RSA'; - $paramStr = []; - foreach ($params as $k => &$param) - { - $param = '"' . $param . '"'; - $paramStr[] = $k . '=' . $param; - } - - return implode('&', $paramStr); - } - - /** - * 生成请求参数的发送表单HTML - * - * 其实这个函数没有必要,更应该使用签名后的参数自己组装,只不过有时候方便就从官方 SDK 里留下了。 - * - * @param $params 请求参数(未签名的) - * @param $method 请求方法,默认:post,可选 get - * @param $target 提交目标,默认:_self - * @return - * - */ - function buildRequestFormHTML($params, $method = 'post', $target = '_self') - { - $params = $this->buildSignedParameters($params); - $html = '
                config['input_charset'])) . '" method="' . $method . ' target="$target">'; - foreach ($params as $key => $value) - { - $html .= ""; - } - $html .= "
                "; - return $html; - } - - /** - * 准备移动网页支付的请求参数 - * - * 移动网页支付接口不同,需要先服务器提交一次请求,拿到返回 token 再返回客户端发起真实支付请求。 - * 该方法只完成第一次服务端请求,生成参数后需要客户端另行处理(可调用`buildRequestFormHTML`生成表单提交)。 - * - * @param $params - * $params['out_trade_no'] 订单唯一编号 - * $params['subject'] 商品标题 - * $params['total_fee'] 支付总费用 - * $params['merchant_url'] 商品链接地址 - * $params['req_id'] 请求唯一 ID - * $params['it_b_pay'] 超期时间(秒) - * @return / - */ - function prepareMobileTradeData($params) - { - // 不要用 SimpleXML 来构建 xml 结构,因为有第一行文档申明支付宝验证不通过 - $xml_str = '' . - '' . $this->config['notify_url'] . '' . - '' . $this->config['return_url'] . '' . - '' . $this->config['seller_email'] . '' . - '' . $params['out_trade_no'] . '' . - '' . htmlspecialchars($params['subject'], ENT_XML1, 'UTF-8') . '' . - '' . $params['total_fee'] . '' . - '' . $params['merchant_url'] . '' . - (isset($params['it_b_pay']) ? '' . $params['it_b_pay'] . '' : '') . - ''; - $request_data = $this->buildSignedParameters(array( - 'service' => $this->service, - 'partner' => $this->config['partner'], - 'sec_id' => $this->config['sign_type'], - 'format' => 'xml', - 'v' => '2.0', - 'req_id' => $params['req_id'], - 'req_data' => $xml_str - )); - $url = $this->gateway; - $input_charset = trim(strtolower($this->config['input_charset'])); - if (trim($input_charset) != '') - { - $url = $url . "_input_charset=" . $input_charset; - } - $curl = curl_init($url); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证 - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证 - curl_setopt($curl, CURLOPT_CAINFO, $this->config['cacert']); //证书地址 - curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果 - curl_setopt($curl, CURLOPT_POST, true); // post传输数据 - curl_setopt($curl, CURLOPT_POSTFIELDS, $request_data); // post传输数据 - $responseText = curl_exec($curl); - //var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 - curl_close($curl); - if (empty($responseText)) - { - return NULL; - } - parse_str($responseText, $responseData); - if (empty($responseData['res_data'])) - { - return NULL; - } - if ($this->config['sign_type'] == '0001') - { - $responseData['res_data'] = $this->rsaDecrypt($responseData['res_data'], $this->config['private_key_path']); - } - //token从res_data中解析出来(也就是说res_data中已经包含token的内容) - $doc = new DOMDocument(); - $doc->loadXML($responseData['res_data']); - $responseData['request_token'] = $doc->getElementsByTagName("request_token")->item(0)->nodeValue; - $xml_str = '' . - '' . $responseData['request_token'] . '' . - ''; - return array( - 'service' => self::SERVICE_WAP_AUTH, - 'partner' => $this->config['partner'], - 'sec_id' => $this->config['sign_type'], - 'format' => 'xml', - 'v' => '2.0', - 'req_data' => $xml_str - ); - } - - /** - * 支付完成验证返回参数(包含同步和异步) - * - * @return - */ - function verifyCallback() - { - $async = empty($_GET); - $data = $async ? $_POST : $_GET; - if (empty($data)) - { - return FALSE; - } - $signValid = $this->verifyParameters($data, $data["sign"]); - $notify_id = isset($data['notify_id']) ? $data['notify_id'] : NULL; - if ($async && $this->is_mobile) - { - //对notify_data解密 - if ($this->config['sign_type'] == '0001') - { - $data['notify_data'] = $this->rsaDecrypt($data['notify_data'], $this->config['private_key_path']); - } - //notify_id从decrypt_post_para中解析出来(也就是说decrypt_post_para中已经包含notify_id的内容) - $doc = new DOMDocument(); - $doc->loadXML($data['notify_data']); - $notify_id = $doc->getElementsByTagName('notify_id')->item(0)->nodeValue; - } - //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) - $responseTxt = 'true'; - if (!empty($notify_id)) - { - $responseTxt = $this->verifyFromServer($notify_id); - } - //验证 - //$signValid的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 - //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 - return $signValid && preg_match("/true$/i", $responseTxt); - } - - function verifyParameters($params, $sign) - { - $params = $this->filterSignParameter($params); - if (isset($params['notify_data'])) - { - $params = array( - 'service' => $params['service'], - 'v' => $params['v'], - 'sec_id' => $params['sec_id'], - 'notify_data' => $params['notify_data'] - ); - } - else - { - ksort($params); - reset($params); - } - $content = urldecode(http_build_query($params)); - switch (strtoupper(trim($this->config['sign_type']))) - { - case "MD5" : - return md5($content . $this->config['key']) == $sign; - case "RSA" : - case "0001" : - return $this->rsaVerify($content, $this->config['public_key_path'], $sign); - default : - return FALSE; - } - } - - /** - * 过滤参数,去除sign/sign_type参数 - * @param $params - * @return - */ - function filterSignParameter($params) - { - $result = array(); - foreach ($params as $key => $value) - { - if ($key != 'sign' && $key != 'sign_type' && $value) - { - $result[$key] = $value; - } - } - return $result; - } - - function verifyFromServer($notify_id) - { - $transport = strtolower(trim($this->config['transport'])); - $partner = trim($this->config['partner']); - $veryfy_url = ($transport == 'https' ? self::VERIFY_URL_HTTPS : self::VERIFY_URL) . "partner=$partner¬ify_id=$notify_id"; - $curl = curl_init($veryfy_url); - curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头 - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证 - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果 - curl_setopt($curl, CURLOPT_CAINFO, $this->config['cacert']); //证书地址 - $responseText = curl_exec($curl); - // var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 - curl_close($curl); - return $responseText; - } - - /** - * RSA验签,注意验签的公钥是支付宝的公钥,不是自己生成的rsa公钥,可以在淘宝的demo中获得 - * @param $data string 待签名数据 - * @param $ali_public_key_path string 支付宝的公钥文件路径 - * @param $sign string 要校对的的签名结果 - * @return 验证结果 - * @throws Exception - */ - function rsaVerify($data, $ali_public_key_path, $sign) - { - $pubKey = file_get_contents($ali_public_key_path); - $res = openssl_get_publickey($pubKey); - if (!$res) - { - throw new Exception('公钥格式错误'); - } - $result = (bool) openssl_verify($data, base64_decode($sign), $res); - openssl_free_key($res); - return $result; - } - - /** - * RSA解密 - * @param $content string 需要解密的内容,密文 - * @param $private_key_path string 商户私钥文件路径 - * @return string 解密后内容,明文 - */ - function rsaDecrypt($content, $private_key_path) - { - $priKey = file_get_contents($private_key_path); - $res = openssl_get_privatekey($priKey); - //用base64将内容还原成二进制 - $content = base64_decode($content); - //把需要解密的内容,按128位拆开解密 - $result = ''; - for ($i = 0; $i < strlen($content) / 128; $i++) - { - $data = substr($content, $i * 128, 128); - openssl_private_decrypt($data, $decrypt, $res); - $result .= $decrypt; - } - openssl_free_key($res); - return $result; - } - -} diff --git a/extend/fast/payment/Wechat.php b/extend/fast/payment/Wechat.php deleted file mode 100644 index d414099b..00000000 --- a/extend/fast/payment/Wechat.php +++ /dev/null @@ -1,440 +0,0 @@ -_config = array_merge($this->_config, $config); - } - $this->_config = array_merge($this->_config, is_array($options) ? $options : []); - } - - /** - * JSAPI获取prepay_id - * - * @param string $body - * @param string $out_trade_no - * @param int $total_fee - * @param string $openid - * @param array $ext - * @return string - */ - public function getPrepayId($body, $out_trade_no, $total_fee, $openid, $ext = null) - { - $data = $ext? : []; - $data["nonce_str"] = $this->getNonceStr(); - $data["body"] = $body; - $data["out_trade_no"] = $out_trade_no; - $data["total_fee"] = $total_fee; - $data["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"]; - $data["trade_type"] = self::TRADETYPE_JSAPI; - $data["openid"] = $openid; - $result = $this->unifiedOrder($data); - if ($result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS") - { - return $result["prepay_id"]; - } - else - { - $this->error = $result["return_code"] == "SUCCESS" ? $result["err_code_des"] : $result["return_msg"]; - $this->errorXML = $this->array2xml($result); - return null; - } - } - - private function getNonceStr() - { - return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 32); - } - - /** - * 统一下单接口 - */ - public function unifiedOrder($params) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["device_info"] = (isset($params['device_info']) && trim($params['device_info']) != '') ? $params['device_info'] : null; - $data["nonce_str"] = $this->getNonceStr(); - $data["body"] = $params['body']; - $data["detail"] = isset($params['detail']) ? $params['detail'] : null; //optional - $data["attach"] = isset($params['attach']) ? $params['attach'] : null; //optional - $data["out_trade_no"] = isset($params['out_trade_no']) ? $params['out_trade_no'] : null; - $data["fee_type"] = isset($params['fee_type']) ? $params['fee_type'] : 'CNY'; - $data["total_fee"] = $params['total_fee']; - $data["spbill_create_ip"] = $params['spbill_create_ip']; - $data["time_start"] = isset($params['time_start']) ? $params['time_start'] : null; //optional - $data["time_expire"] = isset($params['time_expire']) ? $params['time_expire'] : null; //optional - $data["goods_tag"] = isset($params['goods_tag']) ? $params['goods_tag'] : null; - $data["notify_url"] = isset($params['notify_url']) ? $params['notify_url'] : $this->_config['notify_url']; - $data["trade_type"] = $params['trade_type']; - $data["product_id"] = isset($params['product_id']) ? $params['product_id'] : null; //required when trade_type = NATIVE - $data["openid"] = isset($params['openid']) ? $params['openid'] : null; //required when trade_type = JSAPI - $result = $this->post(self::URL_UNIFIEDORDER, $data); - return $result; - } - - private function post($url, $data, $cert = false) - { - if (!isset($data['sign'])) - $data["sign"] = $this->sign($data); - $xml = $this->array2xml($data); - $ch = curl_init(); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_URL, $url); - if ($cert == true) - { - //使用证书:cert 与 key 分别属于两个.pem文件 - curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); - curl_setopt($ch, CURLOPT_SSLCERT, $this->_config['sslcertPath']); - curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); - curl_setopt($ch, CURLOPT_SSLKEY, $this->_config['sslkeyPath']); - } - $content = curl_exec($ch); - $array = $this->xml2array($content); - return $array; - } - - /** - * 扫码支付(模式二)获取支付二维码 - * - * @param string $body - * @param string $out_trade_no - * @param int $total_fee - * @param string $product_id - * @param array $ext - * @return string - */ - public function getCodeUrl($body, $out_trade_no, $total_fee, $product_id, $ext = null) - { - $data = $ext ? $ext : []; - $data["nonce_str"] = $this->getNonceStr(); - $data["body"] = $body; - $data["out_trade_no"] = $out_trade_no; - $data["total_fee"] = $total_fee; - $data["spbill_create_ip"] = $_SERVER["SERVER_ADDR"]; - $data["trade_type"] = self::TRADETYPE_NATIVE; - $data["product_id"] = $product_id; - $result = $this->unifiedOrder($data); - if ($result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS") - { - return $result["code_url"]; - } - else - { - $this->error = $result["return_code"] == "SUCCESS" ? $result["err_code_des"] : $result["return_msg"]; - return null; - } - } - - /** - * 查询订单 - * @param $transaction_id - * @param $out_trade_no - * @return array - */ - public function orderQuery($transaction_id, $out_trade_no) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["transaction_id"] = $transaction_id; - $data["out_trade_no"] = $out_trade_no; - $data["nonce_str"] = $this->getNonceStr(); - $result = $this->post(self::URL_ORDERQUERY, $data); - return $result; - } - - /** - * 关闭订单 - * @param $out_trade_no - * @return array - */ - public function closeOrder($out_trade_no) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["out_trade_no"] = $out_trade_no; - $data["nonce_str"] = $this->getNonceStr(); - $result = $this->post(self::URL_CLOSEORDER, $data); - return $result; - } - - /** - * 申请退款 - 使用商户订单号 - * @param $out_trade_no 商户订单号 - * @param $out_refund_no 退款单号 - * @param $total_fee 总金额(单位:分) - * @param $refund_fee 退款金额(单位:分) - * @param $op_user_id 操作员账号 - * @return array - */ - public function refund($out_trade_no, $out_refund_no, $total_fee, $refund_fee, $op_user_id) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["nonce_str"] = $this->getNonceStr(); - $data["out_trade_no"] = $out_trade_no; - $data["out_refund_no"] = $out_refund_no; - $data["total_fee"] = $total_fee; - $data["refund_fee"] = $refund_fee; - $data["op_user_id"] = $op_user_id; - $result = $this->post(self::URL_REFUND, $data, true); - return $result; - } - - /** - * 申请退款 - 使用微信订单号 - * @param $transaction_id 微信订单号 - * @param $out_refund_no 退款单号 - * @param $total_fee 总金额(单位:分) - * @param $refund_fee 退款金额(单位:分) - * @param $op_user_id 操作员账号 - * @return array - */ - public function refundByTransId($transaction_id, $out_refund_no, $total_fee, $refund_fee, $op_user_id) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["nonce_str"] = $this->getNonceStr(); - $data["transaction_id"] = $transaction_id; - $data["out_refund_no"] = $out_refund_no; - $data["total_fee"] = $total_fee; - $data["refund_fee"] = $refund_fee; - $data["op_user_id"] = $op_user_id; - $result = $this->post(self::URL_REFUND, $data, true); - return $result; - } - - /** - * 下载对账单 - * @param $bill_date 下载对账单的日期,格式:20140603 - * @param string $bill_type 类型 - * @return array - */ - public function downloadBill($bill_date, $bill_type = 'ALL') - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["bill_date"] = $bill_date; - $data["bill_type"] = $bill_type; - $data["nonce_str"] = $this->getNonceStr(); - $result = $this->post(self::URL_DOWNLOADBILL, $data); - return $result; - } - - /** - * 扫码原生支付模式一中的二维码链接转成短链接 - * @param $long_url 需要转换的URL,签名用原串,传输需URLencode - * @return array - */ - public function shortUrl($long_url) - { - $data = array(); - $data["appid"] = $this->_config["appid"]; - $data["mch_id"] = $this->_config["mch_id"]; - $data["long_url"] = $long_url; - $data["nonce_str"] = $this->getNonceStr(); - $data["sign"] = $this->sign($data); - $data["long_url"] = urlencode($long_url); - $result = $this->post(self::URL_SHORTURL, $data); - return $result; - } - - /** - * 获取jsapi支付所需参数 - * - * @param string $prepay_id - * @return array - */ - public function getPackageData($prepay_id) - { - $data = array(); - $data["appId"] = $this->_config["appid"]; - //解决微信支付调用JSAPI缺少参数:timeStamp - $data["timeStamp"] = time(); - $data["nonceStr"] = $this->getNonceStr(); - $data["package"] = "prepay_id=$prepay_id"; - $data["signType"] = "MD5"; - $data["paySign"] = $this->sign($data); - return $data; - } - - /** - * 获取发送到通知地址的数据(在通知地址内使用) - * @return string 结果数组,如果不是微信服务器发送的数据返回null - * appid - * bank_type - * cash_fee - * fee_type - * is_subscribe - * mch_id - * nonce_str - * openid - * out_trade_no 商户订单号 - * result_code - * return_code - * sign - * time_end - * total_fee 总金额 - * trade_type - * transaction_id 微信支付订单号 - */ - public function getNotifyData() - { - $xml = file_get_contents("php://input"); - $data = $this->xml2array($xml); - if ($this->validate($data)) - { - return $data; - } - else - { - return null; - } - } - - /** - * 验证数据签名 - * @param $data 数据数组 - * @return 数据校验结果 - */ - public function validate($data) - { - if (!isset($data["sign"])) - { - return false; - } - $sign = $data["sign"]; - unset($data["sign"]); - return $this->sign($data) == $sign; - } - - /** - * 响应微信支付后台通知 - * @param string $return_code 返回状态码 SUCCESS/FAIL - * @param $return_msg 返回信息 - */ - public function response_back($return_code = "SUCCESS", $return_msg = null) - { - $data = array(); - $data["return_code"] = $return_code; - if ($return_msg) - { - $data["return_msg"] = $return_msg; - } - $xml = $this->array2xml($data); - print $xml; - } - - /** - * 数据签名 - * @param $data - * @return string - */ - private function sign($data) - { - ksort($data); - $string1 = ""; - foreach ($data as $k => $v) - { - if ($v && trim($v) != '') - { - $string1 .= "$k=$v&"; - } - } - $stringSignTemp = $string1 . "key=" . $this->_config["apikey"]; - $sign = strtoupper(md5($stringSignTemp)); - return $sign; - } - - private function array2xml($array) - { - $xml = "" . PHP_EOL; - foreach ($array as $k => $v) - { - if ($v && trim($v) != '') - $xml .= "<$k>" . PHP_EOL; - } - $xml .= ""; - return $xml; - } - - private function xml2array($xml) - { - $array = array(); - $tmp = null; - try - { - $tmp = (array) simplexml_load_string($xml); - } - catch (Exception $e) - { - - } - if ($tmp && is_array($tmp)) - { - foreach ($tmp as $k => $v) - { - $array[$k] = (string) $v; - } - } - return $array; - } - -} diff --git a/extend/fast/service/Alisms.php b/extend/fast/service/Alisms.php deleted file mode 100644 index 92d87cf4..00000000 --- a/extend/fast/service/Alisms.php +++ /dev/null @@ -1,167 +0,0 @@ -config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - } - - /** - * 单例 - * @param array $options 参数 - * @return Alisms - */ - public static function instance($options = []) - { - if (is_null(self::$instance)) - { - self::$instance = new static($options); - } - - return self::$instance; - } - - /** - * 设置签名 - * @param string $sign - * @return Alisms - */ - public function sign($sign = '') - { - $this->_params['sms_free_sign_name'] = $sign; - return $this; - } - - /** - * 设置参数 - * @param array $param - * @return Alisms - */ - public function param(array $param = []) - { - foreach ($param as $k => &$v) - { - $v = (string) $v; - } - unset($v); - $this->_params['sms_param'] = json_encode($param); - return $this; - } - - /** - * 设置模板 - * @param string $code 短信模板 - * @return Alisms - */ - public function template($code = '') - { - $this->_params['sms_template_code'] = $code; - return $this; - } - - /** - * 接收手机 - * @param string $mobile 手机号码 - * @return Alisms - */ - public function mobile($mobile = '') - { - $this->_params['rec_num'] = $mobile; - return $this; - } - - /** - * 立即发送 - * @return boolean - */ - public function send() - { - $this->error = []; - $params = $this->_params(); - $params['sign'] = $this->_signed($params); - $reponse = $this->_curl($params); - if ($reponse !== FALSE) - { - $res = json_decode($reponse, TRUE); - $res = array_pop($res); - if (isset($res['result'])) - return TRUE; - $this->error = $res; - } - else - { - $this->error = array('code' => 0, 'msg' => 'HTTP_RESPONSE_NOT_WELL_FORMED'); - } - return FALSE; - } - - /** - * 获取错误信息 - * @return array - */ - public function getError() - { - return $this->error; - } - - private function _params() - { - return array_merge([ - 'app_key' => $this->config['key'], - 'format' => 'json', - 'method' => 'alibaba.aliqin.fc.sms.num.send', - 'v' => '2.0', - 'timestamp' => date('Y-m-d H:i:s'), - 'sign_method' => 'md5', - 'sms_type' => 'normal' - ], $this->_params); - } - - private function _signed($params) - { - ksort($params); - $sign = $this->config['secret']; - foreach ($params as $k => $v) - { - if (is_string($v) && '@' != substr($v, 0, 1)) - $sign .= $k . $v; - } - $sign .= $this->config['secret']; - return strtoupper(md5($sign)); - } - - private function _curl($params) - { - $uri = 'https://eco.taobao.com/router/rest?' . http_build_query($params); - $ch = curl_init(); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); - curl_setopt($ch, CURLOPT_URL, $uri); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); - curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36"); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); - $reponse = curl_exec($ch); - curl_close($ch); - return $reponse; - } - -} diff --git a/extend/fast/service/Easemob.php b/extend/fast/service/Easemob.php deleted file mode 100644 index c1a9da54..00000000 --- a/extend/fast/service/Easemob.php +++ /dev/null @@ -1,307 +0,0 @@ - $username, 'password' => $password]; - if ($nickname) - { - $params['nickname'] = $nickname; - } - return self::api('users', $params, $token); - } - - /** - * 创建聊天室 - * - * @param string $name 名称 - * @param string $description 描述 - * @param string $owner 创建人 - * @param int $maxusers 最多参与者 - * @param array $members 成员 - * @return array - */ - public static function createRoom($name, $description, $owner, $maxusers = 5000, $members = []) - { - $owner = (string) $owner; - $params = [ - "name" => $name, //聊天室名称,此属性为必须的 - "description" => $description, //聊天室描述,此属性为必须的 - "maxusers" => $maxusers, //聊天室成员最大数(包括群主),值为数值类型,默认值200,最大值5000,此属性为可选的 - "owner" => $owner, //聊天室的管理员,此属性为必须的 - ]; - if ($members) - { - if (!in_array($owner, $members)) - { - $members[] = $owner; - } - $params['members'] = $members; - } - return self::api('chatrooms', $params, TRUE); - } - - /** - * 创建群组 - * - * @param string $name 名称 - * @param string $description 描述 - * @param string $owner 管理员 - * @param int $maxusers 最大成员数量 - * @param array $members 成员列表 - * @param boolean $public 是否公开 - * @param boolean $approval 加入是否审核 - * @return array - */ - public static function createGroup($name, $description, $owner, $maxusers = 2000, $members = [], $public = TRUE, $approval = FALSE) - { - $owner = (string) $owner; - $params = [ - "groupname" => $name, - "desc" => $description, - "public" => (bool) $public, - "maxusers" => $maxusers, - "approval" => (bool) $approval, - "owner" => $owner, - ]; - if ($members) - { - if (!in_array($owner, $members)) - { - $members[] = $owner; - } - $params['members'] = $members; - } - return self::api('chatgroups', $params, TRUE); - } - - /** - * 修改群组信息 - * - * @param int $group_id - * @param string $name - * @param string $description - * @param int $maxusers - * @return array - */ - public static function editGroup($group_id, $name, $description, $maxusers) - { - $params = [ - "groupname" => $name, - "desc" => $description, - "maxusers" => $maxusers, - ]; - return self::api('chatgroups/' . $group_id, $params, TRUE, 'PUT'); - } - - /** - * 获取好友列表 - */ - public static function getFiends($owner_username) - { - return self::api("users/{$owner_username}/contacts/users", [], TRUE, 'GET'); - } - - /** - * 删除群组 - * - * @param int $group_id - * @return array - */ - public static function deleteGroup($group_id) - { - $params = []; - return self::api('chatgroups/' . $group_id, $params, TRUE, 'DELETE'); - } - - /** - * 发送消息 - * - * @param string $from 发件人 - * @param string $to 收件人 - * @param mixed $msg 消息内容 - * @param string $target_type 消息类型 users/chatgroups/chatrooms - * @return array - */ - public static function sendMessage($from, $to, $msg, $target_type = 'users') - { - if (!is_array($msg)) - { - $msg = [ - 'type' => 'txt', - 'msg' => $msg - ]; - } - $data = [ - 'target_type' => $target_type, - 'target' => is_array($to) ? $to : [$to], - 'from' => $from, - ]; - if (isset($msg['ext'])) - { - $data['ext'] = $msg['ext']; - } - unset($msg['ext']); - $data['msg'] = $msg; - return self::api('messages', $data); - } - - /** - * 获取离线消息记录条数 - * @param string $owner_username - * @return array - */ - public static function getOfflineMsgCount($owner_username) - { - return self::api("users/{$owner_username}/offline_msg_count", [], TRUE, 'GET'); - } - - /** - * 群组添加成员 - * @param int $chatroom_id - * @param array $usernames - * @param array - */ - public static function addChatRoomMembers($chatroom_id, $usernames) - { - return self::api("chatgroups/{$chatroom_id}/users", $usernames, TRUE); - } - - /** - * 添加单个成员POST - */ - public static function addOneChatRoomMember($chatroom_id, $username) - { - //return $chatroom_id; - return self::api("chatgroups/{$chatroom_id}/users/{$username}", [], TRUE); - } - - /** - * 群组删除成员 - * @param int $chatroom_id - * @param string $usernames - * @return array - */ - public static function minusChatRoomMembers($chatroom_id, $usernames) - { - return self::api("chatgroups/{$chatroom_id}/users/{$usernames}", [], TRUE, 'DELETE'); - } - - /** - * 添加好友 - */ - public static function addFriends($owner_username, $friend_username) - { - return self::api("users/{$owner_username}/contacts/users/{$friend_username}", [], TRUE); - } - - /** - * 删除好友 - */ - public static function minusFriends($owner_username, $friend_username) - { - return self::api("users/{$owner_username}/contacts/users/{$friend_username}", [], TRUE, 'DELETE'); - } - - /** - * 查看用户参与的所有群组 - * @param type $owner_username - * @return type - */ - public static function joinedChatgroups($owner_username) - { - return self::api("users/{$owner_username}/joined_chatgroups", [], TRUE, 'GET'); - } - - /** - * 调用API接口 - * - * @param string $api 接口 - * @param array $params request head参数 - * @param boolean $token 是否认证模式 - * @param string $method 请求方法 POST/GET - * @param array $options 扩展配置 - * @return array - */ - public static function api($api, $params = [], $token = TRUE, $method = 'POST', $options = []) - { - $header = ['Content-Type:application/json']; - if ($token) - { - $header[] = self::getNewToken(); - } - $config = Config::get('service.easemob'); - $options[CURLOPT_HTTPHEADER] = $header; - - $url = self::URL . '/' . $config['org_name'] . '/' . $config['app_name'] . '/' . $api; - //return $url; - $ret = Http::sendRequest($url, json_encode($params), $method, $options); - if ($ret['ret'] && $ret['msg']) - { - $msg = json_decode($ret['msg'], TRUE); - if (isset($msg['error'])) - { - Log::error($ret['msg']); - } - return isset($msg['error']) ? [] : $msg; - } - else - { - return []; - } - } - - private static function getToken() - { - $tokendata = Cache::get('easemobtoken'); - if ($tokendata && $tokendata['expiretime'] > time()) - { - return $tokendata['access_token']; - } - else - { - $config = Config::get('service.easemob'); - $data = self::api('token', [ - 'grant_type' => 'client_credentials', - 'client_id' => $config['client_id'], - 'client_secret' => $config['client_secret'], - ], FALSE, 'POST'); - if ($data) - { - $data['expiretime'] = time() + $data['expires_in']; - Cache::set('easemobtoken', $data, $data['expires_in'] - 10); - return $data['access_token']; - } - else - { - return ''; - } - } - } - -} diff --git a/extend/fast/service/Qiniu.php b/extend/fast/service/Qiniu.php deleted file mode 100644 index c240bd58..00000000 --- a/extend/fast/service/Qiniu.php +++ /dev/null @@ -1,187 +0,0 @@ -_config['bucket']; - $op = '/move/' . self::qiniuEncode($from) . '/' . self::qiniuEncode($to); - return self::opration($op); - } - - /** - * 复制文件 - * - * @param string $from 来源文件 - * @param string $saveas 目标文件 - * @return bool - */ - public static function copy($from, $saveas) - { - // $bucket = $this->_config['bucket']; - $op = '/copy/' . self::qiniuEncode($from) . '/' . self::qiniuEncode($saveas); - return self::opration($op); - } - - /** - * 获取token - * - * @param string $bucket 空间名 - * @param string $key 密钥 - * @param int $max 文件大小限制 - * @param int $timeout 超时时间 - * @return string - */ - public static function getToken($bucket, $key, $max = 10485760, $timeout = 600) - { - $setting = array( - 'scope' => $bucket, - 'saveKey' => $key, - 'deadline' => $timeout + $_SERVER['REQUEST_TIME'], - 'fsizeLimit' => intval($max), - ); - $setting = self::qiniuEncode(json_encode($setting)); - return self::sign($setting) . ':' . $setting; - } - - /** - * 删除 - * - * @param string $uri 文件路径 - * @return boolean - */ - public static function delete($uri) - { - $file = self::qiniuEncode($uri); - return self::opration('/delete/' . $file); - } - - /** - * 判断文件是否存在 - * - * @param string $uri - * @return boolean - */ - public static function has($uri) - { - $op = '/stat/' . self::qiniuEncode($uri); - return self::opration($op); - } - - /** - * 转pdf - * - * @param string $bucket - * @param string $key - * @param string $saveas - * @return boolean - */ - public static function toPdf($bucket, $key, $saveas) - { - $API = 'http://api.qiniu.com'; - $op = '/pfop/'; - $data = 'bucket=' . $bucket . '&key=' . $key . '&fops=yifangyun_preview|saveas/' . self::qiniuEncode($saveas); - return self::opration($op, $data, $API); - } - - /** - * 七牛操作 - * - * @param string $op 操作命令 - * @param string $data 操作结果 - * @param string $host - * @return boolean - */ - private static function opration($op, $data = null, $host = self::QINIU_RS) - { - $token = self::sign(is_string($data) ? $op . "\n" . $data : $op . "\n"); - $url = $host . $op; - $header = array('Authorization: QBox ' . $token); - - if ($ch = curl_init($url)) - { - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, $header); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); - if ($data) - { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - } - curl_setopt($ch, CURLOPT_HEADER, 1); - $response = curl_exec($ch); - $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - - if ($status == 200) - { - return true; - } - // elseif (\Config::get('debug')) - // { - // /*操作出错*/ - // \Log::debug($response, '七牛请求出错'); - // } - } - Log::error('[QINIU]七牛错误' . $url . ':' . ($response ? : '请求失败'), 'ERROR'); - return false; - } - - /** - * 获取url签名 - * - * @param string $url - * @return string - */ - private static function sign($url) - { - $config = self::$_config ? : (self::$_config = Config::get('service.qiniu')); - $sign = hash_hmac('sha1', $url, $config['secretkey'], true); - $ak = $config['accesskey']; - return $ak . ':' . self::qiniuEncode($sign); - } - - /** - * 七牛安全编码 - */ - private static function qiniuEncode($str) - { - return strtr(base64_encode($str), ['+' => '-', '/' => '_']); - } - -} diff --git a/extend/fast/service/Upyun.php b/extend/fast/service/Upyun.php deleted file mode 100644 index eaddea02..00000000 --- a/extend/fast/service/Upyun.php +++ /dev/null @@ -1,572 +0,0 @@ -config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - } - - /* }}} */ - - /** - * 获取当前SDK版本号 - */ - public function version() - { - return self::VERSION; - } - - /** - * 创建目录 - * @param $path 路径 - * @param $auto_mkdir 是否自动创建父级目录,最多10层次 - * - * @return void - */ - public function makeDir($path, $auto_mkdir = false) - {/* {{{ */ - $headers = array('Folder' => 'true'); - if ($auto_mkdir) - $headers['Mkdir'] = 'true'; - return $this->_do_request('PUT', $path, $headers); - } - - /* }}} */ - - /** - * 删除目录和文件 - * @param string $path 路径 - * - * @return boolean - */ - public function delete($path) - {/* {{{ */ - return $this->_do_request('DELETE', $path); - } - - /* }}} */ - - /** - * 上传文件 - * @param string $path 存储路径或文件 - * @param mixed $file 需要上传的文件,可以是文件流或者文件内容 - * @param boolean $auto_mkdir 自动创建目录 - * @param array $opts 可选参数 - */ - public function upload($path, $file = NULL, $auto_mkdir = True, $opts = NULL) - { - return $this->writeFile($path, $file, $auto_mkdir, $opts); - } - - public function writeFile($path, $file = NULL, $auto_mkdir = True, $opts = NULL) - {/* {{{ */ - if (is_null($file)) - $file = ROOT_PATH . 'public/' . $path; - if (is_null($opts)) - $opts = array(); - if (!is_null($this->_content_md5) || !is_null($this->_file_secret)) - { - //if (!is_null($this->_content_md5)) array_push($opts, self::CONTENT_MD5 . ": {$this->_content_md5}"); - //if (!is_null($this->_file_secret)) array_push($opts, self::CONTENT_SECRET . ": {$this->_file_secret}"); - if (!is_null($this->_content_md5)) - $opts[self::CONTENT_MD5] = $this->_content_md5; - if (!is_null($this->_file_secret)) - $opts[self::CONTENT_SECRET] = $this->_file_secret; - } - - // 如果设置了缩略版本或者缩略图类型,则添加默认压缩质量和锐化参数 - //if (isset($opts[self::X_GMKERL_THUMBNAIL]) || isset($opts[self::X_GMKERL_TYPE])) { - // if (!isset($opts[self::X_GMKERL_QUALITY])) $opts[self::X_GMKERL_QUALITY] = 95; - // if (!isset($opts[self::X_GMKERL_UNSHARP])) $opts[self::X_GMKERL_UNSHARP] = 'true'; - //} - - if ($auto_mkdir === True) - $opts['Mkdir'] = 'true'; - - $this->_file_infos = $this->_do_request('PUT', $path, $opts, $file); - - return $this->_file_infos; - } - - /* }}} */ - - /** - * 下载文件 - * @param string $path 文件路径 - * @param mixed $file_handle - * - * @return mixed - */ - public function readFile($path, $file_handle = NULL) - {/* {{{ */ - return $this->_do_request('GET', $path, NULL, NULL, $file_handle); - } - - /* }}} */ - - /** - * 获取目录文件列表 - * - * @param string $path 查询路径 - * - * @return mixed - */ - public function getList($path = '/') - {/* {{{ */ - $rsp = $this->_do_request('GET', $path); - - $list = array(); - if ($rsp) - { - $rsp = explode("\n", $rsp); - foreach ($rsp as $item) - { - @list($name, $type, $size, $time) = explode("\t", trim($item)); - if (!empty($time)) - { - $type = $type == 'N' ? 'file' : 'folder'; - } - - $item = array( - 'name' => $name, - 'type' => $type, - 'size' => intval($size), - 'time' => intval($time), - ); - array_push($list, $item); - } - } - - return $list; - } - - /* }}} */ - - /** - * @deprecated - * @param string $path 目录路径 - * @return mixed - */ - public function getFolderUsage($path = '/') - {/* {{{ */ - $rsp = $this->_do_request('GET', '/?usage'); - return floatval($rsp); - } - - /* }}} */ - - /** - * 获取文件、目录信息 - * - * @param string $path 路径 - * - * @return mixed - */ - public function getFileInfo($path) - {/* {{{ */ - $rsp = $this->_do_request('HEAD', $path); - - return $rsp; - } - - /* }}} */ - - /** - * 连接签名方法 - * @param $method 请求方式 {GET, POST, PUT, DELETE} - * return 签名字符串 - */ - private function sign($method, $uri, $date, $length) - {/* {{{ */ - //$uri = urlencode($uri); - $sign = "{$method}&{$uri}&{$date}&{$length}&{$this->config['password']}"; - return 'UpYun ' . $this->config['username'] . ':' . md5($sign); - } - - /* }}} */ - - /** - * HTTP REQUEST 封装 - * @param string $method HTTP REQUEST方法,包括PUT、POST、GET、OPTIONS、DELETE - * @param string $path 除Bucketname之外的请求路径,包括get参数 - * @param array $headers 请求需要的特殊HTTP HEADERS - * @param array $body 需要POST发送的数据 - * - * @return mixed - */ - protected function _do_request($method, $path, $headers = NULL, $body = NULL, $file_handle = NULL) - {/* {{{ */ - $uri = "/{$this->config['bucket']}{$path}"; - $ch = curl_init("http://{$this->config['endpoint']}{$uri}"); - - $_headers = array('Expect:'); - if (!is_null($headers) && is_array($headers)) - { - foreach ($headers as $k => $v) - { - array_push($_headers, "{$k}: {$v}"); - } - } - - $length = 0; - $date = gmdate('D, d M Y H:i:s \G\M\T'); - - if (!is_null($body)) - { - if (!is_resource($body) && file_exists($body)) - { - $body = fopen($body, "rb"); - } - if (is_resource($body)) - { - fseek($body, 0, SEEK_END); - $length = ftell($body); - fseek($body, 0); - - array_push($_headers, "Content-Length: {$length}"); - curl_setopt($ch, CURLOPT_INFILE, $body); - curl_setopt($ch, CURLOPT_INFILESIZE, $length); - } - else - { - $length = @strlen($body); - array_push($_headers, "Content-Length: {$length}"); - curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - } - else - { - array_push($_headers, "Content-Length: {$length}"); - } - - array_push($_headers, "Authorization: {$this->sign($method, $uri, $date, $length)}"); - array_push($_headers, "Date: {$date}"); - - curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers); - curl_setopt($ch, CURLOPT_TIMEOUT, $this->config['timeout']); - curl_setopt($ch, CURLOPT_HEADER, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); - - if ($method == 'PUT' || $method == 'POST') - { - curl_setopt($ch, CURLOPT_POST, 1); - } - else - { - curl_setopt($ch, CURLOPT_POST, 0); - } - - if ($method == 'GET' && is_resource($file_handle)) - { - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_FILE, $file_handle); - } - - if ($method == 'HEAD') - { - curl_setopt($ch, CURLOPT_NOBODY, true); - } - $response = curl_exec($ch); - $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - if ($http_code == 0) - throw new Exception('Connection Failed', $http_code); - - curl_close($ch); - - $header_string = ''; - $body = ''; - - if ($method == 'GET' && is_resource($file_handle)) - { - $header_string = ''; - $body = $response; - } - else - { - list($header_string, $body) = explode("\r\n\r\n", $response, 2); - } - $this->setXRequestId($header_string); - if ($http_code == 200) - { - if ($method == 'GET' && is_null($file_handle)) - { - return $body; - } - else - { - $data = $this->_getHeadersData($header_string); - return count($data) > 0 ? $data : true; - } - } - else - { - $message = $this->_getErrorMessage($header_string); - if (is_null($message) && $method == 'GET' && is_resource($file_handle)) - { - $message = 'File Not Found'; - } - switch ($http_code) - { - case 401: - throw new Exception($message, $http_code); - break; - case 403: - throw new Exception($message, $http_code); - break; - case 404: - throw new Exception($message, $http_code); - break; - case 406: - throw new Exception($message, $http_code); - break; - case 503: - throw new Exception($message, $http_code); - break; - default: - throw new Exception($message, $http_code); - } - } - } - - /* }}} */ - - /** - * 处理HTTP HEADERS中返回的自定义数据 - * - * @param string $text header字符串 - * - * @return array - */ - private function _getHeadersData($text) - {/* {{{ */ - $headers = explode("\r\n", $text); - $items = array(); - foreach ($headers as $header) - { - $header = trim($header); - if (stripos($header, 'x-upyun') !== False) - { - list($k, $v) = explode(':', $header); - $items[trim($k)] = in_array(substr($k, 8, 5), array('width', 'heigh', 'frame')) ? intval($v) : trim($v); - } - } - return $items; - } - - /* }}} */ - - /** - * 获取返回的错误信息 - * - * @param string $header_string - * - * @return mixed - */ - private function _getErrorMessage($header_string) - { - list($status, $stash) = explode("\r\n", $header_string, 2); - list($v, $code, $message) = explode(" ", $status, 3); - return $message . " X-Request-Id: " . $this->getXRequestId(); - } - - private function setXRequestId($header_string) - { - preg_match('~^X-Request-Id: ([0-9a-zA-Z]{32})~ism', $header_string, $result); - $this->x_request_id = isset($result[1]) ? $result[1] : ''; - } - - public function getXRequestId() - { - return $this->x_request_id; - } - - /** - * 删除目录 - * @deprecated - * @param $path 路径 - * - * @return void - */ - public function rmDir($path) - {/* {{{ */ - $this->_do_request('DELETE', $path); - } - - /* }}} */ - - /** - * 删除文件 - * - * @deprecated - * @param string $path 要删除的文件路径 - * - * @return boolean - */ - public function deleteFile($path) - {/* {{{ */ - $rsp = $this->_do_request('DELETE', $path); - } - - /* }}} */ - - /** - * 获取目录文件列表 - * @deprecated - * - * @param string $path 要获取列表的目录 - * - * @return array - */ - public function readDir($path) - {/* {{{ */ - return $this->getList($path); - } - - /* }}} */ - - /** - * 获取空间使用情况 - * - * @deprecated 推荐直接使用 getFolderUsage('/')来获取 - * @return mixed - */ - public function getBucketUsage() - {/* {{{ */ - return $this->getFolderUsage('/'); - } - - /* }}} */ - - /** - * 获取文件信息 - * - * #deprecated - * @param $file 文件路径(包含文件名) - * return array('type'=> file | folder, 'size'=> file size, 'date'=> unix time) 或 null - */ - //public function getFileInfo($file){/*{{{*/ - // $result = $this->head($file); - // if(is_null($r))return null; - // return array('type'=> $this->tmp_infos['x-upyun-file-type'], 'size'=> @intval($this->tmp_infos['x-upyun-file-size']), 'date'=> @intval($this->tmp_infos['x-upyun-file-date'])); - //}/*}}}*/ - - /** - * 切换 API 接口的域名 - * - * @deprecated - * @param $domain {默然 v0.api.upyun.com 自动识别, v1.api.upyun.com 电信, v2.api.upyun.com 联通, v3.api.upyun.com 移动} - * return null; - */ - public function setApiDomain($domain) - {/* {{{ */ - $this->config['endpoint'] = $domain; - } - - /* }}} */ - - /** - * 设置待上传文件的 Content-MD5 值(如又拍云服务端收到的文件MD5值与用户设置的不一致,将回报 406 Not Acceptable 错误) - * - * @deprecated - * @param $str (文件 MD5 校验码) - * return null; - */ - public function setContentMD5($str) - {/* {{{ */ - $this->_content_md5 = $str; - } - - /* }}} */ - - /** - * 设置待上传文件的 访问密钥(注意:仅支持图片空!,设置密钥后,无法根据原文件URL直接访问,需带 URL 后面加上 (缩略图间隔标志符+密钥) 进行访问) - * 如缩略图间隔标志符为 ! ,密钥为 bac,上传文件路径为 /folder/test.jpg ,那么该图片的对外访问地址为: http://空间域名/folder/test.jpg!bac - * - * @deprecated - * @param $str (文件 MD5 校验码) - * return null; - */ - public function setFileSecret($str) - {/* {{{ */ - $this->_file_secret = $str; - } - - /* }}} */ - - /** - * @deprecated - * 获取上传文件后的信息(仅图片空间有返回数据) - * @param $key 信息字段名(x-upyun-width、x-upyun-height、x-upyun-frames、x-upyun-file-type) - * return value or NULL - */ - public function getWritedFileInfo($key) - {/* {{{ */ - if (!isset($this->_file_infos)) - return NULL; - return $this->_file_infos[$key]; - } - - /* }}} */ -} diff --git a/extend/fast/service/Wechat.php b/extend/fast/service/Wechat.php deleted file mode 100644 index 84312938..00000000 --- a/extend/fast/service/Wechat.php +++ /dev/null @@ -1,213 +0,0 @@ - array( - 'name' => '签到送积分', - 'config' => array( - ) - ), - 'article' => array( - 'name' => '关联文章', - 'config' => array( - array( - 'type' => 'text', - 'caption' => '文章ID', - 'field' => 'id', - 'options' => '' - ) - ) - ), - 'page' => array( - 'name' => '关联单页', - 'config' => array( - array( - 'type' => 'text', - 'caption' => '单页ID', - 'field' => 'id', - 'options' => '' - ) - ) - ), - 'service' => array( - 'name' => '在线客服', - 'config' => array( - ) - ), - ); - } - - // 微信输入交互内容指令 - public function command($obj, $openid, $content, $context) - { - $response = FALSE; - if (isset($content['app'])) - { - switch ($content['app']) - { - case 'signin': - case 'article': - case 'page': - break; - case 'service': - $service = (array) json_decode(WechatConfig::value('service'), true); - list($begintime, $endtime) = explode('-', $service['onlinetime']); - $session = $obj->app->staff_session; - $staff = $obj->app->staff; - - $kf_account = $session->get($openid)->kf_account; - $time = time(); - if (!$kf_account && ($time < strtotime(date("Y-m-d {$begintime}")) || $time > strtotime(date("Y-m-d {$endtime}")))) - { - return $service['offlinemsg']; - } - if (!$kf_account) - { - $kf_list = $staff->onlines()->kf_online_list; - if ($kf_list) - { - $kfarr = []; - foreach ($kf_list as $k => $v) - { - $kfarr[$v['kf_account']] = $v['accepted_case']; - } - $kfkeys = array_keys($kfarr, min($kfarr)); - $kf_account = reset($kfkeys); - $session->create($kf_account, $openid); - $response = $service['waitformsg']; - } - else - { - $response = $service['nosessionmsg']; - } - } - else - { - $server = $obj->app->server; - $server->setMessageHandler(function($message) { - return new Transfer(); - }); - $response = $server->serve(); - $response->send(); - exit; - } - - break; - default: - break; - } - } - else - { - $response = isset($content['content']) ? $content['content'] : $response; - } - return $response; - } - - // 微信点击菜单event指令 - public function response($obj, $openid, $content, $context) - { - $upload = Config::get('upload'); - $response = FALSE; - if (isset($content['app'])) - { - switch ($content['app']) - { - case 'signin': - $thirdinfo = UserThird::get(['platform' => 'wechat', 'openid' => $openid]); - if (!$thirdinfo) - { - $response = '您还没有绑定用户还不能签到!'; - } - else - { - $user_id = $thirdinfo->user_id; - $usersign = new UserSignin; - $signdata = $usersign->where('user_id', '=', $user_id)->where('createtime', '>=', Date::unixtime())->find(); - if ($signdata) - { - $response = '今天已签到,请明天再来!'; - } - else - { - $signdata = (array) json_decode(WechatConfig::value('signin'), TRUE); - - $lastdata = $usersign->where('user_id', $user_id)->order('id', 'desc')->limit(1)->find(); - $successions = $lastdata && $lastdata['createtime'] > Date::unixtime('day', -1) ? $lastdata['successions'] + 1 : 1; - $usersign->save(['user_id' => $thirdinfo['user_id'], 'successions' => $successions, 'createtime' => time()]); - $score = isset($signdata['s' . $successions]) ? $signdata['s' . $successions] : $signdata['sn']; - User::where(['id' => $user_id])->setInc('score', $score); - $response = '签到成功!连续签到' . $successions . '天!获得' . $score . '积分'; - } - } - - break; - case 'article': - $id = explode(',', $content['id']); - $pagelist = Page::all($id); - $response = []; - foreach ($pagelist as $k => $pageinfo) - { - if ($pageinfo) - { - $news = new News(); - $news->title = $pageinfo['title']; - $news->url = $pageinfo['url'] ? $pageinfo['url'] : url('index/page/show', ['id' => $pageinfo['id']], true, true); - $news->image = $upload['cdnurl'] . $pageinfo['image']; - $news->description = $pageinfo['description']; - $response[] = $news; - } - } - - case 'page': - $id = isset($content['id']) ? $content['id'] : 0; - $pageinfo = Page::get($id); - if ($pageinfo) - { - $news = new News(); - $news->title = $pageinfo['title']; - $news->url = $pageinfo['url'] ? $pageinfo['url'] : url('index/page/show', ['id' => $pageinfo['id']], true, true); - $news->image = $upload['cdnurl'] . $pageinfo['image']; - $news->description = $pageinfo['description']; - return $news; - } - break; - case 'service': - $response = $this->command($obj, $openid, $content, $context); - break; - default: - break; - } - } - else - { - $response = isset($content['content']) ? $content['content'] : $response; - } - return $response; - } - -} diff --git a/extend/fast/third/Application.php b/extend/fast/third/Application.php deleted file mode 100644 index de16a3a6..00000000 --- a/extend/fast/third/Application.php +++ /dev/null @@ -1,76 +0,0 @@ - 'Qq', - 'weibo' => 'Weibo', - 'wechat' => 'Wechat', - ]; - - /** - * 服务对象信息 - * @var array - */ - protected $services = []; - - public function __construct($options = []) - { - if ($config = Config::get('third')) - { - $this->config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - - //注册服务器提供者 - $this->registerProviders(); - } - - /** - * 注册服务提供者 - */ - private function registerProviders() - { - foreach ($this->providers as $k => $v) - { - $this->services[$k] = function() use ($k, $v) - { - $options = $this->config[$k]; - $options['app_id'] = isset($options['app_id']) ? $options['app_id'] : ''; - $options['app_secret'] = isset($options['app_secret']) ? $options['app_secret'] : ''; - // 如果未定义回调地址则自动生成 - $options['callback'] = isset($options['callback']) && $options['callback'] ? $options['callback'] : url('user/third?action=callback&platform=' . $k, [], false, true); - // 如果非http地址则转换一下 - $options['callback'] = substr($options['callback'], 0, 7) == 'http://' || substr($options['callback'], 0, 8) == 'https://' ? $options['callback'] : url($options['callback'], '', false, true); - $objname = __NAMESPACE__ . "\\{$v}"; - return new $objname($options); - }; - } - } - - public function __set($key, $value) - { - $this->services[$key] = $value; - } - - public function __get($key) - { - return $this->services[$key]($this); - } - -} diff --git a/extend/fast/third/Qq.php b/extend/fast/third/Qq.php deleted file mode 100644 index f7a2e65b..00000000 --- a/extend/fast/third/Qq.php +++ /dev/null @@ -1,145 +0,0 @@ -config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - } - - /** - * 登陆 - */ - public function login() - { - header("Location:" . $this->getAuthorizeUrl()); - } - - /** - * 获取authorize_url - */ - public function getAuthorizeUrl() - { - $state = md5(uniqid(rand(), TRUE)); - Session::set('state', $state); - $queryarr = array( - "response_type" => "code", - "client_id" => $this->config['app_id'], - "redirect_uri" => $this->config['callback'], - "scope" => $this->config['scope'], - "state" => $state, - ); - request()->isMobile() && $queryarr['display'] = 'mobile'; - $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr); - return $url; - } - - /** - * 获取用户信息 - * @param array $params - * @return array - */ - public function getUserInfo($params = []) - { - $params = $params ? $params : $_GET; - if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) - { - //获取access_token - $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; - $access_token = isset($data['access_token']) ? $data['access_token'] : ''; - $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; - $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; - if ($access_token) - { - $openid = $this->getOpenId($access_token); - //获取用户信息 - $queryarr = [ - "access_token" => $access_token, - "oauth_consumer_key" => $this->config['app_id'], - "openid" => $openid, - ]; - $ret = Http::get(self::GET_USERINFO_URL, $queryarr); - $userinfo = json_decode($ret, TRUE); - if (!$userinfo || !isset($userinfo['ret']) || $userinfo['ret'] !== 0) - return []; - $userinfo = $userinfo ? $userinfo : []; - $userinfo['avatar'] = isset($userinfo['figureurl_qq_2']) ? $userinfo['figureurl_qq_2'] : ''; - $data = [ - 'access_token' => $access_token, - 'refresh_token' => $refresh_token, - 'expires_in' => $expires_in, - 'openid' => $openid, - 'userinfo' => $userinfo - ]; - return $data; - } - } - return []; - } - - /** - * 获取access_token - * @param string $code - * @return array - */ - private function getAccessToken($code = '') - { - if (!$code) - return ''; - $queryarr = array( - "grant_type" => "authorization_code", - "client_id" => $this->config['app_id'], - "client_secret" => $this->config['app_secret'], - "redirect_uri" => $this->config['callback'], - "code" => $code, - ); - $ret = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr); - $params = []; - parse_str($ret, $params); - return $params ? $params : []; - } - - /** - * 获取open_id - * @param string $access_token - * @return string - */ - private function getOpenId($access_token = '') - { - $response = Http::get(self::GET_OPENID_URL, ['access_token' => $access_token]); - if (strpos($response, "callback") !== false) - { - $lpos = strpos($response, "("); - $rpos = strrpos($response, ")"); - $response = substr($response, $lpos + 1, $rpos - $lpos - 1); - } - $user = json_decode($response, TRUE); - return isset($user['openid']) ? $user['openid'] : ''; - } - -} diff --git a/extend/fast/third/Wechat.php b/extend/fast/third/Wechat.php deleted file mode 100644 index d616ddd5..00000000 --- a/extend/fast/third/Wechat.php +++ /dev/null @@ -1,124 +0,0 @@ -config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - } - - /** - * 登陆 - */ - public function login() - { - header("Location:" . $this->getAuthorizeUrl()); - } - - /** - * 获取authorize_url - */ - public function getAuthorizeUrl() - { - $state = md5(uniqid(rand(), TRUE)); - Session::set('state', $state); - $queryarr = array( - "appid" => $this->config['app_id'], - "redirect_uri" => $this->config['callback'], - "response_type" => "code", - "scope" => $this->config['scope'], - "state" => $state, - ); - request()->isMobile() && $queryarr['display'] = 'mobile'; - $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect'; - return $url; - } - - /** - * 获取用户信息 - * @param array $params - * @return array - */ - public function getUserInfo($params = []) - { - $params = $params ? $params : $_GET; - if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) - { - //获取access_token - $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; - $access_token = isset($data['access_token']) ? $data['access_token'] : ''; - $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; - $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; - if ($access_token) - { - $openid = isset($data['openid']) ? $data['openid'] : ''; - //获取用户信息 - $queryarr = [ - "access_token" => $access_token, - "openid" => $openid, - "lang" => 'zh_CN' - ]; - $ret = Http::post(self::GET_USERINFO_URL, $queryarr); - $userinfo = json_decode($ret, TRUE); - if (!$userinfo || isset($userinfo['errcode'])) - return []; - $userinfo = $userinfo ? $userinfo : []; - $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : ''; - $data = [ - 'access_token' => $access_token, - 'refresh_token' => $refresh_token, - 'expires_in' => $expires_in, - 'openid' => $openid, - 'userinfo' => $userinfo - ]; - return $data; - } - } - return []; - } - - /** - * 获取access_token - * @param string code - * @return array - */ - private function getAccessToken($code = '') - { - if (!$code) - return ''; - $queryarr = array( - "appid" => $this->config['app_id'], - "secret" => $this->config['app_secret'], - "code" => $code, - "grant_type" => "authorization_code", - ); - $response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr); - $ret = json_decode($response, TRUE); - return $ret ? $ret : []; - } - -} diff --git a/extend/fast/third/Weibo.php b/extend/fast/third/Weibo.php deleted file mode 100644 index fb1dbabc..00000000 --- a/extend/fast/third/Weibo.php +++ /dev/null @@ -1,124 +0,0 @@ -config = array_merge($this->config, $config); - } - $this->config = array_merge($this->config, is_array($options) ? $options : []); - } - - /** - * 登陆 - */ - public function login() - { - header("Location:" . $this->getAuthorizeUrl()); - } - - /** - * 获取authorize_url - */ - public function getAuthorizeUrl() - { - $state = md5(uniqid(rand(), TRUE)); - Session::set('state', $state); - $queryarr = array( - "response_type" => "code", - "client_id" => $this->config['app_id'], - "redirect_uri" => $this->config['callback'], - "state" => $state, - ); - request()->isMobile() && $queryarr['display'] = 'mobile'; - $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr); - return $url; - } - - /** - * 获取用户信息 - * @param array $params - * @return array - */ - public function getUserInfo($params = []) - { - $params = $params ? $params : $_GET; - if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) - { - //获取access_token - $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; - $access_token = isset($data['access_token']) ? $data['access_token'] : ''; - $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; - $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; - if ($access_token) - { - $uid = isset($data['uid']) ? $data['uid'] : ''; - //获取用户信息 - $queryarr = [ - "access_token" => $access_token, - "uid" => $uid, - ]; - $ret = Http::get(self::GET_USERINFO_URL, $queryarr); - $userinfo = json_decode($ret, TRUE); - if (!$userinfo || isset($userinfo['error_code'])) - return []; - $userinfo = $userinfo ? $userinfo : []; - $userinfo['nickname'] = isset($userinfo['screen_name']) ? $userinfo['screen_name'] : ''; - $userinfo['avatar'] = isset($userinfo['profile_image_url']) ? $userinfo['profile_image_url'] : ''; - $data = [ - 'access_token' => $access_token, - 'refresh_token' => $refresh_token, - 'expires_in' => $expires_in, - 'openid' => $uid, - 'userinfo' => $userinfo - ]; - return $data; - } - } - return []; - } - - /** - * 获取access_token - * @param string code - * @return array - */ - private function getAccessToken($code = '') - { - if (!$code) - return ''; - $queryarr = array( - "grant_type" => "authorization_code", - "client_id" => $this->config['app_id'], - "client_secret" => $this->config['app_secret'], - "redirect_uri" => $this->config['callback'], - "code" => $code, - ); - $response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr); - $ret = json_decode($response, TRUE); - return $ret ? $ret : []; - } - -} diff --git a/extend/fast/ucenter/client/Client.php b/extend/fast/ucenter/client/Client.php deleted file mode 100644 index 58ed17be..00000000 --- a/extend/fast/ucenter/client/Client.php +++ /dev/null @@ -1,31 +0,0 @@ -initConfig(); - Loader::import('client', dirname(__FILE__) . "/uc_client/"); //加载uc客户端主脚本 - } - - //加载配置 - public function initConfig() - { - if (!defined('UC_API')) - { - new Exception('未发现uc常量配置信息'); - } - } - - function __call($method, $params) - { - return call_user_func_array($method, $params); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/client.php b/extend/fast/ucenter/client/uc_client/client.php deleted file mode 100644 index 67f361ff..00000000 --- a/extend/fast/ucenter/client/uc_client/client.php +++ /dev/null @@ -1,840 +0,0 @@ - $val) - { - $string[$key] = uc_addslashes($val, $force, $strip); - } - } - else - { - $string = addslashes($strip ? stripslashes($string) : $string); - } - } - return $string; -} - -if (!function_exists('daddslashes')) -{ - - function daddslashes($string, $force = 0) - { - return uc_addslashes($string, $force); - } - -} - -if (!function_exists('dhtmlspecialchars')) -{ - - function dhtmlspecialchars($string, $flags = null) - { - if (is_array($string)) - { - foreach ($string as $key => $val) - { - $string[$key] = dhtmlspecialchars($val, $flags); - } - } - else - { - if ($flags === null) - { - $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string); - if (strpos($string, '&#') !== false) - { - $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string); - } - } - else - { - if (PHP_VERSION < '5.4.0') - { - $string = htmlspecialchars($string, $flags); - } - else - { - if (strtolower(CHARSET) == 'utf-8') - { - $charset = 'UTF-8'; - } - else - { - $charset = 'ISO-8859-1'; - } - $string = htmlspecialchars($string, $flags, $charset); - } - } - } - return $string; - } - -} - -if (!function_exists('fsocketopen')) -{ - - function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15) - { - $fp = ''; - if (function_exists('fsockopen')) - { - $fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout); - } - elseif (function_exists('pfsockopen')) - { - $fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout); - } - elseif (function_exists('stream_socket_client')) - { - $fp = @stream_socket_client($hostname . ':' . $port, $errno, $errstr, $timeout); - } - return $fp; - } - -} - -function uc_stripslashes($string) -{ - !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); - if (MAGIC_QUOTES_GPC) - { - return stripslashes($string); - } - else - { - return $string; - } -} - -// 采用POST请求形式 -function uc_api_post($module, $action, $arg = array()) -{ - $s = $sep = ''; - foreach ($arg as $k => $v) - { - $k = urlencode($k); - if (is_array($v)) - { - $s2 = $sep2 = ''; - foreach ($v as $k2 => $v2) - { - $k2 = urlencode($k2); - $s2 .= "$sep2{$k}[$k2]=" . urlencode(uc_stripslashes($v2)); - $sep2 = '&'; - } - $s .= $sep . $s2; - } - else - { - $s .= "$sep$k=" . urlencode(uc_stripslashes($v)); - } - $sep = '&'; - } - $postdata = uc_api_requestdata($module, $action, $s); - return uc_fopen2(UC_API . '/index.php', 500000, $postdata, '', TRUE, UC_IP, 20); -} - -function uc_api_requestdata($module, $action, $arg = '', $extra = '') -{ - $input = uc_api_input($arg); - $post = "m=$module&a=$action&inajax=2&release=" . UC_CLIENT_RELEASE . "&input=$input&appid=" . UC_APPID . $extra; - return $post; -} - -function uc_api_url($module, $action, $arg = '', $extra = '') -{ - $url = UC_API . '/index.php?' . uc_api_requestdata($module, $action, $arg, $extra); - return $url; -} - -function uc_api_input($data) -{ - $s = urlencode(uc_authcode($data . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . "&time=" . time(), 'ENCODE', UC_KEY)); - return $s; -} - -// 直连数据库的形式 -function uc_api_mysql($model, $action, $args = array()) -{ - global $uc_controls; - if (empty($uc_controls[$model])) - { - // 优先使用mysqli - if (function_exists("mysqli_connect")) - { - include_once UC_ROOT . './lib/dbi.class.php'; - } - else - { - include_once UC_ROOT . './lib/db.class.php'; - } - include_once UC_ROOT . './model/base.php'; - include_once UC_ROOT . "./control/$model.php"; - $classname = $model . 'control'; - $uc_controls[$model] = new $classname(); - } - if ($action{0} != '_') - { - $args = uc_addslashes($args, 1, TRUE); - $action = 'on' . $action; - $uc_controls[$model]->input = $args; - return $uc_controls[$model]->$action($args); - } - else - { - return ''; - } -} - -function uc_serialize($arr, $htmlon = 0) -{ - include_once UC_ROOT . './lib/xml.class.php'; - return xml_serialize($arr, $htmlon); -} - -function uc_unserialize($s) -{ - include_once UC_ROOT . './lib/xml.class.php'; - return @xml_unserialize($s); -} - -function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) -{ - - $ckey_length = 4; - - $key = md5($key ? $key : UC_KEY); - $keya = md5(substr($key, 0, 16)); - $keyb = md5(substr($key, 16, 16)); - $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; - - $cryptkey = $keya . md5($keya . $keyc); - $key_length = strlen($cryptkey); - - $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; - $string_length = strlen($string); - - $result = ''; - $box = range(0, 255); - - $rndkey = array(); - for ($i = 0; $i <= 255; $i++) - { - $rndkey[$i] = ord($cryptkey[$i % $key_length]); - } - - for ($j = $i = 0; $i < 256; $i++) - { - $j = ($j + $box[$i] + $rndkey[$i]) % 256; - $tmp = $box[$i]; - $box[$i] = $box[$j]; - $box[$j] = $tmp; - } - - for ($a = $j = $i = 0; $i < $string_length; $i++) - { - $a = ($a + 1) % 256; - $j = ($j + $box[$a]) % 256; - $tmp = $box[$a]; - $box[$a] = $box[$j]; - $box[$j] = $tmp; - $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); - } - - if ($operation == 'DECODE') - { - if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) - { - return substr($result, 26); - } - else - { - return ''; - } - } - else - { - return $keyc . str_replace('=', '', base64_encode($result)); - } -} - -function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) -{ - $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1; - if ($__times__ > 2) - { - return ''; - } - $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__"; - return uc_fopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block); -} - -function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) -{ - $return = ''; - $matches = parse_url($url); - !isset($matches['scheme']) && $matches['scheme'] = ''; - !isset($matches['host']) && $matches['host'] = ''; - !isset($matches['path']) && $matches['path'] = ''; - !isset($matches['query']) && $matches['query'] = ''; - !isset($matches['port']) && $matches['port'] = ''; - $scheme = $matches['scheme']; - $host = $matches['host']; - $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/'; - $port = !empty($matches['port']) ? $matches['port'] : 80; - if ($post) - { - $out = "POST $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; - $header .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n"; - $header .= "Host: $host\r\n"; - $header .= 'Content-Length: ' . strlen($post) . "\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cache-Control: no-cache\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header . $post; - } - else - { - $out = "GET $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $header .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n"; - $header .= "Host: $host\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header; - } - $fpflag = 0; - if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) - { - $context = array( - 'http' => array( - 'method' => $post ? 'POST' : 'GET', - 'header' => $header, - 'content' => $post, - 'timeout' => $timeout, - ), - ); - $context = stream_context_create($context); - $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context); - $fpflag = 1; - } - if (!$fp) - { - return ''; - } - else - { - stream_set_blocking($fp, $block); - stream_set_timeout($fp, $timeout); - @fwrite($fp, $out); - $status = stream_get_meta_data($fp); - if (!$status['timed_out']) - { - while (!feof($fp) && !$fpflag) - { - if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) - { - break; - } - } - - $stop = false; - while (!feof($fp) && !$stop) - { - $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit)); - $return .= $data; - if ($limit) - { - $limit -= strlen($data); - $stop = $limit <= 0; - } - } - } - @fclose($fp); - return $return; - } -} - -function uc_app_ls() -{ - $return = call_user_func(UC_API_FUNC, 'app', 'ls', array()); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_feed_add($icon, $uid, $username, $title_template = '', $title_data = '', $body_template = '', $body_data = '', $body_general = '', $target_ids = '', $images = array()) -{ - return call_user_func(UC_API_FUNC, 'feed', 'add', array( - 'icon' => $icon, - 'appid' => UC_APPID, - 'uid' => $uid, - 'username' => $username, - 'title_template' => $title_template, - 'title_data' => $title_data, - 'body_template' => $body_template, - 'body_data' => $body_data, - 'body_general' => $body_general, - 'target_ids' => $target_ids, - 'image_1' => $images[0]['url'], - 'image_1_link' => $images[0]['link'], - 'image_2' => $images[1]['url'], - 'image_2_link' => $images[1]['link'], - 'image_3' => $images[2]['url'], - 'image_3_link' => $images[2]['link'], - 'image_4' => $images[3]['url'], - 'image_4_link' => $images[3]['link'] - ) - ); -} - -function uc_feed_get($limit = 100, $delete = TRUE) -{ - $return = call_user_func(UC_API_FUNC, 'feed', 'get', array('limit' => $limit, 'delete' => $delete)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_friend_add($uid, $friendid, $comment = '') -{ - return call_user_func(UC_API_FUNC, 'friend', 'add', array('uid' => $uid, 'friendid' => $friendid, 'comment' => $comment)); -} - -function uc_friend_delete($uid, $friendids) -{ - return call_user_func(UC_API_FUNC, 'friend', 'delete', array('uid' => $uid, 'friendids' => $friendids)); -} - -function uc_friend_totalnum($uid, $direction = 0) -{ - return call_user_func(UC_API_FUNC, 'friend', 'totalnum', array('uid' => $uid, 'direction' => $direction)); -} - -function uc_friend_ls($uid, $page = 1, $pagesize = 10, $totalnum = 10, $direction = 0) -{ - $return = call_user_func(UC_API_FUNC, 'friend', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'totalnum' => $totalnum, 'direction' => $direction)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_user_register($username, $password, $email = '', $mobile = '', $extend = []) -{ - return call_user_func(UC_API_FUNC, 'user', 'register', array('username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend)); -} - -function uc_user_login($username, $password, $isuid = 0, $extend = []) -{ - $isuid = intval($isuid); - $return = call_user_func(UC_API_FUNC, 'user', 'login', array('username' => $username, 'password' => $password, 'isuid' => $isuid, 'extend' => $extend)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -/** - * 同步注册 - * @param int $uid - * @param string $password - * @return string - */ -function uc_user_synregister($uid, $password) -{ - $uid = intval($uid); - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synregister', array('uid' => $uid, 'password' => $password)); - } - else - { - $return = ''; - } - } - return $return; -} - -/** - * 同步登录 - * @param int $uid - * @return string - */ -function uc_user_synlogin($uid) -{ - $uid = intval($uid); - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synlogin', array('uid' => $uid)); - } - else - { - $return = ''; - } - } - return $return; -} - -/** - * 同步退出 - * @return string - */ -function uc_user_synlogout() -{ - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synlogout', array()); - } - else - { - $return = ''; - } - } - return $return; -} - -/** - * 修改用户信息 - * @param int $uid 会员ID - * @param string $username 用户名 - * @param string $password 密码 - * @param string $email 邮箱 - * @param string $mobile 手机号 - * @param array $extend 扩展信息 - * @return type - */ -function uc_user_edit($uid, $username, $password, $email = '', $mobile = '', $extend = []) -{ - return call_user_func(UC_API_FUNC, 'user', 'edit', array('uid' => $uid, 'username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend)); -} - -function uc_user_delete($uid) -{ - return call_user_func(UC_API_FUNC, 'user', 'delete', array('uid' => $uid)); -} - -function uc_user_deleteavatar($uid) -{ - uc_api_post('user', 'deleteavatar', array('uid' => $uid)); -} - -function uc_user_checkname($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_username', array('username' => $username)); -} - -function uc_user_checkemail($email) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_email', array('email' => $email)); -} - -function uc_user_checkmobile($mobile) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_mobile', array('mobile' => $mobile)); -} - -function uc_user_addprotected($username, $admin = '') -{ - return call_user_func(UC_API_FUNC, 'user', 'addprotected', array('username' => $username, 'admin' => $admin)); -} - -function uc_user_deleteprotected($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'deleteprotected', array('username' => $username)); -} - -function uc_user_getprotected() -{ - $return = call_user_func(UC_API_FUNC, 'user', 'getprotected', array('1' => 1)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_get_user($username, $isuid = 0) -{ - $return = call_user_func(UC_API_FUNC, 'user', 'get_user', array('username' => $username, 'isuid' => $isuid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_user_merge($oldusername, $newusername, $uid, $password, $email) -{ - return call_user_func(UC_API_FUNC, 'user', 'merge', array('oldusername' => $oldusername, 'newusername' => $newusername, 'uid' => $uid, 'password' => $password, 'email' => $email)); -} - -function uc_user_merge_remove($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'merge_remove', array('username' => $username)); -} - -function uc_user_getcredit($appid, $uid, $credit) -{ - return uc_api_post('user', 'getcredit', array('appid' => $appid, 'uid' => $uid, 'credit' => $credit)); -} - -function uc_user_logincheck($username, $ip) -{ - return call_user_func(UC_API_FUNC, 'user', 'logincheck', array('username' => $username, 'ip' => $ip)); -} - -function uc_pm_location($uid, $newpm = 0) -{ - $apiurl = uc_api_url('pm_client', 'ls', "uid=$uid", ($newpm ? '&folder=newbox' : '')); - @header("Expires: 0"); - @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE); - @header("Pragma: no-cache"); - @header("location: $apiurl"); -} - -function uc_pm_checknew($uid, $more = 0) -{ - $return = call_user_func(UC_API_FUNC, 'pm', 'check_newpm', array('uid' => $uid, 'more' => $more)); - return (!$more || UC_CONNECT == 'mysql') ? $return : uc_unserialize($return); -} - -function uc_pm_send($fromuid, $msgto, $subject, $message, $instantly = 1, $replypmid = 0, $isusername = 0, $type = 0) -{ - if ($instantly) - { - $replypmid = @is_numeric($replypmid) ? $replypmid : 0; - return call_user_func(UC_API_FUNC, 'pm', 'sendpm', array('fromuid' => $fromuid, 'msgto' => $msgto, 'subject' => $subject, 'message' => $message, 'replypmid' => $replypmid, 'isusername' => $isusername, 'type' => $type)); - } - else - { - $fromuid = intval($fromuid); - $subject = rawurlencode($subject); - $msgto = rawurlencode($msgto); - $message = rawurlencode($message); - $replypmid = @is_numeric($replypmid) ? $replypmid : 0; - $replyadd = $replypmid ? "&pmid=$replypmid&do=reply" : ''; - $apiurl = uc_api_url('pm_client', 'send', "uid=$fromuid", "&msgto=$msgto&subject=$subject&message=$message$replyadd"); - @header("Expires: 0"); - @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE); - @header("Pragma: no-cache"); - @header("location: " . $apiurl); - } -} - -function uc_pm_delete($uid, $folder, $pmids) -{ - return call_user_func(UC_API_FUNC, 'pm', 'delete', array('uid' => $uid, 'pmids' => $pmids)); -} - -function uc_pm_deleteuser($uid, $touids) -{ - return call_user_func(UC_API_FUNC, 'pm', 'deleteuser', array('uid' => $uid, 'touids' => $touids)); -} - -function uc_pm_deletechat($uid, $plids, $type = 0) -{ - return call_user_func(UC_API_FUNC, 'pm', 'deletechat', array('uid' => $uid, 'plids' => $plids, 'type' => $type)); -} - -function uc_pm_readstatus($uid, $uids, $plids = array(), $status = 0) -{ - return call_user_func(UC_API_FUNC, 'pm', 'readstatus', array('uid' => $uid, 'uids' => $uids, 'plids' => $plids, 'status' => $status)); -} - -function uc_pm_list($uid, $page = 1, $pagesize = 10, $folder = 'inbox', $filter = 'newpm', $msglen = 0) -{ - $uid = intval($uid); - $page = intval($page); - $pagesize = intval($pagesize); - $return = call_user_func(UC_API_FUNC, 'pm', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'filter' => $filter, 'msglen' => $msglen)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_ignore($uid) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'ignore', array('uid' => $uid)); -} - -function uc_pm_view($uid, $pmid = 0, $touid = 0, $daterange = 1, $page = 0, $pagesize = 10, $type = 0, $isplid = 0) -{ - $uid = intval($uid); - $touid = intval($touid); - $page = intval($page); - $pagesize = intval($pagesize); - $pmid = @is_numeric($pmid) ? $pmid : 0; - $return = call_user_func(UC_API_FUNC, 'pm', 'view', array('uid' => $uid, 'pmid' => $pmid, 'touid' => $touid, 'daterange' => $daterange, 'page' => $page, 'pagesize' => $pagesize, 'type' => $type, 'isplid' => $isplid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_view_num($uid, $touid, $isplid) -{ - $uid = intval($uid); - $touid = intval($touid); - $isplid = intval($isplid); - return call_user_func(UC_API_FUNC, 'pm', 'viewnum', array('uid' => $uid, 'touid' => $touid, 'isplid' => $isplid)); -} - -function uc_pm_viewnode($uid, $type, $pmid) -{ - $uid = intval($uid); - $type = intval($type); - $pmid = @is_numeric($pmid) ? $pmid : 0; - $return = call_user_func(UC_API_FUNC, 'pm', 'viewnode', array('uid' => $uid, 'type' => $type, 'pmid' => $pmid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_chatpmmemberlist($uid, $plid = 0) -{ - $uid = intval($uid); - $plid = intval($plid); - $return = call_user_func(UC_API_FUNC, 'pm', 'chatpmmemberlist', array('uid' => $uid, 'plid' => $plid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_kickchatpm($plid, $uid, $touid) -{ - $uid = intval($uid); - $plid = intval($plid); - $touid = intval($touid); - return call_user_func(UC_API_FUNC, 'pm', 'kickchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid)); -} - -function uc_pm_appendchatpm($plid, $uid, $touid) -{ - $uid = intval($uid); - $plid = intval($plid); - $touid = intval($touid); - return call_user_func(UC_API_FUNC, 'pm', 'appendchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid)); -} - -function uc_pm_blackls_get($uid) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_get', array('uid' => $uid)); -} - -function uc_pm_blackls_set($uid, $blackls) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_set', array('uid' => $uid, 'blackls' => $blackls)); -} - -function uc_pm_blackls_add($uid, $username) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_add', array('uid' => $uid, 'username' => $username)); -} - -function uc_pm_blackls_delete($uid, $username) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_delete', array('uid' => $uid, 'username' => $username)); -} - -function uc_domain_ls() -{ - $return = call_user_func(UC_API_FUNC, 'domain', 'ls', array('1' => 1)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_credit_exchange_request($uid, $from, $to, $toappid, $amount) -{ - $uid = intval($uid); - $from = intval($from); - $toappid = intval($toappid); - $to = intval($to); - $amount = intval($amount); - return uc_api_post('credit', 'request', array('uid' => $uid, 'from' => $from, 'to' => $to, 'toappid' => $toappid, 'amount' => $amount)); -} - -function uc_tag_get($tagname, $nums = 0) -{ - $return = call_user_func(UC_API_FUNC, 'tag', 'gettag', array('tagname' => $tagname, 'nums' => $nums)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_avatar($uid, $type = 'virtual', $returnhtml = 1) -{ - $uid = intval($uid); - $uc_input = uc_api_input("uid=$uid"); - $uc_avatarflash = UC_API . '/images/camera.swf?inajax=1&appid=' . UC_APPID . '&input=' . $uc_input . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . '&ucapi=' . urlencode(str_replace('http://', '', UC_API)) . '&avatartype=' . $type . '&uploadSize=2048'; - if ($returnhtml) - { - return ' - - - - - - - - - '; - } - else - { - return array( - 'width', '450', - 'height', '253', - 'scale', 'exactfit', - 'src', $uc_avatarflash, - 'id', 'mycamera', - 'name', 'mycamera', - 'quality', 'high', - 'bgcolor', '#ffffff', - 'menu', 'false', - 'swLiveConnect', 'true', - 'allowScriptAccess', 'always' - ); - } -} - -function uc_mail_queue($uids, $emails, $subject, $message, $frommail = '', $charset = 'gbk', $htmlon = FALSE, $level = 1) -{ - return call_user_func(UC_API_FUNC, 'mail', 'add', array('uids' => $uids, 'emails' => $emails, 'subject' => $subject, 'message' => $message, 'frommail' => $frommail, 'charset' => $charset, 'htmlon' => $htmlon, 'level' => $level)); -} - -function uc_check_avatar($uid, $size = 'middle', $type = 'virtual') -{ - $url = UC_API . "/avatar.php?uid=$uid&size=$size&type=$type&check_file_exists=1"; - $res = uc_fopen2($url, 500000, '', '', TRUE, UC_IP, 20); - if ($res == 1) - { - return 1; - } - else - { - return 0; - } -} - -function uc_check_version() -{ - $return = uc_api_post('version', 'check', array()); - $data = uc_unserialize($return); - return is_array($data) ? $data : $return; -} diff --git a/extend/fast/ucenter/client/uc_client/control/app.php b/extend/fast/ucenter/client/uc_client/control/app.php deleted file mode 100644 index dc66f54b..00000000 --- a/extend/fast/ucenter/client/uc_client/control/app.php +++ /dev/null @@ -1,63 +0,0 @@ -appcontrol(); - } - - function appcontrol() - { - parent::__construct(); - $this->load('app'); - } - - function onls() - { - $this->init_input(); - $applist = $_ENV['app']->get_apps('appid, type, name, url, tagtemplates, viewprourl, synlogin'); - $applist2 = array(); - foreach ($applist as $key => $app) - { - $app['tagtemplates'] = $this->unserialize($app['tagtemplates']); - $applist2[$app['appid']] = $app; - } - return $applist2; - } - - function onadd() - { - - } - - function onucinfo() - { - - } - - function _random($length, $numeric = 0) - { - - } - - function _generate_key() - { - - } - - function _format_notedata($notedata) - { - - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/cache.php b/extend/fast/ucenter/client/uc_client/control/cache.php deleted file mode 100644 index e8a621c8..00000000 --- a/extend/fast/ucenter/client/uc_client/control/cache.php +++ /dev/null @@ -1,30 +0,0 @@ -cachecontrol(); - } - - function cachecontrol() - { - parent::__construct(); - } - - function onupdate($arr) - { - $this->load("cache"); - $_ENV['cache']->updatedata(); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/client.php b/extend/fast/ucenter/client/uc_client/control/client.php deleted file mode 100644 index 9536bca1..00000000 --- a/extend/fast/ucenter/client/uc_client/control/client.php +++ /dev/null @@ -1,817 +0,0 @@ - $val) - { - $string[$key] = uc_addslashes($val, $force, $strip); - } - } - else - { - $string = addslashes($strip ? stripslashes($string) : $string); - } - } - return $string; -} - -if (!function_exists('daddslashes')) -{ - - function daddslashes($string, $force = 0) - { - return uc_addslashes($string, $force); - } - -} - -if (!function_exists('dhtmlspecialchars')) -{ - - function dhtmlspecialchars($string, $flags = null) - { - if (is_array($string)) - { - foreach ($string as $key => $val) - { - $string[$key] = dhtmlspecialchars($val, $flags); - } - } - else - { - if ($flags === null) - { - $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string); - if (strpos($string, '&#') !== false) - { - $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string); - } - } - else - { - if (PHP_VERSION < '5.4.0') - { - $string = htmlspecialchars($string, $flags); - } - else - { - if (strtolower(CHARSET) == 'utf-8') - { - $charset = 'UTF-8'; - } - else - { - $charset = 'ISO-8859-1'; - } - $string = htmlspecialchars($string, $flags, $charset); - } - } - } - return $string; - } - -} - -if (!function_exists('fsocketopen')) -{ - - function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15) - { - $fp = ''; - if (function_exists('fsockopen')) - { - $fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout); - } - elseif (function_exists('pfsockopen')) - { - $fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout); - } - elseif (function_exists('stream_socket_client')) - { - $fp = @stream_socket_client($hostname . ':' . $port, $errno, $errstr, $timeout); - } - return $fp; - } - -} - -function uc_stripslashes($string) -{ - !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); - if (MAGIC_QUOTES_GPC) - { - return stripslashes($string); - } - else - { - return $string; - } -} - -// 采用POST请求形式 -function uc_api_post($module, $action, $arg = array()) -{ - $s = $sep = ''; - foreach ($arg as $k => $v) - { - $k = urlencode($k); - if (is_array($v)) - { - $s2 = $sep2 = ''; - foreach ($v as $k2 => $v2) - { - $k2 = urlencode($k2); - $s2 .= "$sep2{$k}[$k2]=" . urlencode(uc_stripslashes($v2)); - $sep2 = '&'; - } - $s .= $sep . $s2; - } - else - { - $s .= "$sep$k=" . urlencode(uc_stripslashes($v)); - } - $sep = '&'; - } - $postdata = uc_api_requestdata($module, $action, $s); - return uc_fopen2(UC_API . '/index.php', 500000, $postdata, '', TRUE, UC_IP, 20); -} - -function uc_api_requestdata($module, $action, $arg = '', $extra = '') -{ - $input = uc_api_input($arg); - $post = "m=$module&a=$action&inajax=2&release=" . UC_CLIENT_RELEASE . "&input=$input&appid=" . UC_APPID . $extra; - return $post; -} - -function uc_api_url($module, $action, $arg = '', $extra = '') -{ - $url = UC_API . '/index.php?' . uc_api_requestdata($module, $action, $arg, $extra); - return $url; -} - -function uc_api_input($data) -{ - $s = urlencode(uc_authcode($data . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . "&time=" . time(), 'ENCODE', UC_KEY)); - return $s; -} - -// 直连数据库的形式 -function uc_api_mysql($model, $action, $args = array()) -{ - global $uc_controls; - if (empty($uc_controls[$model])) - { - // 优先使用mysqli - if (function_exists("mysqli_connect")) - { - include_once UC_ROOT . './lib/dbi.class.php'; - } - else - { - include_once UC_ROOT . './lib/db.class.php'; - } - include_once UC_ROOT . './model/base.php'; - include_once UC_ROOT . "./control/$model.php"; - $classname = $model . 'control'; - $uc_controls[$model] = new $classname(); - } - if ($action{0} != '_') - { - $args = uc_addslashes($args, 1, TRUE); - $action = 'on' . $action; - $uc_controls[$model]->input = $args; - return $uc_controls[$model]->$action($args); - } - else - { - return ''; - } -} - -function uc_serialize($arr, $htmlon = 0) -{ - include_once UC_ROOT . './lib/xml.class.php'; - return xml_serialize($arr, $htmlon); -} - -function uc_unserialize($s) -{ - include_once UC_ROOT . './lib/xml.class.php'; - return @xml_unserialize($s); -} - -function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) -{ - - $ckey_length = 4; - - $key = md5($key ? $key : UC_KEY); - $keya = md5(substr($key, 0, 16)); - $keyb = md5(substr($key, 16, 16)); - $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; - - $cryptkey = $keya . md5($keya . $keyc); - $key_length = strlen($cryptkey); - - $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; - $string_length = strlen($string); - - $result = ''; - $box = range(0, 255); - - $rndkey = array(); - for ($i = 0; $i <= 255; $i++) - { - $rndkey[$i] = ord($cryptkey[$i % $key_length]); - } - - for ($j = $i = 0; $i < 256; $i++) - { - $j = ($j + $box[$i] + $rndkey[$i]) % 256; - $tmp = $box[$i]; - $box[$i] = $box[$j]; - $box[$j] = $tmp; - } - - for ($a = $j = $i = 0; $i < $string_length; $i++) - { - $a = ($a + 1) % 256; - $j = ($j + $box[$a]) % 256; - $tmp = $box[$a]; - $box[$a] = $box[$j]; - $box[$j] = $tmp; - $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); - } - - if ($operation == 'DECODE') - { - if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) - { - return substr($result, 26); - } - else - { - return ''; - } - } - else - { - return $keyc . str_replace('=', '', base64_encode($result)); - } -} - -function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) -{ - $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1; - if ($__times__ > 2) - { - return ''; - } - $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__"; - return uc_fopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block); -} - -function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) -{ - $return = ''; - $matches = parse_url($url); - !isset($matches['scheme']) && $matches['scheme'] = ''; - !isset($matches['host']) && $matches['host'] = ''; - !isset($matches['path']) && $matches['path'] = ''; - !isset($matches['query']) && $matches['query'] = ''; - !isset($matches['port']) && $matches['port'] = ''; - $scheme = $matches['scheme']; - $host = $matches['host']; - $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/'; - $port = !empty($matches['port']) ? $matches['port'] : 80; - if ($post) - { - $out = "POST $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; - $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n"; - $header .= "Host: $host\r\n"; - $header .= 'Content-Length: ' . strlen($post) . "\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cache-Control: no-cache\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header . $post; - } - else - { - $out = "GET $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n"; - $header .= "Host: $host\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header; - } - - $fpflag = 0; - if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) - { - $context = array( - 'http' => array( - 'method' => $post ? 'POST' : 'GET', - 'header' => $header, - 'content' => $post, - 'timeout' => $timeout, - ), - ); - $context = stream_context_create($context); - $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context); - $fpflag = 1; - } - - if (!$fp) - { - return ''; - } - else - { - stream_set_blocking($fp, $block); - stream_set_timeout($fp, $timeout); - @fwrite($fp, $out); - $status = stream_get_meta_data($fp); - if (!$status['timed_out']) - { - while (!feof($fp) && !$fpflag) - { - if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) - { - break; - } - } - - $stop = false; - while (!feof($fp) && !$stop) - { - $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit)); - $return .= $data; - if ($limit) - { - $limit -= strlen($data); - $stop = $limit <= 0; - } - } - } - @fclose($fp); - return $return; - } -} - -function uc_app_ls() -{ - $return = call_user_func(UC_API_FUNC, 'app', 'ls', array()); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_feed_add($icon, $uid, $username, $title_template = '', $title_data = '', $body_template = '', $body_data = '', $body_general = '', $target_ids = '', $images = array()) -{ - return call_user_func(UC_API_FUNC, 'feed', 'add', array( - 'icon' => $icon, - 'appid' => UC_APPID, - 'uid' => $uid, - 'username' => $username, - 'title_template' => $title_template, - 'title_data' => $title_data, - 'body_template' => $body_template, - 'body_data' => $body_data, - 'body_general' => $body_general, - 'target_ids' => $target_ids, - 'image_1' => $images[0]['url'], - 'image_1_link' => $images[0]['link'], - 'image_2' => $images[1]['url'], - 'image_2_link' => $images[1]['link'], - 'image_3' => $images[2]['url'], - 'image_3_link' => $images[2]['link'], - 'image_4' => $images[3]['url'], - 'image_4_link' => $images[3]['link'] - ) - ); -} - -function uc_feed_get($limit = 100, $delete = TRUE) -{ - $return = call_user_func(UC_API_FUNC, 'feed', 'get', array('limit' => $limit, 'delete' => $delete)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_friend_add($uid, $friendid, $comment = '') -{ - return call_user_func(UC_API_FUNC, 'friend', 'add', array('uid' => $uid, 'friendid' => $friendid, 'comment' => $comment)); -} - -function uc_friend_delete($uid, $friendids) -{ - return call_user_func(UC_API_FUNC, 'friend', 'delete', array('uid' => $uid, 'friendids' => $friendids)); -} - -function uc_friend_totalnum($uid, $direction = 0) -{ - return call_user_func(UC_API_FUNC, 'friend', 'totalnum', array('uid' => $uid, 'direction' => $direction)); -} - -function uc_friend_ls($uid, $page = 1, $pagesize = 10, $totalnum = 10, $direction = 0) -{ - $return = call_user_func(UC_API_FUNC, 'friend', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'totalnum' => $totalnum, 'direction' => $direction)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_user_register($username, $password, $email = '', $mobile = '', $extend = []) -{ - return call_user_func(UC_API_FUNC, 'user', 'register', array('username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend)); -} - -function uc_user_login($username, $password, $isuid = 0, $extend = []) -{ - $isuid = intval($isuid); - $return = call_user_func(UC_API_FUNC, 'user', 'login', array('username' => $username, 'password' => $password, 'isuid' => $isuid, 'extend' => $extend)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_user_synregister($uid, $password) -{ - $uid = intval($uid); - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synregister', array('uid' => $uid, 'password' => $password)); - } - else - { - $return = ''; - } - } - return $return; -} - -function uc_user_synlogin($uid) -{ - $uid = intval($uid); - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synlogin', array('uid' => $uid)); - } - else - { - $return = ''; - } - } - return $return; -} - -function uc_user_synlogout() -{ - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - $return = uc_api_post('user', 'synlogout', array()); - } - else - { - $return = ''; - } - } - return $return; -} - -function uc_user_edit($uid, $username, $password, $email = '', $mobile = '', $extend = []) -{ - return call_user_func(UC_API_FUNC, 'user', 'edit', array('uid' => $uid, 'username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend)); -} - -function uc_user_delete($uid) -{ - return call_user_func(UC_API_FUNC, 'user', 'delete', array('uid' => $uid)); -} - -function uc_user_deleteavatar($uid) -{ - uc_api_post('user', 'deleteavatar', array('uid' => $uid)); -} - -function uc_user_checkname($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_username', array('username' => $username)); -} - -function uc_user_checkemail($email) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_email', array('email' => $email)); -} - -function uc_user_checkmobile($mobile) -{ - return call_user_func(UC_API_FUNC, 'user', 'check_mobile', array('mobile' => $mobile)); -} - -function uc_user_addprotected($username, $admin = '') -{ - return call_user_func(UC_API_FUNC, 'user', 'addprotected', array('username' => $username, 'admin' => $admin)); -} - -function uc_user_deleteprotected($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'deleteprotected', array('username' => $username)); -} - -function uc_user_getprotected() -{ - $return = call_user_func(UC_API_FUNC, 'user', 'getprotected', array('1' => 1)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_get_user($username, $isuid = 0) -{ - $return = call_user_func(UC_API_FUNC, 'user', 'get_user', array('username' => $username, 'isuid' => $isuid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_user_merge($oldusername, $newusername, $uid, $password, $email) -{ - return call_user_func(UC_API_FUNC, 'user', 'merge', array('oldusername' => $oldusername, 'newusername' => $newusername, 'uid' => $uid, 'password' => $password, 'email' => $email)); -} - -function uc_user_merge_remove($username) -{ - return call_user_func(UC_API_FUNC, 'user', 'merge_remove', array('username' => $username)); -} - -function uc_user_getcredit($appid, $uid, $credit) -{ - return uc_api_post('user', 'getcredit', array('appid' => $appid, 'uid' => $uid, 'credit' => $credit)); -} - -function uc_user_logincheck($username, $ip) -{ - return call_user_func(UC_API_FUNC, 'user', 'logincheck', array('username' => $username, 'ip' => $ip)); -} - -function uc_pm_location($uid, $newpm = 0) -{ - $apiurl = uc_api_url('pm_client', 'ls', "uid=$uid", ($newpm ? '&folder=newbox' : '')); - @header("Expires: 0"); - @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE); - @header("Pragma: no-cache"); - @header("location: $apiurl"); -} - -function uc_pm_checknew($uid, $more = 0) -{ - $return = call_user_func(UC_API_FUNC, 'pm', 'check_newpm', array('uid' => $uid, 'more' => $more)); - return (!$more || UC_CONNECT == 'mysql') ? $return : uc_unserialize($return); -} - -function uc_pm_send($fromuid, $msgto, $subject, $message, $instantly = 1, $replypmid = 0, $isusername = 0, $type = 0) -{ - if ($instantly) - { - $replypmid = @is_numeric($replypmid) ? $replypmid : 0; - return call_user_func(UC_API_FUNC, 'pm', 'sendpm', array('fromuid' => $fromuid, 'msgto' => $msgto, 'subject' => $subject, 'message' => $message, 'replypmid' => $replypmid, 'isusername' => $isusername, 'type' => $type)); - } - else - { - $fromuid = intval($fromuid); - $subject = rawurlencode($subject); - $msgto = rawurlencode($msgto); - $message = rawurlencode($message); - $replypmid = @is_numeric($replypmid) ? $replypmid : 0; - $replyadd = $replypmid ? "&pmid=$replypmid&do=reply" : ''; - $apiurl = uc_api_url('pm_client', 'send', "uid=$fromuid", "&msgto=$msgto&subject=$subject&message=$message$replyadd"); - @header("Expires: 0"); - @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE); - @header("Pragma: no-cache"); - @header("location: " . $apiurl); - } -} - -function uc_pm_delete($uid, $folder, $pmids) -{ - return call_user_func(UC_API_FUNC, 'pm', 'delete', array('uid' => $uid, 'pmids' => $pmids)); -} - -function uc_pm_deleteuser($uid, $touids) -{ - return call_user_func(UC_API_FUNC, 'pm', 'deleteuser', array('uid' => $uid, 'touids' => $touids)); -} - -function uc_pm_deletechat($uid, $plids, $type = 0) -{ - return call_user_func(UC_API_FUNC, 'pm', 'deletechat', array('uid' => $uid, 'plids' => $plids, 'type' => $type)); -} - -function uc_pm_readstatus($uid, $uids, $plids = array(), $status = 0) -{ - return call_user_func(UC_API_FUNC, 'pm', 'readstatus', array('uid' => $uid, 'uids' => $uids, 'plids' => $plids, 'status' => $status)); -} - -function uc_pm_list($uid, $page = 1, $pagesize = 10, $folder = 'inbox', $filter = 'newpm', $msglen = 0) -{ - $uid = intval($uid); - $page = intval($page); - $pagesize = intval($pagesize); - $return = call_user_func(UC_API_FUNC, 'pm', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'filter' => $filter, 'msglen' => $msglen)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_ignore($uid) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'ignore', array('uid' => $uid)); -} - -function uc_pm_view($uid, $pmid = 0, $touid = 0, $daterange = 1, $page = 0, $pagesize = 10, $type = 0, $isplid = 0) -{ - $uid = intval($uid); - $touid = intval($touid); - $page = intval($page); - $pagesize = intval($pagesize); - $pmid = @is_numeric($pmid) ? $pmid : 0; - $return = call_user_func(UC_API_FUNC, 'pm', 'view', array('uid' => $uid, 'pmid' => $pmid, 'touid' => $touid, 'daterange' => $daterange, 'page' => $page, 'pagesize' => $pagesize, 'type' => $type, 'isplid' => $isplid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_view_num($uid, $touid, $isplid) -{ - $uid = intval($uid); - $touid = intval($touid); - $isplid = intval($isplid); - return call_user_func(UC_API_FUNC, 'pm', 'viewnum', array('uid' => $uid, 'touid' => $touid, 'isplid' => $isplid)); -} - -function uc_pm_viewnode($uid, $type, $pmid) -{ - $uid = intval($uid); - $type = intval($type); - $pmid = @is_numeric($pmid) ? $pmid : 0; - $return = call_user_func(UC_API_FUNC, 'pm', 'viewnode', array('uid' => $uid, 'type' => $type, 'pmid' => $pmid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_chatpmmemberlist($uid, $plid = 0) -{ - $uid = intval($uid); - $plid = intval($plid); - $return = call_user_func(UC_API_FUNC, 'pm', 'chatpmmemberlist', array('uid' => $uid, 'plid' => $plid)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_pm_kickchatpm($plid, $uid, $touid) -{ - $uid = intval($uid); - $plid = intval($plid); - $touid = intval($touid); - return call_user_func(UC_API_FUNC, 'pm', 'kickchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid)); -} - -function uc_pm_appendchatpm($plid, $uid, $touid) -{ - $uid = intval($uid); - $plid = intval($plid); - $touid = intval($touid); - return call_user_func(UC_API_FUNC, 'pm', 'appendchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid)); -} - -function uc_pm_blackls_get($uid) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_get', array('uid' => $uid)); -} - -function uc_pm_blackls_set($uid, $blackls) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_set', array('uid' => $uid, 'blackls' => $blackls)); -} - -function uc_pm_blackls_add($uid, $username) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_add', array('uid' => $uid, 'username' => $username)); -} - -function uc_pm_blackls_delete($uid, $username) -{ - $uid = intval($uid); - return call_user_func(UC_API_FUNC, 'pm', 'blackls_delete', array('uid' => $uid, 'username' => $username)); -} - -function uc_domain_ls() -{ - $return = call_user_func(UC_API_FUNC, 'domain', 'ls', array('1' => 1)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_credit_exchange_request($uid, $from, $to, $toappid, $amount) -{ - $uid = intval($uid); - $from = intval($from); - $toappid = intval($toappid); - $to = intval($to); - $amount = intval($amount); - return uc_api_post('credit', 'request', array('uid' => $uid, 'from' => $from, 'to' => $to, 'toappid' => $toappid, 'amount' => $amount)); -} - -function uc_tag_get($tagname, $nums = 0) -{ - $return = call_user_func(UC_API_FUNC, 'tag', 'gettag', array('tagname' => $tagname, 'nums' => $nums)); - return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return); -} - -function uc_avatar($uid, $type = 'virtual', $returnhtml = 1) -{ - $uid = intval($uid); - $uc_input = uc_api_input("uid=$uid"); - $uc_avatarflash = UC_API . '/images/camera.swf?inajax=1&appid=' . UC_APPID . '&input=' . $uc_input . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . '&ucapi=' . urlencode(str_replace('http://', '', UC_API)) . '&avatartype=' . $type . '&uploadSize=2048'; - if ($returnhtml) - { - return ' - - - - - - - - - '; - } - else - { - return array( - 'width', '450', - 'height', '253', - 'scale', 'exactfit', - 'src', $uc_avatarflash, - 'id', 'mycamera', - 'name', 'mycamera', - 'quality', 'high', - 'bgcolor', '#ffffff', - 'menu', 'false', - 'swLiveConnect', 'true', - 'allowScriptAccess', 'always' - ); - } -} - -function uc_mail_queue($uids, $emails, $subject, $message, $frommail = '', $charset = 'gbk', $htmlon = FALSE, $level = 1) -{ - return call_user_func(UC_API_FUNC, 'mail', 'add', array('uids' => $uids, 'emails' => $emails, 'subject' => $subject, 'message' => $message, 'frommail' => $frommail, 'charset' => $charset, 'htmlon' => $htmlon, 'level' => $level)); -} - -function uc_check_avatar($uid, $size = 'middle', $type = 'virtual') -{ - $url = UC_API . "/avatar.php?uid=$uid&size=$size&type=$type&check_file_exists=1"; - $res = uc_fopen2($url, 500000, '', '', TRUE, UC_IP, 20); - if ($res == 1) - { - return 1; - } - else - { - return 0; - } -} - -function uc_check_version() -{ - $return = uc_api_post('version', 'check', array()); - $data = uc_unserialize($return); - return is_array($data) ? $data : $return; -} diff --git a/extend/fast/ucenter/client/uc_client/control/domain.php b/extend/fast/ucenter/client/uc_client/control/domain.php deleted file mode 100644 index a7c76a94..00000000 --- a/extend/fast/ucenter/client/uc_client/control/domain.php +++ /dev/null @@ -1,31 +0,0 @@ -domaincontrol(); - } - - function domaincontrol() - { - parent::__construct(); - $this->init_input(); - $this->load('domain'); - } - - function onls() - { - return $_ENV['domain']->get_list(1, 9999, 9999); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/feed.php b/extend/fast/ucenter/client/uc_client/control/feed.php deleted file mode 100644 index 86a58b39..00000000 --- a/extend/fast/ucenter/client/uc_client/control/feed.php +++ /dev/null @@ -1,114 +0,0 @@ -feedcontrol(); - } - - function feedcontrol() - { - parent::__construct(); - $this->init_input(); - } - - function onadd() - { - $this->load('misc'); - $appid = intval($this->input('appid')); - $icon = $this->input('icon'); - $uid = intval($this->input('uid')); - $username = $this->input('username'); - $body_data = $_ENV['misc']->array2string($this->input('body_data')); - $title_data = $_ENV['misc']->array2string($this->input('title_data')); - - $title_template = $this->_parsetemplate($this->input('title_template')); - $body_template = $this->_parsetemplate($this->input('body_template')); - $body_general = $this->input('body_general'); - $target_ids = $this->input('target_ids'); - $image_1 = $this->input('image_1'); - $image_1_link = $this->input('image_1_link'); - $image_2 = $this->input('image_2'); - $image_2_link = $this->input('image_2_link'); - $image_3 = $this->input('image_3'); - $image_3_link = $this->input('image_3_link'); - $image_4 = $this->input('image_4'); - $image_4_link = $this->input('image_4_link'); - - $hash_template = md5($title_template . $body_template); - $hash_data = md5($title_template . $title_data . $body_template . $body_data); - $dateline = $this->time; - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "feeds SET appid='$appid', icon='$icon', uid='$uid', username='$username', - title_template='$title_template', title_data='$title_data', body_template='$body_template', body_data='$body_data', body_general='$body_general', - image_1='$image_1', image_1_link='$image_1_link', image_2='$image_2', image_2_link='$image_2_link', - image_3='$image_3', image_3_link='$image_3_link', image_4='$image_4', image_4_link='$image_4_link', - hash_template='$hash_template', hash_data='$hash_data', target_ids='$target_ids', dateline='$dateline'"); - return $this->db->insert_id(); - } - - function ondelete() - { - $start = $this->input('start'); - $limit = $this->input('limit'); - $end = $start + $limit; - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "feeds WHERE feedid>'$start' AND feedid<'$end'"); - } - - function onget() - { - $this->load('misc'); - $limit = intval($this->input('limit')); - $delete = $this->input('delete'); - $feedlist = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "feeds ORDER BY feedid DESC LIMIT $limit"); - if ($feedlist) - { - $maxfeedid = $feedlist[0]['feedid']; - foreach ($feedlist as $key => $feed) - { - $feed['body_data'] = $_ENV['misc']->string2array($feed['body_data']); - $feed['title_data'] = $_ENV['misc']->string2array($feed['title_data']); - $feedlist[$key] = $feed; - } - } - if (!empty($feedlist)) - { - if (!isset($delete) || $delete) - { - $this->_delete(0, $maxfeedid); - } - } - return $feedlist; - } - - function _delete($start, $end) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "feeds WHERE feedid>='$start' AND feedid<='$end'"); - } - - function _parsetemplate($template) - { - $template = str_replace(array("\r", "\n"), '', $template); - $template = str_replace(array('
                ', '
                ', '
                ', '
                '), "\n", $template); - $template = str_replace(array('', ''), '[B]', $template); - $template = str_replace(array('', ''), '[I]', $template); - $template = str_replace(array('', ''), '[U]', $template); - $template = str_replace(array('', ''), '[/B]', $template); - $template = str_replace(array('', ''), '[/I]', $template); - $template = str_replace(array('', ''), '[/U]', $template); - $template = dhtmlspecialchars($template); - $template = nl2br($template); - $template = str_replace(array('[B]', '[I]', '[U]', '[/B]', '[/I]', '[/U]'), array('', '', '', '', '', ''), $template); - return $template; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/friend.php b/extend/fast/ucenter/client/uc_client/control/friend.php deleted file mode 100644 index 01768b54..00000000 --- a/extend/fast/ucenter/client/uc_client/control/friend.php +++ /dev/null @@ -1,64 +0,0 @@ -friendcontrol(); - } - - function friendcontrol() - { - parent::__construct(); - $this->init_input(); - $this->load('friend'); - } - - function ondelete() - { - $uid = intval($this->input('uid')); - $friendids = $this->input('friendids'); - $id = $_ENV['friend']->delete($uid, $friendids); - return $id; - } - - function onadd() - { - $uid = intval($this->input('uid')); - $friendid = $this->input('friendid'); - $comment = $this->input('comment'); - $id = $_ENV['friend']->add($uid, $friendid, $comment); - return $id; - } - - function ontotalnum() - { - $uid = intval($this->input('uid')); - $direction = intval($this->input('direction')); - $totalnum = $_ENV['friend']->get_totalnum_by_uid($uid, $direction); - return $totalnum; - } - - function onls() - { - $uid = intval($this->input('uid')); - $page = intval($this->input('page')); - $pagesize = intval($this->input('pagesize')); - $totalnum = intval($this->input('totalnum')); - $direction = intval($this->input('direction')); - $pagesize = $pagesize ? $pagesize : UC_PPP; - $totalnum = $totalnum ? $totalnum : $_ENV['friend']->get_totalnum_by_uid($uid); - $data = $_ENV['friend']->get_list($uid, $page, $pagesize, $totalnum, $direction); - return $data; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/index.htm b/extend/fast/ucenter/client/uc_client/control/index.htm deleted file mode 100644 index 0519ecba..00000000 --- a/extend/fast/ucenter/client/uc_client/control/index.htm +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/control/mail.php b/extend/fast/ucenter/client/uc_client/control/mail.php deleted file mode 100644 index 28bdedda..00000000 --- a/extend/fast/ucenter/client/uc_client/control/mail.php +++ /dev/null @@ -1,42 +0,0 @@ -mailcontrol(); - } - - function mailcontrol() - { - parent::__construct(); - $this->init_input(); - } - - function onadd() - { - $this->load('mail'); - $mail = array(); - $mail['appid'] = UC_APPID; - $mail['uids'] = explode(',', $this->input('uids')); - $mail['emails'] = explode(',', $this->input('emails')); - $mail['subject'] = $this->input('subject'); - $mail['message'] = $this->input('message'); - $mail['charset'] = $this->input('charset'); - $mail['htmlon'] = intval($this->input('htmlon')); - $mail['level'] = abs(intval($this->input('level'))); - $mail['frommail'] = $this->input('frommail'); - $mail['dateline'] = $this->time; - return $_ENV['mail']->add($mail); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/pm.php b/extend/fast/ucenter/client/uc_client/control/pm.php deleted file mode 100644 index 940d3987..00000000 --- a/extend/fast/ucenter/client/uc_client/control/pm.php +++ /dev/null @@ -1,463 +0,0 @@ -pmcontrol(); - } - - function pmcontrol() - { - parent::__construct(); - $this->load('user'); - $this->load('pm'); - } - - function oncheck_newpm() - { - $this->init_input(); - $uid = intval($this->input('uid')); - $more = intval($this->input('more')); - if (!$_ENV['pm']->isnewpm($uid) && !$more) - { - return 0; - } - $newprvpm = $_ENV['pm']->getpmnum($uid, 1, 1); - $newchatpm = $_ENV['pm']->getpmnum($uid, 2, 1); - $newpm = $newprvpm + $newchatpm; - if ($more == 0) - { - return $newpm; - } - elseif ($more == 1) - { - return array('newpm' => $newpm, 'newprivatepm' => $newprvpm); - } - elseif ($more == 2 || $more == 3) - { - if ($more == 2) - { - return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm); - } - else - { - $lastpm = $_ENV['pm']->lastpm($uid); - require_once UC_ROOT . 'lib/uccode.class.php'; - $this->uccode = new uccode(); - $lastpm['lastsummary'] = $this->uccode->complie($lastpm['lastsummary']); - return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm, 'lastdate' => $lastpm['lastdateline'], 'lastmsgfromid' => $lastpm['lastauthorid'], 'lastmsgfrom' => $lastpm['lastauthorusername'], 'lastmsg' => $lastpm['lastsummary']); - } - } - elseif ($more == 4) - { - return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm); - } - else - { - return 0; - } - } - - function onsendpm() - { - $this->init_input(); - $fromuid = $this->input('fromuid'); - $msgto = $this->input('msgto'); - $subject = $this->input('subject'); - $message = $this->input('message'); - $replypmid = $this->input('replypmid'); - $isusername = $this->input('isusername'); - $type = $this->input('type'); - - if (!$fromuid) - { - return 0; - } - - $user = $_ENV['user']->get_user_by_uid($fromuid); - $user = daddslashes($user, 1); - if (!$user) - { - return 0; - } - $this->user['uid'] = $user['uid']; - $this->user['username'] = $user['username']; - - if ($replypmid) - { - $isusername = 0; - $plid = $_ENV['pm']->getplidbypmid($replypmid); - $msgto = $_ENV['pm']->getuidbyplid($plid); - unset($msgto[$this->user['uid']]); - } - else - { - if (!empty($msgto)) - { - $msgto = array_unique(explode(',', $msgto)); - } - } - - if ($isusername) - { - $msgto = $_ENV['user']->name2id($msgto); - } - $countmsgto = count($msgto); - - if ($this->settings['pmsendregdays']) - { - if ($user['regdate'] > $this->time - $this->settings['pmsendregdays'] * 86400) - { - return PMSENDREGDAYS; - } - } - if ($this->settings['chatpmmemberlimit']) - { - if ($type == 1 && ($countmsgto > ($this->settings['chatpmmemberlimit'] - 1))) - { - return CHATPMMEMBERLIMIT_ERROR; - } - } - if ($this->settings['pmfloodctrl']) - { - if (!$_ENV['pm']->ispminterval($this->user['uid'], $this->settings['pmfloodctrl'])) - { - return PMFLOODCTRL_ERROR; - } - } - if ($this->settings['privatepmthreadlimit']) - { - if (!$_ENV['pm']->isprivatepmthreadlimit($this->user['uid'], $this->settings['privatepmthreadlimit'])) - { - return PRIVATEPMTHREADLIMIT_ERROR; - } - } - if ($this->settings['chatpmthreadlimit']) - { - if (!$_ENV['pm']->ischatpmthreadlimit($this->user['uid'], $this->settings['chatpmthreadlimit'])) - { - return CHATPMTHREADLIMIT_ERROR; - } - } - - $lastpmid = 0; - if ($replypmid) - { - $lastpmid = $_ENV['pm']->replypm($plid, $this->user['uid'], $this->user['username'], $message); - } - else - { - $lastpmid = $_ENV['pm']->sendpm($this->user['uid'], $this->user['username'], $msgto, $subject, $message, $type); - } - return $lastpmid; - } - - function ondelete() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $pmids = $this->input('pmids'); - if (empty($pmids)) - { - return 0; - } - if (is_array($pmids)) - { - $this->apps = $this->cache('apps'); - if ($this->apps[$this->app['appid']]['type'] == 'UCHOME') - { - $id = $_ENV['pm']->deletepmbyplids($this->user['uid'], $this->input('pmids')); - } - else - { - $id = $_ENV['pm']->deletepmbypmids($this->user['uid'], $this->input('pmids')); - } - } - else - { - $id = $_ENV['pm']->deletepmbypmid($this->user['uid'], $this->input('pmids')); - } - return $id; - } - - function ondeletechat() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $plids = $this->input('plids'); - $type = intval($this->input('type')); - if ($type == 1) - { - return $_ENV['pm']->deletepmbyplids($this->user['uid'], $plids); - } - else - { - return $_ENV['pm']->quitchatpm($this->user['uid'], $plids); - } - } - - function ondeleteuser() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $id = $_ENV['pm']->deletepmbyplids($this->user['uid'], $this->input('touids'), 1); - return $id; - } - - function onreadstatus() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $_ENV['pm']->setpmstatus($this->user['uid'], $this->input('uids'), $this->input('plids'), $this->input('status')); - } - - function onignore() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - return $_ENV['pm']->set_ignore($this->user['uid']); - } - - function onls() - { - $this->init_input(); - $pagesize = $this->input('pagesize'); - $filter = $this->input('filter'); - $page = $this->input('page'); - $msglen = $this->input('msglen'); - $this->user['uid'] = intval($this->input('uid')); - - $filter = $filter ? (in_array($filter, array('newpm', 'privatepm')) ? $filter : '') : ''; - if ($filter == 'newpm') - { - $type = 0; - $new = 1; - } - elseif ($filter == 'privatepm') - { - $type = 0; - $new = 0; - } - else - { - return array(); - } - $pmnum = $_ENV['pm']->getpmnum($this->user['uid'], $type, $new); - $start = $this->page_get_start($page, $pagesize, $pmnum); - - if ($pagesize > 0) - { - $pms = $_ENV['pm']->getpmlist($this->user['uid'], $filter, $start, $pagesize); - if (is_array($pms) && !empty($pms)) - { - foreach ($pms as $key => $pm) - { - if ($msglen) - { - $pms[$key]['lastsummary'] = $_ENV['pm']->removecode($pms[$key]['lastsummary'], $msglen); - } - else - { - unset($pms[$key]['lastsummary']); - } - } - } - $result['data'] = $pms; - } - $result['count'] = $pmnum; - return $result; - } - - function onview() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $pmid = $this->input('pmid'); - $touid = $this->input('touid'); - $daterange = $this->input('daterange'); - $page = $this->input('page'); - $pagesize = $this->input('pagesize'); - $isplid = $this->input('isplid'); - $type = $this->input('type'); - - $daterange = empty($daterange) ? 1 : $daterange; - $today = $this->time - ($this->time + $this->settings['timeoffset']) % 86400; - if ($daterange == 1) - { - $starttime = $today; - } - elseif ($daterange == 2) - { - $starttime = $today - 86400; - } - elseif ($daterange == 3) - { - $starttime = $today - 172800; - } - elseif ($daterange == 4) - { - $starttime = $today - 604800; - } - elseif ($daterange == 5) - { - $starttime = 0; - } - $endtime = $this->time; - - if (!$isplid) - { - $plid = $_ENV['pm']->getplidbytouid($this->user['uid'], $touid); - } - else - { - $plid = $touid; - } - if ($page) - { - $pmnum = $_ENV['pm']->getpmnumbyplid($this->user['uid'], $plid); - $start = $this->page_get_start($page, $pagesize, $pmnum); - $ppp = $pagesize; - } - else - { - $pmnum = 0; - $start = 0; - $ppp = 0; - } - - if ($pmid) - { - $pms = $_ENV['pm']->getpmbypmid($this->user['uid'], $pmid); - } - else - { - $pms = $_ENV['pm']->getpmbyplid($this->user['uid'], $plid, $starttime, $endtime, $start, $ppp, $type); - } - - require_once UC_ROOT . 'lib/uccode.class.php'; - $this->uccode = new uccode(); - if ($pms) - { - foreach ($pms as $key => $pm) - { - $pms[$key]['message'] = $this->uccode->complie($pms[$key]['message']); - } - } - return $pms; - } - - function onviewnum() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $touid = $this->input('touid'); - $isplid = $this->input('isplid'); - if (!$isplid) - { - $plid = $_ENV['pm']->getplidbytouid($this->user['uid'], $touid); - } - else - { - $plid = $touid; - } - $pmnum = $_ENV['pm']->getpmnumbyplid($this->user['uid'], $plid); - return $pmnum; - } - - function onviewnode() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $type = $this->input('type'); - $pmid = $this->input('pmid'); - $type = 0; - $pms = $_ENV['pm']->getpmbypmid($this->user['uid'], $pmid); - - require_once UC_ROOT . 'lib/uccode.class.php'; - $this->uccode = new uccode(); - if ($pms) - { - foreach ($pms as $key => $pm) - { - $pms[$key]['message'] = $this->uccode->complie($pms[$key]['message']); - } - } - $pms = $pms[0]; - return $pms; - } - - function onchatpmmemberlist() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $plid = intval($this->input('plid')); - return $_ENV['pm']->chatpmmemberlist($this->user['uid'], $plid); - } - - function onkickchatpm() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $plid = intval($this->input('plid')); - $touid = intval($this->input('touid')); - return $_ENV['pm']->kickchatpm($plid, $this->user['uid'], $touid); - } - - function onappendchatpm() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $plid = intval($this->input('plid')); - $touid = intval($this->input('touid')); - return $_ENV['pm']->appendchatpm($plid, $this->user['uid'], $touid); - } - - function onblackls_get() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - return $_ENV['pm']->get_blackls($this->user['uid']); - } - - function onblackls_set() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $blackls = $this->input('blackls'); - return $_ENV['pm']->set_blackls($this->user['uid'], $blackls); - } - - function onblackls_add() - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $username = $this->input('username'); - return $_ENV['pm']->update_blackls($this->user['uid'], $username, 1); - } - - function onblackls_delete($arr) - { - $this->init_input(); - $this->user['uid'] = intval($this->input('uid')); - $username = $this->input('username'); - return $_ENV['pm']->update_blackls($this->user['uid'], $username, 2); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/tag.php b/extend/fast/ucenter/client/uc_client/control/tag.php deleted file mode 100644 index 8fc80aa2..00000000 --- a/extend/fast/ucenter/client/uc_client/control/tag.php +++ /dev/null @@ -1,102 +0,0 @@ -tagcontrol(); - } - - function tagcontrol() - { - parent::__construct(); - $this->init_input(); - $this->load('tag'); - $this->load('misc'); - } - - function ongettag() - { - $appid = $this->input('appid'); - $tagname = $this->input('tagname'); - $nums = $this->input('nums'); - if (empty($tagname)) - { - return NULL; - } - $return = $apparray = $appadd = array(); - - if ($nums && is_array($nums)) - { - foreach ($nums as $k => $num) - { - $apparray[$k] = $k; - } - } - - $data = $_ENV['tag']->get_tag_by_name($tagname); - if ($data) - { - $apparraynew = array(); - foreach ($data as $tagdata) - { - $row = $r = array(); - $tmp = explode("\t", $tagdata['data']); - $type = $tmp[0]; - array_shift($tmp); - foreach ($tmp as $tmp1) - { - $tmp1 != '' && $r[] = $_ENV['misc']->string2array($tmp1); - } - if (in_array($tagdata['appid'], $apparray)) - { - if ($tagdata['expiration'] > 0 && $this->time - $tagdata['expiration'] > 3600) - { - $appadd[] = $tagdata['appid']; - $_ENV['tag']->formatcache($tagdata['appid'], $tagname); - } - else - { - $apparraynew[] = $tagdata['appid']; - } - $datakey = array(); - $count = 0; - foreach ($r as $data) - { - $return[$tagdata['appid']]['data'][] = $data; - $return[$tagdata['appid']]['type'] = $type; - $count++; - if ($count >= $nums[$tagdata['appid']]) - { - break; - } - } - } - } - $apparray = array_diff($apparray, $apparraynew); - } - else - { - foreach ($apparray as $appid) - { - $_ENV['tag']->formatcache($appid, $tagname); - } - } - if ($apparray) - { - $this->load('note'); - $_ENV['note']->add('gettag', "id=$tagname", '', $appadd, -1); - } - return $return; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/control/user.php b/extend/fast/ucenter/client/uc_client/control/user.php deleted file mode 100644 index 42d0b4e8..00000000 --- a/extend/fast/ucenter/client/uc_client/control/user.php +++ /dev/null @@ -1,443 +0,0 @@ -usercontrol(); - } - - function usercontrol() - { - parent::__construct(); - $this->load('user'); - $this->app = $this->cache['apps'][UC_APPID]; - } - - // 同步注册 - function onsynregister() - { - $this->init_input(); - $uid = $this->input('uid'); - $password = $this->input('password'); - if ($this->app['synlogin']) - { - if ($this->user = $_ENV['user']->get_user_by_uid($uid)) - { - $params = 'action=synregister' . - '&username=' . $this->user['username'] . - '&uid=' . $this->user['uid'] . - '&password=' . $password . - '&email=' . $this->user['email'] . - '&mobile=' . $this->user['mobile'] . - '&time=' . $this->time; - $synstr = ''; - foreach ($this->cache['apps'] as $appid => $app) - { - if ($app['synlogin'] && $app['appid'] != $this->app['appid']) - { - $synstr .= ''; - } - } - return $synstr; - } - } - return ''; - } - - // 同步登录 - function onsynlogin() - { - $this->init_input(); - $uid = $this->input('uid'); - if ($this->app['synlogin']) - { - if ($this->user = $_ENV['user']->get_user_by_uid($uid)) - { - $params = 'action=synlogin' . - '&username=' . $this->user['username'] . - '&uid=' . $this->user['uid'] . - '&password=' . $this->user['password'] . - '&time=' . $this->time; - $synstr = ''; - foreach ($this->cache['apps'] as $appid => $app) - { - if ($app['synlogin'] && $app['appid'] != $this->app['appid']) - { - $synstr .= ''; - } - } - return $synstr; - } - } - return ''; - } - - // 同步退出 - function onsynlogout() - { - $this->init_input(); - if ($this->app['synlogin']) - { - $synstr = ''; - foreach ($this->cache['apps'] as $appid => $app) - { - if ($app['synlogin'] && $app['appid'] != $this->app['appid']) - { - $synstr .= ''; - } - } - return $synstr; - } - return ''; - } - - // 同步注册 - function onregister() - { - $this->init_input(); - $username = $this->input('username'); - $password = $this->input('password'); - $email = $this->input('email'); - $mobile = $this->input('mobile'); - $extend = $this->input('extend'); - $extend = $extend ? $extend : []; - if (($status = $this->_check_username($username)) < 0) - { - return $status; - } - if ($email && ($status = $this->_check_email($email)) < 0) - { - return $status; - } - if ($mobile && ($status = $this->_check_mobile($mobile)) < 0) - { - return $status; - } - $uid = $_ENV['user']->add_user($username, $password, $email, $mobile, 0, $extend); - return $uid; - } - - // 编辑ucenter中信息 - function onedit() - { - $this->init_input(); - $uid = intval($this->input('uid')); - $username = $this->input('username'); - $password = $this->input('password'); - $email = $this->input('email'); - $mobile = $this->input('mobile'); - $extend = $this->input('extend'); - $extend = $extend ? $extend : []; - - $status = $_ENV['user']->edit_user($username, $password, $email, $mobile, $uid, $extend); - - if ($status > 0) - { - if (@include UC_ROOT . './data/cache/apps.php') - { - if (count($_CACHE['apps']) > 1) - { - //手动调用一次同步到所有应用 - uc_api_post('user', 'edit', $this->input); - } - } - return $status; - $this->load('note'); - $_ENV['note']->add('updateinfo', http_build_query($this->input)); - } - return $status; - } - - // 登录ucenter账号 - function onlogin() - { - $this->init_input(); - $username = $this->input('username'); - $password = $this->input('password'); - $isuid = $this->input('isuid'); //0用户名 1UID 2邮箱 3手机 - - if ($isuid == 1) - { - $user = $_ENV['user']->get_user_by_uid($username); - } - elseif ($isuid == 2) - { - $user = $_ENV['user']->get_user_by_email($username); - } - elseif ($isuid == 3) - { - $user = $_ENV['user']->get_user_by_mobile($username); - } - else - { - $user = $_ENV['user']->get_user_by_username($username); - } - - $passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password); - if (empty($user)) - { - $status = -1; - } - elseif ($user['password'] != md5($passwordmd5 . $user['salt'])) - { - $status = -2; - } - else - { - $status = $user['uid']; - } - $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0; - return [ - 'status' => $status, - 'uid' => isset($user['uid']) ? $user['uid'] : 0, - 'username' => isset($user['username']) ? $user['username'] : '', - 'password' => $password, - 'email' => isset($user['email']) ? $user['email'] : '', - 'mobile' => isset($user['mobile']) ? $user['mobile'] : '', - 'merge' => $merge - ]; - } - - function onlogincheck() - { - $this->init_input(); - $username = $this->input('username'); - $ip = $this->input('ip'); - return $_ENV['user']->can_do_login($username, $ip); - } - - function oncheck_email() - { - $this->init_input(); - $email = $this->input('email'); - return $this->_check_email($email); - } - - function oncheck_username() - { - $this->init_input(); - $username = $this->input('username'); - if (($status = $this->_check_username($username)) < 0) - { - return $status; - } - else - { - return 1; - } - } - - function onget_user() - { - $this->init_input(); - $username = $this->input('username'); - $isuid = $this->input('isuid'); //0用户名 1UID 2邮箱 3手机 - if ($isuid == 1) - { - $member = $_ENV['user']->get_user_by_uid($username); - } - else if ($isuid == 2) - { - $member = $_ENV['user']->get_user_by_email($username); - } - else if ($isuid == 3) - { - $member = $_ENV['user']->get_user_by_mobile($username); - } - else - { - $member = $_ENV['user']->get_user_by_username($username); - } - if ($member) - { - // 加载扩展表 - $memberfields = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='{$member['uid']}'"); - - $memberfields = $memberfields ? $memberfields : []; - $member = [ - 'uid' => $member['uid'], - 'username' => $member['username'], - 'email' => $member['email'], - 'mobile' => $member['mobile'] - ]; - return array_merge($member, $memberfields); - } - else - { - return 0; - } - } - - function ongetprotected() - { - $this->init_input(); - $protectedmembers = $this->db->fetch_all("SELECT uid,username FROM " . UC_DBTABLEPRE . "protectedmembers GROUP BY username"); - return $protectedmembers; - } - - function ondelete() - { - $this->init_input(); - $uid = $this->input('uid'); - return $_ENV['user']->delete_user($uid); - } - - function onaddprotected() - { - $this->init_input(); - $username = $this->input('username'); - $admin = $this->input('admin'); - $appid = $this->app['appid']; - $usernames = (array) $username; - foreach ($usernames as $username) - { - $user = $_ENV['user']->get_user_by_username($username); - $uid = $user['uid']; - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "protectedmembers SET uid='$uid', username='$username', appid='$appid', dateline='{$this->time}', admin='$admin'", 'SILENT'); - } - return $this->db->errno() ? -1 : 1; - } - - function ondeleteprotected() - { - $this->init_input(); - $username = $this->input('username'); - $appid = $this->app['appid']; - $usernames = (array) $username; - foreach ($usernames as $username) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "protectedmembers WHERE username='$username' AND appid='$appid'"); - } - return $this->db->errno() ? -1 : 1; - } - - function onmerge() - { - $this->init_input(); - $uid = $this->input('uid'); - $oldusername = $this->input('oldusername'); - $newusername = $this->input('newusername'); - $password = $this->input('password'); - $email = $this->input('email'); - $mobile = $this->input('mobile'); - $extend = $this->input('extend'); - $extend = $extend ? $extend : []; - if (($status = $this->_check_username($newusername)) < 0) - { - return $status; - } - $uid = $_ENV['user']->add_user($newusername, $password, $email, $mobile, $uid, $extend); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->app['appid'] . "' AND username='$oldusername'"); - return $uid; - } - - function onmerge_remove() - { - $this->init_input(); - $username = $this->input('username'); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->app['appid'] . "' AND username='$username'"); - return NULL; - } - - function _check_username($username) - { - $username = addslashes(trim(stripslashes($username))); - if (!$_ENV['user']->check_username($username)) - { - return UC_USER_CHECK_USERNAME_FAILED; - } - elseif (!$_ENV['user']->check_usernamecensor($username)) - { - return UC_USER_USERNAME_BADWORD; - } - elseif ($_ENV['user']->check_usernameexists($username)) - { - return UC_USER_USERNAME_EXISTS; - } - return 1; - } - - function _check_email($email, $username = '') - { - if (empty($this->settings)) - { - $this->settings = $this->cache('settings'); - } - if (!$_ENV['user']->check_emailformat($email)) - { - return UC_USER_EMAIL_FORMAT_ILLEGAL; - } - elseif (!$_ENV['user']->check_emailaccess($email)) - { - return UC_USER_EMAIL_ACCESS_ILLEGAL; - } - elseif (!$this->settings['doublee'] && $_ENV['user']->check_emailexists($email, $username)) - { - return UC_USER_EMAIL_EXISTS; - } - else - { - return 1; - } - } - - function _check_mobile($mobile, $username = '') - { - if (empty($this->settings)) - { - $this->settings = $this->cache('settings'); - } - if (!$_ENV['user']->check_mobileformat($mobile)) - { - return UC_USER_EMAIL_FORMAT_ILLEGAL; - } - elseif (!$_ENV['user']->check_mobileaccess($mobile)) - { - return UC_USER_EMAIL_ACCESS_ILLEGAL; - } - elseif (!$this->settings['doublee'] && $_ENV['user']->check_mobileexists($mobile, $username)) - { - return UC_USER_EMAIL_EXISTS; - } - else - { - return 1; - } - } - - function onuploadavatar() - { - - } - - function onrectavatar() - { - - } - - function flashdata_decode($s) - { - - } - -} diff --git a/extend/fast/ucenter/client/uc_client/data/cache/apps.php b/extend/fast/ucenter/client/uc_client/data/cache/apps.php deleted file mode 100644 index b0f1f519..00000000 --- a/extend/fast/ucenter/client/uc_client/data/cache/apps.php +++ /dev/null @@ -1,40 +0,0 @@ - - array ( - 'appid' => '1', - 'type' => 'OTHER', - 'name' => 'FastAdmin', - 'url' => 'http://www.fa.com/index/ucenter', - 'ip' => '', - 'viewprourl' => '', - 'apifilename' => 'index', - 'charset' => '', - 'synlogin' => '1', - 'extra' => - array ( - 'apppath' => '', - 'extraurl' => ' ', - ), - 'recvnote' => '1', - ), - 2 => - array ( - 'appid' => '2', - 'type' => 'DISCUZX', - 'name' => 'Discuz!', - 'url' => 'http://www.discuz.com', - 'ip' => '', - 'viewprourl' => '', - 'apifilename' => 'uc.php', - 'charset' => 'utf-8', - 'synlogin' => '1', - 'extra' => - array ( - 'apppath' => '', - 'extraurl' => ' ', - ), - 'recvnote' => '1', - ), - 'UC_API' => 'http://www.ucenter.com', -); diff --git a/extend/fast/ucenter/client/uc_client/data/cache/badwords.php b/extend/fast/ucenter/client/uc_client/data/cache/badwords.php deleted file mode 100644 index c3ca52b4..00000000 --- a/extend/fast/ucenter/client/uc_client/data/cache/badwords.php +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/data/cache/index.htm b/extend/fast/ucenter/client/uc_client/data/cache/index.htm deleted file mode 100644 index e69de29b..00000000 diff --git a/extend/fast/ucenter/client/uc_client/data/cache/settings.php b/extend/fast/ucenter/client/uc_client/data/cache/settings.php deleted file mode 100644 index 069021ea..00000000 --- a/extend/fast/ucenter/client/uc_client/data/cache/settings.php +++ /dev/null @@ -1,32 +0,0 @@ - '', - 'censoremail' => '', - 'censorusername' => '', - 'dateformat' => 'y-n-j', - 'doublee' => '0', - 'nextnotetime' => '0', - 'timeoffset' => '28800', - 'privatepmthreadlimit' => '25', - 'chatpmthreadlimit' => '30', - 'chatpmmemberlimit' => '35', - 'pmfloodctrl' => '15', - 'pmcenter' => '1', - 'sendpmseccode' => '1', - 'pmsendregdays' => '0', - 'maildefault' => 'username@21cn.com', - 'mailsend' => '1', - 'mailserver' => 'smtp.21cn.com', - 'mailport' => '25', - 'mailauth' => '1', - 'mailfrom' => 'UCenter ', - 'mailauth_username' => 'username@21cn.com', - 'mailauth_password' => 'password', - 'maildelimiter' => '0', - 'mailusername' => '1', - 'mailsilent' => '1', - 'version' => '1.6.0', - 'credits' => 'N;', -); - -?> \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/data/index.htm b/extend/fast/ucenter/client/uc_client/data/index.htm deleted file mode 100644 index e69de29b..00000000 diff --git a/extend/fast/ucenter/client/uc_client/index.htm b/extend/fast/ucenter/client/uc_client/index.htm deleted file mode 100644 index 0519ecba..00000000 --- a/extend/fast/ucenter/client/uc_client/index.htm +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/lib/db.class.php b/extend/fast/ucenter/client/uc_client/lib/db.class.php deleted file mode 100644 index 0c1f20bc..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/db.class.php +++ /dev/null @@ -1,210 +0,0 @@ -dbhost = $dbhost; - $this->dbuser = $dbuser; - $this->dbpw = $dbpw; - $this->dbname = $dbname; - $this->dbcharset = $dbcharset; - $this->pconnect = $pconnect; - $this->tablepre = $tablepre; - $this->time = $time; - - if ($pconnect) - { - if (!$this->link = mysql_pconnect($dbhost, $dbuser, $dbpw)) - { - $this->halt('Can not connect to MySQL server'); - } - } - else - { - if (!$this->link = mysql_connect($dbhost, $dbuser, $dbpw)) - { - $this->halt('Can not connect to MySQL server'); - } - } - - if ($this->version() > '4.1') - { - if ($dbcharset) - { - mysql_query("SET character_set_connection=" . $dbcharset . ", character_set_results=" . $dbcharset . ", character_set_client=binary", $this->link); - } - - if ($this->version() > '5.0.1') - { - mysql_query("SET sql_mode=''", $this->link); - } - } - - if ($dbname) - { - mysql_select_db($dbname, $this->link); - } - } - - function fetch_array($query, $result_type = MYSQL_ASSOC) - { - return mysql_fetch_array($query, $result_type); - } - - function result_first($sql) - { - $query = $this->query($sql); - return $this->result($query, 0); - } - - function fetch_first($sql) - { - $query = $this->query($sql); - return $this->fetch_array($query); - } - - function fetch_all($sql, $id = '') - { - $arr = array(); - $query = $this->query($sql); - while ($data = $this->fetch_array($query)) - { - $id ? $arr[$data[$id]] = $data : $arr[] = $data; - } - return $arr; - } - - function cache_gc() - { - $this->query("DELETE FROM {$this->tablepre}sqlcaches WHERE expiry<$this->time"); - } - - function query($sql, $type = '', $cachetime = FALSE) - { - $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ? 'mysql_unbuffered_query' : 'mysql_query'; - if (!($query = $func($sql, $this->link)) && $type != 'SILENT') - { - $this->halt('MySQL Query Error', $sql); - } - $this->querynum++; - $this->histories[] = $sql; - return $query; - } - - function affected_rows() - { - return mysql_affected_rows($this->link); - } - - function error() - { - return (($this->link) ? mysql_error($this->link) : mysql_error()); - } - - function errno() - { - return intval(($this->link) ? mysql_errno($this->link) : mysql_errno()); - } - - function result($query, $row) - { - $query = @mysql_result($query, $row); - return $query; - } - - function num_rows($query) - { - $query = mysql_num_rows($query); - return $query; - } - - function num_fields($query) - { - return mysql_num_fields($query); - } - - function free_result($query) - { - return mysql_free_result($query); - } - - function insert_id() - { - return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0); - } - - function fetch_row($query) - { - $query = mysql_fetch_row($query); - return $query; - } - - function fetch_fields($query) - { - return mysql_fetch_field($query); - } - - function version() - { - return mysql_get_server_info($this->link); - } - - function escape_string($str) - { - return mysql_escape_string($str); - } - - function close() - { - return mysql_close($this->link); - } - - function halt($message = '', $sql = '') - { - $error = mysql_error(); - $errorno = mysql_errno(); - if ($errorno == 2006 && $this->goneaway-- > 0) - { - $this->connect($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname, $this->dbcharset, $this->pconnect, $this->tablepre, $this->time); - $this->query($sql); - } - else - { - $s = ''; - if ($message) - { - $s = "UCenter info: $message
                "; - } - if ($sql) - { - $s .= 'SQL:' . htmlspecialchars($sql) . '
                '; - } - $s .= 'Error:' . $error . '
                '; - $s .= 'Errno:' . $errorno . '
                '; - $s = str_replace(UC_DBTABLEPRE, '[Table]', $s); - exit($s); - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/lib/dbi.class.php b/extend/fast/ucenter/client/uc_client/lib/dbi.class.php deleted file mode 100644 index 2972e92c..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/dbi.class.php +++ /dev/null @@ -1,200 +0,0 @@ -dbhost = $dbhost; - $this->dbuser = $dbuser; - $this->dbpw = $dbpw; - $this->dbname = $dbname; - $this->dbcharset = $dbcharset; - $this->pconnect = $pconnect; - $this->tablepre = $tablepre; - $this->time = $time; - - if (!$this->link = new mysqli($dbhost, $dbuser, $dbpw, $dbname)) - { - $this->halt('Can not connect to MySQL server'); - } - - if ($this->version() > '4.1') - { - if ($dbcharset) - { - $this->link->set_charset($dbcharset); - } - - if ($this->version() > '5.0.1') - { - $this->link->query("SET sql_mode=''"); - } - } - } - - function fetch_array($query, $result_type = MYSQLI_ASSOC) - { - return $query ? $query->fetch_array($result_type) : null; - } - - function result_first($sql) - { - $query = $this->query($sql); - return $this->result($query, 0); - } - - function fetch_first($sql) - { - $query = $this->query($sql); - return $this->fetch_array($query); - } - - function fetch_all($sql, $id = '') - { - $arr = array(); - $query = $this->query($sql); - while ($data = $this->fetch_array($query)) - { - $id ? $arr[$data[$id]] = $data : $arr[] = $data; - } - return $arr; - } - - function cache_gc() - { - $this->query("DELETE FROM {$this->tablepre}sqlcaches WHERE expiry<$this->time"); - } - - function query($sql, $type = '', $cachetime = FALSE) - { - $resultmode = $type == 'UNBUFFERED' ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT; - if (!($query = $this->link->query($sql, $resultmode)) && $type != 'SILENT') - { - $this->halt('MySQL Query Error', $sql); - } - $this->querynum++; - $this->histories[] = $sql; - return $query; - } - - function affected_rows() - { - return $this->link->affected_rows; - } - - function error() - { - return (($this->link) ? $this->link->error : mysqli_error()); - } - - function errno() - { - return intval(($this->link) ? $this->link->errno : mysqli_errno()); - } - - function result($query, $row) - { - if (!$query || $query->num_rows == 0) - { - return null; - } - $query->data_seek($row); - $assocs = $query->fetch_row(); - return $assocs[0]; - } - - function num_rows($query) - { - $query = $query ? $query->num_rows : 0; - return $query; - } - - function num_fields($query) - { - return $query ? $query->field_count : 0; - } - - function free_result($query) - { - return $query ? $query->free() : false; - } - - function insert_id() - { - return ($id = $this->link->insert_id) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0); - } - - function fetch_row($query) - { - $query = $query ? $query->fetch_row() : null; - return $query; - } - - function fetch_fields($query) - { - return $query ? $query->fetch_field() : null; - } - - function version() - { - return $this->link->server_info; - } - - function escape_string($str) - { - return $this->link->escape_string($str); - } - - function close() - { - return $this->link->close(); - } - - function halt($message = '', $sql = '') - { - $error = $this->error(); - $errorno = $this->errno(); - if ($errorno == 2006 && $this->goneaway-- > 0) - { - $this->connect($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname, $this->dbcharset, $this->pconnect, $this->tablepre, $this->time); - $this->query($sql); - } - else - { - $s = ''; - if ($message) - { - $s = "UCenter info: $message
                "; - } - if ($sql) - { - $s .= 'SQL:' . htmlspecialchars($sql) . '
                '; - } - $s .= 'Error:' . $error . '
                '; - $s .= 'Errno:' . $errorno . '
                '; - $s = str_replace(UC_DBTABLEPRE, '[Table]', $s); - exit($s); - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/lib/index.htm b/extend/fast/ucenter/client/uc_client/lib/index.htm deleted file mode 100644 index 0519ecba..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/index.htm +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php b/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php deleted file mode 100644 index dcc165da..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php +++ /dev/null @@ -1,159 +0,0 @@ -base->cache['apps'][$mail['appid']]['name']; -$mail['subject'] = '=?' . $mail['charset'] . '?B?' . base64_encode(str_replace("\r", '', str_replace("\n", '', '[' . $appname . '] ' . $mail['subject']))) . '?='; -$mail['message'] = chunk_split(base64_encode(str_replace("\r\n.", " \r\n..", str_replace("\n", "\r\n", str_replace("\r", "\n", str_replace("\r\n", "\n", str_replace("\n\r", "\r", $mail['message']))))))); - -$email_from = $mail['frommail'] == '' ? '=?' . $mail['charset'] . '?B?' . base64_encode($appname) . "?= <$mail_setting[maildefault]>" : (preg_match('/^(.+?) \<(.+?)\>$/', $email_from, $from) ? '=?' . $mail['charset'] . '?B?' . base64_encode($from[1]) . "?= <$from[2]>" : $mail['frommail']); - -foreach (explode(',', $mail['email_to']) as $touser) -{ - $tousers[] = preg_match('/^(.+?) \<(.+?)\>$/', $touser, $to) ? ($mailusername ? '=?' . $mail['charset'] . '?B?' . base64_encode($to[1]) . "?= <$to[2]>" : $to[2]) : $touser; -} - -$mail['email_to'] = implode(',', $tousers); - -$headers = "From: $email_from{$maildelimiter}X-Priority: 3{$maildelimiter}X-Mailer: Discuz! $version{$maildelimiter}MIME-Version: 1.0{$maildelimiter}Content-type: text/" . ($mail['htmlon'] ? 'html' : 'plain') . "; charset=$mail[charset]{$maildelimiter}Content-Transfer-Encoding: base64{$maildelimiter}"; - -$mail_setting['mailport'] = $mail_setting['mailport'] ? $mail_setting['mailport'] : 25; - -if ($mail_setting['mailsend'] == 1 && function_exists('mail')) -{ - - return @mail($mail['email_to'], $mail['subject'], $mail['message'], $headers); -} -elseif ($mail_setting['mailsend'] == 2) -{ - - if (!$fp = fsocketopen($mail_setting['mailserver'], $mail_setting['mailport'], $errno, $errstr, 30)) - { - return false; - } - - stream_set_blocking($fp, true); - - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != '220') - { - return false; - } - - fputs($fp, ($mail_setting['mailauth'] ? 'EHLO' : 'HELO') . " discuz\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250) - { - return false; - } - - while (1) - { - if (substr($lastmessage, 3, 1) != '-' || empty($lastmessage)) - { - break; - } - $lastmessage = fgets($fp, 512); - } - - if ($mail_setting['mailauth']) - { - fputs($fp, "AUTH LOGIN\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 334) - { - return false; - } - - fputs($fp, base64_encode($mail_setting['mailauth_username']) . "\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 334) - { - return false; - } - - fputs($fp, base64_encode($mail_setting['mailauth_password']) . "\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 235) - { - return false; - } - - $email_from = $mail_setting['mailfrom']; - } - - fputs($fp, "MAIL FROM: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from) . ">\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 250) - { - fputs($fp, "MAIL FROM: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from) . ">\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 250) - { - return false; - } - } - - $email_tos = array(); - foreach (explode(',', $mail['email_to']) as $touser) - { - $touser = trim($touser); - if ($touser) - { - fputs($fp, "RCPT TO: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser) . ">\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 250) - { - fputs($fp, "RCPT TO: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser) . ">\r\n"); - $lastmessage = fgets($fp, 512); - return false; - } - } - } - - fputs($fp, "DATA\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 354) - { - return false; - } - - $headers .= 'Message-ID: <' . gmdate('YmdHs') . '.' . substr(md5($mail['message'] . microtime()), 0, 6) . rand(100000, 999999) . '@' . $_SERVER['HTTP_HOST'] . ">{$maildelimiter}"; - - fputs($fp, "Date: " . gmdate('r') . "\r\n"); - fputs($fp, "To: " . $mail['email_to'] . "\r\n"); - fputs($fp, "Subject: " . $mail['subject'] . "\r\n"); - fputs($fp, $headers . "\r\n"); - fputs($fp, "\r\n\r\n"); - fputs($fp, "$mail[message]\r\n.\r\n"); - $lastmessage = fgets($fp, 512); - if (substr($lastmessage, 0, 3) != 250) - { - return false; - } - - fputs($fp, "QUIT\r\n"); - return true; -} -elseif ($mail_setting['mailsend'] == 3) -{ - - ini_set('SMTP', $mail_setting['mailserver']); - ini_set('smtp_port', $mail_setting['mailport']); - ini_set('sendmail_from', $email_from); - - return @mail($mail['email_to'], $mail['subject'], $mail['message'], $headers); -} \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/lib/uccode.class.php b/extend/fast/ucenter/client/uc_client/lib/uccode.class.php deleted file mode 100644 index 47150b54..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/uccode.class.php +++ /dev/null @@ -1,174 +0,0 @@ -uccode(); - } - - function uccode() - { - $this->uccode = array( - 'pcodecount' => -1, - 'codecount' => 0, - 'codehtml' => '' - ); - } - - function codedisp($code) - { - $this->uccode['pcodecount'] ++; - $code = str_replace('\\"', '"', preg_replace("/^[\n\r]*(.+?)[\n\r]*$/is", "\\1", $code)); - $this->uccode['codehtml'][$this->uccode['pcodecount']] = $this->tpl_codedisp($code); - $this->uccode['codecount'] ++; - return "[\tUCENTER_CODE_" . $this->uccode[pcodecount] . "\t]"; - } - - function complie($message) - { - $message = dhtmlspecialchars($message); - if (strpos($message, '[/code]') !== FALSE) - { - $message = preg_replace("/\s*\[code\](.+?)\[\/code\]\s*/ies", "\$this->codedisp('\\1')", $message); - } - if (strpos($message, '[/url]') !== FALSE) - { - $message = preg_replace("/\[url(=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\/\/|www\.)([^\[\"']+?))?\](.+?)\[\/url\]/ies", "\$this->parseurl('\\1', '\\5')", $message); - } - if (strpos($message, '[/email]') !== FALSE) - { - $message = preg_replace("/\[email(=([a-z0-9\-_.+]+)@([a-z0-9\-_]+[.][a-z0-9\-_.]+))?\](.+?)\[\/email\]/ies", "\$this->parseemail('\\1', '\\4')", $message); - } - $message = str_replace(array( - '[/color]', '[/size]', '[/font]', '[/align]', '[b]', '[/b]', - '[i]', '[/i]', '[u]', '[/u]', '[list]', '[list=1]', '[list=a]', - '[list=A]', '[*]', '[/list]', '[indent]', '[/indent]', '[/float]' - ), array( - '', '', '', '

                ', '', '', '', - '', '', '', '
                  ', '
                    ', '
                      ', - '
                        ', '
                      • ', '
                      ', '
                      ', '
                      ', '' - ), preg_replace(array( - "/\[color=([#\w]+?)\]/i", - "/\[size=(\d+?)\]/i", - "/\[size=(\d+(\.\d+)?(px|pt|in|cm|mm|pc|em|ex|%)+?)\]/i", - "/\[font=([^\[\<]+?)\]/i", - "/\[align=(left|center|right)\]/i", - "/\[float=(left|right)\]/i" - ), array( - "", - "", - "", - "", - "

                      ", - "" - ), $message)); - if (strpos($message, '[/quote]') !== FALSE) - { - $message = preg_replace("/\s*\[quote\][\n\r]*(.+?)[\n\r]*\[\/quote\]\s*/is", $this->tpl_quote(), $message); - } - if (strpos($message, '[/img]') !== FALSE) - { - $message = preg_replace(array( - "/\[img\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ies", - "/\[img=(\d{1,4})[x|\,](\d{1,4})\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ies" - ), array( - "\$this->bbcodeurl('\\1', '\"\"')", - "\$this->bbcodeurl('\\3', '\"\"')" - ), $message); - } - for ($i = 0; $i <= $this->uccode['pcodecount']; $i++) - { - $message = str_replace("[\tUCENTER_CODE_$i\t]", $this->uccode['codehtml'][$i], $message); - } - return nl2br(str_replace(array("\t", ' ', ' '), array('        ', '   ', '  '), $message)); - } - - function parseurl($url, $text) - { - if (!$url && preg_match("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\/\/|www\.)[^\[\"']+/i", trim($text), $matches)) - { - $url = $matches[0]; - $length = 65; - if (strlen($url) > $length) - { - $text = substr($url, 0, intval($length * 0.5)) . ' ... ' . substr($url, - intval($length * 0.3)); - } - return '' . $text . ''; - } - else - { - $url = substr($url, 1); - if (substr(strtolower($url), 0, 4) == 'www.') - { - $url = 'http://' . $url; - } - return '' . $text . ''; - } - } - - function parseemail($email, $text) - { - $text = str_replace('\"', '"', $text); - if (!$email && preg_match("/\s*([a-z0-9\-_.+]+)@([a-z0-9\-_]+[.][a-z0-9\-_.]+)\s*/i", $text, $matches)) - { - $email = trim($matches[0]); - return '' . $email . ''; - } - else - { - return '' . $text . ''; - } - } - - function bbcodeurl($url, $tags) - { - if (!preg_match("/<.+?>/s", $url)) - { - if (!in_array(strtolower(substr($url, 0, 6)), array('http:/', 'https:', 'ftp://', 'rtsp:/', 'mms://'))) - { - $url = 'http://' . $url; - } - return str_replace(array('submit', 'logging.php'), array('', ''), sprintf($tags, $url, addslashes($url))); - } - else - { - return ' ' . $url; - } - } - - function tpl_codedisp($code) - { - return '

                      ' . $code . '
                      '; - } - - function tpl_quote() - { - return '
                      \\1
                      '; - } - -} - -/* - -Usage: -$str = <<uccode = new uccode(); -echo $this->uccode->complie($str); - -*/ \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/lib/xml.class.php b/extend/fast/ucenter/client/uc_client/lib/xml.class.php deleted file mode 100644 index 73c528bb..00000000 --- a/extend/fast/ucenter/client/uc_client/lib/xml.class.php +++ /dev/null @@ -1,129 +0,0 @@ -parse($xml); - $xml_parser->destruct(); - return $data; -} - -function xml_serialize($arr, $htmlon = FALSE, $isnormal = FALSE, $level = 1) -{ - $s = $level == 1 ? "\r\n\r\n" : ''; - $space = str_repeat("\t", $level); - foreach ($arr as $k => $v) - { - if (!is_array($v)) - { - $s .= $space . "" . ($htmlon ? '' : '') . "\r\n"; - } - else - { - $s .= $space . "\r\n" . xml_serialize($v, $htmlon, $isnormal, $level + 1) . $space . "\r\n"; - } - } - $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s); - return $level == 1 ? $s . "" : $s; -} - -class XML -{ - - var $parser; - var $document; - var $stack; - var $data; - var $last_opened_tag; - var $isnormal; - var $attrs = array(); - var $failed = FALSE; - - function __construct($isnormal) - { - $this->XML($isnormal); - } - - function XML($isnormal) - { - $this->isnormal = $isnormal; - $this->parser = xml_parser_create('ISO-8859-1'); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); - xml_set_object($this->parser, $this); - xml_set_element_handler($this->parser, 'open', 'close'); - xml_set_character_data_handler($this->parser, 'data'); - } - - function destruct() - { - xml_parser_free($this->parser); - } - - function parse(&$data) - { - $this->document = array(); - $this->stack = array(); - return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : ''; - } - - function open(&$parser, $tag, $attributes) - { - $this->data = ''; - $this->failed = FALSE; - if (!$this->isnormal) - { - if (isset($attributes['id']) && !is_string($this->document[$attributes['id']])) - { - $this->document = &$this->document[$attributes['id']]; - } - else - { - $this->failed = TRUE; - } - } - else - { - if (!isset($this->document[$tag]) || !is_string($this->document[$tag])) - { - $this->document = &$this->document[$tag]; - } - else - { - $this->failed = TRUE; - } - } - $this->stack[] = &$this->document; - $this->last_opened_tag = $tag; - $this->attrs = $attributes; - } - - function data(&$parser, $data) - { - if ($this->last_opened_tag != NULL) - { - $this->data .= $data; - } - } - - function close(&$parser, $tag) - { - if ($this->last_opened_tag == $tag) - { - $this->document = $this->data; - $this->last_opened_tag = NULL; - } - array_pop($this->stack); - if ($this->stack) - { - $this->document = &$this->stack[count($this->stack) - 1]; - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/app.php b/extend/fast/ucenter/client/uc_client/model/app.php deleted file mode 100644 index a3fdac59..00000000 --- a/extend/fast/ucenter/client/uc_client/model/app.php +++ /dev/null @@ -1,40 +0,0 @@ -appmodel($base); - } - - function appmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function get_apps($col = '*', $where = '') - { - $arr = $this->db->fetch_all("SELECT $col FROM " . UC_DBTABLEPRE . "applications" . ($where ? ' WHERE ' . $where : ''), 'appid'); - foreach ($arr as $k => $v) - { - isset($v['extra']) && !empty($v['extra']) && $v['extra'] = unserialize($v['extra']); - unset($v['authkey']); - $arr[$k] = $v; - } - return $arr; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/base.php b/extend/fast/ucenter/client/uc_client/model/base.php deleted file mode 100644 index 32dcf161..00000000 --- a/extend/fast/ucenter/client/uc_client/model/base.php +++ /dev/null @@ -1,347 +0,0 @@ -base(); - } - - function base() - { - $this->init_var(); - $this->init_db(); - $this->init_cache(); - $this->init_note(); - $this->init_mail(); - } - - function init_var() - { - $this->time = time(); - $cip = getenv('HTTP_CLIENT_IP'); - $xip = getenv('HTTP_X_FORWARDED_FOR'); - $rip = getenv('REMOTE_ADDR'); - $srip = $_SERVER['REMOTE_ADDR']; - if ($cip && strcasecmp($cip, 'unknown')) - { - $this->onlineip = $cip; - } - elseif ($xip && strcasecmp($xip, 'unknown')) - { - $this->onlineip = $xip; - } - elseif ($rip && strcasecmp($rip, 'unknown')) - { - $this->onlineip = $rip; - } - elseif ($srip && strcasecmp($srip, 'unknown')) - { - $this->onlineip = $srip; - } - preg_match("/[\d\.]{7,15}/", $this->onlineip, $match); - $this->onlineip = $match[0] ? $match[0] : 'unknown'; - $this->app['appid'] = UC_APPID; - } - - function init_input() - { - - } - - function init_db() - { - if (function_exists("mysqli_connect")) - { - require_once UC_ROOT . 'lib/dbi.class.php'; - } - else - { - require_once UC_ROOT . 'lib/db.class.php'; - } - $this->db = new ucclient_db(); - $this->db->connect(UC_DBHOST, UC_DBUSER, UC_DBPW, '', UC_DBCHARSET, UC_DBCONNECT, UC_DBTABLEPRE); - } - - function load($model, $base = NULL) - { - $base = $base ? $base : $this; - if (empty($_ENV[$model])) - { - require_once UC_ROOT . "./model/{$model}.php"; - $classname = $model . 'model'; - $_ENV[$model] = new $classname($base); - } - return $_ENV[$model]; - } - - function date($time, $type = 3) - { - if (!$this->settings) - { - $this->settings = $this->cache('settings'); - } - $format[] = $type & 2 ? (!empty($this->settings['dateformat']) ? $this->settings['dateformat'] : 'Y-n-j') : ''; - $format[] = $type & 1 ? (!empty($this->settings['timeformat']) ? $this->settings['timeformat'] : 'H:i') : ''; - return gmdate(implode(' ', $format), $time + $this->settings['timeoffset']); - } - - function page_get_start($page, $ppp, $totalnum) - { - $totalpage = ceil($totalnum / $ppp); - $page = max(1, min($totalpage, intval($page))); - return ($page - 1) * $ppp; - } - - function implode($arr) - { - return "'" . implode("','", (array) $arr) . "'"; - } - - function &cache($cachefile) - { - static $_CACHE = array(); - if (!isset($_CACHE[$cachefile])) - { - $cachepath = UC_DATADIR . './cache/' . $cachefile . '.php'; - if (!file_exists($cachepath)) - { - $this->load('cache'); - $_ENV['cache']->updatedata($cachefile); - } - else - { - include_once $cachepath; - } - } - return $_CACHE[$cachefile]; - } - - function get_setting($k = array(), $decode = FALSE) - { - $return = array(); - $sqladd = $k ? "WHERE k IN (" . $this->implode($k) . ")" : ''; - $settings = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "settings $sqladd"); - if (is_array($settings)) - { - foreach ($settings as $arr) - { - $return[$arr['k']] = $decode ? unserialize($arr['v']) : $arr['v']; - } - } - return $return; - } - - function init_cache() - { - $this->settings = $this->cache('settings'); - $this->cache['apps'] = $this->cache('apps'); - - if (PHP_VERSION > '5.1') - { - $timeoffset = intval($this->settings['timeoffset'] / 3600); - @date_default_timezone_set('Etc/GMT' . ($timeoffset > 0 ? '-' : '+') . (abs($timeoffset))); - } - } - - function cutstr($string, $length, $dot = ' ...') - { - if (strlen($string) <= $length) - { - return $string; - } - - $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string); - - $strcut = ''; - if (strtolower(UC_CHARSET) == 'utf-8') - { - - $n = $tn = $noc = 0; - while ($n < strlen($string)) - { - - $t = ord($string[$n]); - if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) - { - $tn = 1; - $n++; - $noc++; - } - elseif (194 <= $t && $t <= 223) - { - $tn = 2; - $n += 2; - $noc += 2; - } - elseif (224 <= $t && $t < 239) - { - $tn = 3; - $n += 3; - $noc += 2; - } - elseif (240 <= $t && $t <= 247) - { - $tn = 4; - $n += 4; - $noc += 2; - } - elseif (248 <= $t && $t <= 251) - { - $tn = 5; - $n += 5; - $noc += 2; - } - elseif ($t == 252 || $t == 253) - { - $tn = 6; - $n += 6; - $noc += 2; - } - else - { - $n++; - } - - if ($noc >= $length) - { - break; - } - } - if ($noc > $length) - { - $n -= $tn; - } - - $strcut = substr($string, 0, $n); - } - else - { - for ($i = 0; $i < $length; $i++) - { - $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i]; - } - } - - $strcut = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $strcut); - - return $strcut . $dot; - } - - function init_note() - { - if ($this->note_exists()) - { - $this->load('note'); - $_ENV['note']->send(); - } - } - - function note_exists() - { - $noteexists = $this->db->result_first("SELECT value FROM " . UC_DBTABLEPRE . "vars WHERE name='noteexists" . UC_APPID . "'"); - if (empty($noteexists)) - { - return FALSE; - } - else - { - return TRUE; - } - } - - function init_mail() - { - if ($this->mail_exists() && !getgpc('inajax')) - { - $this->load('mail'); - $_ENV['mail']->send(); - } - } - - function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) - { - return uc_authcode($string, $operation, $key, $expiry); - } - - function unserialize($s) - { - return uc_unserialize($s); - } - - function input($k) - { - return isset($this->input[$k]) ? (is_array($this->input[$k]) ? $this->input[$k] : trim($this->input[$k])) : NULL; - } - - function mail_exists() - { - $mailexists = $this->db->result_first("SELECT value FROM " . UC_DBTABLEPRE . "vars WHERE name='mailexists'"); - if (empty($mailexists)) - { - return FALSE; - } - else - { - return TRUE; - } - } - - function dstripslashes($string) - { - if (is_array($string)) - { - foreach ($string as $key => $val) - { - $string[$key] = $this->dstripslashes($val); - } - } - else - { - $string = stripslashes($string); - } - return $string; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/cache.php b/extend/fast/ucenter/client/uc_client/model/cache.php deleted file mode 100644 index d0851ede..00000000 --- a/extend/fast/ucenter/client/uc_client/model/cache.php +++ /dev/null @@ -1,119 +0,0 @@ -cachemodel($base); - } - - function cachemodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - $this->map = array( - 'settings' => array('settings'), - 'badwords' => array('badwords'), - 'apps' => array('apps') - ); - } - - function updatedata($cachefile = '') - { - if ($cachefile) - { - foreach ((array) $this->map[$cachefile] as $modules) - { - $s = "$method(), TRUE) . ";\r\n"; - } - $s .= "\r\n?>"; - @file_put_contents(UC_DATADIR . "./cache/$cachefile.php", $s); - } - } - else - { - foreach ((array) $this->map as $file => $modules) - { - $s = "$method(), TRUE) . ";\r\n"; - } - $s .= "\r\n?>"; - @file_put_contents(UC_DATADIR . "./cache/$file.php", $s); - } - } - } - - function updatetpl() - { - - } - - function _get_badwords() - { - $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "badwords"); - $return = array(); - if (is_array($data)) - { - foreach ($data as $k => $v) - { - $return['findpattern'][$k] = $v['findpattern']; - $return['replace'][$k] = $v['replacement']; - } - } - return $return; - } - - function _get_apps() - { - $this->base->load('app'); - $apps = $_ENV['app']->get_apps(); - $apps2 = array(); - if (is_array($apps)) - { - foreach ($apps as $v) - { - $v['extra'] = unserialize($v['extra']); - $apps2[$v['appid']] = $v; - } - } - return $apps2; - } - - function _get_settings() - { - return $this->base->get_setting(); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/domain.php b/extend/fast/ucenter/client/uc_client/model/domain.php deleted file mode 100644 index 6fc966fe..00000000 --- a/extend/fast/ucenter/client/uc_client/model/domain.php +++ /dev/null @@ -1,63 +0,0 @@ -domainmodel($base); - } - - function domainmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function add_domain($domain, $ip) - { - if ($domain) - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "domains SET domain='$domain', ip='$ip'"); - } - return $this->db->insert_id(); - } - - function get_total_num() - { - $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "domains"); - return $data; - } - - function get_list($page, $ppp, $totalnum) - { - $start = $this->base->page_get_start($page, $ppp, $totalnum); - $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "domains LIMIT $start, $ppp"); - return $data; - } - - function delete_domain($arr) - { - $domainids = $this->base->implode($arr); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "domains WHERE id IN ($domainids)"); - return $this->db->affected_rows(); - } - - function update_domain($domain, $ip, $id) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "domains SET domain='$domain', ip='$ip' WHERE id='$id'"); - return $this->db->affected_rows(); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/friend.php b/extend/fast/ucenter/client/uc_client/model/friend.php deleted file mode 100644 index 58c641aa..00000000 --- a/extend/fast/ucenter/client/uc_client/model/friend.php +++ /dev/null @@ -1,148 +0,0 @@ -friendmodel($base); - } - - function friendmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function add($uid, $friendid, $comment = '') - { - $direction = $this->db->result_first("SELECT direction FROM " . UC_DBTABLEPRE . "friends WHERE uid='$friendid' AND friendid='$uid' LIMIT 1"); - if ($direction == 1) - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "friends SET uid='$uid', friendid='$friendid', comment='$comment', direction='3'", 'SILENT'); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "friends SET direction='3' WHERE uid='$friendid' AND friendid='$uid'"); - return 1; - } - elseif ($direction == 2) - { - return 1; - } - elseif ($direction == 3) - { - return -1; - } - else - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "friends SET uid='$uid', friendid='$friendid', comment='$comment', direction='1'", 'SILENT'); - return $this->db->insert_id(); - } - } - - function delete($uid, $friendids) - { - $friendids = $this->base->implode($friendids); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "friends WHERE uid='$uid' AND friendid IN ($friendids)"); - $affectedrows = $this->db->affected_rows(); - if ($affectedrows > 0) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "friends SET direction=1 WHERE uid IN ($friendids) AND friendid='$uid' AND direction='3'"); - } - return $affectedrows; - } - - function get_totalnum_by_uid($uid, $direction = 0) - { - $sqladd = ''; - if ($direction == 0) - { - $sqladd = "uid='$uid'"; - } - elseif ($direction == 1) - { - $sqladd = "uid='$uid' AND direction='1'"; - } - elseif ($direction == 2) - { - $sqladd = "friendid='$uid' AND direction='1'"; - } - elseif ($direction == 3) - { - $sqladd = "uid='$uid' AND direction='3'"; - } - $totalnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "friends WHERE $sqladd"); - return $totalnum; - } - - function get_list($uid, $page, $pagesize, $totalnum, $direction = 0) - { - $start = $this->base->page_get_start($page, $pagesize, $totalnum); - $sqladd = ''; - if ($direction == 0) - { - $sqladd = "f.uid='$uid'"; - } - elseif ($direction == 1) - { - $sqladd = "f.uid='$uid' AND f.direction='1'"; - } - elseif ($direction == 2) - { - $sqladd = "f.friendid='$uid' AND f.direction='1'"; - } - elseif ($direction == 3) - { - $sqladd = "f.uid='$uid' AND f.direction='3'"; - } - if ($sqladd) - { - $data = $this->db->fetch_all("SELECT f.*, m.username FROM " . UC_DBTABLEPRE . "friends f LEFT JOIN " . UC_DBTABLEPRE . "members m ON f.friendid=m.uid WHERE $sqladd LIMIT $start, $pagesize"); - return $data; - } - else - { - return array(); - } - } - - function is_friend($uid, $friendids, $direction = 0) - { - $friendid_str = implode("', '", $friendids); - $sqladd = ''; - if ($direction == 0) - { - $sqladd = "uid='$uid'"; - } - elseif ($direction == 1) - { - $sqladd = "uid='$uid' AND friendid IN ('$friendid_str') AND direction='1'"; - } - elseif ($direction == 2) - { - $sqladd = "friendid='$uid' AND uid IN ('$friendid_str') AND direction='1'"; - } - elseif ($direction == 3) - { - $sqladd = "uid='$uid' AND friendid IN ('$friendid_str') AND direction='3'"; - } - if ($this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "friends WHERE $sqladd") == count($friendids)) - { - return true; - } - else - { - return false; - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/index.htm b/extend/fast/ucenter/client/uc_client/model/index.htm deleted file mode 100644 index 0519ecba..00000000 --- a/extend/fast/ucenter/client/uc_client/model/index.htm +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/extend/fast/ucenter/client/uc_client/model/mail.php b/extend/fast/ucenter/client/uc_client/model/mail.php deleted file mode 100644 index 46e9983d..00000000 --- a/extend/fast/ucenter/client/uc_client/model/mail.php +++ /dev/null @@ -1,181 +0,0 @@ -mailmodel($base); - } - - function mailmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - $this->apps = &$this->base->cache['apps']; - } - - function get_total_num() - { - $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "mailqueue"); - return $data; - } - - function get_list($page, $ppp, $totalnum) - { - $start = $this->base->page_get_start($page, $ppp, $totalnum); - $data = $this->db->fetch_all("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid ORDER BY dateline DESC LIMIT $start, $ppp"); - foreach ((array) $data as $k => $v) - { - $data[$k]['subject'] = dhtmlspecialchars($v['subject']); - $data[$k]['tomail'] = empty($v['tomail']) ? $v['email'] : $v['tomail']; - $data[$k]['dateline'] = $v['dateline'] ? $this->base->date($data[$k]['dateline']) : ''; - $data[$k]['appname'] = $this->base->cache['apps'][$v['appid']]['name']; - } - return $data; - } - - function delete_mail($ids) - { - $ids = $this->base->implode($ids); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mailqueue WHERE mailid IN ($ids)"); - return $this->db->affected_rows(); - } - - function add($mail) - { - if ($mail['level']) - { - $sql = "INSERT INTO " . UC_DBTABLEPRE . "mailqueue (touid, tomail, subject, message, frommail, charset, htmlon, level, dateline, failures, appid) VALUES "; - $values_arr = array(); - foreach ($mail['uids'] as $uid) - { - if (empty($uid)) - continue; - $values_arr[] = "('$uid', '', '$mail[subject]', '$mail[message]', '$mail[frommail]', '$mail[charset]', '$mail[htmlon]', '$mail[level]', '$mail[dateline]', '0', '$mail[appid]')"; - } - foreach ($mail['emails'] as $email) - { - if (empty($email)) - continue; - $values_arr[] = "('', '$email', '$mail[subject]', '$mail[message]', '$mail[frommail]', '$mail[charset]', '$mail[htmlon]', '$mail[level]', '$mail[dateline]', '0', '$mail[appid]')"; - } - $sql .= implode(',', $values_arr); - $this->db->query($sql); - $insert_id = $this->db->insert_id(); - $insert_id && $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='mailexists', value='1'"); - return $insert_id; - } else - { - $mail['email_to'] = array(); - $uids = 0; - foreach ($mail['uids'] as $uid) - { - if (empty($uid)) - continue; - $uids .= ',' . $uid; - } - $users = $this->db->fetch_all("SELECT uid, username, email FROM " . UC_DBTABLEPRE . "members WHERE uid IN ($uids)"); - foreach ($users as $v) - { - $mail['email_to'][] = $v['username'] . '<' . $v['email'] . '>'; - } - foreach ($mail['emails'] as $email) - { - if (empty($email)) - continue; - $mail['email_to'][] = $email; - } - $mail['message'] = str_replace('\"', '"', $mail['message']); - $mail['email_to'] = implode(',', $mail['email_to']); - return $this->send_one_mail($mail); - } - } - - function send() - { - register_shutdown_function(array($this, '_send')); - } - - function _send() - { - - $mail = $this->_get_mail(); - if (empty($mail)) - { - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='mailexists', value='0'"); - return NULL; - } - else - { - $mail['email_to'] = $mail['tomail'] ? $mail['tomail'] : $mail['username'] . '<' . $mail['email'] . '>'; - if ($this->send_one_mail($mail)) - { - $this->_delete_one_mail($mail['mailid']); - return true; - } - else - { - $this->_update_failures($mail['mailid']); - return false; - } - } - } - - function send_by_id($mailid) - { - if ($this->send_one_mail($this->_get_mail_by_id($mailid))) - { - $this->_delete_one_mail($mailid); - return true; - } - } - - function send_one_mail($mail) - { - if (empty($mail)) - return; - $mail['email_to'] = $mail['email_to'] ? $mail['email_to'] : $mail['username'] . '<' . $mail['email'] . '>'; - $mail_setting = $this->base->settings; - return include UC_ROOT . 'lib/sendmail.inc.php'; - } - - function _get_mail() - { - $data = $this->db->fetch_first("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid WHERE failures<'" . UC_MAIL_REPEAT . "' ORDER BY level DESC, mailid ASC LIMIT 1"); - return $data; - } - - function _get_mail_by_id($mailid) - { - $data = $this->db->fetch_first("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid WHERE mailid='$mailid'"); - return $data; - } - - function _delete_one_mail($mailid) - { - $mailid = intval($mailid); - return $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mailqueue WHERE mailid='$mailid'"); - } - - function _update_failures($mailid) - { - $mailid = intval($mailid); - return $this->db->query("UPDATE " . UC_DBTABLEPRE . "mailqueue SET failures=failures+1 WHERE mailid='$mailid'"); - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/misc.php b/extend/fast/ucenter/client/uc_client/model/misc.php deleted file mode 100644 index bb83ab50..00000000 --- a/extend/fast/ucenter/client/uc_client/model/misc.php +++ /dev/null @@ -1,198 +0,0 @@ -miscmodel($base); - } - - function miscmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function get_apps($col = '*', $where = '') - { - $arr = $this->db->fetch_all("SELECT $col FROM " . UC_DBTABLEPRE . "applications" . ($where ? ' WHERE ' . $where : '')); - return $arr; - } - - function delete_apps($appids) - { - - } - - function update_app($appid, $name, $url, $authkey, $charset, $dbcharset) - { - - } - - function alter_app_table($appid, $operation = 'ADD') - { - - } - - function get_host_by_url($url) - { - - } - - function check_url($url) - { - - } - - function check_ip($url) - { - - } - - function test_api($url, $ip = '') - { - - } - - function dfopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype = 'URLENCODE') - { - $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1; - if ($__times__ > 2) - { - return ''; - } - $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__"; - return $this->dfopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block, $encodetype); - } - - function dfopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype = 'URLENCODE') - { - $return = ''; - $matches = parse_url($url); - $scheme = $matches['scheme']; - $host = $matches['host']; - $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/'; - $port = !empty($matches['port']) ? $matches['port'] : 80; - - if ($post) - { - $out = "POST $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $boundary = $encodetype == 'URLENCODE' ? '' : ';' . substr($post, 0, trim(strpos($post, "\n"))); - $header .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n"; - $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n"; - $header .= "Host: $host:$port\r\n"; - $header .= 'Content-Length: ' . strlen($post) . "\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cache-Control: no-cache\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header . $post; - } - else - { - $out = "GET $path HTTP/1.0\r\n"; - $header = "Accept: */*\r\n"; - $header .= "Accept-Language: zh-cn\r\n"; - $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n"; - $header .= "Host: $host:$port\r\n"; - $header .= "Connection: Close\r\n"; - $header .= "Cookie: $cookie\r\n\r\n"; - $out .= $header; - } - - $fpflag = 0; - if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout)) - { - $context = array( - 'http' => array( - 'method' => $post ? 'POST' : 'GET', - 'header' => $header, - 'content' => $post, - 'timeout' => $timeout, - ), - ); - $context = stream_context_create($context); - $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context); - $fpflag = 1; - } - - if (!$fp) - { - return ''; - } - else - { - stream_set_blocking($fp, $block); - stream_set_timeout($fp, $timeout); - @fwrite($fp, $out); - $status = stream_get_meta_data($fp); - if (!$status['timed_out']) - { - while (!feof($fp) && !$fpflag) - { - if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) - { - break; - } - } - - $stop = false; - while (!feof($fp) && !$stop) - { - $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit)); - $return .= $data; - if ($limit) - { - $limit -= strlen($data); - $stop = $limit <= 0; - } - } - } - @fclose($fp); - return $return; - } - } - - function array2string($arr) - { - $s = $sep = ''; - if ($arr && is_array($arr)) - { - foreach ($arr as $k => $v) - { - $s .= $sep . addslashes($k) . UC_ARRAY_SEP_1 . $v; - $sep = UC_ARRAY_SEP_2; - } - } - return $s; - } - - function string2array($s) - { - $arr = explode(UC_ARRAY_SEP_2, $s); - $arr2 = array(); - foreach ($arr as $k => $v) - { - list($key, $val) = explode(UC_ARRAY_SEP_1, $v); - $arr2[$key] = $val; - } - return $arr2; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/note.php b/extend/fast/ucenter/client/uc_client/model/note.php deleted file mode 100644 index 0ca5141e..00000000 --- a/extend/fast/ucenter/client/uc_client/model/note.php +++ /dev/null @@ -1,230 +0,0 @@ -notemodel($base); - } - - function notemodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - $this->apps = $this->base->cache('apps'); - $this->operations = array( - 'test' => array('', 'action=test'), - 'deleteuser' => array('', 'action=deleteuser'), - 'deletefriend' => array('', 'action=deletefriend'), - 'gettag' => array('', 'action=gettag', 'tag', 'updatedata'), - 'getcreditsettings' => array('', 'action=getcreditsettings'), - 'getcredit' => array('', 'action=getcredit'), - 'updatecreditsettings' => array('', 'action=updatecreditsettings'), - 'updateclient' => array('', 'action=updateclient'), - 'updatepw' => array('', 'action=updatepw'), - 'updateinfo' => array('', 'action=updateinfo'), - 'updatebadwords' => array('', 'action=updatebadwords'), - 'updatehosts' => array('', 'action=updatehosts'), - 'updateapps' => array('', 'action=updateapps'), - 'updatecredit' => array('', 'action=updatecredit'), - ); - } - - function get_total_num($all = TRUE) - { - - } - - function get_list($page, $ppp, $totalnum, $all = TRUE) - { - - } - - function delete_note($ids) - { - - } - - function add($operation, $getdata = '', $postdata = '', $appids = array(), $pri = 0) - { - $extra = $varextra = ''; - $appadd = $varadd = array(); - foreach ((array) $this->apps as $appid => $app) - { - $appid = $app['appid']; - if ($appid == intval($appid)) - { - if ($appids && !in_array($appid, $appids)) - { - $appadd[] = 'app' . $appid . "='1'"; - } - else - { - $varadd[] = "('noteexists{$appid}', '1')"; - } - } - } - if ($appadd) - { - $extra = implode(',', $appadd); - $extra = $extra ? ', ' . $extra : ''; - } - if ($varadd) - { - $varextra = implode(', ', $varadd); - $varextra = $varextra ? ', ' . $varextra : ''; - } - - $getdata = addslashes($getdata); - $postdata = addslashes($postdata); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "notelist SET getdata='$getdata', operation='$operation', pri='$pri', postdata='$postdata'$extra"); - $insert_id = $this->db->insert_id(); - $insert_id && $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars (name, value) VALUES ('noteexists', '1')$varextra"); - $this->noteid = $insert_id; - return $insert_id; - } - - function send() - { - register_shutdown_function(array($this, '_send')); - } - - function _send() - { - $note = $this->_get_note(); - if (empty($note)) - { - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='noteexists" . UC_APPID . "', value='0'"); - return NULL; - } - $this->sendone(UC_APPID, 0, $note); - $this->_gc(); - } - - function sendone($appid, $noteid = 0, $note = '') - { - require_once UC_ROOT . './lib/xml.class.php'; - $return = FALSE; - $app = $this->apps[$appid]; - if ($noteid) - { - $note = $this->_get_note_by_id($noteid); - } - $this->base->load('misc'); - $apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php'; - if ($app['extra']['apppath'] && @include $app['extra']['apppath'] . './api/' . $apifilename) - { - $uc_note = new uc_note(); - $method = $note['operation']; - if (is_string($method) && !empty($method)) - { - parse_str($note['getdata'], $note['getdata']); - if (get_magic_quotes_gpc()) - { - $note['getdata'] = $this->base->dstripslashes($note['getdata']); - } - $note['postdata'] = @xml_unserialize($note['postdata']); - $response = $uc_note->$method($note['getdata'], $note['postdata']); - } - unset($uc_note); - } - else - { - $url = $this->get_url_code($note['operation'], $note['getdata'], $appid); - $note['postdata'] = str_replace(array("\n", "\r"), '', $note['postdata']); - $response = trim($_ENV['misc']->dfopen2($url, 0, $note['postdata'], '', 1, $app['ip'], UC_NOTE_TIMEOUT, TRUE)); - } - - $returnsucceed = $response != '' && ($response == 1 || is_array(@xml_unserialize($response))); - - $closedsqladd = $this->_close_note($note, $this->apps, $returnsucceed, $appid) ? ",closed='1'" : ''; - - if ($returnsucceed) - { - if ($this->operations[$note['operation']][2]) - { - $this->base->load($this->operations[$note['operation']][2]); - $func = $this->operations[$note['operation']][3]; - $_ENV[$this->operations[$note['operation']][2]]->$func($appid, $response); - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "notelist SET app$appid='1', totalnum=totalnum+1, succeednum=succeednum+1, dateline='{$this->base->time}' $closedsqladd WHERE noteid='$note[noteid]'", 'SILENT'); - $return = TRUE; - } - else - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "notelist SET app$appid = app$appid-'1', totalnum=totalnum+1, dateline='{$this->base->time}' $closedsqladd WHERE noteid='$note[noteid]'", 'SILENT'); - $return = FALSE; - } - return $return; - } - - function _get_note() - { - $app_field = 'app' . UC_APPID; - $data = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "notelist WHERE closed='0' AND $app_field<'1' AND $app_field>'-" . UC_NOTE_REPEAT . "' LIMIT 1"); - return $data; - } - - function _gc() - { - rand(0, UC_NOTE_GC) == 0 && $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "notelist WHERE closed='1'"); - } - - function _close_note($note, $apps, $returnsucceed, $appid) - { - $note['app' . $appid] = $returnsucceed ? 1 : $note['app' . $appid] - 1; - $appcount = count($apps); - foreach ($apps as $key => $app) - { - $appstatus = $note['app' . $app['appid']]; - if (!$app['recvnote'] || $appstatus == 1 || $appstatus <= -UC_NOTE_REPEAT) - { - $appcount--; - } - } - if ($appcount < 1) - { - return TRUE; - } - } - - function _get_note_by_id($noteid) - { - $data = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "notelist WHERE noteid='$noteid'"); - return $data; - } - - function get_url_code($operation, $getdata, $appid) - { - $app = $this->apps[$appid]; - $authkey = UC_KEY; - $url = $app['url']; - $apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php'; - $action = $this->operations[$operation][1]; - $code = urlencode($this->base->authcode("$action&" . ($getdata ? "$getdata&" : '') . "time=" . $this->base->time, 'ENCODE', $authkey)); - return $url . "/api/$apifilename?code=$code"; - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/pm.php b/extend/fast/ucenter/client/uc_client/model/pm.php deleted file mode 100644 index 672ec0f8..00000000 --- a/extend/fast/ucenter/client/uc_client/model/pm.php +++ /dev/null @@ -1,1261 +0,0 @@ -pmmodel($base); - } - - function pmmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function pmintval($pmid) - { - return @is_numeric($pmid) ? $pmid : 0; - } - - function getpmbypmid($uid, $pmid) - { - if (!$pmid) - { - return array(); - } - $arr = array(); - $pm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_indexes i LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=i.plid WHERE i.pmid='$pmid'"); - if ($this->isprivilege($pm['plid'], $uid)) - { - $pms = $this->db->fetch_all("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($pm['plid']) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=p.plid WHERE p.pmid='$pm[pmid]'"); - $arr = $this->getpostlist($pms); - } - return $arr; - } - - function isprivilege($plid, $uid) - { - if (!$plid || !$uid) - { - return true; - } - $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$uid'"); - if ($this->db->fetch_array($query)) - { - return true; - } - else - { - return false; - } - } - - function getpmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp, $type = 0) - { - if (!$type) - { - $pm = $this->getprivatepmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp); - } - else - { - $pm = $this->getchatpmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp); - } - return $this->getpostlist($pm); - } - - function getpostlist($list) - { - if (empty($list)) - { - return array(); - } - $authoridarr = $authorarr = array(); - foreach ($list as $key => $value) - { - $authoridarr[$value['authorid']] = $value['authorid']; - } - if ($authoridarr) - { - $this->base->load('user'); - $authorarr = $_ENV['user']->id2name($authoridarr); - } - foreach ($list as $key => $value) - { - if ($value['pmtype'] == 1) - { - $users = explode('_', $value['min_max']); - if ($value['authorid'] == $users[0]) - { - $value['touid'] = $users[1]; - } - else - { - $value['touid'] = $users[0]; - } - } - else - { - $value['touid'] = 0; - } - $value['author'] = $authorarr[$value['authorid']]; - - $value['msgfromid'] = $value['authorid']; - $value['msgfrom'] = $value['author']; - $value['msgtoid'] = $value['touid']; - - unset($value['min_max']); - unset($value['delstatus']); - unset($value['lastmessage']); - $list[$key] = $value; - } - return $list; - } - - function setpmstatus($uid, $touids, $plids, $status = 0) - { - if (!$uid) - { - return false; - } - if (!$status) - { - $oldstatus = 1; - $newstatus = 0; - } - else - { - $oldstatus = 0; - $newstatus = 1; - } - if ($touids) - { - foreach ($touids as $key => $value) - { - if ($uid == $value || !$value) - { - return false; - } - $relastionship[] = $this->relationship($uid, $value); - } - $plid = $plidpostarr = array(); - $query = $this->db->query("SELECT plid FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max IN (" . $this->base->implode($relationship) . ")"); - while ($thread = $this->db->fetch_array($query)) - { - $plidarr[] = $thread['plid']; - } - if ($plidarr) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew='$newstatus' WHERE plid IN (" . $this->base->implode($plidarr) . ") AND uid='$uid' AND isnew='$oldstatus'"); - } - } - if ($plids) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew='$newstatus' WHERE plid IN (" . $this->base->implode($plids) . ") AND uid='$uid' AND isnew='$oldstatus'"); - } - return true; - } - - function set_ignore($uid) - { - return $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'"); - } - - function isnewpm($uid) - { - return $this->db->result_first("SELECT uid FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'"); - } - - function lastpm($uid) - { - $lastpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE m.uid='$uid' ORDER BY m.lastdateline DESC LIMIT 1"); - $lastmessage = unserialize($lastpm['lastmessage']); - if ($lastmessage['lastauthorid']) - { - $lastpm['lastauthorid'] = $lastmessage['lastauthorid']; - $lastpm['lastauthor'] = $lastmessage['lastauthor']; - $lastpm['lastsummary'] = $lastmessage['lastsummary']; - } - else - { - $lastpm['lastauthorid'] = $lastmessage['firstauthorid']; - $lastpm['lastauthor'] = $lastmessage['firstauthor']; - $lastpm['lastsummary'] = $lastmessage['firstsummary']; - } - return $lastpm; - } - - function getpmnum($uid, $type = 0, $isnew = 0) - { - $newsql = ''; - $newnum = 0; - - if ($isnew) - { - $newsql = 'AND m.isnew=1'; - } - if (!$type) - { - $newnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m WHERE m.uid='$uid' $newsql"); - } - else - { - $newnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=m.plid WHERE m.uid='$uid' $newsql AND t.pmtype='$type'"); - } - return $newnum; - } - - function getpmnumbyplid($uid, $plid) - { - return $this->db->result_first("SELECT pmnum FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$uid'"); - } - - function sendpm($fromuid, $fromusername, $touids, $subject, $message, $type = 0) - { - if (!$fromuid || !$fromusername || !$touids || !$message) - { - return 0; - } - $touids = array_unique($touids); - $relationship = $existplid = $pm_member_insertsql = array(); - $this->base->load('user'); - $tmptouidarr = $touids; - $blackls = $this->get_blackls($fromuid, $touids); - - foreach ($tmptouidarr as $key => $value) - { - if ($fromuid == $value || !$value) - { - return PMSENDSELF_ERROR; - } - - if (in_array('{ALL}', $blackls[$value])) - { - unset($touids[$key]); - continue; - } - $blackls[$value] = $_ENV['user']->name2id($blackls[$value]); - if (!(isset($blackls[$value]) && !in_array($fromuid, $blackls[$value]))) - { - unset($touids[$key]); - } - else - { - $relationship[$value] = $this->relationship($fromuid, $value); - } - } - if (empty($touids)) - { - return PMSENDNONE_ERROR; - } - if ($type == 1 && count($touids) < 2) - { - return PMSENDCHATNUM_ERROR; - } - - $_CACHE['badwords'] = $this->base->cache('badwords'); - if ($_CACHE['badwords']['findpattern']) - { - $subject = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $subject); - $message = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $message); - } - if (!$subject) - { - $subject = $this->removecode(trim($message), 80); - } - else - { - $subject = dhtmlspecialchars($subject); - } - $lastsummary = $this->removecode(trim(stripslashes($message)), 150); - - if (!$type) - { - $query = $this->db->query("SELECT plid, min_max FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max IN (" . $this->base->implode($relationship) . ")"); - while ($thread = $this->db->fetch_array($query)) - { - $existplid[$thread['min_max']] = $thread['plid']; - } - $lastmessage = array('lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary); - $lastmessage = addslashes(serialize($lastmessage)); - foreach ($relationship as $key => $value) - { - if (!isset($existplid[$value])) - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_lists(authorid, pmtype, subject, members, min_max, dateline, lastmessage) VALUES('$fromuid', '1', '$subject', 2, '$value', '" . $this->base->time . "', '$lastmessage')"); - $plid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')"); - $pmid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)"); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$key', '1', '1', '0', '" . $this->base->time . "')"); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')"); - } - else - { - $plid = $existplid[$value]; - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')"); - $pmid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)"); - $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$key', '1', '1', '0', '" . $this->base->time . "')", 'SILENT'); - if (!$result) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$key'"); - } - $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')", 'SILENT'); - if (!$result) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, pmnum=pmnum+1, lastupdate='" . $this->base->time . "', lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'"); - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET lastmessage='$lastmessage' WHERE plid='$plid'"); - } - } - } - else - { - $lastmessage = array('firstauthorid' => $fromuid, 'firstauthor' => $fromusername, 'firstsummary' => $lastsummary); - $lastmessage = addslashes(serialize($lastmessage)); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_lists(authorid, pmtype, subject, members, min_max, dateline, lastmessage) VALUES('$fromuid', '2', '$subject', '" . (count($touids) + 1) . "', '', '" . $this->base->time . "', '$lastmessage')"); - $plid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')"); - $pmid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)"); - $pm_member_insertsql[] = "('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')"; - foreach ($touids as $key => $value) - { - $pm_member_insertsql[] = "('$plid', '$value', '1', '1', '0', '" . $this->base->time . "')"; - } - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES " . implode(',', $pm_member_insertsql)); - } - - $newpm = array(); - foreach ($touids as $key => $value) - { - $newpm[] = "('$value')"; - } - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "newpm(uid) VALUES " . implode(',', $newpm)); - return $pmid; - } - - function replypm($plid, $fromuid, $fromusername, $message) - { - if (!$plid || !$fromuid || !$fromusername || !$message) - { - return 0; - } - - $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"); - if (empty($threadpm)) - { - return PMTHREADNONE_ERROR; - } - - if ($threadpm['pmtype'] == 1) - { - $users = explode('_', $threadpm['min_max']); - if ($users[0] == $fromuid) - { - $touid = $users[1]; - } - elseif ($users[1] == $fromuid) - { - $touid = $users[0]; - } - else - { - return PMPRIVILEGENONE_ERROR; - } - - $blackls = $this->get_blackls($fromuid, $touid); - if (in_array('{ALL}', $blackls[$touid])) - { - return PMINBALCKLIST_ERROR; - } - $this->base->load('user'); - $blackls[$touid] = $_ENV['user']->name2id($blackls[$touid]); - if (!(isset($blackls[$touid]) && !in_array($fromuid, $blackls[$touid]))) - { - return PMINBALCKLIST_ERROR; - } - } - - $memberuid = array(); - $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'"); - while ($member = $this->db->fetch_array($query)) - { - $memberuid[$member['uid']] = "('$member[uid]')"; - } - if (!isset($memberuid[$fromuid])) - { - return PMPRIVILEGENONE_ERROR; - } - - $_CACHE['badwords'] = $this->base->cache('badwords'); - if ($_CACHE['badwords']['findpattern']) - { - $message = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $message); - } - $lastsummary = $this->removecode(trim(stripslashes($message)), 150); - - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')"); - $pmid = $this->db->insert_id(); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)"); - if ($threadpm['pmtype'] == 1) - { - $lastmessage = array('lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary); - $lastmessage = addslashes(serialize($lastmessage)); - $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$touid', '1', '1', '0', '" . $this->base->time . "')", 'SILENT'); - if (!$result) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$touid'"); - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, pmnum=pmnum+1, lastupdate='" . $this->base->time . "', lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'"); - } - else - { - $lastmessage = unserialize($threadpm['lastmessage']); - $lastmessage = array('firstauthorid' => $lastmessage['firstauthorid'], 'firstauthor' => $lastmessage['firstauthor'], 'firstsummary' => $lastmessage['firstsummary'], 'lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary); - $lastmessage = addslashes(serialize($lastmessage)); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid'"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, lastupdate='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'"); - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET lastmessage='$lastmessage' WHERE plid='$plid'"); - - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "newpm(uid) VALUES " . implode(',', $memberuid) . ""); - - return $pmid; - } - - function appendchatpm($plid, $uid, $touid) - { - if (!$plid || !$uid || !$touid) - { - return 0; - } - $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"); - if (empty($threadpm)) - { - return PMTHREADNONE_ERROR; - } - if ($threadpm['pmtype'] != 2) - { - return PMCHATTYPE_ERROR; - } - if ($threadpm['authorid'] != $uid) - { - return PMPRIVILEGENONE_ERROR; - } - - $blackls = $this->get_blackls($uid, $touid); - if (in_array('{ALL}', $blackls[$touid])) - { - return PMINBALCKLIST_ERROR; - } - $this->base->load('user'); - $blackls[$touid] = $_ENV['user']->name2id($blackls[$touid]); - if (!(isset($blackls[$touid]) && !in_array($uid, $blackls[$touid]))) - { - return PMINBALCKLIST_ERROR; - } - - $pmnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " WHERE plid='$plid'"); - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$touid', '1', '$pmnum', '0', '0')", 'SILENT'); - $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members='$num' WHERE plid='$plid'"); - - return 1; - } - - function kickchatpm($plid, $uid, $touid) - { - if (!$uid || !$touid || !$plid || $uid == $touid) - { - return 0; - } - $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"); - if ($threadpm['pmtype'] != 2) - { - return PMCHATTYPE_ERROR; - } - if ($threadpm['authorid'] != $uid) - { - return PMPRIVILEGENONE_ERROR; - } - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$touid'"); - $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members='$num' WHERE plid='$plid'"); - return 1; - } - - function quitchatpm($uid, $plids) - { - if (!$uid || !$plids) - { - return 0; - } - $list = array(); - $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE m.plid IN (" . $this->base->implode($plids) . ") AND m.uid='$uid'"); - while ($threadpm = $this->db->fetch_array($query)) - { - if ($threadpm['pmtype'] != 2) - { - return PMCHATTYPE_ERROR; - } - if ($threadpm['authorid'] == $uid) - { - return PMPRIVILEGENONE_ERROR; - } - $list[] = $threadpm['plid']; - } - - if ($list) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid IN (" . $this->base->implode($list) . ") AND uid='$uid'"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members=members-1 WHERE plid IN (" . $this->base->implode($list) . ")"); - } - - return 1; - } - - function deletepmbypmid($uid, $pmid) - { - if (!$uid || !$pmid) - { - return 0; - } - $index = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_indexes i LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON i.plid=t.plid WHERE i.pmid='$pmid'"); - if ($index['pmtype'] != 1) - { - return PMUIDTYPE_ERROR; - } - $users = explode('_', $index['min_max']); - if (!in_array($uid, $users)) - { - return PMPRIVILEGENONE_ERROR; - } - if ($index['authorid'] != $uid) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " SET delstatus=2 WHERE pmid='$pmid' AND delstatus=0"); - $updatenum = $this->db->affected_rows(); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE pmid='$pmid' AND delstatus=1"); - $deletenum = $this->db->affected_rows(); - } - else - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " SET delstatus=1 WHERE pmid='$pmid' AND delstatus=0"); - $updatenum = $this->db->affected_rows(); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE pmid='$pmid' AND delstatus=2"); - $deletenum = $this->db->affected_rows(); - } - - if (!$this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE plid='$index[plid]'")) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$index[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$index[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$index[plid]'"); - } - else - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET pmnum=pmnum-" . ($updatenum + $deletenum) . " WHERE plid='" . $index['plid'] . "' AND uid='$uid'"); - } - return 1; - } - - function deletepmbypmids($uid, $pmids) - { - if ($pmids) - { - foreach ($pmids as $key => $pmid) - { - $this->deletepmbypmid($uid, $pmid); - } - } - return 1; - } - - /* - function deletepmbypmids($uid, $pmids) { - if(!$uid || !$pmids) { - return 0; - } - $pmplid = $delstatus1pm = $delstatus2pm = $pmplidpost = array(); - $existplid = array(); - $query = $this->db->query("SELECT * FROM ".UC_DBTABLEPRE."pm_indexes i LEFT JOIN ".UC_DBTABLEPRE."pm_lists t ON i.plid=t.plid WHERE i.pmid IN (".$this->base->implode($pmids).") AND t.pmtype=1"); - while($index = $this->db->fetch_array($query)) { - $users = explode('_', $index['min_max']); - if(!in_array($uid, $users)) { - return PMPRIVILEGENONE_ERROR; - } - if($index['authorid'] == $uid) { - $delstatus1pm[$this->getposttablename($index['plid'])][] = $index['pmid']; - } else { - $delstatus2pm[$this->getposttablename($index['plid'])][] = $index['pmid']; - } - $pmplidpost[$this->getposttablename($index['plid'])][] = $index['plid']; - $pmplid[$index['plid']] = $index['plid']; - } - if(empty($pmplidpost)) { - return 0; - } - - if($delstatus1pm) { - foreach($delstatus1pm as $key => $value) { - $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=1 WHERE pmid IN (".$this->base->implode($value).") AND delstatus=0"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE pmid IN (".$this->base->implode($value).") AND delstatus=2"); - } - } - - if($delstatus2pm) { - foreach($delstatus2pm as $key => $value) { - $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=2 WHERE pmid IN (".$this->base->implode($value).") AND delstatus=0"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE pmid IN (".$this->base->implode($value).") AND delstatus=1"); - } - } - - foreach($pmplidpost as $key => $value) { - $query = $this->db->query("SELECT DISTINCT plid FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")"); - while($pmpostarr = $this->db->fetch_array($query)) { - $existplid[] = $pmpostarr['plid']; - } - } - $pmplid = array_diff($pmplid, $existplid); - if($pmplid) { - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($pmplid).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($pmplid).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($pmplid).")"); - } - return 1; - } - */ - - function deletepmbyplid($uid, $plid, $isuser = 0) - { - if (!$uid || !$plid) - { - return 0; - } - - if ($isuser) - { - $relationship = $this->relationship($uid, $plid); - $sql = "SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max='$relationship'"; - } - else - { - $sql = "SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"; - } - - $query = $this->db->query($sql); - if ($list = $this->db->fetch_array($query)) - { - if ($list['pmtype'] == 1) - { - $user = explode('_', $list['min_max']); - if (!in_array($uid, $user)) - { - return PMPRIVILEGENONE_ERROR; - } - } - else - { - if ($uid != $list['authorid']) - { - return PMPRIVILEGENONE_ERROR; - } - } - } - else - { - return PMTHREADNONE_ERROR; - } - - if ($list['pmtype'] == 1) - { - if ($uid == $list['authorid']) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]' AND delstatus=2"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " SET delstatus=1 WHERE plid='$list[plid]' AND delstatus=0"); - } - else - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]' AND delstatus=1"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " SET delstatus=2 WHERE plid='$list[plid]' AND delstatus=0"); - } - $count = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]'"); - if (!$count) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$list[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$list[plid]'"); - } - else - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]' AND uid='$uid'"); - } - } - else - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$list[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]'"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$list[plid]'"); - } - return 1; - } - - function deletepmbyplids($uid, $plids, $isuser = 0) - { - if ($plids) - { - foreach ($plids as $key => $plid) - { - $this->deletepmbyplid($uid, $plid, $isuser); - } - } - return 1; - } - - /* - function deletepmbyplid($uid, $plids, $isuser = 0) { - if(!$uid || !$plids) { - return 0; - } - - $privatepm = $chatpm = array(); - $privatepmauthorpost = $privatepmpost = $privatepmpostall = array(); - $existplid = array(); - if($isuser) { - $relationship = array(); - foreach($plids as $key => $value) { - if($uid == $value || !$value) { - return PMDATA_ERROR; - } - $relationship[] = $this->relationship($uid, $value); - } - $sql = "SELECT * FROM ".UC_DBTABLEPRE."pm_lists WHERE min_max IN (".$this->base->implode($relationship).")"; - } else { - $sql = "SELECT * FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($plids).")"; - } - $query = $this->db->query($sql); - while($threadpm = $this->db->fetch_array($query)) { - if($threadpm['pmtype'] == 1) { - $users = explode('_', $threadpm['min_max']); - if($users[0] == $uid) { - $touid = $users[1]; - } elseif($users[1] == $uid) { - $touid = $users[0]; - } else { - continue; - } - - if($threadpm['authorid'] == $uid) { - $privatepmauthorpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid']; - } else { - $privatepmpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid']; - } - $privatepmpostall[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid']; - $privatepm[] = $threadpm['plid']; - } else { - if($uid != $threadpm['authorid']) { - continue; - } - $chatpm[] = $threadpm['plid']; - $chatpmpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid']; - } - } - - if($privatepmauthorpost) { - foreach($privatepmauthorpost as $key => $value) { - $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=1 WHERE plid IN (".$this->base->implode($value).") AND delstatus=0"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).") AND delstatus=2"); - } - } - - if($privatepmpost) { - foreach($privatepmpost as $key => $value) { - $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=2 WHERE plid IN (".$this->base->implode($value).") AND delstatus=0"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).") AND delstatus=1"); - } - } - if($privatepmpostall) { - foreach($privatepmpostall as $key => $value) { - $query = $this->db->query("SELECT DISTINCT plid FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")"); - while($postpm = $this->db->fetch_array($query)) { - $existplid[] = $postpm['plid']; - } - } - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($privatepm).") AND uid='$uid'"); - $privatepm = array_diff($privatepm, $existplid); - if(!empty($privatepm)) { - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($privatepm).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($privatepm).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($privatepm).")"); - } - } - if($chatpmpost) { - foreach($chatpmpost as $key => $value) { - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")"); - } - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($chatpm).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($chatpm).")"); - $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($chatpm).")"); - } - return 1; - } - */ - - function getprivatepmbyplid($uid, $plid, $starttime = 0, $endtime = 0, $start = 0, $ppp = 0) - { - if (!$uid || !$plid) - { - return 0; - } - if (!$this->isprivilege($plid, $uid)) - { - return 0; - } - $thread = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"); - if ($thread['pmtype'] != 1) - { - return 0; - } - $pms = $addsql = array(); - $addsql[] = "p.plid='$plid'"; - if ($thread['authorid'] == $uid) - { - $addsql[] = 'p.delstatus IN (0,2)'; - } - else - { - $addsql[] = 'p.delstatus IN (0,1)'; - } - if ($starttime) - { - $addsql[] = "p.dateline>'$starttime'"; - } - if ($endtime) - { - $addsql[] = "p.dateline<'$endtime'"; - } - if ($addsql) - { - $addsql = implode(' AND ', $addsql); - } - else - { - $addsql = ''; - } - if ($ppp) - { - $limitsql = 'LIMIT ' . intval($start) . ', ' . intval($ppp); - } - else - { - $limitsql = ''; - } - $pms = $this->db->fetch_all("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON p.plid=t.plid WHERE $addsql ORDER BY p.dateline DESC $limitsql"); - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0 WHERE plid='$plid' AND uid='$uid' AND isnew=1"); - return array_reverse($pms); - } - - function getchatpmbyplid($uid, $plid, $starttime = 0, $endtime = 0, $start = 0, $ppp = 0) - { - if (!$uid || !$plid) - { - return 0; - } - if (!$this->isprivilege($plid, $uid)) - { - return 0; - } - $pms = $addsql = array(); - $addsql[] = "p.plid='$plid'"; - if ($starttime) - { - $addsql[] = "p.dateline>'$starttime'"; - } - if ($endtime) - { - $addsql[] = "p.dateline<'$endtime'"; - } - if ($addsql) - { - $addsql = implode(' AND ', $addsql); - } - else - { - $addsql = ''; - } - if ($ppp) - { - $limitsql = 'LIMIT ' . intval($start) . ', ' . intval($ppp); - } - else - { - $limitsql = ''; - } - $query = $this->db->query("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON p.plid=t.plid WHERE $addsql ORDER BY p.dateline DESC $limitsql"); - while ($pm = $this->db->fetch_array($query)) - { - if ($pm['pmtype'] != 2) - { - return 0; - } - $pms[] = $pm; - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0 WHERE plid='$plid' AND uid='$uid' AND isnew=1"); - return array_reverse($pms); - } - - function getpmlist($uid, $filter, $start, $ppp = 10) - { - if (!$uid) - { - return 0; - } - $members = $touidarr = $tousernamearr = array(); - - if ($filter == 'newpm') - { - $addsql = 'm.isnew=1 AND '; - } - else - { - $addsql = ''; - } - $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=m.plid WHERE $addsql m.uid='$uid' ORDER BY m.lastdateline DESC LIMIT $start, $ppp"); - while ($member = $this->db->fetch_array($query)) - { - if ($member['pmtype'] == 1) - { - $users = explode('_', $member['min_max']); - $member['touid'] = $users[0] == $uid ? $users[1] : $users[0]; - } - else - { - $member['touid'] = 0; - } - $touidarr[$member['touid']] = $member['touid']; - $members[] = $member; - } - - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'"); - - $array = array(); - if ($members) - { - $today = $this->base->time - $this->base->time % 86400; - $this->base->load('user'); - $tousernamearr = $_ENV['user']->id2name($touidarr); - foreach ($members as $key => $data) - { - - $daterange = 5; - $data['founddateline'] = $data['dateline']; - $data['dateline'] = $data['lastdateline']; - $data['pmid'] = $data['plid']; - $lastmessage = unserialize($data['lastmessage']); - if ($lastmessage['firstauthorid']) - { - $data['firstauthorid'] = $lastmessage['firstauthorid']; - $data['firstauthor'] = $lastmessage['firstauthor']; - $data['firstsummary'] = $lastmessage['firstsummary']; - } - if ($lastmessage['lastauthorid']) - { - $data['lastauthorid'] = $lastmessage['lastauthorid']; - $data['lastauthor'] = $lastmessage['lastauthor']; - $data['lastsummary'] = $lastmessage['lastsummary']; - } - $data['msgfromid'] = $lastmessage['lastauthorid']; - $data['msgfrom'] = $lastmessage['lastauthor']; - $data['message'] = $lastmessage['lastsummary']; - - $data['new'] = $data['isnew']; - - $data['msgtoid'] = $data['touid']; - if ($data['lastdateline'] >= $today) - { - $daterange = 1; - } - elseif ($data['lastdateline'] >= $today - 86400) - { - $daterange = 2; - } - elseif ($data['lastdateline'] >= $today - 172800) - { - $daterange = 3; - } - elseif ($data['lastdateline'] >= $today - 604800) - { - $daterange = 4; - } - $data['daterange'] = $daterange; - - $data['tousername'] = $tousernamearr[$data['touid']]; - unset($data['min_max']); - $array[] = $data; - } - } - return $array; - } - - function getplidbypmid($pmid) - { - if (!$pmid) - { - return false; - } - return $this->db->result_first("SELECT plid FROM " . UC_DBTABLEPRE . "pm_indexes WHERE pmid='$pmid'"); - } - - function getplidbytouid($uid, $touid) - { - if (!$uid || !$touid) - { - return 0; - } - return $this->db->result_first("SELECT plid FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max='" . $this->relationship($uid, $touid) . "'"); - } - - function getuidbyplid($plid) - { - if (!$plid) - { - return array(); - } - $uidarr = array(); - $query = $this->db->query("SELECT uid FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'"); - while ($uid = $this->db->fetch_array($query)) - { - $uidarr[$uid['uid']] = $uid['uid']; - } - return $uidarr; - } - - function chatpmmemberlist($uid, $plid) - { - if (!$uid || !$plid) - { - return 0; - } - $uidarr = $this->getuidbyplid($plid); - if (empty($uidarr)) - { - return 0; - } - if (!isset($uidarr[$uid])) - { - return 0; - } - $authorid = $this->db->result_first("SELECT authorid FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'"); - return array('author' => $authorid, 'member' => $uidarr); - } - - function relationship($fromuid, $touid) - { - if ($fromuid < $touid) - { - return $fromuid . '_' . $touid; - } - elseif ($fromuid > $touid) - { - return $touid . '_' . $fromuid; - } - else - { - return ''; - } - } - - function getposttablename($plid) - { - $id = substr((string) $plid, -1, 1); - return 'pm_messages_' . intval($id); - } - - function get_blackls($uid, $uids = array()) - { - if (!$uids) - { - $blackls = $this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'"); - } - else - { - $uids = $this->base->implode($uids); - $blackls = array(); - $query = $this->db->query("SELECT uid, blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid IN ($uids)"); - while ($data = $this->db->fetch_array($query)) - { - $blackls[$data['uid']] = explode(',', $data['blacklist']); - } - } - return $blackls; - } - - function set_blackls($uid, $blackls) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET blacklist='$blackls' WHERE uid='$uid'"); - return $this->db->affected_rows(); - } - - function update_blackls($uid, $username, $action = 1) - { - $username = !is_array($username) ? array($username) : $username; - if ($action == 1) - { - if (!in_array('{ALL}', $username)) - { - $usernames = $this->base->implode($username); - $query = $this->db->query("SELECT username FROM " . UC_DBTABLEPRE . "members WHERE username IN ($usernames)"); - $usernames = array(); - while ($data = $this->db->fetch_array($query)) - { - $usernames[addslashes($data['username'])] = addslashes($data['username']); - } - if (!$usernames) - { - return 0; - } - $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'")); - if ($blackls) - { - $list = explode(',', $blackls); - foreach ($list as $k => $v) - { - if (in_array($v, $usernames)) - { - unset($usernames[$v]); - } - } - } - if (!$usernames) - { - return 1; - } - $listnew = implode(',', $usernames); - $blackls .= $blackls !== '' ? ',' . $listnew : $listnew; - } - else - { - $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'")); - $blackls .= ',{ALL}'; - } - } - else - { - $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'")); - $list = $blackls = explode(',', $blackls); - foreach ($list as $k => $v) - { - if (in_array($v, $username)) - { - unset($blackls[$k]); - } - } - $blackls = implode(',', $blackls); - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET blacklist='$blackls' WHERE uid='$uid'"); - return 1; - } - - function removecode($str, $length) - { - static $uccode = null; - if ($uccode === null) - { - require_once UC_ROOT . 'lib/uccode.class.php'; - $uccode = new uccode(); - } - $str = $uccode->complie($str); - return trim($this->base->cutstr(strip_tags($str), $length)); - } - - function ispminterval($uid, $interval = 0) - { - if (!$uid) - { - return 0; - } - $interval = intval($interval); - if (!$interval) - { - return 1; - } - $lastupdate = $this->db->result_first("SELECT lastupdate FROM " . UC_DBTABLEPRE . "pm_members WHERE uid='$uid' ORDER BY lastupdate DESC LIMIT 1"); - if (($this->base->time - $lastupdate) > $interval) - { - return 1; - } - else - { - return 0; - } - } - - function isprivatepmthreadlimit($uid, $maxnum = 0) - { - if (!$uid) - { - return 0; - } - $maxnum = intval($maxnum); - if (!$maxnum) - { - return 1; - } - $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE uid='$uid' AND lastupdate>'" . ($this->base->time - 86400) . "' AND t.pmtype=1"); - if ($maxnum - $num < 0) - { - return 0; - } - else - { - return 1; - } - } - - function ischatpmthreadlimit($uid, $maxnum = 0) - { - if (!$uid) - { - return 0; - } - $maxnum = intval($maxnum); - if (!$maxnum) - { - return 1; - } - $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_lists WHERE authorid='$uid' AND dateline>'" . ($this->base->time - 86400) . "'"); - if ($maxnum - $num < 0) - { - return 0; - } - else - { - return 1; - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/tag.php b/extend/fast/ucenter/client/uc_client/model/tag.php deleted file mode 100644 index 4a8261f8..00000000 --- a/extend/fast/ucenter/client/uc_client/model/tag.php +++ /dev/null @@ -1,84 +0,0 @@ -tagmodel($base); - } - - function tagmodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function get_tag_by_name($tagname) - { - $arr = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$tagname'"); - return $arr; - } - - function get_template($appid) - { - $result = $this->db->result_first("SELECT tagtemplates FROM " . UC_DBTABLEPRE . "applications WHERE appid='$appid'"); - return $result; - } - - function updatedata($appid, $data) - { - $appid = intval($appid); - include_once UC_ROOT . 'lib/xml.class.php'; - $data = @xml_unserialize($data); - $this->base->load('app'); - $data[0] = addslashes($data[0]); - $datanew = array(); - if (is_array($data[1])) - { - foreach ($data[1] as $r) - { - $datanew[] = $_ENV['misc']->array2string($r); - } - } - $tmp = $_ENV['app']->get_apps('type', "appid='$appid'"); - $datanew = addslashes($tmp[0]['type'] . "\t" . implode("\t", $datanew)); - if (!empty($data[0])) - { - $return = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$data[0]' AND appid='$appid'"); - if ($return) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "tags SET data='$datanew', expiration='" . $this->base->time . "' WHERE tagname='$data[0]' AND appid='$appid'"); - } - else - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "tags (tagname, appid, data, expiration) VALUES ('$data[0]', '$appid', '$datanew', '" . $this->base->time . "')"); - } - } - } - - function formatcache($appid, $tagname) - { - $return = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$tagname' AND appid='$appid'"); - if ($return) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "tags SET expiration='0' WHERE tagname='$tagname' AND appid='$appid'"); - } - else - { - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "tags (tagname, appid, expiration) VALUES ('$tagname', '$appid', '0')"); - } - } - -} diff --git a/extend/fast/ucenter/client/uc_client/model/user.php b/extend/fast/ucenter/client/uc_client/model/user.php deleted file mode 100644 index 07662270..00000000 --- a/extend/fast/ucenter/client/uc_client/model/user.php +++ /dev/null @@ -1,439 +0,0 @@ -usermodel($base); - } - - function usermodel(&$base) - { - $this->base = $base; - $this->db = $base->db; - } - - function get_user_by_uid($uid) - { - $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'"); - return $arr; - } - - function get_user_by_username($username) - { - $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE username='$username'"); - return $arr; - } - - function get_user_by_email($email) - { - $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE email='$email'"); - return $arr; - } - - function get_user_by_mobile($mobile) - { - $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile'"); - return $arr; - } - - function check_username($username) - { - $guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8'; - $len = $this->dstrlen($username); - if ($len > 15 || $len < 3 || preg_match("/\s+|^c:\\con\\con|[%,\*\"\s\<\>\&]|$guestexp/is", $username)) - { - return FALSE; - } - else - { - return TRUE; - } - } - - function dstrlen($str) - { - if (strtolower(UC_CHARSET) != 'utf-8') - { - return strlen($str); - } - $count = 0; - for ($i = 0; $i < strlen($str); $i++) - { - $value = ord($str[$i]); - if ($value > 127) - { - $count++; - if ($value >= 192 && $value <= 223) - $i++; - elseif ($value >= 224 && $value <= 239) - $i = $i + 2; - elseif ($value >= 240 && $value <= 247) - $i = $i + 3; - } - $count++; - } - return $count; - } - - function check_mergeuser($username) - { - $data = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->base->app['appid'] . "' AND username='$username'"); - return $data; - } - - function check_usernamecensor($username) - { - $_CACHE['badwords'] = $this->base->cache('badwords'); - $censorusername = $this->base->get_setting('censorusername'); - $censorusername = $censorusername['censorusername']; - $censorexp = '/^(' . str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censorusername = trim($censorusername)), '/')) . ')$/i'; - $usernamereplaced = isset($_CACHE['badwords']['findpattern']) && !empty($_CACHE['badwords']['findpattern']) ? @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username) : $username; - return !(($usernamereplaced != $username) || ($censorusername && preg_match($censorexp, $username))); - } - - function check_usernameexists($username) - { - $data = $this->db->result_first("SELECT username FROM " . UC_DBTABLEPRE . "members WHERE username='$username'"); - return $data; - } - - function check_emailformat($email) - { - return strlen($email) > 6 && strlen($email) <= 32 && preg_match("/^([a-z0-9\-_.+]+)@([a-z0-9\-]+[.][a-z0-9\-.]+)$/", $email); - } - - function check_emailaccess($email) - { - $setting = $this->base->get_setting(array('accessemail', 'censoremail')); - $accessemail = $setting['accessemail']; - $censoremail = $setting['censoremail']; - $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessemail), '/')) . ')$/i'; - $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censoremail), '/')) . ')$/i'; - if ($accessemail || $censoremail) - { - return !(($accessemail && !preg_match($accessexp, $email)) || ($censoremail && preg_match($censorexp, $email))); - } - else - { - return TRUE; - } - } - - function check_emailexists($email, $username = '') - { - $sqladd = $username !== '' ? "AND username<>'$username'" : ''; - $email = $this->db->result_first("SELECT email FROM " . UC_DBTABLEPRE . "members WHERE email='$email' $sqladd"); - return $email; - } - - function check_mobileformat($mobile) - { - return strlen($mobile) >= 11 && preg_match("/^1[34578]\d{9}$/", $mobile); - } - - function check_mobileaccess($mobile) - { - $setting = $this->base->get_setting(array('accessmobile', 'censormobile')); - $accessmobile = $setting['accessmobile']; - $censormobile = $setting['censormobile']; - $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessmobile), '/')) . ')$/i'; - $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censormobile), '/')) . ')$/i'; - if ($accessmobile || $censormobile) - { - return !(($accessmobile && !preg_match($accessexp, $mobile)) || ($censormobile && preg_match($censorexp, $mobile))); - } - else - { - return TRUE; - } - } - - function check_mobileexists($mobile, $username = '') - { - $sqladd = $username !== '' ? "AND username<>'$username'" : ''; - $mobile = $this->db->result_first("SELECT mobile FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile' $sqladd"); - return $mobile; - } - - /** - * 检测是否登录 - * @param string $username - * @param string $password - * @param array $user - * @return int - */ - function check_login($username, $password, &$user) - { - $user = $this->get_user_by_username($username); - if (empty($user['username'])) - { - return -1; - } - elseif ($user['password'] != md5(md5($password) . $user['salt'])) - { - return -2; - } - return $user['uid']; - } - - /** - * 在Ucenter中添加一个账号 - * @param string $username - * @param string $password - * @param string $email - * @param string $mobile - * @param int $uid - * @param array $extend - * @return int - */ - function add_user($username, $password, $email = '', $mobile = '', $uid = 0, $extend = []) - { - $regip = $this->base->onlineip; - $salt = substr(uniqid(rand()), -6); - $password = md5(md5($password) . $salt); - - $values = $uid ? "uid='" . intval($uid) . "'," : ''; - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "members SET $values username='$username', password='$password', email='$email', regip='$regip', regdate='" . $this->base->time . "', salt='$salt'"); - $uid = $this->db->insert_id(); - $extendfields = []; - foreach ($extend as $k => $v) - { - $extendfields[] = "{$k} = '{$v}'"; - } - $extendfields = $extendfields ? ',' . implode(',', $extendfields) : ''; - $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "memberfields SET uid='$uid' {$extendfields}"); - return $uid; - } - - /** - * 编辑Ucenter中的账号 - * @param string $username - * @param string $password - * @param string $email - * @param string $mobile - * @return int - */ - function edit_user($username, $password = '', $email = '', $mobile = '', $uid = 0, $extend = []) - { - $uid = intval($uid); - $data = $this->db->fetch_first("SELECT username, uid, password, salt FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'"); - if (!$data) - { - return -7; - } - $isprotected = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid = '{$data['uid']}'"); - if ($isprotected) - { - return -8; - } - $fields = []; - if ($username) - $fields[] = "username = '{$username}'"; - if ($email) - $fields[] = "email = '{$email}'"; - if ($mobile) - $fields[] = "mobile = '{$mobile}'"; - if ($password) - $fields[] = "password = '" . md5(md5($password) . $data['salt']) . "'"; - $values = implode(',', $fields); - if ($values || $extend) - { - if ($values) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "members SET $values WHERE uid='{$data['uid']}'"); - } - $extendfields = []; - foreach ($extend as $k => $v) - { - $extendfields[] = "{$k} = '{$v}'"; - } - $extendfields = $extendfields ? implode(',', $extendfields) : ''; - if ($extendfields) - { - $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET {$extendfields} WHERE uid='{$data['uid']}'"); - } - return 1; - } - else - { - return -7; - } - } - - /** - * 删除一个账号 - * @param array $uidsarr - * @return int - */ - function delete_user($uidsarr) - { - $uidsarr = (array) $uidsarr; - if (!$uidsarr) - { - return 0; - } - $uids = $this->base->implode($uidsarr); - $arr = $this->db->fetch_all("SELECT uid FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid IN ($uids)"); - $puids = array(); - foreach ((array) $arr as $member) - { - $puids[] = $member['uid']; - } - $uids = $this->base->implode(array_diff($uidsarr, $puids)); - if ($uids) - { - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "members WHERE uid IN($uids)"); - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "memberfields WHERE uid IN($uids)"); - uc_user_deleteavatar($uidsarr); - $this->base->load('note'); - $_ENV['note']->add('deleteuser', "ids=$uids"); - return $this->db->affected_rows(); - } - else - { - return 0; - } - } - - function delete_useravatar($uidsarr) - { - $uidsarr = (array) $uidsarr; - foreach ((array) $uidsarr as $uid) - { - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big', 'real')) && unlink($avatar_file); - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle', 'real')) && unlink($avatar_file); - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small', 'real')) && unlink($avatar_file); - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big')) && unlink($avatar_file); - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle')) && unlink($avatar_file); - file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small')) && unlink($avatar_file); - } - } - - /** - * 获取账号总数 - * @param string $sqladd - * @return int - */ - function get_total_num($sqladd = '') - { - $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "members $sqladd"); - return $data; - } - - /** - * 获取列表 - * @param int $page - * @param int $ppp - * @param int $totalnum - * @param string $sqladd - * @return array - */ - function get_list($page, $ppp, $totalnum, $sqladd) - { - $start = $this->base->page_get_start($page, $ppp, $totalnum); - $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "members $sqladd LIMIT $start, $ppp"); - return $data; - } - - function name2id($usernamesarr) - { - $usernamesarr = uc_addslashes($usernamesarr, 1, TRUE); - $usernames = $this->base->implode($usernamesarr); - $query = $this->db->query("SELECT uid FROM " . UC_DBTABLEPRE . "members WHERE username IN($usernames)"); - $arr = array(); - while ($user = $this->db->fetch_array($query)) - { - $arr[] = $user['uid']; - } - return $arr; - } - - function id2name($uidarr) - { - $arr = array(); - $query = $this->db->query("SELECT uid, username FROM " . UC_DBTABLEPRE . "members WHERE uid IN (" . $this->base->implode($uidarr) . ")"); - while ($user = $this->db->fetch_array($query)) - { - $arr[$user['uid']] = $user['username']; - } - return $arr; - } - - function quescrypt($questionid, $answer) - { - return $questionid > 0 && $answer != '' ? substr(md5($answer . md5($questionid)), 16, 8) : ''; - } - - function can_do_login($username, $ip = '') - { - - $check_times = $this->base->settings['login_failedtime'] < 1 ? 5 : $this->base->settings['login_failedtime']; - - $username = substr(md5($username), 8, 15); - $expire = 15 * 60; - if (!$ip) - { - $ip = $this->base->onlineip; - } - - $ip_check = $user_check = array(); - $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "failedlogins WHERE ip='" . $ip . "' OR ip='$username'"); - while ($row = $this->db->fetch_array($query)) - { - if ($row['ip'] === $username) - { - $user_check = $row; - } - elseif ($row['ip'] === $ip) - { - $ip_check = $row; - } - } - - if (empty($ip_check) || ($this->base->time - $ip_check['lastupdate'] > $expire)) - { - $ip_check = array(); - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$ip}', '0', '{$this->base->time}')"); - } - - if (empty($user_check) || ($this->base->time - $user_check['lastupdate'] > $expire)) - { - $user_check = array(); - $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$username}', '0', '{$this->base->time}')"); - } - - if ($ip_check || $user_check) - { - $time_left = min(($check_times - $ip_check['count']), ($check_times - $user_check['count'])); - return $time_left; - } - - $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "failedlogins WHERE lastupdate<" . ($this->base->time - ($expire + 1)), 'UNBUFFERED'); - - return $check_times; - } - - function loginfailed($username, $ip = '') - { - $username = substr(md5($username), 8, 15); - if (!$ip) - { - $ip = $this->base->onlineip; - } - $this->db->query("UPDATE " . UC_DBTABLEPRE . "failedlogins SET count=count+1, lastupdate='" . $this->base->time . "' WHERE ip='" . $ip . "' OR ip='$username'"); - } - -} diff --git a/extend/fast/ucenter/common/Functions.php b/extend/fast/ucenter/common/Functions.php deleted file mode 100644 index 9f9df9d7..00000000 --- a/extend/fast/ucenter/common/Functions.php +++ /dev/null @@ -1,98 +0,0 @@ - 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) - { - return substr($result, 26); - } - else - { - return ''; - } - } - else - { - return $keyc . str_replace('=', '', base64_encode($result)); - } -} - -function _uc_stripslashes($string) -{ - if (is_array($string)) - { - foreach ($string as $key => $val) - { - $string[$key] = _stripslashes($val); - } - } - else - { - $string = stripslashes($string); - } - return $string; -} - -/** - * 字符串命名风格转换 - * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 - * @param string $name 字符串 - * @param integer $type 转换类型 - * @return string - */ -function parse_name($name, $type = 0) -{ - if ($type) - { - return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match) - { - return strtoupper($match[1]); - }, $name)); - } - else - { - return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); - } -} diff --git a/extend/fast/ucenter/common/XML.php b/extend/fast/ucenter/common/XML.php deleted file mode 100644 index 938fbd59..00000000 --- a/extend/fast/ucenter/common/XML.php +++ /dev/null @@ -1,129 +0,0 @@ -parse($xml); - $xml_parser->destruct(); - return $data; -} - -function xml_serialize($arr, $htmlon = FALSE, $isnormal = FALSE, $level = 1) -{ - $s = $level == 1 ? "\r\n\r\n" : ''; - $space = str_repeat("\t", $level); - foreach ($arr as $k => $v) - { - if (!is_array($v)) - { - $s .= $space . "" . ($htmlon ? '' : '') . "\r\n"; - } - else - { - $s .= $space . "\r\n" . xml_serialize($v, $htmlon, $isnormal, $level + 1) . $space . "\r\n"; - } - } - $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s); - return $level == 1 ? $s . "" : $s; -} - -class XML -{ - - var $parser; - var $document; - var $stack; - var $data; - var $last_opened_tag; - var $isnormal; - var $attrs = array(); - var $failed = FALSE; - - function __construct($isnormal) - { - $this->XML($isnormal); - } - - function XML($isnormal) - { - $this->isnormal = $isnormal; - $this->parser = xml_parser_create('ISO-8859-1'); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); - xml_set_object($this->parser, $this); - xml_set_element_handler($this->parser, 'open', 'close'); - xml_set_character_data_handler($this->parser, 'data'); - } - - function destruct() - { - xml_parser_free($this->parser); - } - - function parse(&$data) - { - $this->document = array(); - $this->stack = array(); - return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : ''; - } - - function open(&$parser, $tag, $attributes) - { - $this->data = ''; - $this->failed = FALSE; - if (!$this->isnormal) - { - if (isset($attributes['id']) && !is_string($this->document[$attributes['id']])) - { - $this->document = &$this->document[$attributes['id']]; - } - else - { - $this->failed = TRUE; - } - } - else - { - if (!isset($this->document[$tag]) || !is_string($this->document[$tag])) - { - $this->document = &$this->document[$tag]; - } - else - { - $this->failed = TRUE; - } - } - $this->stack[] = &$this->document; - $this->last_opened_tag = $tag; - $this->attrs = $attributes; - } - - function data(&$parser, $data) - { - if ($this->last_opened_tag != NULL) - { - $this->data .= $data; - } - } - - function close(&$parser, $tag) - { - if ($this->last_opened_tag == $tag) - { - $this->document = $this->data; - $this->last_opened_tag = NULL; - } - array_pop($this->stack); - if ($this->stack) - { - $this->document = &$this->stack[count($this->stack) - 1]; - } - } - -} diff --git a/public/assets/css/backend.css b/public/assets/css/backend.css index e68f9d6f..849b68fd 100644 --- a/public/assets/css/backend.css +++ b/public/assets/css/backend.css @@ -60,6 +60,9 @@ body.is-dialog { .content-wrapper { position: relative; } +.control-relative { + position: relative; +} .tab-addtabs { overflow: hidden; } @@ -371,6 +374,11 @@ table.table-template { width: 25px; height: 25px; } +@media (min-width: 768px) { + .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > .treeview-menu { + top: 41px; + } +} .fieldlist dd { display: block; margin: 5px 0; diff --git a/public/assets/css/index.css b/public/assets/css/index.css new file mode 100644 index 00000000..9e9a9929 --- /dev/null +++ b/public/assets/css/index.css @@ -0,0 +1,422 @@ +html, +body { + height: 100%; + width: 100%; +} +body { + font-family: 'Muli', 'Helvetica', 'Arial', 'sans-serif'; +} +a { + -webkit-transition: all 0.35s; + -moz-transition: all 0.35s; + transition: all 0.35s; + color: #fdcc52; +} +a:hover, +a:focus { + color: #fcbd20; +} +hr { + max-width: 100px; + margin: 25px auto 0; + border-width: 1px; + border-color: rgba(34, 34, 34, 0.1); +} +hr.light { + border-color: white; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: 200; + letter-spacing: 1px; +} +p { + font-size: 16px; + line-height: 1.5; + margin-bottom: 20px; +} +.navbar-default { + background-color: white; + border-color: rgba(34, 34, 34, 0.05); + -webkit-transition: all 0.35s; + -moz-transition: all 0.35s; + transition: all 0.35s; + font-family: 'Catamaran', 'Helvetica', 'Arial', 'sans-serif'; + font-weight: 200; + letter-spacing: 1px; +} +.navbar-default .navbar-header .navbar-brand { + font-family: 'Catamaran', 'Helvetica', 'Arial', 'sans-serif'; + font-weight: 200; + letter-spacing: 1px; + color: #fdcc52; +} +.navbar-default .navbar-header .navbar-brand:hover, +.navbar-default .navbar-header .navbar-brand:focus { + color: #fcbd20; +} +.navbar-default .navbar-header .navbar-toggle { + font-size: 12px; + color: #222222; + padding: 8px 10px; +} +.navbar-default .nav > li > a { + text-transform: uppercase; + letter-spacing: 2px; + font-size: 14px; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:focus { + color: #222222; +} +.navbar-default .nav > li > a:hover, +.navbar-default .nav > li > a:focus:hover { + color: #fdcc52; +} +.navbar-default .nav > li.active > a, +.navbar-default .nav > li.active > a:focus { + color: #fdcc52 !important; + background-color: transparent; +} +.navbar-default .nav > li.active > a:hover, +.navbar-default .nav > li.active > a:focus:hover { + background-color: transparent; +} +.navbar-default .navbar-header .navbar-brand { + padding-top:3px; +} +@media (min-width: 768px) { + .navbar-default { + background-color: transparent; + border-color: transparent; + } + .navbar-default .navbar-header .navbar-brand { + color: rgba(255, 255, 255, 0.7); + } + .navbar-default .navbar-header .navbar-brand:hover, + .navbar-default .navbar-header .navbar-brand:focus { + color: white; + } + .navbar-default .nav > li > a, + .navbar-default .nav > li > a:focus { + color: rgba(255, 255, 255, 0.7); + } + .navbar-default .nav > li > a:hover, + .navbar-default .nav > li > a:focus:hover { + color: white; + } + .navbar-default.affix { + background-color: white; + border-color: rgba(34, 34, 34, 0.1); + } + .navbar-default.affix .navbar-header .navbar-brand { + color: #222222; + } + .navbar-default.affix .navbar-header .navbar-brand:hover, + .navbar-default.affix .navbar-header .navbar-brand:focus { + color: #fdcc52; + } + .navbar-default.affix .nav > li > a, + .navbar-default.affix .nav > li > a:focus { + color: #222222; + } + .navbar-default.affix .nav > li > a:hover, + .navbar-default.affix .nav > li > a:focus:hover { + color: #fdcc52; + } +} +header { + position: relative; + width: 100%; + min-height: auto; + overflow-y: hidden; + background: url("../img/bg-pattern.png"), #7b4397; + /* fallback for old browsers */ + background: url("../img/bg-pattern.png"), -webkit-linear-gradient(to left, #328944, #247cdc); + /* Chrome 10-25, Safari 5.1-6 */ + background: url(../img/bg-pattern.png), linear-gradient(to left, #328944, #247cdc); + /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ + color: white; +} +header .header-content { + text-align: center; + padding: 150px 0 50px; + position: relative; +} +header .header-content .header-content-inner { + position: relative; + margin: 0 auto; +} +header .header-content .header-content-inner h1 { + margin-top: 0; + margin-bottom: 30px; + font-size: 80px; +} +header .header-content .header-content-inner .list-badges { + margin-bottom: 25px; +} +header .header-content .header-content-inner .list-badges img { + height: 50px; + margin-bottom: 25px; +} +header .device-container { + max-width: 300px; + margin: 0 auto 100px; +} +header .device-container .screen img { + border-radius: 3px; +} +@media (min-width: 768px) { + header { + min-height: 100%; + } + header .header-content { + text-align: center; + padding: 0; + height: 100vh; + } + header .header-content .header-content-inner { + width:100%; + margin: 0; + position: absolute; + top: 50%; + transform: translateY(-50%); + } + header .header-content .header-content-inner h1 { + font-size: 35px; + } + header .device-container { + max-width: none; + max-height: calc(0vh); + margin: 100px auto 0; + } +} +@media (min-width: 992px) { + header .header-content .header-content-inner h1 { + font-size: 80px; + } +} + +@media (max-width: 767px) { + header .header-content .header-content-inner h1 { + font-size: 50px; + } +} +section { + padding: 100px 0; +} +section h2 { + font-size: 50px; +} +section.download { + padding: 150px 0; + position: relative; +} +section.download h2 { + margin-top: 0; + font-size: 50px; +} +section.download .badges .badge-link { + display: block; + margin-bottom: 25px; +} +section.download .badges .badge-link:last-child { + margin-bottom: 0; +} +section.download .badges .badge-link img { + height: 60px; +} +@media (min-width: 768px) { + section.download .badges .badge-link { + display: inline-block; + margin-bottom: 0; + } +} +@media (min-width: 768px) { + section.download h2 { + font-size: 70px; + } +} +section.features .section-heading { + margin-bottom: 100px; +} +section.features .section-heading h2 { + margin-top: 0; +} +section.features .section-heading p { + margin-bottom: 0; +} +section.features .device-container, +section.features .feature-item { + max-width: 300px; + margin: 0 auto; + height:215px; +} +section.features .device-container { + margin-bottom: 100px; +} +@media (min-width: 992px) { + section.features .device-container { + margin-bottom: 0; + } +} +section.features .feature-item { + text-align: center; + margin-bottom: 80px; +} +section.features .feature-item h3 { + font-size: 24px; +} +section.features .feature-item i { + font-size: 60px; + + background: -webkit-linear-gradient(to left,#328944, #247cdc); + background: linear-gradient(to left, #328944, #247cdc); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} +@media (min-width: 992px) { + section.features .device-container, + section.features .feature-item { + max-width: none; + } +} +section.cta { + position: relative; + -webkit-background-size: cover; + -moz-background-size: cover; + background-size: cover; + -o-background-size: cover; + background-position: center; + background-image: url('../img/bg-middle.jpg'); + padding: 250px 0; +} +section.cta .cta-content { + position: relative; + z-index: 1; +} +section.cta .cta-content h2 { + margin-top: 0; + margin-bottom: 25px; + color: white; + max-width: 450px; + font-size: 50px; +} +@media (min-width: 768px) { + section.cta .cta-content h2 { + font-size: 70px; + } +} +section.cta .overlay { + height: 100%; + width: 100%; + background-color: rgba(0, 0, 0, 0.5); + position: absolute; + top: 0; + left: 0; +} +section.contact { + text-align: center; +} +section.contact h2 { + margin-top: 0; + margin-bottom: 25px; +} +section.contact h2 i { + color: #dd4b39; +} +section.contact ul.list-social { + margin-bottom: 0; +} +section.contact ul.list-social li a { + display: block; + height: 80px; + width: 80px; + line-height: 80px; + font-size: 40px; + border-radius: 100%; + color: white; +} +section.contact ul.list-social li.social-github a { + background-color: #444; +} +section.contact ul.list-social li.social-github a:hover { + background-color: #111; +} +section.contact ul.list-social li.social-qq a { + background-color: #1da1f2; +} +section.contact ul.list-social li.social-qq a:hover { + background-color: #0d95e8; +} +section.contact ul.list-social li.social-weibo a { + background-color: #dd4b39; +} +section.contact ul.list-social li.social-weibo a:hover { + background-color: #d73925; +} +footer { + background-color: #222222; + padding: 25px 0; + color: rgba(255, 255, 255, 0.3); + text-align: center; +} +footer p { + font-size: 12px; + margin: 0; +} +footer ul { + margin-bottom: 0; +} +footer ul li a { + font-size: 12px; + color: rgba(255, 255, 255, 0.3); +} +footer ul li a:hover, +footer ul li a:focus, +footer ul li a:active, +footer ul li a.active { + text-decoration: none; +} +.bg-primary { + background: #fdcc52; + background: -webkit-linear-gradient(#fdcc52, #fdc539); + background: linear-gradient(#fdcc52, #fdc539); +} +.text-primary { + color: #fdcc52; +} +.no-gutter > [class*='col-'] { + padding-right: 0; + padding-left: 0; +} +.btn-outline { + color: white; + border-color: white; + border: 1px solid; +} +.btn-outline:hover, +.btn-outline:focus, +.btn-outline:active, +.btn-outline.active { + color: white; + background-color: #fdcc52; + border-color: #fdcc52; +} +.btn { + text-transform: uppercase; + letter-spacing: 2px; + border-radius: 300px; +} +.btn-xl { + margin-top:20px; + padding: 10px 45px; + font-size: 14px; +} +body { + webkit-tap-highlight-color: #222222; +} diff --git a/public/assets/img/bg-middle.jpg b/public/assets/img/bg-middle.jpg new file mode 100755 index 0000000000000000000000000000000000000000..7775b8fe2beee45c6e3ee954b2bbcc32cdfafd23 GIT binary patch literal 44976 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 bqW#>3@{A4-1PMhDl6l1DSG(AXzuNu>&kZ(M literal 0 HcmV?d00001 diff --git a/public/assets/img/bg-pattern.png b/public/assets/img/bg-pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..cfd79110639b72f96f028efdba77979408402368 GIT binary patch literal 633 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 iXSn4SUY{bd%3e>&CI8!GHRN!}v>oYPL+*6;ot{ z>Qy(~EwOx?vAv~Kl_OmW-X2eO6az|<0dz=XuH8a!pr%>14$Y}SFVPASlhltYAKb;{ z0(^96mT7gu zsWE3;r6VSV;+%iP{xBJ$me3`Mzhx3&f=91F0wZQrwMmP-ItOP6t}LNJ@x(?fR_F!D z*7^z5_z8W&3Ui_1g9LHdl)}QAykAWqi($#~C0UE1KMdQ{P~cL~AY>Jr=O0^(ODgKf zGseV77EWZ?j3lhRe=9d%-rCaE3o2XMZA)GHViBrp$sBT**57R@7NYwEraW9%t(du> zuBltuF$*$(@^Px!+-uMNQ!@tbB}fE_w`f4}6quw3kT!Y)wbB37S0nTLOFaH}kwIk` z@pSZ0HWb0{b`M2O5GYDSUHUWSXe>l=zUmEIo);%+_~eh0pS+2L=scL)LgK=Xyuuv~ z&zZ(Ed|jtkP1@Y}%ZR=kMf6d|HhJ3Krm@qNHz0xT{D%}X+gnI#%vV^OArv@V*abv% zMCdMR#4NS37}9&)4Z-27i@pVLADi!#s_0nPXes=`h-&XNN=_tnjWqym4B!fcSS_uljuRAwE2H~KfwKf0Ne`*2&9!+0GaHC0RvQ| zMaY4V0A}_1FLP#vMi+}JD+{AHNkpn3+OtX~!wtoB-$e*$Q?C>ETWRu_+LG}q78ml2 zC$7kX{rp1uf?LsG=%EqQ*c)iv%rf8K%;0;E7*sLGK{t{T8qOfl2fK+uXlz-CUPsL@YKpGuJpLIU#VW2WR8NOs+(O#VyHe(+=}^ zC_BwvCaNGhB`ta_n~N;)0;bjl%ZtJSnwpkGrYjwF^UIeP>Nt7UCLoyE-28i(TS~@- zRV$(&2Bbu-IJ4d9Y|@HoR->NNrNB{#{6+&K-GFrdTh3gwJ2Ym5Y&+VO=yZcy;82Te z+L3^5SEmH@au_Q+aZOywmZCaQr`})V(r)MHnU~~2YI(?NM631{meSLe}(wQ(@%Y^=kBd64*#+vT(wAsvmq38o``^} z2xznfm=A!Pa=;?Msbfb*(DVm*)&uEME3HMqMM@o6z+zHqLC1%~u`7D+TxvE_{OzT+ z;cC(%3zIdmk=q#s1Ja%yda4;|xr^&G&*{ViO)UzGXXrEf@N}2{5N1}o5wq!3OZHYT z4R@sz=b5IYJv(N&*Ci#IsZH{LoQlDjZCnvOr~Mi>CK>BCo!YD%5Rm5D8t7!YVn#|- zZpe`|*FD-i#=2XMT@fje3OR7{EO5}6%t}fsX5ZW?Q;Lr4 zG@>CO{(K`xLmCRzXL+ z6@dFj^MF^7I(=S0v)Wg7ma-RDuLINXgjLoZv)yNxY8^O-J)+|0)I}}kYZO=AOYJ&sB%SY3@pBrRUUrF1 z!TmE!BhGBy@acH}Oh+dcn}v^`x%8Zlz7BMU(q^E$fY!Ra0b01b;_b7@M5k+Cf$9Pw zl;gzg+?U&rpJ@gjD<*I?->9i|Ey&eeVtqT<4}-iIXH#?9oHJBc5M+4zMiJfon8N5Y zn>Rd5z49~X)x^KcV>C4-41EqA-+6xf$vm+ch3owM`InX+U;1p7qWe3q`U0!?9UuA* zZ|;*QieIOF{pn-bzI!_kPvyT4jDovgw{-Ar`1n~%jd_ht%?TwiDIlBp_?ZJZP$5Cf z0`mC;a11pvUIPXS2S|?sSf|1aB(_6od;d%(gdvUwAfp_?2Ey2XKLE8tG@&bp*vX*) YGKJ*;m;@^6g)otfg{XtLs{a2?0H+szssI20 diff --git a/public/assets/img/loginbg.jpg b/public/assets/img/loginbg.jpg new file mode 100755 index 0000000000000000000000000000000000000000..8b942b9e1d3815591d2b4b6c021691e602d03b5b GIT binary patch literal 70837 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 SOJY)Jx*m{tSB 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 Iv?o*l1;;_-XaE2J diff --git a/public/assets/img/third.jpg b/public/assets/img/third.jpg deleted file mode 100644 index e8c852e1b155d0f8d584c57fff2658dddb87f983..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47784 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 XnKi!Qc>n2Nz8T{?=zmxL()oV?YDmcN diff --git a/public/assets/js/addons.js b/public/assets/js/addons.js new file mode 100644 index 00000000..d017888b --- /dev/null +++ b/public/assets/js/addons.js @@ -0,0 +1,3 @@ +define(['backend'], function (Backend) { + +}); \ No newline at end of file diff --git a/public/assets/js/adminlte.js b/public/assets/js/adminlte.js index 94e1f53a..6c169a2e 100644 --- a/public/assets/js/adminlte.js +++ b/public/assets/js/adminlte.js @@ -7,7 +7,7 @@ * @Author Almsaeed Studio * @Support * @Email - * @version 2.3.7 + * @version 2.3.8 * @license MIT */ @@ -63,6 +63,8 @@ $.AdminLTE.options = { //choose to enable the plugin, make sure you load the script //before AdminLTE's app.js enableFastclick: false, + //Control Sidebar Tree views + enableControlTreeView: true, //Control Sidebar Options enableControlSidebar: true, controlSidebarOptions: { @@ -160,7 +162,9 @@ $(function () { $.AdminLTE.layout.activate(); //Enable sidebar tree view controls - $.AdminLTE.tree('.sidebar'); + if (o.enableControlTreeView) { + $.AdminLTE.tree('.sidebar'); + } //Enable control sidebar if (o.enableControlSidebar) { @@ -184,7 +188,8 @@ $(function () { //Activate Bootstrap tooltip if (o.enableBSToppltip) { $('body').tooltip({ - selector: o.BSTooltipSelector + selector: o.BSTooltipSelector, + container: 'body' }); } @@ -242,20 +247,24 @@ function _init() { var _this = this; _this.fix(); _this.fixSidebar(); + $('body, html, .wrapper').css('height', 'auto'); $(window, ".wrapper").resize(function () { _this.fix(); _this.fixSidebar(); }); }, fix: function () { + // Remove overflow from .wrapper if layout-boxed exists + $(".layout-boxed > .wrapper").css('overflow', 'hidden'); //Get window height and the wrapper height - var neg = $('.main-header').outerHeight() + $('.main-footer').outerHeight(); + var footer_height = $('.main-footer').outerHeight() || 0; + var neg = $('.main-header').outerHeight() + footer_height; var window_height = $(window).height(); - var sidebar_height = $(".sidebar").height(); + var sidebar_height = $(".sidebar").height() || 0; //Set the min-height of the content and sidebar based on the //the height of the document. if ($("body").hasClass("fixed")) { - $(".content-wrapper, .right-side").css('min-height', window_height - $('.main-footer').outerHeight()); + $(".content-wrapper, .right-side").css('min-height', window_height - footer_height); } else { var postSetWidth; if (window_height >= sidebar_height) { @@ -289,13 +298,15 @@ function _init() { if ($.AdminLTE.options.sidebarSlimScroll) { if (typeof $.fn.slimScroll != 'undefined') { //Destroy if it exists - $(".sidebar").slimScroll({destroy: true}).height("auto"); - //Add slimscroll - $(".sidebar").slimscroll({ - height: ($(window).height() - $(".main-header").height()) + "px", - color: "rgba(0,0,0,0.2)", - size: "3px" - }); + $(".sidebar").slimScroll({destroy: true}).height("auto").css("overflow", "inherit"); + if (!$("body").hasClass('sidebar-collapse')) { + //Add slimscroll + $(".sidebar").slimscroll({ + height: ($(window).height() - $(".main-header").height()) + "px", + color: "rgba(0,0,0,0.2)", + size: "3px" + }); + } } } } @@ -333,6 +344,7 @@ function _init() { $("body").addClass('sidebar-open').trigger('expanded.pushMenu'); } } + $.AdminLTE.layout.fixSidebar(); }); $(".content-wrapper").click(function () { @@ -343,9 +355,7 @@ function _init() { }); //Enable expand on hover for sidebar mini - if ($.AdminLTE.options.sidebarExpandOnHover - || ($('body').hasClass('fixed') - && $('body').hasClass('sidebar-mini'))) { + if ($.AdminLTE.options.sidebarExpandOnHover) { this.expandOnHover(); } }, @@ -408,6 +418,7 @@ function _init() { else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) { //Get the parent menu var parent = $this.parents('ul').first(); + // modified by FastAdmin if ($(".show-submenu", menu).size() == 0) { //Close all open menus within the parent var ul = parent.find('ul:visible').slideUp(animationSpeed); @@ -430,6 +441,7 @@ function _init() { if (!$this.parent().hasClass("active")) { $this.parent().addClass("active"); } + // modified by FastAdmin if ($(".show-submenu", menu).size() == 0) { $this.parent().siblings().find("ul.menu-open").slideUp(); } diff --git a/public/assets/js/backend.js b/public/assets/js/backend.js index 70677861..cf590d7f 100755 --- a/public/assets/js/backend.js +++ b/public/assets/js/backend.js @@ -46,8 +46,8 @@ define(['fast', 'moment'], function (Fast, Moment) { leftlink = top.window.$(dom.replace(/\{url\}/, baseurl)); //能找到相对地址 if (leftlink.size() > 0) { - icon = typeof icon != 'undefined' ? icon : leftlink.find("i").attr("class"); - title = typeof title != 'undefined' ? title : leftlink.find("span:first").text(); + icon = typeof icon !== 'undefined' ? icon : leftlink.find("i").attr("class"); + title = typeof title !== 'undefined' ? title : leftlink.find("span:first").text(); leftlink.trigger("fa.event.toggleitem"); } var navnode = $(".nav-tabs ul li a[node-url='" + url + "']"); @@ -56,8 +56,8 @@ define(['fast', 'moment'], function (Fast, Moment) { } else { //追加新的tab var id = Math.floor(new Date().valueOf() * Math.random()); - icon = typeof icon != 'undefined' ? icon : 'fa fa-circle-o'; - title = typeof title != 'undefined' ? title : ''; + icon = typeof icon !== 'undefined' ? icon : 'fa fa-circle-o'; + title = typeof title !== 'undefined' ? title : ''; top.window.$("").append(' ' + title + '').prop("href", url).attr({url: url, addtabs: id}).addClass("hide").appendTo(top.window.document.body).trigger("click"); } } @@ -67,17 +67,28 @@ define(['fast', 'moment'], function (Fast, Moment) { init: function () { //公共代码 //配置Toastr的参数 - Toastr.options.positionClass = Config.controllername == 'index' ? "toast-top-right-index" : "toast-top-right"; + Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right"; //点击包含.btn-dialog的元素时弹出dialog $(document).on('click', '.btn-dialog,.dialogit', function (e) { e.preventDefault(); - Backend.api.open(Backend.api.fixurl($(this).attr('href')), $(this).attr('title')); + var options = $(this).data(); + options = options ? options : {}; + Backend.api.open(Backend.api.fixurl($(this).attr('href')), $(this).attr('title'), options); }); //点击包含.btn-addtabs的元素时事件 $(document).on('click', '.btn-addtabs,.addtabsit', function (e) { e.preventDefault(); Backend.api.addtabs($(this).attr("href"), $(this).attr("title")); }); + //点击包含.btn-ajax的元素时事件 + $(document).on('click', '.btn-ajax,.ajaxit', function (e) { + e.preventDefault(); + var options = $(this).data(); + if (typeof options.url === 'undefined' && $(this).attr("href")) { + options.url = $(this).attr("href"); + } + Backend.api.ajax(options); + }); //修复含有fixed-footer类的body边距 if ($(".fixed-footer").size() > 0) { $(document.body).css("padding-bottom", $(".fixed-footer").height()); diff --git a/public/assets/js/backend/addon.js b/public/assets/js/backend/addon.js new file mode 100644 index 00000000..188fd89c --- /dev/null +++ b/public/assets/js/backend/addon.js @@ -0,0 +1,213 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) { + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: Config.fastadmin.api_url + '/addon/index', + add_url: '', + edit_url: '', + del_url: '', + multi_url: '' + } + }); + + var table = $("#table"); + + Template.helper("Moment", Moment); + Template.helper("addons", Config['addons']); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + columns: [ + [ + {field: 'id', title: 'ID'}, + {field: 'name', title: __('Name')}, + {field: 'title', title: __('Title')} + ] + ], + templateView: true, + search: false, + showColumns: false, + showToggle: false, + showExport: false, + commonSearch: true, + searchFormVisible: false, + pageSize: 12 + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + + require(['upload'], function (Upload) { + Upload.api.plupload("#plupload-addon", function (data, ret) { + Config['addons'][data.addon.name] = data.addon; + $('.btn-refresh').trigger('click'); + Toastr.success(ret.msg); + }); + }); + + //点击安装 + $(document).on("click", ".btn-install", function () { + var name = $(this).closest(".operate").data("name"); + var install = function (name, force) { + Fast.api.ajax({ + url: 'addon/install', + data: {name: name, force: force ? 1 : 0} + }, function (data, ret) { + Layer.closeAll(); + Config['addons'][data.addon.name] = ret.data.addon; + $('.btn-refresh').trigger('click'); + }, function (data, ret) { + //如果是需要购买的插件则弹出二维码提示 + if (ret && ret.code === -1) { + //扫码支付 + Layer.open({ + content: Template("paytpl", ret.data), + shade: 0.8, + area: ['800px', '600px'], + skin: 'layui-layer-msg layui-layer-pay', + title: false, + closeBtn: true, + btn: false, + resize: false, + end: function () { + Layer.alert("支付完成后请稍等1~5分钟后再尝试安装,请不要重复支付,如果仍然无法安装,请加QQ群:636393962向管理员反馈"); + } + }); + } else if (ret && ret.code === -2) { + //跳转支付 + Layer.alert('请点击这里在新窗口中进行支付!', { + btn: ['立即支付', '取消'], + icon: 0, + success: function (layero) { + $(".layui-layer-btn0", layero).attr("href", ret.data.payurl).attr("target", "_blank"); + } + }, function () { + Layer.alert("请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!", {icon: 0}); + }); + + } else if (ret && ret.code === -3) { + //插件目录发现影响全局的文件 + Layer.open({ + content: Template("conflicttpl", ret.data), + shade: 0.8, + area: ['800px', '600px'], + title: "温馨提示", + btn: ['继续安装', '取消'], + end: function () { + + }, + yes: function () { + install(name, true); + } + }); + + } else { + Layer.alert(ret.msg); + } + return false; + }); + }; + install(name, false); + }); + + //点击卸载 + $(document).on("click", ".btn-uninstall", function () { + var name = $(this).closest(".operate").data("name"); + var uninstall = function (name, force) { + Fast.api.ajax({ + url: 'addon/uninstall', + data: {name: name, force: force ? 1 : 0} + }, function (data, ret) { + delete Config['addons'][name]; + Layer.closeAll(); + $('.btn-refresh').trigger('click'); + }, function (data, ret) { + if (ret && ret.code === -3) { + //插件目录发现影响全局的文件 + Layer.open({ + content: Template("conflicttpl", ret.data), + shade: 0.8, + area: ['800px', '600px'], + title: "温馨提示", + btn: ['继续卸载', '取消'], + end: function () { + + }, + yes: function () { + uninstall(name, true); + } + }); + + } else { + Layer.alert(ret.msg); + } + return false; + }); + }; + Layer.confirm("确认卸载插件?

                      卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!

                      如有重要数据请备份后再操作!", function () { + uninstall(name, false); + }); + }); + + //点击配置 + $(document).on("click", ".btn-config", function () { + var name = $(this).closest(".operate").data("name"); + Fast.api.open("addon/config?name=" + name, "修改配置"); + }); + + //点击启用/禁用 + $(document).on("click", ".btn-enable,.btn-disable", function () { + var name = $(this).closest(".operate").data("name"); + var action = $(this).data("action"); + var operate = function (name, action, force) { + Fast.api.ajax({ + url: 'addon/state', + data: {name: name, action: action, force: force ? 1 : 0} + }, function (data, ret) { + var addon = Config['addons'][name]; + addon.state = action === 'enable' ? 1 : 0; + Layer.closeAll(); + $('.btn-refresh').trigger('click'); + }, function (data, ret) { + if (ret && ret.code === -3) { + //插件目录发现影响全局的文件 + Layer.open({ + content: Template("conflicttpl", ret.data), + shade: 0.8, + area: ['800px', '600px'], + title: "温馨提示", + btn: ['继续操作', '取消'], + end: function () { + + }, + yes: function () { + operate(name, action, true); + } + }); + + } else { + Layer.alert(ret.msg); + } + return false; + }); + }; + operate(name, action, false); + }); + }, + add: function () { + Controller.api.bindevent(); + }, + config: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +}); \ No newline at end of file diff --git a/public/assets/js/backend/auth/admin.js b/public/assets/js/backend/auth/admin.js index 8fe1eae5..64e1183f 100755 --- a/public/assets/js/backend/auth/admin.js +++ b/public/assets/js/backend/auth/admin.js @@ -28,7 +28,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'email', title: __('Email')}, {field: 'status', title: __("Status"), formatter: Table.api.formatter.status}, {field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} + {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: function (value, row, index) { + if(row.id == 1){ + return ''; + } + return Table.api.formatter.operate.call(this, value, row, index, table); + }} ] ] }); diff --git a/public/assets/js/backend/auth/group.js b/public/assets/js/backend/auth/group.js index 15b546d6..88912b2c 100755 --- a/public/assets/js/backend/auth/group.js +++ b/public/assets/js/backend/auth/group.js @@ -42,7 +42,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function ( {field: 'name', title: __('Name'), align: 'left'}, {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: function (value, row, index) { - if(row.id == 1){ + if (row.id == 1) { return ''; } return Table.api.formatter.operate.call(this, value, row, index, table); @@ -59,23 +59,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function ( }, add: function () { - Form.api.bindevent($("form[role=form]")); Controller.api.bindevent(); }, edit: function () { - Form.api.bindevent($("form[role=form]")); Controller.api.bindevent(); }, api: { - refreshrules: function () { - if ($("#treeview").size() > 0) { - var r = $("#treeview").jstree("get_all_checked"); - $("input[name='row[rules]']").val(r.join(',')); - } - return true; - }, bindevent: function () { - Form.api.custom.refreshrules = Controller.api.refreshrules; + Form.api.bindevent($("form[role=form]"), null, null, function () { + if ($("#treeview").size() > 0) { + var r = $("#treeview").jstree("get_all_checked"); + $("input[name='row[rules]']").val(r.join(',')); + } + return true; + }); //渲染权限节点树 //变更级别后需要重建节点树 $(document).on("change", "select[name='row[pid]']", function () { diff --git a/public/assets/js/backend/category.js b/public/assets/js/backend/category.js index b0fa426f..056e2c8e 100644 --- a/public/assets/js/backend/category.js +++ b/public/assets/js/backend/category.js @@ -27,12 +27,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {checkbox: true}, {field: 'id', title: __('Id')}, {field: 'type', title: __('Type')}, - {field: 'name', title: __('Name'), align:'left'}, + {field: 'name', title: __('Name'), align: 'left'}, {field: 'nickname', title: __('Nickname')}, - {field: 'flag', title: __('Flag'), operate:false, formatter: Table.api.formatter.flag}, - {field: 'image', title: __('Image'), operate:false, formatter: Table.api.formatter.image}, - {field: 'weigh', title: __('Weigh'), operate:false}, - {field: 'status', title: __('Status'), operate:false, formatter: Table.api.formatter.status}, + {field: 'flag', title: __('Flag'), operate: false, formatter: Table.api.formatter.flag}, + {field: 'image', title: __('Image'), operate: false, formatter: Table.api.formatter.image}, + {field: 'weigh', title: __('Weigh'), operate: false}, + {field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status}, {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} ] ] @@ -49,6 +49,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }, api: { bindevent: function () { + $(document).on("change", "#c-type", function () { + $("#c-pid option[data-type='all']").prop("selected", true); + $("#c-pid option").removeClass("hide"); + $("#c-pid option[data-type!='" + $(this).val() + "'][data-type!='all']").addClass("hide"); + $("#c-pid").selectpicker("refresh"); + }); Form.api.bindevent($("form[role=form]")); } } diff --git a/public/assets/js/backend/example/bootstraptable.js b/public/assets/js/backend/example/bootstraptable.js deleted file mode 100644 index a6c36399..00000000 --- a/public/assets/js/backend/example/bootstraptable.js +++ /dev/null @@ -1,162 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'example/bootstraptable/index', - add_url: '', - edit_url: '', - del_url: 'example/bootstraptable/del', - multi_url: '', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - columns: [ - [ - //该列为复选框字段,如果后台的返回state值将会默认选中 - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID', operate: false}, - //默认隐藏该列 - {field: 'admin_id', title: __('Admin_id'), visible: false, operate: false}, - //直接响应搜索 - {field: 'username', title: __('Username'), formatter: Table.api.formatter.search}, - //模糊搜索 - {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'}, - //通过Ajax渲染searchList,也可以使用JSON数据 - {field: 'url', title: __('Url'), align: 'left', searchList: $.getJSON('ajax/typeahead?search=a&field=row[user_id]'), formatter: Controller.api.formatter.url}, - //点击IP时同时执行搜索此IP,同时普通搜索使用下拉列表的形式 - {field: 'ip', title: __('IP'), searchList: ['127.0.0.1', '127.0.0.2'], events: Controller.api.events.ip, formatter: Controller.api.formatter.ip}, - //自定义栏位 - {field: 'custom', title: __('Custom'), operate: false, formatter: Controller.api.formatter.custom}, - //browser是一个不存在的字段 - //通过formatter来渲染数据,同时为它添加上事件 - {field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser}, - //启用时间段搜索 - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD HH:mm:ss"'}, - //我们向操作栏额外添加上一个详情按钮,并保留已有的编辑和删除控制,同时为这个按钮添加上点击事件 - {field: 'operate', title: __('Operate'), events: Controller.api.events.operate, formatter: function (value, row, index) { - var detail = '详情 '; - return detail + Table.api.formatter.operate.call(this, value, row, index, table); - }} - ], - ], - //禁用默认搜索 - search: false, - //启用普通表单搜索 - commonSearch: true, - //可以控制是否默认显示搜索单表,false则隐藏,默认为false - searchFormVisible: true - }); - - //在表格内容渲染完成后回调的事件 - table.on('post-body.bs.table', function (e, settings, json, xhr) { - - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - - //指定搜索条件 - $(document).on("click", ".btn-singlesearch", function () { - var options = table.bootstrapTable('getOptions'); - options.pageNumber = 1; - options.queryParams = function (params) { - return { - search: params.search, - sort: params.sort, - order: params.order, - filter: JSON.stringify({admin_id: 1}), - op: JSON.stringify({admin_id: '='}), - offset: params.offset, - limit: params.limit, - }; - }; - table.bootstrapTable('refresh', {}); - Toastr.info("当前执行的是自定义搜索"); - return false; - }); - - //获取选中项 - $(document).on("click", ".btn-selected", function () { - Layer.alert(JSON.stringify(table.bootstrapTable('getSelections'))); - }); - - //启动和暂停按钮 - $(document).on("click", ".btn-start,.btn-pause", function () { - //在table外不可以使用添加.btn-change的方法 - //只能自己调用Table.api.multi实现 - Table.api.multi("changestatus", 0, table, this); - }); - - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - }, - formatter: {//渲染的方法 - url: function (value, row, index) { - return '
                      '; - }, - ip: function (value, row, index) { - return ' ' + value + ''; - }, - browser: function (value, row, index) { - //这里我们直接使用row的数据 - return '' + row.useragent.split(" ")[0] + ''; - }, - custom: function (value, row, index) { - //添加上btn-change可以自定义请求的URL进行数据处理 - return '' + __('Locked') + ''; - }, - operate: function (value, row, index) { - //返回字符串加上Table.api.formatter.operate的结果 - //默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入 - //传入了table以后如果edit_url为空则不显示编辑按钮,如果del_url为空则不显显删除按钮 - return ' ' + __('Detail') + ' ' - + Table.api.formatter.operate(value, row, index, $("#table")); - }, - }, - events: {//绑定事件的方法 - ip: { - //格式为:方法名+空格+DOM元素 - 'click .btn-ip': function (e, value, row, index) { - e.stopPropagation(); - console.log(); - var container = $("#table").data("bootstrap.table").$container; - var options = $("#table").bootstrapTable('getOptions'); - //这里我们手动将数据填充到表单然后提交 - $("form.form-commonsearch [name='ip']", container).val(value); - $("form.form-commonsearch", container).trigger('submit'); - Toastr.info("执行了自定义搜索操作"); - } - }, - browser: { - 'click .btn-browser': function (e, value, row, index) { - e.stopPropagation(); - Layer.alert("该行数据为: " + JSON.stringify(row) + ""); - } - }, - operate: $.extend({ - 'click .btn-detail': function (e, value, row, index) { - e.stopPropagation(); - Backend.api.open('example/bootstraptable/detail/ids/' + row['id'], __('Detail')); - } - }, Table.api.events.operate) - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/colorbadge.js b/public/assets/js/backend/example/colorbadge.js deleted file mode 100644 index 323057b1..00000000 --- a/public/assets/js/backend/example/colorbadge.js +++ /dev/null @@ -1,55 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'example/colorbadge/index', - add_url: '', - edit_url: '', - del_url: 'example/colorbadge/del', - multi_url: '', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'title', title: __('Title')}, - {field: 'ip', title: __('IP')}, - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: function (value, row, index) { - return Table.api.formatter.operate(value, row, index, table); - } - } - ] - ], - onLoadSuccess: function (data) { - // 在表格第次加载成功后,刷新左侧菜单栏彩色小角标,支持一次渲染多个 - // 如果需要在进入后台即显示左侧的彩色小角标,请使用服务端渲染方式,详情修改application/admin/controller/Index.php - Backend.api.sidebar({ - 'example/colorbadge': data.total - }); - Toastr.info("左侧角标已经刷新成功"); - } - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Form.api.bindevent($("form[role=form]")); - }, - edit: function () { - Form.api.bindevent($("form[role=form]")); - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/controllerjump.js b/public/assets/js/backend/example/controllerjump.js deleted file mode 100644 index 650355c7..00000000 --- a/public/assets/js/backend/example/controllerjump.js +++ /dev/null @@ -1,62 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'example/controllerjump/index', - add_url: '', - edit_url: '', - del_url: 'example/controllerjump/del', - multi_url: '', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'admin_id', title: __('Admin_id')}, - {field: 'title', title: __('Title')}, - {field: 'ip', title: __('IP'), formatter: Controller.api.formatter.ip}, - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: function (value, row, index) { - return Table.api.formatter.operate(value, row, index, table); - } - } - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Form.api.bindevent($("form[role=form]")); - }, - edit: function () { - Form.api.bindevent($("form[role=form]")); - }, - api: { - formatter: { - ip: function (value, row, index) { - //这里手动构造URL - url = "example/bootstraptable?" + this.field + "=" + value; - - //方式一,直接返回class带有addtabsit的链接,这可以方便自定义显示内容 - return '' + __('Search %s', value) + ''; - - //方式二,直接调用Table.api.formatter.addtabs - return Table.api.formatter.addtabs(value, row, index, url); - } - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/cxselect.js b/public/assets/js/backend/example/cxselect.js deleted file mode 100644 index 355b77a0..00000000 --- a/public/assets/js/backend/example/cxselect.js +++ /dev/null @@ -1,14 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - $("#cxselect-example .col-xs-12").each(function () { - $("textarea", this).val($(this).prev().prev().html().replace(/[ ]{2}/g, '')); - }); - - //这里需要手动为Form绑定上元素事件 - Form.api.bindevent($("form#cxselectform")); - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/multitable.js b/public/assets/js/backend/example/multitable.js deleted file mode 100644 index e4f5431d..00000000 --- a/public/assets/js/backend/example/multitable.js +++ /dev/null @@ -1,86 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init(); - - // 表格1 - var table1 = $("#table1").bootstrapTable({ - url: 'general/attachment/index', - extend: { - index_url: 'general/attachment/index', - add_url: 'general/attachment/add', - edit_url: 'general/attachment/edit', - del_url: 'general/attachment/del', - multi_url: 'general/attachment/multi', - table: 'attachment', - }, - toolbar: '#toolbar1', - sortName: 'id', - search: false, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'url', title: __('Url'), formatter: Table.api.formatter.url}, - {field: 'imagewidth', title: __('Imagewidth')}, - {field: 'imageheight', title: __('Imageheight')}, - {field: 'mimetype', title: __('Mimetype')}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格1绑定事件 - Table.api.bindevent(table1); - - // 表格2 - var table2 = $("#table2").bootstrapTable({ - url: 'general/crontab/index', - extend: { - index_url: 'general/crontab/index', - add_url: 'general/crontab/add', - edit_url: 'general/crontab/edit', - del_url: 'general/crontab/del', - multi_url: 'general/crontab/multi', - table: 'crontab', - }, - toolbar: '#toolbar2', - sortName: 'weigh', - search: false, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'type', title: __('Type')}, - {field: 'title', title: __('Title')}, - {field: 'maximums', title: __('Maximums')}, - {field: 'executes', title: __('Executes')}, - {field: 'begintime', title: __('Begin time'), formatter: Table.api.formatter.datetime}, - {field: 'endtime', title: __('End time'), formatter: Table.api.formatter.datetime}, - {field: 'executetime', title: __('Execute time'), formatter: Table.api.formatter.datetime}, - {field: 'weigh', title: __('Weigh')}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格2绑定事件 - Table.api.bindevent(table2); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - }, - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/relationmodel.js b/public/assets/js/backend/example/relationmodel.js deleted file mode 100644 index 87471146..00000000 --- a/public/assets/js/backend/example/relationmodel.js +++ /dev/null @@ -1,50 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'example/relationmodel/index', - add_url: '', - edit_url: '', - del_url: 'example/relationmodel/del', - multi_url: '', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID', operate: '='}, - {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '关键字,模糊搜索'}, - {field: 'admin.avatar', title: __('Avatar'), operate: false, formatter: Table.api.formatter.image}, - {field: 'admin.username', title: __('Username'), operate: '='}, - {field: 'admin.nickname', title: __('Nickname'), operate: 'LIKE %...%', placeholder: '关键字,模糊搜索'}, - {field: 'ip', title: __('IP'), operate: '='}, - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD"'}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: function (value, row, index) { - return Table.api.formatter.operate(value, row, index, table); - } - } - ] - ], - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Form.api.bindevent($("form[role=form]")); - }, - edit: function () { - Form.api.bindevent($("form[role=form]")); - }, - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/example/tabletemplate.js b/public/assets/js/backend/example/tabletemplate.js deleted file mode 100644 index c3378d1b..00000000 --- a/public/assets/js/backend/example/tabletemplate.js +++ /dev/null @@ -1,128 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'example/tabletemplate/index', - add_url: '', - edit_url: '', - del_url: 'example/tabletemplate/del', - multi_url: '', - } - }); - - var table = $("#table"); - - Template.helper("Moment", Moment); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - templateView: true, - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID', operate: false}, - //直接响应搜索 - {field: 'username', title: __('Username'), formatter: Table.api.formatter.search}, - //模糊搜索 - {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'}, - //通过Ajax渲染searchList - {field: 'url', title: __('Url'), align: 'left', searchList: $.getJSON('ajax/typeahead?search=a&field=row[user_id]'), formatter: Controller.api.formatter.url}, - //点击IP时同时执行搜索此IP,同时普通搜索使用下拉列表的形式 - {field: 'ip', title: __('IP'), searchList: ['127.0.0.1', '127.0.0.2'], events: Controller.api.events.ip, formatter: Controller.api.formatter.ip}, - //browser是一个不存在的字段 - //通过formatter来渲染数据,同时为它添加上事件 - {field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser}, - //启用时间段搜索 - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD HH:mm:ss"'}, - //我们向操作栏额外添加上一个详情按钮,并保留已有的编辑和删除控制,同时为这个按钮添加上点击事件 - {field: 'operate', title: __('Operate'), events: Controller.api.events.operate, formatter: Controller.api.formatter.operate} - ], - ], - //禁用默认搜索 - search: false, - //启用普通表单搜索 - commonSearch: false, - //可以控制是否默认显示搜索单表,false则隐藏,默认为false - searchFormVisible: false, - //分页大小 - pageSize: 12 - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - - //指定搜索条件 - $(document).on("click", ".btn-toggle-view", function () { - var options = table.bootstrapTable('getOptions'); - table.bootstrapTable('refreshOptions', {templateView: !options.templateView}); - }); - - //点击详情 - $(document).on("click", ".btn-detail[data-id]", function () { - Backend.api.open('example/bootstraptable/detail/ids/' + $(this).data('id'), __('Detail')); - }); - - //获取选中项 - $(document).on("click", ".btn-selected", function () { - //在templateView的模式下不能调用table.bootstrapTable('getSelections')来获取选中的ID,只能通过下面的Table.api.selectedids来获取 - Layer.alert(JSON.stringify(Table.api.selectedids(table))); - }); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - }, - formatter: { - url: function (value, row, index) { - return '
                      '; - }, - ip: function (value, row, index) { - return ' ' + value + ''; - }, - browser: function (value, row, index) { - //这里我们直接使用row的数据 - return '' + row.useragent.split(" ")[0] + ''; - }, - operate: function (value, row, index) { - //返回字符串加上Table.api.formatter.operate的结果 - //默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入 - //传入了table以后如果edit_url为空则不显示编辑按钮,如果del_url为空则不显显删除按钮 - return ' ' + __('Detail') + ' ' - + Table.api.formatter.operate(value, row, index, $("#table")); - }, - }, - events: { - ip: { - 'click .btn-ip': function (e, value, row, index) { - var options = $("#table").bootstrapTable('getOptions'); - //这里我们手动将数据填充到表单然后提交 - $("#commonSearchContent_" + options.idTable + " form [name='ip']").val(value); - $("#commonSearchContent_" + options.idTable + " form").trigger('submit'); - Toastr.info("执行了自定义搜索操作"); - } - }, - browser: { - 'click .btn-browser': function (e, value, row, index) { - Layer.alert("该行数据为: " + JSON.stringify(row) + ""); - } - }, - operate: $.extend({ - 'click .btn-detail': function (e, value, row, index) { - Backend.api.open('example/tabletemplate/detail/ids/' + row['id'], __('Detail')); - } - }, Table.api.events.operate) - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/general/attachment.js b/public/assets/js/backend/general/attachment.js index fe88b757..8e0dfd4d 100644 --- a/public/assets/js/backend/general/attachment.js +++ b/public/assets/js/backend/general/attachment.js @@ -70,13 +70,9 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin {field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime}, {field: 'operate', title: __('Operate'), events: { 'click .btn-chooseone': function (e, value, row, index) { - var callback = Backend.api.query('callback'); - var id = Backend.api.query('element_id'); var multiple = Backend.api.query('multiple'); multiple = multiple == 'true' ? true : false; - if (id && callback) { - parent.window[callback](id, {url: row.url}, multiple); - } + Fast.api.close({url: row.url, multiple: false}); }, }, formatter: function () { return ' ' + __('Choose') + ''; @@ -87,13 +83,13 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin // 选中多个 $(document).on("click", ".btn-choose-multi", function () { - var callback = Backend.api.query('callback'); - var id = Backend.api.query('element_id'); var urlArr = new Array(); $.each(table.bootstrapTable("getAllSelections"), function (i, j) { urlArr.push(j.url); }); - parent.window[callback](id, {url: urlArr.join(",")}, true); + var multiple = Backend.api.query('multiple'); + multiple = multiple == 'true' ? true : false; + Fast.api.close({url: urlArr.join(","), multiple: true}); }); // 为表格绑定事件 diff --git a/public/assets/js/backend/general/crontab.js b/public/assets/js/backend/general/crontab.js deleted file mode 100644 index 3bed041c..00000000 --- a/public/assets/js/backend/general/crontab.js +++ /dev/null @@ -1,74 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'general/crontab/index', - add_url: 'general/crontab/add', - edit_url: 'general/crontab/edit', - del_url: 'general/crontab/del', - multi_url: 'general/crontab/multi', - table: 'crontab' - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'weigh', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'type_text', title: __('Type'), operate:false}, - {field: 'title', title: __('Title')}, - {field: 'maximums', title: __('Maximums')}, - {field: 'executes', title: __('Executes')}, - {field: 'begintime', title: __('Begin time'), formatter: Table.api.formatter.datetime}, - {field: 'endtime', title: __('End time'), formatter: Table.api.formatter.datetime}, - {field: 'nexttime', title: __('Next execute time'), formatter: Table.api.formatter.datetime, operate:false}, - {field: 'executetime', title: __('Execute time'), formatter: Table.api.formatter.datetime}, - {field: 'weigh', title: __('Weigh')}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - $('#schedule').on('valid.field', function (e, result) { - $("#pickdays").trigger("change"); - }); - Form.api.bindevent($("form[role=form]")); - $(document).on("change", "#pickdays", function () { - $("#scheduleresult").html(__('Loading')); - $.post("general/crontab/get_schedule_future", {schedule: $("#schedule").val(), days:$(this).val()}, function (ret) { - $("#scheduleresult").html(""); - if (typeof ret.futuretime !== 'undefined' && $.isArray(ret.futuretime)) { - $.each(ret.futuretime, function (i, j) { - $("#scheduleresult").append("
                    • " + j + "" + (i + 1) + "
                    • "); - }); - } - }, 'json'); - - }); - $("#pickdays").trigger("change"); - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/general/database.js b/public/assets/js/backend/general/database.js deleted file mode 100755 index 4985913d..00000000 --- a/public/assets/js/backend/general/database.js +++ /dev/null @@ -1,39 +0,0 @@ -define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) { - - var Controller = { - index: function () { - - //禁止在操作select元素时关闭dropdown的关闭事件 - $("#database").on('click', '.dropdown-menu input, .dropdown-menu label, .dropdown-menu select', function (e) { - e.stopPropagation(); - }); - - //提交时检查是否有删除或清空操作 - $("#database").on("submit", "#sqlexecute", function () { - var v = $("#sqlquery").val().toLowerCase(); - if ((v.indexOf("delete ") >= 0 || v.indexOf("truncate ") >= 0) && !confirm(__('Are you sure you want to delete or turncate?'))) { - return false; - } - }); - - //事件按钮操作 - $("#database").on("click", "ul#subaction li input", function () { - $("#topaction").val($(this).attr("rel")); - return true; - }); - - //窗口变更的时候重设结果栏高度 - $(window).on("resize", function () { - $("#database .well").height($(window).height() - $("#database #sqlexecute").height() - $("#ribbon").outerHeight() - $(".panel-heading").outerHeight() - 130); - }); - - //修复iOS下iframe无法滚动的BUG - if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) { - $("#resultparent").css({"-webkit-overflow-scrolling": "touch", "overflow": "auto"}); - } - - $(window).resize(); - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/general/profile.js b/public/assets/js/backend/general/profile.js index b957a92e..6375e482 100755 --- a/public/assets/js/backend/general/profile.js +++ b/public/assets/js/backend/general/profile.js @@ -37,7 +37,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function ( // 为表格绑定事件 Table.api.bindevent(table);//当内容渲染完成后 - Form.api.bindevent($("#update-form"), null, function () { + Form.api.bindevent($("#update-form"), function () { $("input[name='row[password]']").val(''); var url = Backend.api.cdnurl($("#c-avatar").val()); top.window.$(".user-panel .image img,.user-menu > a > img,.user-header > img").prop("src", url); diff --git a/public/assets/js/backend/index.js b/public/assets/js/backend/index.js index 39fc7ae6..6bafb087 100755 --- a/public/assets/js/backend/index.js +++ b/public/assets/js/backend/index.js @@ -56,15 +56,9 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi Backend.api.addtabs($(this).data("url")); }); - //此处为FastAdmin的统计代码,正式使用请移除 - var s = document.createElement("script"); - s.type = "text/javascript"; - s.src = "https://hm.baidu.com/hm.js?58347d769d009bcf6074e9a0ab7ba05e"; - $("head").append(s); - //读取FastAdmin的更新信息 $.ajax({ - url: 'http://demo.fastadmin.net/index/index/news', + url: Config.fastadmin.api_url + '/news/index', type: 'post', dataType: 'jsonp', success: function (ret) { @@ -77,57 +71,51 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi } }); - //读取FastAdmin的Commits信息 - $.ajax({ - url: 'https://api.github.com/repos/karsonzhang/fastadmin/commits?state=open&per_page=10&page=1&sort=updated', - type: 'get', - dataType: 'jsonp', - success: function (ret) { - $(".github-commits > a span").text(ret.data.length); - $(".github-commits .footer a").attr("href", "https://github.com/karsonzhang/fastadmin/commits/master"); + //版本检测 + var checkupdate = function (ignoreversion, tips = false) { + $.ajax({ + url: Config.fastadmin.api_url + '/version/check', + type: 'post', + data: {version: Config.fastadmin.version}, + dataType: 'jsonp', + success: function (ret) { + if (ret.data && ignoreversion !== ret.data.newversion) { + Layer.open({ + title: '发现新版本', + area: ["500px", "auto"], + content: '
                      你的版本是:' + ret.data.version + ',新版本:' + ret.data.newversion + '
                      更新说明
                      ' + ret.data.upgradetext, + btn: ['去下载更新', '忽略此次更新', '不再提示'], + btn2: function (index, layero) { + localStorage.setItem("ignoreversion", ret.data.newversion); + }, + btn3: function (index, layero) { + localStorage.setItem("ignoreversion", "*"); + }, + success: function (layero, index) { + $(".layui-layer-btn0", layero).attr("href", ret.data.downloadurl).attr("target", "_blank"); + } + }); + } else { + if (tips) { + Toastr.success("当前已经是最新版本"); + } + } + }, error: function (e) { + if (tips) { + Toastr.error("发生未知错误:" + e.message); + } + } + }); + } - var dateDiff = function (hisTime, nowTime) { - if (!arguments.length) - return ''; - var arg = arguments, - now = arg[1] ? arg[1] : new Date().getTime(), - diffValue = now - arg[0], - result = '', - minute = 1000 * 60, - hour = minute * 60, - day = hour * 24, - halfamonth = day * 15, - month = day * 30, - year = month * 12, - _year = diffValue / year, - _month = diffValue / month, - _week = diffValue / (7 * day), - _day = diffValue / day, - _hour = diffValue / hour, - _min = diffValue / minute; - - if (_year >= 1) - result = parseInt(_year) + "年前"; - else if (_month >= 1) - result = parseInt(_month) + "个月前"; - else if (_week >= 1) - result = parseInt(_week) + "周前"; - else if (_day >= 1) - result = parseInt(_day) + "天前"; - else if (_hour >= 1) - result = parseInt(_hour) + "个小时前"; - else if (_min >= 1) - result = parseInt(_min) + "分钟前"; - else - result = "刚刚"; - return result; - }; - $.each(ret.data, function (i, j) { - var author = j.author ? j.author : {html_url: "https://github.com/karsonzhang", avatar_url: "/assets/img/avatar.png", login: "Anonymous"}; - var item = '
                    • ' + author.login + '

                      ' + author.login + ' ' + dateDiff(new Date(j.commit.committer.date).getTime()) + '

                      ' + j.commit.message + '

                    • '; - $(item).appendTo($(".github-commits ul.menu")); - }); - } + //读取版本检测信息 + var ignoreversion = localStorage.getItem("ignoreversion"); + if (ignoreversion !== "*") { + checkupdate(ignoreversion); + } + //手动检测版本信息 + $("a[data-toggle='checkupdate']").on('click', function () { + checkupdate('', true); }); //切换左侧sidebar显示隐藏 @@ -219,7 +207,6 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi "skin-purple-light", "skin-green-light" ]; - setup(); /** @@ -394,7 +381,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi }); //为表单绑定事件 - Form.api.bindevent($("#login-form"), null, function (data) { + Form.api.bindevent($("#login-form"), function (data) { localStorage.setItem("lastlogin", JSON.stringify({id: data.id, username: data.username, avatar: data.avatar})); location.href = Backend.api.fixurl(data.url); }); diff --git a/public/assets/js/backend/page.js b/public/assets/js/backend/page.js deleted file mode 100644 index 4b45f7b9..00000000 --- a/public/assets/js/backend/page.js +++ /dev/null @@ -1,61 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'page/index', - add_url: 'page/add', - edit_url: 'page/edit', - del_url: 'page/del', - multi_url: 'page/multi', - table: 'page', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'weigh', - columns: [ - [ - {field: 'state', checkbox: true}, - {field: 'id', title: __('Id'), operate: false}, - {field: 'category_id', title: __('Category_id'), operate: '='}, - {field: 'category.name', title: __('Category'), operate: '='}, - {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '关键字,模糊搜索'}, - {field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag, operate: false}, - {field: 'image', title: __('Image'), formatter: Table.api.formatter.image, operate: false}, - {field: 'views', title: __('Views'), operate: false}, - {field: 'comments', title: __('Comments'), operate: false}, - {field: 'weigh', title: __('Weigh'), operate: false}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status, searchList: {'normal': __('Normal'), 'hidden': __('Hidden')}, style: 'min-width:100px;'}, - {field: 'createtime', title: __('Create Time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD"'}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ], - //普通搜索 - commonSearch: true, - titleForm: '', //为空则不显示标题,不定义默认显示:普通搜索 - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/user/third.js b/public/assets/js/backend/user/third.js deleted file mode 100644 index 156111c8..00000000 --- a/public/assets/js/backend/user/third.js +++ /dev/null @@ -1,57 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefined, Backend, Form, Table) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'user_third/index', - add_url: 'user_third/add', - edit_url: 'user_third/edit', - del_url: 'user_third/del', - multi_url: 'user_third/multi', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: __('Id')}, - {field: 'user_id', title: __('User_id')}, - {field: 'platform', title: __('Platform')}, - {field: 'openid', title: __('Openid')}, - {field: 'openname', title: __('Openname')}, - {field: 'expires_in', title: __('Expires_in')}, - {field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime}, - {field: 'logintime', title: __('Logintime'), formatter: Table.api.formatter.datetime}, - {field: 'expiretime', title: __('Expiretime'), formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - } - } - - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/user/user.js b/public/assets/js/backend/user/user.js deleted file mode 100644 index fa85ec39..00000000 --- a/public/assets/js/backend/user/user.js +++ /dev/null @@ -1,65 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefined, Backend, Form, Table) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'user_user/index', - add_url: 'user_user/add', - edit_url: 'user_user/edit', - del_url: 'user_user/del', - multi_url: 'user_user/multi', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: __('Id')}, - {field: 'partner_id', title: __('Partner_id')}, - {field: 'role_id', title: __('Role_id')}, - {field: 'area_id', title: __('Area_id')}, - {field: 'editor_id', title: __('Editor_id')}, - {field: 'level', title: __('Level')}, - {field: 'star', title: __('Star')}, - {field: 'username', title: __('Username')}, - {field: 'nickname', title: __('Nickname')}, - {field: 'email', title: __('Email')}, - {field: 'mobile', title: __('Mobile')}, - {field: 'avatar', title: __('Avatar'), formatter: Table.api.formatter.image}, - {field: 'gender', title: __('Gender')}, - {field: 'birthday', title: __('Birthday')}, - {field: 'score', title: __('Score')}, - {field: 'prevtime', title: __('Prevtime'), formatter: Table.api.formatter.datetime}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - } - } - - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/version.js b/public/assets/js/backend/version.js deleted file mode 100644 index 98aa8dd2..00000000 --- a/public/assets/js/backend/version.js +++ /dev/null @@ -1,58 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'version/index', - add_url: 'version/add', - edit_url: 'version/edit', - del_url: 'version/del', - multi_url: 'version/multi', - table: 'version', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'weigh', - columns: [ - [ - {field: 'state', checkbox: true}, - {field: 'id', title: __('Id')}, - {field: 'oldversion', title: __('Oldversion')}, - {field: 'newversion', title: __('Newversion')}, - {field: 'packagesize', title: __('Packagesize')}, - {field: 'content', title: __('Content')}, - {field: 'downloadurl', title: __('Downloadurl'), formatter: Table.api.formatter.url}, - {field: 'enforce', title: __('Enforce')}, - {field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime}, - {field: 'updatetime', title: __('Updatetime'), formatter: Table.api.formatter.datetime}, - {field: 'weigh', title: __('Weigh')}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/wechat/autoreply.js b/public/assets/js/backend/wechat/autoreply.js deleted file mode 100644 index 88ff6a05..00000000 --- a/public/assets/js/backend/wechat/autoreply.js +++ /dev/null @@ -1,77 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefined, Backend, Form, Table) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'wechat/autoreply/index', - add_url: 'wechat/autoreply/add', - edit_url: 'wechat/autoreply/edit', - del_url: 'wechat/autoreply/del', - multi_url: 'wechat/autoreply/multi', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: __('Id')}, - {field: 'title', title: __('Title')}, - {field: 'text', title: __('Text')}, - {field: 'eventkey', title: __('Event key')}, - {field: 'remark', title: __('Remark')}, - {field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime}, - {field: 'updatetime', title: __('Update time'), formatter: Table.api.formatter.datetime}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - - $(document).on('click', "#select-resources", function () { - var key = $("input[name='row[eventkey]']").val(); - Backend.api.open($(this).attr("href") + "?callback=refreshkey&key=" + key, __('Select'), {area: ['90%', '90%']}); - return false; - }); - - $(document).on('click', "#add-resources", function () { - Backend.api.open($(this).attr("href") + "?callback=refreshkey&key=", __('Add'), {area: ['90%', '90%']}); - return false; - }); - window.refreshkey = function (data) { - $("input[name='row[eventkey]']").val(data.eventkey).trigger("change"); - layer.closeAll(); - var keytitle = data.title; - var cont = $(".clickbox .create-click:first"); - $(".keytitle", cont).remove(); - if (keytitle) { - cont.append('
                      资源名:' + keytitle + '
                      '); - } - }; - } - } - - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/wechat/config.js b/public/assets/js/backend/wechat/config.js deleted file mode 100644 index 7f6e223b..00000000 --- a/public/assets/js/backend/wechat/config.js +++ /dev/null @@ -1,97 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'wechat/config/index', - add_url: 'wechat/config/add', - edit_url: 'wechat/config/edit', - del_url: 'wechat/config/del', - multi_url: 'wechat/config/multi', - table: 'wechat_config', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - pk: 'id', - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true}, - {field: 'id', title: __('Id')}, - {field: 'name', title: __('Name')}, - {field: 'title', title: __('Title')}, - {field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime}, - {field: 'updatetime', title: __('Updatetime'), formatter: Table.api.formatter.datetime}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Controller.api.bindevent(); - }, - edit: function () { - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - Form.api.bindevent($("form[role=form]")); - $(document).on('click', ".btn-jsoneditor", function () { - $("#c-value").toggle(); - $(".fieldlist").toggleClass("hide"); - $(".btn-insertlink").toggle(); - $("input[name='row[mode]']").val($("#c-value").is(":visible") ? "textarea" : "json"); - }); - $(document).on('click', ".btn-insertlink", function () { - var textarea = $("textarea[name='row[value]']"); - var cursorPos = textarea.prop('selectionStart'); - var v = textarea.val(); - var textBefore = v.substring(0, cursorPos); - var textAfter = v.substring(cursorPos, v.length); - - Layer.prompt({title: '请输入显示的文字', formType: 3}, function (text, index) { - Layer.close(index); - Layer.prompt({title: '请输入跳转的链接URL(包含http)', formType: 3}, function (link, index) { - text = text == '' ? link : text; - textarea.val(textBefore + '' + text + '' + textAfter); - Layer.close(index); - }); - }); - }); - $("input[name='row[type]']:checked").trigger("click"); - - $(document).on("click", ".fieldlist .append", function () { - var rel = parseInt($(this).closest("dl").attr("rel")) + 1; - $(this).closest("dl").attr("rel", rel); - $('
                      ').insertBefore($(this).parent()); - }); - $(document).on("click", ".fieldlist dd .btn-remove", function () { - $(this).parent().remove(); - }); - //拖拽排序 - require(['dragsort'], function () { - //绑定拖动排序 - $("dl.fieldlist").dragsort({ - itemSelector: 'dd', - dragSelector: ".btn-dragsort", - dragEnd: function () { - - }, - placeHolderTemplate: "
                      " - }); - }); - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/wechat/menu.js b/public/assets/js/backend/wechat/menu.js deleted file mode 100644 index 42779120..00000000 --- a/public/assets/js/backend/wechat/menu.js +++ /dev/null @@ -1,289 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'sortable'], function ($, undefined, Backend, Table, Form, Sortable) { - var Controller = { - index: function () { - String.prototype.subByte = function (start, bytes) { - for (var i = start; bytes > 0; i++) { - var code = this.charCodeAt(i); - bytes -= code < 256 ? 1 : 2; - } - return this.slice(start, i + bytes) - }; - var init_menu = function (menu) { - var str = ""; - var items = menu; - var type = action = ""; - for (i in items) { - if (items[i]['sub_button'] != undefined) { - type = action = ""; - } else { - type = items[i]['type']; - if (items[i]['url'] != undefined) - action = "url|" + items[i]['url']; - if (items[i]['key'] != undefined) - action = "key|" + items[i]['key']; - } - str += ''; - } - } - str += ''; - str += ''; - } - $("#add-item").before(str); - }; - var refresh_type = function () { - if ($('input[name=type]:checked').val() == 'view') { - $(".is-view").show(); - $(".is-click").hide(); - } else { - $(".is-view").hide(); - $(".is-click").show(); - } - }; - //初始化菜单 - init_menu(menu); - //拖动排序 - new Sortable($("#menu-list")[0], {draggable: 'li.menu-item'}); - $(".sub-menu-list").each(function () { - new Sortable(this, {draggable: 'li.sub-menu-item'}); - }); - //添加主菜单 - $(document).on('click', '#add-item', function () { - var menu_item_total = $(".menu-item").size(); - if (menu_item_total < 3) { - var item = ''; - var itemDom = $(item); - itemDom.insertBefore(this); - itemDom.trigger("click"); - $(".sub-menu-box", itemDom).show(); - new Sortable($(".sub-menu-list", itemDom)[0], {draggable: 'li.sub-menu-item'}); - } - }); - $(document).on('change', 'input[name=type]', function () { - refresh_type(); - }); - $(document).on('click', '#item_delete', function () { - var current = $("#menu-list li.current"); - var prev = current.prev("li[data-type]"); - var next = current.next("li[data-type]"); - - if (prev.size() == 0 && next.size() == 0 && $(".sub-menu-box", current).size() == 0) { - last = current.closest(".menu-item"); - } else if (prev.size() > 0 || next.size() > 0) { - last = prev.size() > 0 ? prev : next; - } else { - last = null; - $(".weixin-content").hide(); - $(".no-weixin-content").show(); - } - $("#menu-list li.current").remove(); - if (last) { - last.trigger('click'); - } else { - $("input[name='item-title']").val(''); - } - updateChangeMenu(); - }); - - //更新修改与变动 - var updateChangeMenu = function () { - var title = $("input[name='item-title']").val(); - var type = $("input[name='type']:checked").val(); - var key = value = ''; - if (type == 'view') { - key = 'url'; - } else { - key = 'key'; - } - value = $("input[name='" + key + "']").val(); - - if (key == 'key') { - var keytitle = typeof responselist[value] != 'undefined' ? responselist[value] : ''; - var cont = $(".is-click .create-click:first"); - $(".keytitle", cont).remove(); - cont.append('
                      资源名:' + keytitle + '
                      '); - } - var currentItem = $("#menu-list li.current"); - if (currentItem.size() > 0) { - currentItem.attr('data-type', type); - currentItem.attr('data-action', key + "|" + value); - if (currentItem.siblings().size() == 4) { - $(".add-sub-item").show(); - } else if (false) { - - } - currentItem.children("a").find("span").text(title.subByte(0, 16)); - $("input[name='item-title']").val(title); - currentItem.attr('data-name', title); - $('#current-item-name').text(title); - } - menuUpdate(); - } - //更新菜单数据 - var menuUpdate = function () { - $.post("wechat/menu/edit", {menu: JSON.stringify(getMenuList())}, function (data) { - if (data['code'] == 1) { - } else { - Toastr.error(__('Operation failed')); - } - }, 'json'); - }; - //获取菜单数据 - var getMenuList = function () { - var menus = new Array(); - var sub_button = new Array(); - var menu_i = 0; - var sub_menu_i = 0; - var item; - $("#menu-list li").each(function (i) { - item = $(this); - var name = item.attr('data-name'); - var type = item.attr('data-type'); - var action = item.attr('data-action'); - if (name != null) { - actions = action.split('|'); - if (item.hasClass('menu-item')) { - sub_menu_i = 0; - if (item.find('.sub-menu-item').size() > 0) { - menus[menu_i] = {"name": name, "sub_button": "sub_button"} - } else { - if (actions[0] == 'url') - menus[menu_i] = {"name": name, "type": type, "url": actions[1]}; - else - menus[menu_i] = {"name": name, "type": type, "key": actions[1]}; - } - if (menu_i > 0) { - if (menus[menu_i - 1]['sub_button'] == "sub_button") - menus[menu_i - 1]['sub_button'] = sub_button; - else - menus[menu_i - 1]['sub_button']; - } - sub_button = new Array(); - menu_i++; - } else { - if (actions[0] == 'url') - sub_button[sub_menu_i++] = {"name": name, "type": type, "url": actions[1]}; - else - sub_button[sub_menu_i++] = {"name": name, "type": type, "key": actions[1]}; - } - } - }); - if (sub_button.length > 0) { - var len = menus.length; - menus[len - 1]['sub_button'] = sub_button; - } - return menus; - } - //添加子菜单 - $(document).on('click', ".add-sub-item", function () { - var sub_menu_item_total = $(this).parent().find(".sub-menu-item").size(); - if (sub_menu_item_total < 5) { - var item = ''; - var itemDom = $(item); - itemDom.insertBefore(this); - itemDom.trigger("click"); - if (sub_menu_item_total == 4) { - $(this).hide(); - } - } - return false; - }); - //主菜单子菜单点击事件 - $(document).on('click', ".menu-item, .sub-menu-item", function () { - if ($(this).hasClass("sub-menu-item")) { - $("#menu-list li").removeClass('current'); - $(".is-item").show(); - $(".is-sub-item").show(); - } else { - $("#menu-list li").removeClass('current'); - $("#menu-list > li").not(this).find(".sub-menu-box").hide(); - $(".sub-menu-box", this).toggle(); - //如果当前还没有子菜单 - if ($(".sub-menu-item", this).size() == 0) { - $(".is-item").show(); - $(".is-sub-item").show(); - } else { - $(".is-item").hide(); - $(".is-sub-item").hide(); - } - } - $(this).addClass('current'); - var type = $(this).attr('data-type'); - var action = $(this).attr('data-action'); - var title = $(this).attr('data-name'); - - actions = action.split('|'); - $("input[name=type][value='" + type + "']").prop("checked", true); - $("input[name='item-title']").val(title); - $('#current-item-name').text(title); - if (actions[0] == 'url') { - $('input[name=key]').val(''); - } else { - $('input[name=url]').val(''); - } - $("input[name='" + actions[0] + "']").val(actions[1]); - if (actions[0] == 'key') { - var keytitle = typeof responselist[actions[1]] != 'undefined' ? responselist[actions[1]] : ''; - var cont = $(".is-click .create-click:first"); - $(".keytitle", cont).remove(); - if (keytitle) { - cont.append('
                      资源名:' + keytitle + '
                      '); - } - } else { - - } - - $(".weixin-content").show(); - $(".no-weixin-content").hide(); - - refresh_type(); - - return false; - }); - $("form").on('change', "input,textarea", function () { - updateChangeMenu(); - }); - $(document).on('click', "#menuSyn", function () { - $.post("wechat/menu/sync", {}, function (ret) { - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code == 1) { - Backend.api.toastr.success('菜单同步更新成功,生效时间看微信官网说明,或者你重新关注微信号!'); - } else { - Backend.api.toastr.error(msg ? msg : __('Operation failed')); - } - }, 'json'); - }); - $(document).on('click', "#select-resources", function () { - var key = $("#key").val(); - Backend.api.open($(this).attr("href") + "?callback=refreshkey&key=" + key, __('Select')); - return false; - }); - - $(document).on('click', "#add-resources", function () { - Backend.api.open($(this).attr("href") + "?callback=refreshkey&key=" + key, __('Add')); - return false; - }); - window.refreshkey = function (data) { - responselist[data.eventkey] = data.title; - $("input[name=key]").val(data.eventkey).trigger("change"); - layer.closeAll(); - }; - }, - add: function () { - Form.api.bindevent($("form[role=form]")); - }, - edit: function () { - Form.api.bindevent($("form[role=form]")); - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/backend/wechat/response.js b/public/assets/js/backend/wechat/response.js deleted file mode 100644 index ab5ed776..00000000 --- a/public/assets/js/backend/wechat/response.js +++ /dev/null @@ -1,187 +0,0 @@ -define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { - - var Controller = { - index: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'wechat/response/index', - add_url: 'wechat/response/add', - edit_url: 'wechat/response/edit', - del_url: 'wechat/response/del', - multi_url: 'wechat/response/multi', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'type', title: __('Type')}, - {field: 'title', title: __('Resource title')}, - {field: 'eventkey', title: __('Event key')}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status, operate:false}, - {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - select: function () { - // 初始化表格参数配置 - Table.api.init({ - extend: { - index_url: 'wechat/response/index', - } - }); - - var table = $("#table"); - - // 初始化表格 - table.bootstrapTable({ - url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: 'id', - columns: [ - [ - {field: 'state', checkbox: true, }, - {field: 'id', title: 'ID'}, - {field: 'type', title: __('Type')}, - {field: 'title', title: __('Title')}, - {field: 'event', title: __('Event')}, - {field: 'status', title: __('Status'), formatter: Table.api.formatter.status, operate:false}, - {field: 'operate', title: __('Operate'), events: { - 'click .btn-chooseone': function (e, value, row, index) { - var callback = Backend.api.query('callback'); - if (callback) { - parent.window[callback](row); - } - }, - }, formatter: function () { - return ' ' + __('Choose') + ''; - }} - ] - ] - }); - - // 为表格绑定事件 - Table.api.bindevent(table); - }, - add: function () { - Form.api.bindevent($("form[role=form]"), null, function (ret) { - var callback = Backend.api.query('callback'); - if (callback) { - parent.window[callback](ret); - } else { - parent.$(".btn-refresh").trigger("click"); - var index = parent.Layer.getFrameIndex(window.name); - parent.Layer.close(index); - } - }); - Controller.api.bindevent(); - }, - edit: function () { - Form.api.bindevent($("form[role=form]")); - Controller.api.bindevent(); - }, - api: { - bindevent: function () { - var getAppFileds = function (app) { - var app = apps[app]; - var appConfig = app['config']; - var str = ''; - for (i in appConfig) { - if (appConfig[i]['type'] == 'text' || appConfig[i]['type'] == 'textarea') { - var pattern_str = 'pattern ="required" '; - var alt = ''; - if (undefined != appConfig[i]['alt']) - alt = appConfig[i]['alt']; - if (undefined != appConfig[i]['pattern']) - pattern_str = 'pattern ="' + appConfig[i]['pattern'] + '" '; - if (appConfig[i]['type'] == 'textarea') { - str += '
                      '; - } else { - str += '
                      '; - } - } else { - var options = appConfig[i]['options']; - options = options.split(','); - var option_str = ''; - if (appConfig[i]['type'] == 'select') { - for (o in options) { - var option = options[o]; - var item = option.split(':'); - option_str += ''; - } - option_str = ''; - } else if (appConfig[i]['type'] == 'checkbox') { - for (o in options) { - var option = options[o]; - var item = option.split(':'); - option_str += ' '; - } - - } else if (appConfig[i]['type'] == 'radio') { - for (o in options) { - var option = options[o]; - var item = option.split(':'); - option_str += ' '; - } - } - str += '
                      ' + option_str + '
                      '; - } - - } - return str; - }; - $(document).on('change', "#app", function () { - var app = $(this).val(); - $("#appfields").html(getAppFileds(app)); - if (datas.app == app) { - delete(datas.app); - var form = $("form.form-ajax"); - $.each(datas, function (i, j) { - form.field("row[content][" + i + "]" + ($("input[name='row[content][" + i + "][]']", form).size() > 0 ? '[]' : ''), j); - }); - } - }); - $(document).on('click', "input[name='row[type]']", function () { - var type = $(this).val(); - if (type == 'text') { - $("#expand").html('
                      '); - $("form.form-ajax").field("row[content][content]", datas.content); - } else if (type == 'app') { - $("#expand").html('
                      '); - $("form.form-ajax").field("row[content][app]", datas.app); - $("#app").trigger('change'); - } - }); - $(document).on('click', ".btn-insertlink", function () { - var textarea = $("textarea[name='row[content][content]']"); - var cursorPos = textarea.prop('selectionStart'); - var v = textarea.val(); - var textBefore = v.substring(0, cursorPos); - var textAfter = v.substring(cursorPos, v.length); - - Layer.prompt({title: '请输入显示的文字', formType: 3}, function (text, index) { - Layer.close(index); - Layer.prompt({title: '请输入跳转的链接URL(包含http)', formType: 3}, function (link, index) { - text = text == '' ? link : text; - textarea.val(textBefore + '' + text + '' + textAfter); - Layer.close(index); - }); - }); - }); - $("input[name='row[type]']:checked").trigger("click"); - } - } - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/fast.js b/public/assets/js/fast.js index 4c476616..aa37cc6e 100644 --- a/public/assets/js/fast.js +++ b/public/assets/js/fast.js @@ -20,42 +20,64 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine "hideMethod": "fadeOut" } }, + events: { + //请求成功的回调 + onAjaxSuccess: function (ret, onAjaxSuccess) { + var data = typeof ret.data !== 'undefined' ? ret.data : null; + var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg : __('Operation completed'); + + if (typeof onAjaxSuccess === 'function') { + var result = onAjaxSuccess.call(this, data, ret); + if (result === false) + return; + } + Toastr.success(msg); + }, + //请求错误的回调 + onAjaxError: function (ret, onAjaxError) { + var data = typeof ret.data !== 'undefined' ? ret.data : null; + if (typeof onAjaxError === 'function') { + var result = onAjaxError.call(this, data, ret); + if (result === false) { + return; + } + } + Toastr.error(ret.msg + "(code:" + ret.code + ")"); + }, + //服务器响应数据后 + onAjaxResponse: function (response) { + try { + var ret = typeof response === 'object' ? response : JSON.parse(response); + if (!ret.hasOwnProperty('code')) { + $.extend(ret, {code: -2, msg: response, data: null}); + } + } catch (e) { + var ret = {code: -1, msg: e.message, data: null}; + } + return ret; + } + }, api: { //发送Ajax请求 - ajax: function (options, success, failure) { - options = typeof options == 'string' ? {url: options} : options; + ajax: function (options, success, error) { + options = typeof options === 'string' ? {url: options} : options; var index = Layer.load(); options = $.extend({ type: "POST", - dataType: 'json', + dataType: "json", success: function (ret) { Layer.close(index); - if (ret.hasOwnProperty("code")) { - var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : null; - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code === 1) { - if (typeof success == 'function') { - var onAfterResult = success.call(undefined, data); - if (!onAfterResult) { - return false; - } - } - Toastr.success(msg ? msg : __('Operation completed')); - } else { - Toastr.error(msg ? msg : __('Operation failed')); - } + ret = Fast.events.onAjaxResponse(ret); + if (ret.code === 1) { + Fast.events.onAjaxSuccess(ret, success); } else { - Toastr.error(__('Unknown data format')); + Fast.events.onAjaxError(ret, error); } - }, error: function () { + }, + error: function (err) { Layer.close(index); - if (typeof failure == 'function') { - var onAfterResult = failure.call(undefined, data); - if (!onAfterResult) { - return false; - } - } - Toastr.error(__('Network error')); + var ret = {code: err.code, msg: err.message, data: null}; + Fast.events.onAjaxError(ret, error); } }, options); $.ajax(options); @@ -88,44 +110,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }, - //上传文件 - upload: function (file, callback) { - var data = new FormData(); - data.append("file", file); - $.ajax({ - url: "ajax/upload", - data: data, - cache: false, - contentType: false, - processData: false, - type: 'POST', - dataType: 'json', - success: function (ret) { - if (ret.hasOwnProperty("code")) { - var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : null; - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code === 1) { - if (typeof callback == 'function') { - var onAfterResult = success.call(undefined, data); - if (!onAfterResult) { - return false; - } - } - if ($('.summernote').size() > 0 && data && typeof data.url !== 'undefined') { - $('.summernote').summernote("insertImage", data.url, 'filename'); - } - Toastr.success(__('Operation completed')); - } else { - Toastr.error(msg ? msg : __('Operation failed')); - } - } else { - Toastr.error(__('Unknown data format')); - } - }, error: function () { - Toastr.error(__('Network error')); - } - }); - }, + //打开一个弹出窗口 open: function (url, title, options) { title = title ? title : ""; url = Fast.api.fixurl(url); @@ -144,6 +129,8 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine skin: 'layui-layer-noborder', success: function (layero, index) { var that = this; + //存储callback事件 + $(layero).data("callback", that.callback); //$(layero).removeClass("layui-layer-border"); Layer.setTop(layero); var frame = Layer.getChildFrame('html', index); @@ -174,6 +161,17 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine }, options ? options : {})); return false; }, + //关闭窗口并回传数据 + close: function (data) { + var index = parent.Layer.getFrameIndex(window.name); + var callback = parent.$("#layui-layer" + index).data("callback"); + //再执行关闭 + parent.Layer.close(index); + //再调用回传函数 + if (typeof callback === 'function') { + callback.call(undefined, data); + } + }, layerfooter: function (layero, index, that) { var frame = Layer.getChildFrame('html', index); var layerfooter = frame.find(".layer-footer"); diff --git a/public/assets/js/frontend/demo.js b/public/assets/js/frontend/demo.js deleted file mode 100644 index c3ed5ea6..00000000 --- a/public/assets/js/frontend/demo.js +++ /dev/null @@ -1,152 +0,0 @@ -define(['jquery', 'bootstrap', 'frontend'], function ($, undefined, Frontend) { - - var Controller = { - qrcode: function () { - $("form").submit(function () { - $("#qrcodeimg").prop("src", Config.moduleurl + "/demo/qrcode?" + $(this).serialize()); - return false; - }); - $("form").trigger('submit'); - }, - bootstrap: function () { - //Popover & Tooltip - $('.bs-component [data-toggle="popover"]').popover(); - $('.bs-component [data-toggle="tooltip"]').tooltip(); - - //Toastr - var i = -1; - var toastCount = 0; - var $toastlast; - - var getMessage = function () { - var msgs = ['My name is Inigo Montoya. You killed my father. Prepare to die!', - '
                      ', - 'Are you the six fingered man?', - 'Inconceivable!', - 'I do not think that means what you think it means.', - 'Have fun storming the castle!' - ]; - i++; - if (i === msgs.length) { - i = 0; - } - - return msgs[i]; - }; - $('#showtoast').click(function () { - var shortCutFunction = $("#toastTypeGroup input:radio:checked").val(); - var msg = $('#message').val(); - var title = $('#title').val() || ''; - var $showDuration = $('#showDuration'); - var $hideDuration = $('#hideDuration'); - var $timeOut = $('#timeOut'); - var $extendedTimeOut = $('#extendedTimeOut'); - var $showEasing = $('#showEasing'); - var $hideEasing = $('#hideEasing'); - var $showMethod = $('#showMethod'); - var $hideMethod = $('#hideMethod'); - var toastIndex = toastCount++; - - Toastr.options = { - closeButton: $('#closeButton').prop('checked'), - debug: $('#debugInfo').prop('checked'), - positionClass: $('#positionGroup input:radio:checked').val() || 'toast-top-right', - onclick: null - }; - - if ($('#addBehaviorOnToastClick').prop('checked')) { - Toastr.options.onclick = function () { - alert('You can perform some custom action after a toast goes away'); - }; - } - - if ($showDuration.val().length) { - Toastr.options.showDuration = $showDuration.val(); - } - - if ($hideDuration.val().length) { - Toastr.options.hideDuration = $hideDuration.val(); - } - - if ($timeOut.val().length) { - Toastr.options.timeOut = $timeOut.val(); - } - - if ($extendedTimeOut.val().length) { - Toastr.options.extendedTimeOut = $extendedTimeOut.val(); - } - - if ($showEasing.val().length) { - Toastr.options.showEasing = $showEasing.val(); - } - - if ($hideEasing.val().length) { - Toastr.options.hideEasing = $hideEasing.val(); - } - - if ($showMethod.val().length) { - Toastr.options.showMethod = $showMethod.val(); - } - - if ($hideMethod.val().length) { - Toastr.options.hideMethod = $hideMethod.val(); - } - - if (!msg) { - msg = getMessage(); - } - - $("#toastrOptions").text("Command: toastr[" - + shortCutFunction - + "](\"" - + msg - + (title ? "\", \"" + title : '') - + "\")\n\nToastr.options = " - + JSON.stringify(Toastr.options, null, 2) - ); - - var $toast = Toastr[shortCutFunction](msg, title); // Wire up an event handler to a button in the toast, if it exists - $toastlast = $toast; - if ($toast.find('#okBtn').length) { - $toast.delegate('#okBtn', 'click', function () { - alert('you clicked me. i was toast #' + toastIndex + '. goodbye!'); - $toast.remove(); - }); - } - if ($toast.find('#surpriseBtn').length) { - $toast.delegate('#surpriseBtn', 'click', function () { - alert('Surprise! you clicked me. i was toast #' + toastIndex + '. You could perform an action here.'); - }); - } - }); - function getLastToast() { - return $toastlast; - } - $('#clearlasttoast').click(function () { - Toastr.clear(getLastToast()); - }); - $('#cleartoasts').click(function () { - Toastr.clear(); - }); - $(document).on("click", "#dialog-normal", function () { - BootstrapDialog.show({ - title: 'Say-hello dialog', - message: 'Hi Apple!' - }); - }); - $(document).on("click", "#dialog-alert", function () { - BootstrapDialog.alert('Hi Apple!'); - }); - $(document).on("click", "#dialog-confirm", function () { - BootstrapDialog.confirm('Hi Apple, are you sure?', function (result) { - if (result) { - alert('Yup.'); - } else { - alert('Nope.'); - } - }); - }); - }, - }; - return Controller; -}); \ No newline at end of file diff --git a/public/assets/js/require-backend.js b/public/assets/js/require-backend.js index f5c7aa27..4011d687 100644 --- a/public/assets/js/require-backend.js +++ b/public/assets/js/require-backend.js @@ -4,7 +4,8 @@ require.config({ name: 'moment', location: '../libs/moment', main: 'moment' - }], + } + ], //在打包压缩时将会把include中的模块合并到主文件中 include: ['css', 'layer', 'toastr', 'fast', 'backend', 'table', 'form', 'dragsort', 'drag', 'drop', 'addtabs', 'selectpage'], paths: { @@ -48,9 +49,12 @@ require.config({ 'cxselect': '../libs/jquery-cxselect/js/jquery.cxselect', 'template': '../libs/art-template/dist/template-native', 'selectpage': '../libs/selectpage/selectpage', + 'citypicker': '../libs/city-picker/dist/js/city-picker.min', + 'citypicker-data': '../libs/city-picker/dist/js/city-picker.data', }, // shim依赖配置 shim: { + 'addons': ['backend'], 'bootstrap': ['jquery'], 'bootstrap-table': { deps: [ @@ -112,6 +116,7 @@ require.config({ // 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'], 'validator-lang': ['validator-core'], // 'selectpage': ['css!../libs/selectpage/selectpage.css'], + 'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css'] }, baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径 map: { @@ -138,7 +143,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) { // 初始化 $(function () { require(['fast'], function (Fast) { - require(['backend'], function (Backend) { + require(['backend', 'addons'], function (Backend, Addons) { //加载相应模块 if (Config.jsname) { require([Config.jsname], function (Controller) { diff --git a/public/assets/js/require-backend.min.js b/public/assets/js/require-backend.min.js index e1dabc75..59238f79 100644 --- a/public/assets/js/require-backend.min.js +++ b/public/assets/js/require-backend.min.js @@ -65,6 +65,7 @@ require.config({ }, // shim依赖配置 shim: { + 'addons': ['backend'], 'bootstrap': ['jquery'], 'bootstrap-table': { deps: [ @@ -152,7 +153,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) { // 初始化 $(function () { require(['fast'], function (Fast) { - require(['backend'], function (Backend) { + require(['backend', 'addons'], function (Backend, Addons) { //加载相应模块 if (Config.jsname) { require([Config.jsname], function (Controller) { diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js index 093a5239..543feddf 100755 --- a/public/assets/js/require-form.js +++ b/public/assets/js/require-form.js @@ -2,71 +2,8 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U var Form = { config: { }, - api: { - submit: function (form, onBeforeSubmit, onAfterSubmit) { - if (form.size() == 0) - return Toastr.error("表单未初始化完成,无法提交"); - //提交前事件 - var beforeSubmit = form.data("before-submit"); - //元素绑定函数 - if (beforeSubmit && typeof Form.api.custom[beforeSubmit] == 'function') { - if (!Form.api.custom[beforeSubmit].call(form)) { - return false; - } - } - //自定义函数 - if (typeof onBeforeSubmit == 'function') { - if (!onBeforeSubmit.call(form)) { - return false; - } - } - var type = form.attr("method").toUpperCase(); - type = type && (type == 'GET' || type == 'POST') ? type : 'GET'; - url = form.attr("action"); - url = url ? url : location.href; - $.ajax({ - type: type, - url: url, - data: form.serialize(), - dataType: 'json', - success: function (ret) { - if (ret.hasOwnProperty("code")) { - var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : null; - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code === 1) { - $('.form-group', form).removeClass('has-feedback has-success has-error'); - //成功提交后事件 - var afterSubmit = form.data("after-submit"); - //元素绑定函数 - if (afterSubmit && typeof Form.api.custom[afterSubmit] == 'function') { - if (!Form.api.custom[afterSubmit].call(form, data, ret)) { - return false; - } - } - //自定义函数 - if (typeof onAfterSubmit == 'function') { - if (!onAfterSubmit.call(form, data, ret)) { - return false; - } - } - Toastr.success(msg ? msg : __('Operation completed')); - } else { - if (data && typeof data === 'object' && typeof data.token !== 'undefined') { - $("input[name='__token__']").val(data.token); - } - Toastr.error(msg ? msg : __('Operation failed')); - } - } else { - Toastr.error(__('Unknown data format')); - } - }, error: function () { - Toastr.error(__('Network error')); - }, complete: function (e) { - } - }); - return false; - }, - bindevent: function (form, onBeforeSubmit, onAfterSubmit) { + events: { + validator: function (form, success, error, submit) { //绑定表单事件 form.validator($.extend({ validClass: 'has-success', @@ -88,32 +25,35 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U }, valid: function (ret) { //验证通过提交表单 - Form.api.submit($(ret), onBeforeSubmit, function (data, ret) { - if (typeof onAfterSubmit == 'function') { - if (!onAfterSubmit.call($(this), data, ret)) { + Form.api.submit($(ret), function (data, ret) { + if (typeof success === 'function') { + if (!success.call($(this), data, ret)) { return false; } } //提示及关闭当前窗口 - parent.Toastr.success(__('Operation completed')); + var msg = ret.hasOwnProperty("msg") && ret.msg !== "" ? ret.msg : __('Operation completed'); + parent.Toastr.success(msg); parent.$(".btn-refresh").trigger("click"); var index = parent.Layer.getFrameIndex(window.name); parent.Layer.close(index); - }); + }, error, submit); return false; } }, form.data("validator-options") || {})); - + //移除提交按钮的disabled类 $(".layer-footer .btn.disabled", form).removeClass("disabled"); - + }, + selectpicker: function (form) { //绑定select元素事件 if ($(".selectpicker", form).size() > 0) { require(['bootstrap-select', 'bootstrap-select-lang'], function () { $('.selectpicker', form).selectpicker(); }); } - + }, + selectpage: function (form) { //绑定selectpage元素事件 if ($(".selectpage", form).size() > 0) { require(['selectpage'], function () { @@ -126,112 +66,151 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U $(this).trigger("validate"); }); } - + }, + cxselect: function (form) { //绑定cxselect元素事件 - if ($("[data-toggle='cxselect']").size() > 0) { + if ($("[data-toggle='cxselect']", form).size() > 0) { require(['cxselect'], function () { $.cxSelect.defaults.jsonName = 'name'; $.cxSelect.defaults.jsonValue = 'value'; $.cxSelect.defaults.jsonSpace = 'data'; - $("[data-toggle='cxselect']").cxSelect(); + $("[data-toggle='cxselect']", form).cxSelect(); }); } - + }, + citypicker: function (form) { + //绑定城市远程插件 + if ($("[data-toggle='city-picker']", form).size() > 0) { + require(['citypicker'], function () {}); + } + }, + datetimepicker: function (form) { //绑定日期时间元素事件 if ($(".datetimepicker", form).size() > 0) { require(['bootstrap-datetimepicker'], function () { + var options = { + format: 'YYYY-MM-DD HH:mm:ss', + icons: { + time: 'fa fa-clock-o', + date: 'fa fa-calendar', + up: 'fa fa-chevron-up', + down: 'fa fa-chevron-down', + previous: 'fa fa-chevron-left', + next: 'fa fa-chevron-right', + today: 'fa fa-history', + clear: 'fa fa-trash', + close: 'fa fa-remove' + }, + showTodayButton: true, + showClose: true + }; $('.datetimepicker', form).parent().css('position', 'relative'); - $('.datetimepicker', form) - .datetimepicker({ - format: 'YYYY-MM-DD HH:mm:ss', - icons: { - time: 'fa fa-clock-o', - date: 'fa fa-calendar', - up: 'fa fa-chevron-up', - down: 'fa fa-chevron-down', - previous: 'fa fa-chevron-left', - next: 'fa fa-chevron-right', - today: 'fa fa-history', - clear: 'fa fa-trash', - close: 'fa fa-remove' - }, - showTodayButton: true, - showClose: true - }); + $('.datetimepicker', form).datetimepicker(options); }); } - - //绑定summernote事件 - if ($(".summernote", form).size() > 0) { - require(['summernote'], function () { - $(".summernote", form).summernote({ - height: 250, - lang: 'zh-CN', - fontNames: [ - 'Arial', 'Arial Black', 'Serif', 'Sans', 'Courier', - 'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande', - "Open Sans", "Hiragino Sans GB", "Microsoft YaHei", - '微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆', - ], - fontNamesIgnoreCheck: [ - "Open Sans", "Microsoft YaHei", - '微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆' - ], - dialogsInBody: true, - callbacks: { - onChange: function (contents) { - $(this).val(contents); - $(this).trigger('change'); - }, - onInit: function () { - }, - onImageUpload: function (files) { - var that = this; - //依次上传图片 - for (var i = 0; i < files.length; i++) { - Upload.api.send(files[i], function (data) { - var url = Fast.api.cdnurl(data.url); - $(that).summernote("insertImage", url, 'filename'); - }); - } - } - } - }); - }); - } - + }, + plupload: function (form) { //绑定plupload上传元素事件 if ($(".plupload", form).size() > 0) { Upload.api.plupload(); } - + }, + faselect: function (form) { //绑定fachoose选择附件事件 if ($(".fachoose", form).size() > 0) { $(document).on('click', ".fachoose", function () { + var that = this; var multiple = $(this).data("multiple") ? $(this).data("multiple") : false; var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : ''; - Fast.api.open("general/attachment/select?callback=refreshchoose&element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype, __('Choose')); + parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype, __('Choose'), { + callback: function (data) { + var input_id = $("#" + $(that).attr("id")).data("input-id"); + if (data.multiple) { + var urlArr = []; + var inputObj = $("#" + input_id); + if (inputObj.val() !== "") { + urlArr.push(inputObj.val()); + } + urlArr.push(data.url); + inputObj.val(urlArr.join(",")).trigger("change"); + } else { + $("#" + input_id).val(data.url).trigger("change"); + } + } + }); return false; }); - - //刷新选择的元素 - window.refreshchoose = function (id, data, multiple) { - var input_id = $("#" + id).data("input-id"); - if (multiple) { - var urlArr = []; - var inputObj = $("#" + input_id); - if (inputObj.val() != "") { - urlArr.push(inputObj.val()); - } - urlArr.push(data.url); - inputObj.val(urlArr.join(",")).trigger("change"); - } else { - $("#" + input_id).val(data.url).trigger("change"); - } - Layer.closeAll(); - }; } }, + bindevent: function (form) { + + } + }, + api: { + submit: function (form, success, error, submit) { + if (form.size() === 0) + return Toastr.error("表单未初始化完成,无法提交"); + if (typeof submit === 'function') { + if (!submit.call(form)) { + return false; + } + } + var type = form.attr("method").toUpperCase(); + type = type && (type === 'GET' || type === 'POST') ? type : 'GET'; + url = form.attr("action"); + url = url ? url : location.href; + //调用Ajax请求方法 + Fast.api.ajax({ + type: type, + url: url, + data: form.serialize(), + dataType: 'json' + }, function (data, ret) { + $('.form-group', form).removeClass('has-feedback has-success has-error'); + if (data && typeof data === 'object' && typeof data.token !== 'undefined') { + $("input[name='__token__']", form).val(data.token); + } + if (typeof success === 'function') { + if (!success.call(form, data, ret)) { + return false; + } + } + }, function (data, ret) { + if (data && typeof data === 'object' && typeof data.token !== 'undefined') { + $("input[name='__token__']", form).val(data.token); + } + if (typeof error === 'function') { + if (!error.call(form, data, ret)) { + return false; + } + } + }); + return false; + }, + bindevent: function (form, success, error, submit) { + + form = typeof form === 'object' ? form : $(form); + + var events = Form.events; + + events.bindevent(form); + + events.validator(form, success, error, submit); + + events.selectpicker(form); + + events.selectpage(form); + + events.cxselect(form); + + events.citypicker(form); + + events.datetimepicker(form); + + events.plupload(form); + + events.faselect(form); + }, custom: {} }, }; diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index 70c530c1..05a2a8a3 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -1,4 +1,4 @@ -define(['jquery', 'bootstrap', 'moment', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-mobile', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template'], function ($, undefined, Moment) { +define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-mobile', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template'], function ($, undefined, Moment) { var Table = { list: {}, // Bootstrap-table 基础配置 @@ -153,6 +153,7 @@ define(['jquery', 'bootstrap', 'moment', 'bootstrap-table', 'bootstrap-table-lan $(toolbar).on('click', Table.config.refreshbtn, function () { table.bootstrapTable('refresh'); }); + // 添加按钮事件 $(toolbar).on('click', Table.config.addbtn, function () { var ids = Table.api.selectedids(table); @@ -212,7 +213,6 @@ define(['jquery', 'bootstrap', 'moment', 'bootstrap-table', 'bootstrap-table-lan } }; Fast.api.ajax(params, function (data) { - Toastr.success(__('Operation completed')); table.bootstrapTable('refresh'); }); }, @@ -258,7 +258,6 @@ define(['jquery', 'bootstrap', 'moment', 'bootstrap-table', 'bootstrap-table-lan var params = typeof data.params !== "undefined" ? (typeof data.params == 'object' ? $.param(data.params) : data.params) : ''; var options = {url: url, data: {action: action, ids: ids, params: params}}; Fast.api.ajax(options, function (data) { - Toastr.success(__('Operation completed')); table.bootstrapTable('refresh'); }); }, diff --git a/public/assets/js/require-upload.js b/public/assets/js/require-upload.js index 9a2091b9..c1ed4c75 100755 --- a/public/assets/js/require-upload.js +++ b/public/assets/js/require-upload.js @@ -6,10 +6,85 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, classname: '.plupload:not([initialized])', previewtpl: '
                    • ', }, + events: { + //上传成功的回调 + onUploadSuccess: function (ret, onUploadSuccess, button) { + var data = typeof ret.data !== 'undefined' ? ret.data : null; + //上传成功后回调 + if (button) { + //如果有文本框则填充 + var input_id = $(button).data("input-id") ? $(button).data("input-id") : ""; + if (input_id) { + var urlArr = []; + var inputObj = $("#" + input_id); + if ($(button).data("multiple") && inputObj.val() !== "") { + urlArr.push(inputObj.val()); + } + urlArr.push(data.url); + inputObj.val(urlArr.join(",")).trigger("change"); + } + //如果有回调函数 + var onDomUploadSuccess = $(button).data("upload-success"); + if (onDomUploadSuccess) { + if (typeof onDomUploadSuccess !== 'function' && typeof Upload.api.custom[onDomUploadSuccess] === 'function') { + onDomUploadSuccess = Upload.api.custom[onDomUploadSuccess]; + } + if (typeof onDomUploadSuccess === 'function') { + var result = onDomUploadSuccess.call(button, data, ret); + if (result === false) + return; + } + } + } + + if (typeof onUploadSuccess === 'function') { + var result = onUploadSuccess.call(button, data, ret); + if (result === false) + return; + } + }, + //上传错误的回调 + onUploadError: function (ret, onUploadError, button) { + var data = typeof ret.data !== 'undefined' ? ret.data : null; + if (button) { + var onDomUploadError = $(button).data("upload-error"); + if (onDomUploadError) { + if (typeof onDomUploadError !== 'function' && typeof Upload.api.custom[onDomUploadError] === 'function') { + onDomUploadError = Upload.api.custom[onDomUploadError]; + } + if (typeof onDomUploadError === 'function') { + var result = onDomUploadError.call(button, data, ret); + if (result === false) + return; + } + } + } + + if (typeof onUploadError === 'function') { + var result = onUploadError.call(button, data, ret); + if (result === false) { + return; + } + } + Toastr.error(ret.msg + "(code:" + ret.code + ")"); + }, + //服务器响应数据后 + onUploadResponse: function (response) { + try { + var ret = typeof response === 'object' ? response : JSON.parse(response); + if (!ret.hasOwnProperty('code')) { + $.extend(ret, {code: -2, msg: response, data: null}); + } + } catch (e) { + var ret = {code: -1, msg: e.message, data: null}; + } + return ret; + } + }, api: { //Plupload上传 - plupload: function (element, onAfterUpload) { - element = typeof element == 'undefined' ? Upload.config.classname : element; + plupload: function (element, onUploadSuccess, onUploadError) { + element = typeof element === 'undefined' ? Upload.config.classname : element; $(element, Upload.config.container).each(function () { $(this).attr("initialized", true); var that = this; @@ -19,13 +94,15 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, var mimetype = $(this).data("mimetype"); var multipart = $(this).data("multipart"); var multiple = $(this).data("multiple"); - //上传URL - url = url ? url : Config.upload.uploadurl; - url = Fast.api.fixurl(url); + //填充ID var input_id = $(that).data("input-id") ? $(that).data("input-id") : ""; //预览ID var preview_id = $(that).data("preview-id") ? $(that).data("preview-id") : ""; + + //上传URL + url = url ? url : Config.upload.uploadurl; + url = Fast.api.fixurl(url); //最大可上传 maxsize = typeof maxsize !== "undefined" ? maxsize : Config.upload.maxsize; //文件类型 @@ -42,6 +119,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, container: $(this).parent().get(0), //取按钮的上级元素 flash_swf_url: '/assets/libs/plupload/js/Moxie.swf', silverlight_xap_url: '/assets/libs/plupload/js/Moxie.xap', + headers: {'X-REQUESTED-WITH': 'XMLHttpRequest'}, filters: { max_file_size: maxsize, mime_types: mimetype @@ -53,66 +131,40 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, }, FilesAdded: function (up, files) { - Plupload.each(files, function (file) { - //这里可以改成其它的表现形式 - //document.getElementById('filelist').innerHTML += '
                      ' + file.name + ' (' + plupload.formatSize(file.size) + ')
                      '; - }); - $(that).data("bakup-html", $(that).html()); + var button = up.settings.button; + $(button).data("bakup-html", $(button).html()); //添加后立即上传 setTimeout(function () { - Upload.list[id].start(); + up.start(); }, 1); }, UploadProgress: function (up, file) { + var button = up.settings.button; //这里可以改成其它的表现形式 //document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '' + file.percent + "%"; - $(that).prop("disabled", true).html(" " + __('Upload') + file.percent + "%"); + $(button).prop("disabled", true).html(" " + __('Upload') + file.percent + "%"); }, FileUploaded: function (up, file, info) { - var options = this.getOption(); + var button = up.settings.button; //还原按钮文字及状态 - $(that).prop("disabled", false).html($(that).data("bakup-html")); - //这里可以改成其它的表现形式 - //document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML += (' [Url]: ' + '' + url + ''); - //这里建议不修改 - try { - var ret = JSON.parse(info.response); - if (ret.hasOwnProperty('code')) { - ret.data = ret.code == 200 ? ret : ret.data; - ret.code = ret.code == 200 ? 1 : ret.code; - var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : null; - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code === 1) { - if (input_id) { - var urlArr = []; - var inputObj = $("#" + input_id); - if (options.multi_selection && inputObj.val() != "") { - urlArr.push(inputObj.val()); - } - urlArr.push(data.url); - inputObj.val(urlArr.join(",")).trigger("change"); - } - var afterUpload = $("#" + id).data("after-upload"); - if (afterUpload && typeof Upload.api.custom[afterUpload] == 'function') { - Upload.api.custom[afterUpload].call(that, data); - } - if (typeof onAfterUpload == 'function') { - onAfterUpload.call(that, data); - } - } else { - Toastr.error(msg ? msg : __('Operation failed')); - } - } else { - Toastr.error(e.message + "(code:-2)"); - } - } catch (e) { - Toastr.error(e.message + "(code:-1)"); + $(button).prop("disabled", false).html($(button).data("bakup-html")); + var ret = Upload.events.onUploadResponse(info.response); + if (ret.code === 1) { + Upload.events.onUploadSuccess(ret, onUploadSuccess, button); + } else { + Upload.events.onUploadError(ret, onUploadError, button); } }, Error: function (up, err) { - Toastr.error(err.message + "(code:" + err.code + ")"); + var button = up.settings.button; + $(button).prop("disabled", false).html($(button).data("bakup-html")); + var ret = {code: err.code, msg: err.message, data: null}; + Upload.events.onUploadError(ret, onUploadError, button); } - } + }, + onUploadSuccess: onUploadSuccess, + onUploadError: onUploadError, + button: that }); //拖动排序 @@ -155,7 +207,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, $("#" + input_id).val(urlArr.join(",")); } }); - //移除按钮事件 + // 移除按钮事件 $(document.body).on("click", "#" + preview_id + " .btn-trash", function () { $(this).closest("li").remove(); $("#" + preview_id).trigger("fa.preview.change"); @@ -164,8 +216,8 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, Upload.list[id].init(); }); }, - // AJAX异步上传,主要用于Summernote上传回调 - send: function (file, callback) { + // AJAX异步上传 + send: function (file, onUploadSuccess, onUploadError) { var data = new FormData(); data.append("file", file); $.each(Config.upload.multipart, function (k, v) { @@ -178,28 +230,16 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, contentType: false, processData: false, type: 'POST', - dataType: 'json', success: function (ret) { - if (ret.hasOwnProperty("code")) { - ret.data = ret.code == 200 ? ret : ret.data; - ret.code = ret.code == 200 ? 1 : ret.code; - var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : null; - var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : ""; - if (ret.code === 1) { - // 如果回调存在,则直接调用回调 - if (typeof callback == 'function') { - callback.call(this, data); - } else { - Toastr.success(msg ? msg : __('Operation completed')); - } - } else { - Toastr.error(msg ? msg : __('Operation failed')); - } + ret = Upload.events.onUploadResponse(ret); + if (ret.code === 1) { + Upload.events.onUploadSuccess(ret, onUploadSuccess); } else { - Toastr.error(__('Unknown data format')); + Upload.events.onUploadError(ret, onUploadError); } - }, error: function () { - Toastr.error(__('Network error')); + }, error: function (e) { + var ret = {code: 500, msg: e.message, data: null}; + Upload.events.onUploadError(ret, onUploadError); } }); }, diff --git a/public/assets/less/backend.less b/public/assets/less/backend.less index c861dd88..7b5a3754 100644 --- a/public/assets/less/backend.less +++ b/public/assets/less/backend.less @@ -81,6 +81,9 @@ body.is-dialog { .content-wrapper { position:relative; } +.control-relative{ + position:relative; +} .tab-addtabs { overflow: hidden; .tab-pane { @@ -423,6 +426,12 @@ table.table-template{ } } +@media (min-width: 768px){ + .sidebar-mini.sidebar-collapse .sidebar-menu > li:hover > .treeview-menu { + top: 41px; + } +} + .fieldlist dd { display:block;margin:5px 0; input{display: inline-block;width:300px;}