This commit is contained in:
众产-王坤 2026-01-18 17:01:04 +08:00
parent 3152785e0c
commit ab69be8818
50 changed files with 2109 additions and 685 deletions

View File

@ -282,7 +282,7 @@ CREATE TABLE `ap_log` (
`ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'IP,IP',
`logs` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '详情',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3449 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '日志表' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 3449 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '应用日志表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of ap_log
@ -290,7 +290,7 @@ CREATE TABLE `ap_log` (
-- ----------------------------
-- Table structure for ap_luser
-- ----------------------------
DROP TABLE IF EXISTS `ap_luser`;
DROP TABLE IF EXISTS `ap_lug`;
CREATE TABLE `ap_luser` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`isinout` int(11) NOT NULL COMMENT '|登录|,BOOL,登入.登出',
@ -299,10 +299,10 @@ CREATE TABLE `ap_luser` (
`ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'IP,IP',
`model` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '设备指纹',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3437 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '日志表' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 3437 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '登录日志表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of ap_luser
-- Records of ap_lug
-- ----------------------------
-- ----------------------------
@ -1628,7 +1628,7 @@ CREATE TABLE `zc_log` (
`ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'IP,IP',
`logs` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '详情',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 147 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '日志表' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 147 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '总控日志表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of zc_log
@ -1703,17 +1703,20 @@ INSERT INTO `zc_menu` VALUES (231, 61, '待审批事项', '!MSGmatternotice 需
INSERT INTO `zc_menu` VALUES (232, 61, '知会事项', '!MSGmattertell 待处理、处理中、已处理', '', 10, 1);
INSERT INTO `zc_menu` VALUES (233, 61, '我已批事项', '!MSGmatterapproval 非我审批[有代理人]', '', 10, 1);
INSERT INTO `zc_menu` VALUES (234, 61, '指派代理人', '!MSGmatteragent 指派中,已指派历史', '', 10, 1);
INSERT INTO `zc_menu` VALUES (250, 62, '模版维护', '!MSG在线编辑源码', '', 10, 1);
INSERT INTO `zc_menu` VALUES (251, 62, '栏目管理', '!MSG发布计划。关键词管理ABCDE按组合方式生成关键词。|主题管理[内容方向提示词]。|AI规则管理[绑定知识组]', '', 10, 1);
INSERT INTO `zc_menu` VALUES (252, 62, '文章管理', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (253, 62, '落地页管理', '!MSG单页面图文内容', '', 10, 1);
INSERT INTO `zc_menu` VALUES (254, 62, '锚内关键词', '!MSGSEO用', '', 10, 1);
INSERT INTO `zc_menu` VALUES (255, 62, '用户管理', '!MSG用户注册的资源', '', 10, 1);
INSERT INTO `zc_menu` VALUES (256, 62, '咨询线索管理', '!MSG网站表单留下的联系方式', '', 10, 1);
INSERT INTO `zc_menu` VALUES (257, 62, '远程监管设置', '!MSG新用户、新线索、待发库存预警等数据上报中心', '', 10, 1);
INSERT INTO `zc_menu` VALUES (270, 252, '已发文章', '!MSG网站上显示的文章管理', '', 10, 1);
INSERT INTO `zc_menu` VALUES (271, 252, '待发文章', '!MSG按计划准备自动发的文章库存重要', '', 10, 1);
INSERT INTO `zc_menu` VALUES (272, 252, 'AI生成文章', '!MSG生成的文章需要人工过一遍再到待发', '', 10, 1);
INSERT INTO `zc_menu` VALUES (250, 62, '用户线索', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (251, 62, '文章管理', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (252, 62, '文章生成', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (253, 62, '栏目管理', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (254, 62, '锚内关键词', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (255, 62, '单页管理', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (260, 251, '文章草稿', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (261, 251, '文章待发', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (262, 251, '已发文章', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (263, 251, '热门调优', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (270, 252, '关键词库', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (271, 252, '浓缩知识', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (272, 252, '文章模版', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (273, 252, 'SEO规划', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (300, 63, '私域平台账号', '!MSG添加企业微信、个人微信、QQ号等', '', 10, 1);
INSERT INTO `zc_menu` VALUES (301, 63, '线索客户', '!MSG导入手机号自动分配平台账号加人。加好后按标签策略主动跟客户聊天。', '', 10, 1);
INSERT INTO `zc_menu` VALUES (302, 63, '线索待聊', '!MSG每次回复生成后根据数字量延迟1-几分钟。这期间可以人工介入。', '', 10, 1);
@ -1769,7 +1772,8 @@ INSERT INTO `zc_menu` VALUES (602, 82, '自动化任务', 'rigger/autotask.html'
INSERT INTO `zc_menu` VALUES (603, 82, '表单设计器', '!MSGtabbase 字段设计tabfield', '', 10, 1);
INSERT INTO `zc_menu` VALUES (604, 82, '流程设计器', '!MSGmattertemplate 流程设置matterflow', '', 10, 1);
INSERT INTO `zc_menu` VALUES (610, 82, '数据计算', 'datasse/index.html', 'r=执行', 10, 1);
INSERT INTO `zc_menu` VALUES (621, 82, '文档短链', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (611, 82, '总控API', 'rigger/tokapi.html', '', 10, 1);
INSERT INTO `zc_menu` VALUES (612, 82, '三方接入', 'rigger/tokthd.html', '', 10, 1);
INSERT INTO `zc_menu` VALUES (900, 99, '软件设置', '', '', 10, 1);
INSERT INTO `zc_menu` VALUES (901, 99, '示例代码', '', 'u=管理|n=使用', 10, 1);
INSERT INTO `zc_menu` VALUES (902, 99, '开发工具', '', '', 10, 1);
@ -1982,10 +1986,10 @@ CREATE TABLE `zc_stats` (
-- ----------------------------
-- ----------------------------
-- Table structure for zc_token
-- Table structure for zc_tokthd
-- ----------------------------
DROP TABLE IF EXISTS `zc_token`;
CREATE TABLE `zc_token` (
DROP TABLE IF EXISTS `zc_tokthd`;
CREATE TABLE `zc_tokthd` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '三方平台名称',
`cfgtoken` varchar(180) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ConfigData',
@ -1996,7 +2000,26 @@ CREATE TABLE `zc_token` (
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'API配置表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of zc_token
-- Records of zc_tokthd
-- ----------------------------
-- ----------------------------
-- Table structure for zc_tokapi
-- ----------------------------
DROP TABLE IF EXISTS `zc_tokapi`;
CREATE TABLE `zc_tokapi` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '|appid|',
`vuser` int(11) NOT NULL COMMENT '用户,CATA,adminuser',
`apisecret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ',appkey',
`ips` varchar(180) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '白名单IP,BR',
`addtimes` bigint(20) NOT NULL COMMENT '创建时间,DATE',
`uptimes` bigint(20) NOT NULL COMMENT '活跃时间,DATE',
`pubkey` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '|证书|',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 215699 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'API接口授权' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of zc_tokapi
-- ----------------------------
-- ----------------------------
@ -2018,7 +2041,7 @@ CREATE TABLE `zc_ymock` (
-- ----------------------------
-- Records of zc_ymock
-- ----------------------------
INSERT INTO `zc_ymock` VALUES (6, '', '', 'admin/rigger/mock.testmock', '{\"code\":1,\"data\":12344321}', '/z/?func=admin/rigger/mock.testmock<br/>{\"abc\":\"def\",\"_pf\":\"PC\"}', 1754001371, 1722713211);
INSERT INTO `zc_ymock` VALUES (6, '', '', '/admin/rigger/mock.testmock', '{\"code\":1,\"data\":12344321}', '/z/?func=admin/rigger/mock.testmock<br/>{\"abc\":\"def\",\"_pf\":\"PC\"}', 1754001371, 1722713211);
-- ----------------------------
-- Table structure for zc_zmem_var

View File

@ -55,7 +55,7 @@
app.globalData.mqfunc = [];
app.globalData.srv = 't';
app.globalData.jsnajax = 'z/?func=ambap/';
app.globalData.jsnajax = 'ambap/';
app.globalData.jsnurl = {};
app.globalData.jsnurl.t = 'https://ciyon.ciy.cn/';
app.globalData.demourl = 'https://i.qiboc.cn/app.goc'; //

View File

@ -20,7 +20,7 @@ import (
func main() {
//nohup ./zgo &
//nohup /data/go/ciyon/zgo > /dev/null 2>&1 &
c.CiyVars.Version = "1.0.1"
c.CiyVars.Version = "1.0.2"
c.Clog("---=========================Ciyon=========================---")
c.Clog("Version:", c.CiyVars.Version, " WorkDir:", c.CiyWebDir)
//读取配置文件ini
@ -131,7 +131,7 @@ func main() {
web.SetMockFile() //在web/ud/mock目录下建立对应的json文件。
} else if mock != "" {
web.SetMockFn(func(w http.ResponseWriter, r *http.Request) error {
funname := c.GetQuery("func", r)
funname := r.URL.Path
funs := strings.Split(funname, ".")
if len(funs) < 2 {
return fmt.Errorf("func fmterr func=%v", funname)

View File

@ -8,6 +8,7 @@ import (
"ciyon/web/admin/autotask"
"ciyon/web/admin/datasse"
"ciyon/web/admin/demo"
"ciyon/web/admin/demo/dyn"
"ciyon/web/admin/rigger"
"ciyon/web/admin/wsdemo"
c "ciyon/zciyon"
@ -17,14 +18,11 @@ import (
本文件由node生成
*/
func setWebRoute_adm(web *c.CiyWebServer) {
web.RouterFunc("admin/rigger", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin/rigger", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"logfile": {
"init": rigger.Logfile_init,
"viewlog": rigger.Logfile_viewlog,
},
"datasse": {
"demo": datasse.DataSSE_demo,
},
"statsfunc": {
"init": rigger.Statsfunc_init,
"del": rigger.Statsfunc_del,
@ -134,7 +132,7 @@ func setWebRoute_adm(web *c.CiyWebServer) {
"update": rigger.Role_u_update,
},
})
web.RouterFunc("admin/ap", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin/ap", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"paper": {
"init": ap.Paper_init,
"update": ap.Paper_update,
@ -142,7 +140,7 @@ func setWebRoute_adm(web *c.CiyWebServer) {
"del": ap.Paper_del,
},
})
web.RouterFunc("admin/demo", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin/demo", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"normal": {
"list": demo.Normal_list,
"del": demo.Normal_del,
@ -154,17 +152,28 @@ func setWebRoute_adm(web *c.CiyWebServer) {
"importxls_data": demo.Normal_importxls_data,
},
})
web.RouterFunc("admin/autotask", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin/demo/dyn", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"sse": {
"get": dyn.SSE_get,
"post": dyn.SSE_get,
},
})
web.RouterFunc("/admin/autotask", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"task": {
"main": autotask.Task_main,
},
})
web.RouterFunc("admin/wsdemo", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin/datasse", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"index": {
"demo": datasse.Index_demo,
},
})
web.RouterFunc("/admin/wsdemo", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"go": {
"demo": wsdemo.Wsdemo, //需nginx转发upgrade为websocket协议
},
})
web.RouterFunc("admin", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
web.RouterFunc("/admin", map[string]map[string]func(http.ResponseWriter, *http.Request) bool{
"welcome": {
"init": admin.Welcome_init,
},

View File

@ -95,7 +95,7 @@ class cash_out_apply {
if ($row['cashstatus'] != 10)
continue;
if ($act == 2) { //退余额
\web\cweb_ap::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现审核拒绝');
\web\cwebcomon::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现审核拒绝');
}
$id = $row['id'];
$updata = array();

View File

@ -100,7 +100,7 @@ class cash_out_inv {
if ($row['cashstatus'] != 30)
continue;
if ($act == 2) { //退余额
\web\cweb_ap::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现发票拒绝');
\web\cwebcomon::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现发票拒绝');
}
$id = $row['id'];
$updata = array();

View File

@ -103,7 +103,7 @@ class cash_out_transfer {
$db->begin();
if ($auditstatus == 90) { //退余额
$updata = array();
\web\cweb_ap::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现支付拒绝');
\web\cwebcomon::usercashoe($db, 11, $row['vuser'], $row['cashmoney'], '提现支付拒绝');
}
$id = $row['id'];
$updata = array();

View File

@ -33,9 +33,10 @@ function verifyfast() {
function verifyuser() {
global $db;
global $_token;
$ciyauth = '';
if ($_token['type'] == 'cookie')
$ciyauth = $_COOKIE[$_token['field']];
else
$ciyauth = @$_COOKIE[$_token['field']];
if (!$ciyauth)
$ciyauth = @$_SERVER['HTTP_CIYAUTH'];
if (!$ciyauth)
$ciyauth = get('_ciyauth');
@ -84,6 +85,20 @@ function verifyuser() {
}
return $auth;
}
function verifysign($pubkey, $data, $pairsign) {
$signbin = hex2bin($pairsign);
if ($signbin === false)
return '签名格式错误';
$hashbin = hex2bin(hash('sha256', $data));
if (strpos($pubkey, '-----BEGIN RSA PUBLIC KEY-----') === false && strpos($pubkey, '-----BEGIN PUBLIC KEY-----') === false)
$pubkey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubkey, 64, "\n") . "\n-----END PUBLIC KEY-----";
$result = openssl_verify($hashbin, $signbin, $pubkey, OPENSSL_ALGO_SHA256);
if ($result === 0)
return '数字证书验签失败';
if ($result !== 1)
return '数字证书验签错误:' . openssl_error_string();
return true;
}
//true无权限false有权限
function nopower($db, $userid, $chkpower) {
$csql = new \ciy\sql('zc_admin');

View File

@ -7,7 +7,7 @@ import (
"time"
)
func DataSSE_demo(w http.ResponseWriter, r *http.Request) bool {
func Index_demo(w http.ResponseWriter, r *http.Request) bool {
if !c.SSEInit(w) {
w.Write([]byte("不支持SSE Flush"))
return false
@ -22,11 +22,11 @@ func DataSSE_demo(w http.ResponseWriter, r *http.Request) bool {
c.SSESend_event(w, "您未被授权操作")
return false
}
param := post.Get("param")
param := post.Get("bb")
c.SSESend_data(w, param)
for i := 0; i < 100; i++ {
if i%10 == 1 {
c.SSESend_data(w, "ssr: "+c.Tostr(i), i)
c.SSESend_data(w, "sse: "+c.Tostr(i), i)
}
if !c.SSESend_event(w, c.Tostr(i)) {
return true

View File

@ -14,7 +14,7 @@ class index {
$senddata('param: ' . $param);
for ($i = 0; $i < 100; $i++) {
if ($i % 10 == 1)
$senddata('ssr: ' . $i . "\n\n" . 'ddd', $i);
$senddata('ssr: ' . $i . "\n\n", $i);
$sendevent($i);
usleep(50000);
}

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8" src="/jscss/theme.js"></script>
<style>
.container>div {
padding: 1em;
background: var(--bg1);
margin-bottom: 1em;
border: 1px solid var(--bg5);
}
</style>
</head>
<body>
<div class="container">
<blockquote>获取token</blockquote>
<div>
APIID:
<input type="text" name="apiid" style="width:6em;" value="215698" />
APIKey:
<input type="text" name="apikey" style="width:16em;" value="1nab1AEZvbbOP05dBQfE" />
<button class='btn' onclick="gettoken()">获取token</button>
<input type="text" name="token" style="width:100%;" value="" />
</div>
<blockquote>业务调用</blockquote>
<div>
<br /><button class='btn' onclick="call1()">调用1</button>
<br /><textarea id="result1" style="width: 100%; height: 50vh;"></textarea>
</div>
</div>
<script type="text/javascript" src="/jscss/ciy.js"></script>
<script type="text/javascript">
'use strict';
async function gettoken() {
var postparam = {};
postparam.apiid = document.getElementsByName("apiid")[0].value;
postparam.apikey = document.getElementsByName("apikey")[0].value;
ciyfn.callfunc("gettoken", postparam, function (json) {
document.getElementsByName("token")[0].value = json.token;
});
}
async function call1() {
var postparam = {};
postparam.token = document.getElementsByName("token")[0].value;
ciyfn.callfunc("call1", postparam, function (json) {
document.getElementById("result1").value = JSON.stringify(json, null, 2);
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,42 @@
<?php
namespace web\admin\demo\dyn;
class callapi {
public static function json_gettoken() {
$post = new \ciy\post();
$apiid = $post->getint('apiid');
if (empty($apiid))
return errjson('请输入apiid');
$apikey = $post->get('apikey');
if (empty($apikey))
return errjson('请输入apikey');
$param = array();
$param['apiid'] = $apiid;
$param['apitime'] = time();
$param['sign'] = hash('sha256', $apiid . '&' . $param['apitime'] . '&' . $apikey);
$http = new \ciy\http();
$http->request('https://ciyon.local.ciy.cn/admin/login.gettoken', json_encode($param));
$datastr = $http->get_data();
$data = json_decode($datastr, true);
if ($data === null)
return errjson('API返回错误:' . $datastr);
return succjson($data);
}
public static function json_call1() {
$post = new \ciy\post();
$token = $post->get('token');
if (empty($token))
return errjson('请输入token');
$param = array();
$param['query'] = array('liid' => 10);
$http = new \ciy\http();
$http->set_header('CIYAUTH', $token);
$http->request('https://ciyon.local.ciy.cn/admin/rigger/admin.init', json_encode($param));
$datastr = $http->get_data();
$data = json_decode($datastr, true);
if ($data === null)
return errjson('API返回错误:' . $datastr);
return succjson($data);
}
}

View File

@ -41,6 +41,10 @@
<a class="btn sm" href="web3.html" target="_blank">web3</a>
web3登录、签名、验签
</div>
<div>
<a class="btn sm" href="callapi.html" target="_blank">callapi</a>
api接口调用示例。
</div>
<div>
<a class="btn sm" href="mail.html" target="_blank">mail</a>
Mail收发邮件。

View File

@ -11,6 +11,8 @@ class openai {
$csql = new \ciy\sql('zc_ai_key');
$csql->where('id', 1);
$aikeyrow = $db->getone($csql);
if(!is_array($aikeyrow))
return $senddata('AI密钥不存在');
$openai = new \ciy\openai($aikeyrow);
$openai->debug();
$retai = $openai->chat($messages, function($data) {

72
web/admin/demo/dyn/sse.go Normal file
View File

@ -0,0 +1,72 @@
package dyn
import (
"ciyon/web/admin"
c "ciyon/zciyon"
"net/http"
"time"
)
func SSE_get(w http.ResponseWriter, r *http.Request) bool {
if !c.SSEInit(w) {
w.Write([]byte("不支持SSE Flush"))
return false
}
post := c.NewCiyPost(w, r)
rsuser, err := admin.Verifyuser(r, c.CiyDB, post)
if err != nil {
c.SSESend_event(w, "请重新登录")
return false
}
if admin.Nopower(c.CiyDB, c.Toint(rsuser["id"]), "p610r") {
c.SSESend_event(w, "您未被授权操作")
return false
}
param := post.Get("bb")
c.SSESend_data(w, param)
for i := 0; i < 100; i++ {
if i%10 == 1 {
c.SSESend_data(w, "sse: "+c.Tostr(i), i)
}
if !c.SSESend_event(w, c.Tostr(i)) {
return true
}
c.Sleep(0.05)
}
c.SSESend_event(w, "ok")
return true
}
func SSE_get_ch(w http.ResponseWriter, r *http.Request) bool {
if !c.SSEInit(w) {
w.Write([]byte("不支持SSE Flush"))
return false
}
post := c.NewCiyPost(w, r)
rsuser, err := admin.Verifyuser(r, c.CiyDB, post)
if err != nil {
c.SSESend_event(w, "请重新登录")
return false
}
if admin.Nopower(c.CiyDB, c.Toint(rsuser["id"]), "p610r") {
c.SSESend_event(w, "您未被授权操作")
return false
}
param := post.Get("param")
c.SSESend_data(w, param)
done := r.Context().Done()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
return false
case <-ticker.C:
if !c.SSESend_data(w, time.Now().Format(time.RFC3339)) {
return true
}
}
}
}

View File

@ -9,6 +9,15 @@
<link href="/favicon.ico" rel="shortcut icon">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8" src="/jscss/theme.js"></script>
<script type="text/javascript" charset="utf-8">
//用户误访问/admin自动跳转到/admin/
var lastpath = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);
if (lastpath != '' && lastpath.indexOf('.') == -1) {
location.replace(location.pathname + '/');
document.write('');
document.close();
}
</script>
<style>
.ciy-menu-width {
width: 14em;

View File

@ -70,6 +70,62 @@ class login {
self::savelug($db, 1, $rsuser['id'], $model);
return self::getsync($rsuser, $oid, $sid);
}
public static function json_gettoken() {
global $db;
global $_token;
$post = new \ciy\post();
$apiid = $post->getint('apiid');
if ($apiid <= 0)
return errjson('appid不合法');
$sign = $post->get('sign');
if (empty($sign))
return errjson('无sign');
$apitime = $post->getint('apitime');
if (abs(time() - $apitime) > 600)
return errjson('timestamp与服务器相差超过10分钟服务器时间戳:' . time());
$csql = new \ciy\sql('zc_tokapi');
$csql->where('id', $apiid);
$apirow = $db->getone($csql);
if (!is_array($apirow))
return errjson('appid不存在');
if (empty($apirow['apisecret']))
return errjson('经检测您的api接入不符合要求已经暂停接入请调整代码后重置ApiKey');
$hash = hash('sha256', $apiid . '&' . $apitime . '&' . $apirow['apisecret']);
if ($sign != $hash)
return errjson('sign验证错误'.$apiid . '&' . $apitime . '&' . $apirow['apisecret']);
$ip = getip();
if (!empty($apirow['ips'])) {
$ips = explode("\n", $apirow['ips']);
if (!in_array($ip, $ips)) {
return errjson('ip不在白名单内');
}
}
$expsec = 86400;
$exp = tostamp() + $expsec;
$sid = randstr(10);
$updata = array();
$updata['user'] = $apirow['vuser'];
$updata['targettype'] = 9;
$updata['sid'] = $sid;
$updata['addtimes'] = tostamp();
$updata['exptimes'] = $exp;
$updata['ip'] = getip();
$csql = new \ciy\sql('zc_online');
if ($db->insert($csql, $updata) === false)
return errjson('online数据库更新失败:' . $db->error);
$oid = $db->insert_id();
$auth = array();
$auth['id'] = $apirow['vuser'];
$auth['_o'] = $oid;
$auth['_s'] = $sid;
$auth['_api'] = $apirow['id'];
$authstr = json_encode($auth, JSON_PARTIAL_OUTPUT_ON_ERROR);
$enauth = encrypt($authstr, 'E', $_token['salt']);
$ret['token'] = $enauth;
$ret['expsec'] = $expsec;
return succjson($ret);
}
public static function json_restorage() {
global $db;
$rsuser = verifyfast();

View File

@ -0,0 +1,228 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8" src="/jscss/theme.js"></script>
</head>
<body>
<div class="container">
<form class="search" onsubmit="table.search(this,'btn');return false;">
<ul></ul>
<div>
<div class="sinps"></div>
<div class="sbtns">
<a class="lang btn" onclick="addnew()">新建API通道</a>
<a class="lang btn def" href="/ud/api/api.pdf" target="_blank">API文档</a>
<a class="lang btn def" href="/ud/api/public.pem" onclick="">平台公钥下载</a>
部分API调用需要安装证书具体详见API文档。
</div>
</div>
</form>
<div class="table">
<div class="loading col-24">Loading...</div>
<div class="list"></div>
<div>
<div class="btmbtn">
<a class="lang btn def" onclick="ciyfn.select_all(table)">全选</a>
<a class="lang btn def" onclick="ciyfn.select_diff(table)">反选</a>
|
</div>
<div class="page"></div>
</div>
</div>
</div>
<div id="alert_edit" style="display:none;">
<div class="char4 row">
<div class="ciy-form col-24 col-sm-24 top">
<label class="lang">白名单IP</label>
<div>
<ciy-textarea com="ips" minheight="10em" />
</div>
</div>
</div>
</div>
<div id="alert_pubkey" style="display:none;">
<div class="char4 row">
<div class="ciy-form col-24 col-sm-24 top">
<label class="lang">公钥</label>
<div>
<ciy-textarea com="pubkey" minheight="10em" />
</div>
</div>
<div class="ciy-form col-24 col-sm-24">
<label class="lang">待签数据</label>
<div id="id_hash"></div>
</div>
<div class="ciy-form col-24 col-sm-24">
<label class="lang">签名</label>
<div>
<ciy-textarea com="sign" minheight="10em" />
</div>
</div>
<div class="ciy-form col-24 col-sm-24">
<div class="ciy-tip">
<div><kbd>签名算法</kbd>RSA  <kbd>填充方式</kbd>RSASSA-PKCS1-v1.5  <kbd>秘钥格式</kbd>PEM PKCS#8  <kbd>签名输出格式</kbd>HEX</div>
<div>生成私钥命令行 <code>openssl genpkey -algorithm RSA -out pri.pem -pkeyopt rsa_keygen_bits:2048</code></div>
<div>提取公钥命令行 <code>openssl rsa -in pri.pem -pubout -out pub.pem</code></div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/jscss/ciy.js"></script>
<script type="text/javascript" src="/jscss/ciycmp.js"></script>
<script type="text/javascript" src="/jscss/ciytable.js"></script>
<script type="text/javascript" src="../common.js"></script>
<script type="text/javascript">
'use strict';
var table;
var Glob = {};
ciyfn.pageload(function () {
//Glob.urlp = ciyfn.urlparam();
table = new ciyclass.table({
dom: '.table'
, url: 'list'
, pagecount: 10
, fn_beforedata: function (json) {
ciyfn.fillsearch({
searchdom: '.search'
, data: json
});
return json;
}
, fn_tdcontent: function (key, datashow, field, data) {
if (key == '_btn') {
var html = '';
if(data['pubkey'])
html += `<a class="lang btn def" onclick="menubtn(this, 'pubkey')">更换证书</a>`;
else
html += `<a class="lang btn" onclick="menubtn(this, 'pubkey')">安装证书</a>`;
html += `<a class="lang btn" onclick="menubtn(this, 'edit')">设置</a>`;
html += `<a class="lang btn warn" onclick="menubtn(this, 'rekey')">重置ApiKey</a>`;
html += `<a class="lang btn dag" onclick="menubtn(this, 'del')">删除</a>`;
return html;
}
if (key == 'pubkey') {
if(data['pubkey'])
return '已安装';
else
return '未安装';
}
if (key == 'msg') {
if(data['apisecret'] == '')
return '<a class="lang btn def" onclick="menubtn(this, \'qa\')">质量分析</a> 接入质量较低已经暂停API请重置ApiKey恢复';
else
return '正常';
}
}
, fn_done: function (json) {
// table.mergecol('auditstatus');
// table.mergefix('总计', 'center', 6, 0, 8, 1);
// table.footertotal();
}
});
table.callpage(1);
});
async function menubtn(dom, btn) {
var id = $5(dom).parent('tr').attr('data-id');
if (btn == 'pubkey') {
var oridata = 'CIY' + tostamp();
var hash = await ciyfn.sha256(oridata);
ciyfn.alert({
title: '安装证书'
, width: 'pc'
, content: document.getElementById("alert_pubkey").innerHTML
, fn_showed: function (doc, dom) {
var dat = table.data[id];
ciycmp({ dom: $5('[com=pubkey]', dom) });
ciycmp({ dom: $5('[com=sign]', dom) });
$5('#id_hash', dom).html(hash);
}
, cb: function (opn) {
if (opn.btn == "关闭")
return opn.close();
opn.inputs.id = id;
opn.inputs.oridata = oridata;
opn.inputs.hash = hash;
if (ciyfn.throttle(opn.dombtn)) return;
ciyfn.callfunc('pubkey', opn.inputs, function (json) {
table.updateline(json);
opn.close();
ciyfn.toast('设置成功');
});
},
btns: ["提交", "*关闭"],
});
}
if (btn == 'edit') {
ciyfn.alert({
title: '设置'
, width: 'mb'
, content: document.getElementById("alert_edit").innerHTML
//, noparent:true
, fn_showed: function (doc, dom) {
var dat = table.data[id];
ciycmp({ dom: $5('[com=ips]', dom), value: dat.ips });
}
, cb: function (opn) {
if (opn.btn == "关闭")
return opn.close();
opn.inputs.id = id;
if (ciyfn.throttle(opn.dombtn)) return;
ciyfn.callfunc('edit', opn.inputs, function (json) {
table.updateline(json);
opn.close();
ciyfn.toast('提交成功');
});
},
btns: ["提交", "*关闭"],
});
}
if (btn == 'rekey') {
ciyfn.alert({
content: '是否重置appkey<br/>重置后原appkey不可用'
, btns: ["重置", '*关闭']
, cb: function (opn) {
if (opn.btn == '关闭')
return opn.close();
ciyfn.callfunc("rekey", { id: id }, function (json) {
ciyfn.alert('appid: <kbd>' + id + '</kbd><br/>appkey: <kbd>' + json.secret + '</kbd><br/>请妥善保管!');
opn.close();
});
}
});
}
if (btn == 'del') {
ciyfn.callfastfunc(dom, '是否删除?', 'del', { ids: id }, function (json) { table.delline(json) });
}
}
function getdata(id, act, cb) {
cb({ data: id == 0 ? {} : table.data[id] });
}
function addnew() {
ciyfn.alert({
content: '确认新建一条API通道'
, btns: ["新建", '*关闭']
, cb: function (opn) {
if (opn.btn == '关闭')
return opn.close();
ciyfn.callfunc("addnew", {}, function (json) {
ciyfn.alert('appid: <kbd>' + json.data.id + '</kbd><br/>appkey: <kbd>' + json.data.apisecret + '</kbd><br/>请妥善保管!');
table.updateline(json);
opn.close();
});
}
});
}
function edit(id) {
} </script>
</body>
</html>

245
web/admin/rigger/tokapi.php Normal file
View File

@ -0,0 +1,245 @@
<?php
namespace web\admin\rigger;
class tokapi {
static function setwhere($db, $post, $rsuser) {
$query = $post->get('query');
$csql = new \ciy\sql('zc_tokapi');
$csql->where('vuser', $rsuser['id']);
$order = objstr($query, 'order', 'id desc');
$csql->order($order);
$query['order'] = $order;
return [$query, $csql];
}
public static function json_list() {
global $db;
$rsuser = verifyfast();
$post = new \ciy\post();
list($where, $csql) = self::setwhere($db, $post, $rsuser);
$pageno = $post->getint('pageno', 1);
$pagecount = $post->getint('pagecount', 10);
$csql->limit($pageno, $pagecount);
$mainrowcount = $post->getint('count');
$rows = $db->get($csql, $mainrowcount);
if ($rows === false)
return errjson($db->error);
$ret = array('where' => $where, 'pageno' => $pageno, 'pagecount' => $pagecount, 'count' => $mainrowcount, 'list' => $rows);
if ($post->getbool('field')) {
$field = array();
$fshow = $db->getfield($field, 'zc_tokapi');
foreach ($field as $fr => $v) {
if (get('_' . $fr))
$field[$fr]['c'] = ',' . $field[$fr]['c'];
if ($fr == 'merchantid')
$field[$fr]['c'] = ',' . $field[$fr]['c'];
}
$fshow = fieldadd($fshow, $field, 0, '_btn', '操作');
$fshow = fieldadd($fshow, $field, -1, 'msg', '|状况|');
$field['vuser']['c'] = '';
$ret['field'] = $field;
$ret['fshow'] = $fshow;
}
if ($post->getbool('once')) {
$ret['once'] = array();
$input = array();
$ret['once']['input'] = $input;
}
return succjson($ret);
}
public static function json_addnew() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p u'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
$csql = new \ciy\sql('zc_tokapi');
$csql->where('addtimes>', time() - 86400 * 7);
$csql->where('vuser', $rsuser['id']);
$csql->column('id');
$chkid = toint($db->get1($csql));
if ($chkid > 0)
return errjson('一周内只能建立一条API通道');
$secret = randstr(10) . randstr(10);
try {
$db->begin();
$updata = array();
$updata['vuser'] = $rsuser['id'];
$updata['apisecret'] = $secret;
$updata['ips'] = '';
$updata['addtimes'] = tostamp();
$updata['uptimes'] = 0;
$updata['pubkey'] = '';
$csql = new \ciy\sql('zc_tokapi');
if ($db->insert($csql, $updata) === false)
throw new \Exception('新增失败:' . $db->error);
$updata['id'] = $db->insert_id();
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['data'] = $updata;
return succjson($ret);
}
public static function json_rekey() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p u'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
$id = $post->getint('id');
$secret = randstr(10) . randstr(10);
try {
$db->begin();
$updata = array();
$updata['apisecret'] = $secret;
$csql = new \ciy\sql('zc_tokapi');
$csql->where('id', $id);
if ($db->update($csql, $updata) === false)
throw new \Exception('新增失败:' . $db->error);
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['secret'] = $secret;
return succjson($ret);
}
public static function json_edit() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p u'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
$id = $post->getint('id');
$ips = explode("\n", $post->get('ips'));
$iparr = array();
foreach ($ips as $ip) {
$ip = trim($ip);
if (empty($ip))
continue;
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
return errjson('IP格式错误:' . $ip);
$iparr[] = $ip;
}
try {
$db->begin();
$updata = array();
$updata['ips'] = implode("\n", $iparr);
$csql = new \ciy\sql('zc_tokapi');
$csql->where('id', $id);
if ($db->update($csql, $updata) === false)
throw new \Exception('更新失败:' . $db->error);
$updata['id'] = $id;
//savelogdb($db, $rsuser['id'], 'zc_tokapi', $datarow, $updata);
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['data'] = $updata;
return succjson($ret);
}
public static function json_pubkey() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p u'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
$pubkey = $post->get('pubkey');
$id = $post->getint('id');
$oridata = $post->get('oridata');
$hash = $post->get('hash');
$pubkey = $post->get('pubkey');
$publickey = $pubkey;
if (strpos($publickey, '-----BEGIN PUBLIC KEY-----') === false)
$publickey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publickey, 64, "\n") . "\n-----END PUBLIC KEY-----";
$pubkey = str_replace('-----BEGIN PUBLIC KEY-----', '', $pubkey);
$pubkey = str_replace('-----END PUBLIC KEY-----', '', $pubkey);
$pubkey = str_replace(["\r", "\n"], '', $pubkey);
$pubkey = trim($pubkey);
$csql = new \ciy\sql('aqf_merchantpubkey');
$csql->where('pubkey', $pubkey);
$chkrow = $db->getone($csql);
if (is_array($chkrow))
return errjson('该公钥已存在');
$sign = $post->get('sign');
$timestamp = toint(substr($oridata, 3));
if (abs(time() - $timestamp) > 300)
return errjson('请在5分钟内完成操作');
if (sha256($oridata) != $hash)
return errjson('hash数据校验失败');
$signbin = hex2bin($sign);
if ($signbin === false)
return errjson('签名格式错误');
$hashbin = hex2bin($hash);
if ($hashbin === false)
return errjson('hash格式错误');
$result = openssl_verify($hashbin, $signbin, $publickey, OPENSSL_ALGO_SHA256);
if ($result === 0)
return errjson('验签失败');
else if ($result !== 1)
return errjson('验签错误:' . openssl_error_string());
$hash = strtoupper($hash);
try {
$db->begin();
$updata = array();
$updata['pubkey'] = $pubkey;
$csql = new \ciy\sql('zc_tokapi');
$csql->where('id', $id);
if ($db->update($csql, $updata) === false)
throw new \Exception('更新失败:' . $db->error);
$updata['id'] = $id;
//savelogdb($db, $rsuser['id'], 'zc_tokapi', $datarow, $updata);
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['data'] = $updata;
$ret['aqf_merchantpubkey'] = getrelation($db, [$updata], 'aqf_merchantpubkey', 'pubkeyid');
return succjson($ret);
}
public static function json_del() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p d'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
$ids = $post->get('ids');
if (empty($ids))
return errjson('请选择至少一条');
$csql = new \ciy\sql('zc_tokapi');
$csql->where('vuser', $rsuser['id']);
$csql->where('id in', $ids);
$rows = $db->get($csql);
$vids = array();
try {
$db->begin();
foreach ($rows as $row) {
$delid = $row['id'];
//delall($db, $delid, 'tablexx', 'xxid', '运动员'); //deltimeall
delme($db, $delid, 'zc_tokapi');
$vids[] = $delid;
}
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['ids'] = $vids;
return succjson($ret);
}
}

View File

@ -0,0 +1,140 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<link href="/jscss/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8" src="/jscss/theme.js"></script>
</head>
<body>
<div class="container">
<form class="search" onsubmit="table.search(this,'btn');return false;">
<ul></ul>
<div>
<div class="sinps"></div>
<div class="sbtns">
<button class="lang btn" type="submit">查询</button>
<a class="lang btn" onclick="edit(0)">添加</a>
</div>
</div>
</form>
<div class="table">
<div class="loading col-24">Loading...</div>
<div class="list"></div>
<div>
<div class="btmbtn">
<a class="lang btn def" onclick="ciyfn.select_all(table)">全选</a>
<a class="lang btn def" onclick="ciyfn.select_diff(table)">反选</a>
|
<a class="lang btn dag" onclick="ciyfn.select_callfunc(table, this, 'del','已选{n}条,是否批量删除?', {},function(json){table.delline(json)})">批量删除</a>
</div>
<div class="page"></div>
</div>
</div>
</div>
<div id="alert_edit" style="display:none;">
<div class="char6 row">
<div class="ciy-form col-24 col-sm-24">
<label class="lang imp">三方平台名称</label>
<div>
<input type="text" name="name" style="width:100%;" />
</div>
</div>
<div class="ciy-form col-24 col-sm-24">
<label class="lang">ConfigData</label>
<div>
<ciy-textarea com="cfgtoken" minheight="15em" />
</div>
</div>
<div class="ciy-form col-24 col-sm-24">
<label class="lang">快捷备注</label>
<div>
<input type="text" name="memo" style="width:100%;" />
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/jscss/ciy.js"></script>
<script type="text/javascript" src="/jscss/ciycmp.js"></script>
<script type="text/javascript" src="/jscss/ciytable.js"></script>
<script type="text/javascript" src="../common.js"></script>
<script type="text/javascript">
'use strict';
var table;
var Glob = {};
ciyfn.pageload(function () {
//Glob.urlp = ciyfn.urlparam();
table = new ciyclass.table({
dom: '.table'
, url: 'list'
, pagecount: 10
, chkbox: true
, fn_beforedata: function (json) {
ciyfn.fillsearch({
searchdom: '.search'
, data: json
});
return json;
}
, fn_tdcontent: function (key, datashow, field, data) {
if (key == '_btn') {
var html = '';
html += `<a class="lang btn" onclick="menubtn(this, 'edit')" onmousedown="event.stopPropagation()">修改</a>`;
return html;
}
}
, fn_done: function (json) {
// table.mergecol('auditstatus');
// table.mergefix('总计', 'center', 6, 0, 8, 1);
// table.footertotal();
}
});
table.callpage(1);
});
function menubtn(dom, btn) {
var id = $5(dom).parent('tr').attr('data-id');
if (btn == 'edit') {
edit(id);
}
}
function getdata(id, act, cb) {
cb({ data: id == 0 ? {} : table.data[id] });
}
function edit(id) {
getdata(id, 'edit', function (jsndat) {
ciyfn.alert({
title: id == 0 ? '新建' : '修改'
, width: 'pc'
, content: document.getElementById("alert_edit").innerHTML
//, noparent:true
, fn_showed: function (doc, dom) {
var dat = jsndat.data;
$5('[name=name]', dom).val(dat.name);
ciycmp({ dom: $5('[com=cfgtoken]', dom), value: dat.cfgtoken });
$5('[name=memo]', dom).val(dat.memo);
}
, cb: function (opn) {
if (opn.btn == "关闭")
return opn.close();
opn.inputs.id = id;
if (ciyfn.throttle(opn.dombtn)) return;
ciyfn.callfunc('update', opn.inputs, function (json) {
table.updateline(json);
opn.close();
ciyfn.toast('提交成功');
});
},
btns: id == 0 ? ["新建", "*关闭"] : ["提交", "*关闭"],
});
});
}
</script>
</body>
</html>

136
web/admin/rigger/tokthd.php Normal file
View File

@ -0,0 +1,136 @@
<?php
namespace web\admin\rigger;
class tokthd {
static function setwhere($db, $post, $rsuser) {
$query = $post->get('query', array());
$csql = new \ciy\sql('zc_tokthd');
$csql->where('name like', objstr($query, 'name'));
$csql->wheredaterange('exptimes', objstr($query, 'exptimes'));
$csql->where('memo like', objstr($query, 'memo'));
$order = objstr($query, 'order', 'id desc');
$csql->order($order);
$query['order'] = $order;
return [$query, $csql];
}
public static function json_list() {
global $db;
$rsuser = verifyfast();
$post = new \ciy\post();
list($where, $csql) = self::setwhere($db, $post, $rsuser);
$pageno = $post->getint('pageno', 1);
$pagecount = $post->getint('pagecount', 10);
$csql->limit($pageno, $pagecount);
$mainrowcount = $post->getint('count');
$mrows = $db->get($csql, $mainrowcount);
if ($mrows === false)
return errjson($db->error);
$ret = array('searchwhere' => $where, 'pageno' => $pageno, 'pagecount' => $pagecount, 'count' => $mainrowcount, 'list' => $mrows);
if ($post->getbool('field')) {
$field = array();
$fshow = $db->getfield($field, 'zc_tokthd');
foreach ($field as $fr => $v) {
if (get('_' . $fr))
$field[$fr]['c'] = ',' . $field[$fr]['c'];
}
$fshow = fieldadd($fshow, $field, 0, '_btn', '操作');
$ret['field'] = $field;
$ret['fshow'] = $fshow;
}
if ($post->getbool('once')) {
$ret['once'] = true;
$input = array();
$input[] = array('type' => 'input', 'form' => 'name', 'name' => '三方平台名称', 'prop' => ' style="width:8em;"');
$input[] = array('type' => 'daterange', 'form' => 'exptimes', 'name' => '过期时间');
$input[] = array('type' => 'input', 'form' => 'memo', 'name' => '快捷备注', 'prop' => ' style="width:8em;"');
$ret['searchinput'] = $input;
}
return succjson($ret);
}
public static function json_update() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p u'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
//$db->trace($post->get('_pf'), $rsuser);
$id = $post->getint('id');
$name = $post->get('name');
$cfgtoken = $post->get('cfgtoken');
$memo = $post->get('memo');
if (empty($name))
return errjson('请填写三方平台名称');
$datarow = null;
if ($id > 0) {
$csql = new \ciy\sql('zc_tokthd');
$csql->where('id', $id);
$datarow = $db->getone($csql);
if (!is_array($datarow))
return errjson('数据不存在');
}
try {
$db->begin();
$updata = array();
$updata['name'] = $name;
$updata['cfgtoken'] = $cfgtoken;
$updata['memo'] = $memo;
$csql = new \ciy\sql('zc_tokthd'); //auto
if ($id > 0) {
$csql->where('id', $id);
if ($db->update($csql, $updata) === false)
throw new \Exception('更新失败:' . $db->error);
} else {
$updata['accesstoken'] = '';
$updata['exptimes'] = 0;
if ($db->insert($csql, $updata) === false)
throw new \Exception('新增失败:' . $db->error);
$id = $db->insert_id();
}
$updata['id'] = $id;
//savelogdb($db, $rsuser['id'], 'zc_tokthd', $datarow, $updata);
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['data'] = $updata;
return succjson($ret);
}
public static function json_del() {
global $db;
$rsuser = verifyfast();
//if (nopower($db, $rsuser['id'], 'p d'))
// return errjson('您未被授权操作');
$post = new \ciy\post();
//$db->trace($post->get('_pf'), $rsuser);
$ids = $post->get('ids');
if (empty($ids))
return errjson('请选择至少一条');
$csql = new \ciy\sql('zc_tokthd');
$csql->where('id in', $ids);
$mrows = $db->get($csql);
$vids = array();
try {
$db->begin();
foreach ($mrows as $mrow) {
$delid = $mrow['id'];
//delcheck($db, $delid, 'tablexx', 'xxid', '管理员');
//delall($db, $delid, 'tablexx', 'xxid', '运动员'); //deltimeall
delme($db, $delid, 'zc_tokthd');
savelogdb($db, $rsuser['id'], 'zc_tokthd', $mrow, null);
$vids[] = $delid;
}
$db->commit();
} catch (\Exception $ex) {
$db->rollback();
savelogfile('err_db', $ex->getMessage());
return errjson($ex->getMessage());
}
$ret['ids'] = $vids;
return succjson($ret);
}
}

View File

@ -69,7 +69,7 @@
<body>
<div class="col-24 stl">
<h1 class="lang cursor-p" onclick="window.open('https://ciy.cn/')">众产 <sup>®</sup></h1>
<h1 class="lang">众产 <sup>®</sup></h1>
<div class="cline"></div>
<div class="mt"><span class="lang">您好</span><span id="id_name" style="font-size:1.3em;" class="lang"></span></div>
<div class="m1"><span class="lang">登录账号</span> <span id="id_loginuser"></span></div>

View File

@ -8,19 +8,19 @@ class welcome {
$rsuser = verifyfast();
$works = array();
$csql = new \ciy\sql('hf_adminrisk');
$csql->where("bread=2");
$cnt = toint($db->get1($csql));
if ($cnt > 0)
$works[] = array('title' => '风险待处置 ' . $cnt . '条', 'url' => 'hf/adminrisk.html?liid=1', 'tab' => '风险处置');
// $csql = new \ciy\sql('zc_risk');
// $csql->where("bread=2");
// $cnt = toint($db->get1($csql));
// if ($cnt > 0)
// $works[] = array('title' => '风险待处置 ' . $cnt . '条', 'url' => 'risk.html?liid=1', 'tab' => '风险处置');
$takarr = getstrparam(file_get_contents(PATH_ROOT . 'log/fork_apinotify.tak'), ',');
if ($takarr['curr'] > $takarr['max'] / 2)
$works[] = array('title' => 'apinotify任务排队过长。' . $takarr['curr'] . '/max' . $takarr['max'] . '' . (time() - $takarr['time']) . '秒前');
// $takarr = getstrparam(file_get_contents(PATH_ROOT . 'log/fork_apinotify.tak'), ',');
// if ($takarr['curr'] > $takarr['max'] / 2)
// $works[] = array('title' => 'apinotify任务排队过长。' . $takarr['curr'] . '/max' . $takarr['max'] . '' . (time() - $takarr['time']) . '秒前');
$errlog = file_get_contents(PATH_ROOT . 'log/err_db.log');
if (!empty($errlog))
$works[] = array('title' => '发现异常db数据 ' . count(explode("\n", $errlog)) . ' 条');
$works[] = array('title' => '发现异常db数据 ' . count(explode("\n", $errlog)) . ' 条', 'url' => 'rigger/logfile.html?file=err_db');
$ret['works'] = $works;

View File

@ -19,7 +19,7 @@
<div class="ciy-form col-24 col-md-8">
<label>ws addr</label>
<div>
<input name="ws" style="width:100%;" type="text" value="/ws/?func=admin/wsdemo/go.demo" />
<input name="ws" style="width:100%;" type="text" value="/ws/?func=/admin/wsdemo/go.demo" />
</div>
<div style="flex: none;">
<a class="lang btn" onclick="connect()">connect</a>

View File

@ -132,8 +132,8 @@ function savelog($db, $userid, $types, $msg, $isrequest = false, $time = 0) {
function savelogdb($db, $userid, $types, $oldrow, $newrow) {
savelog($db, $userid, $types, logdbstr($oldrow, $newrow), false);
}
function gettoken($db, $id) {
$csql = new \ciy\sql('zc_token');
function gettokthd($db, $id) {
$csql = new \ciy\sql('zc_tokthd');
$csql->where('id', $id);
$tokenrow = $db->getone($csql);
if (!is_array($tokenrow))
@ -144,8 +144,8 @@ function gettoken($db, $id) {
$cfg['exptimes'] = $tokenrow['exptimes'];
return $cfg;
}
function settoken($db, $id, $access) {
$csql = new \ciy\sql('zc_token');
function settokthd($db, $id, $access) {
$csql = new \ciy\sql('zc_tokthd');
$csql->where('id', $id);
if ($db->update($csql, $access) === false)
return '操作数据库失败:' . $db->error;

View File

@ -198,7 +198,7 @@ class me {
}
try {
$db->begin();
\web\cweb_ap::usercashoe($db, 11, $rsuser['id'], -$cash, '提现');
\web\cwebcomon::usercashoe($db, 11, $rsuser['id'], -$cash, '提现');
$updata = array();
$updata['cashstatus'] = 10;
$updata['cashmoney'] = $cash;

View File

@ -16,7 +16,7 @@ class wxpay {
return self::errlog('回调JSON出错:' . $msg);
if (@$json['event_type'] != 'TRANSACTION.SUCCESS')
return self::errlog('支付失败:' . $msg);
$wxcfg = gettoken($db, 1);
$wxcfg = gettokthd($db, 1);
$aesKey = $wxcfg['v3key']; //v3秘钥
$associatedData = $json['resource']['associated_data'];
$nonceStr = $json['resource']['nonce'];
@ -94,7 +94,7 @@ class wxpay {
return self::errlog('回调JSON出错:' . $msg);
if (@$json['event_type'] != 'MCHTRANSFER.BILL.FINISHED')
return self::errlog('付款失败:' . $msg);
$wxcfg = gettoken($db, 1);
$wxcfg = gettokthd($db, 1);
$aesKey = $wxcfg['v3key']; //v3秘钥
$associatedData = $json['resource']['associated_data'];
$nonceStr = $json['resource']['nonce'];
@ -158,7 +158,7 @@ class wxpay {
return self::errlog('回调JSON出错:' . $msg);
if (@$json['event_type'] != 'TRANSACTION.SUCCESS')
return self::errlog('支付失败:' . $msg);
$wxcfg = gettoken($db, 1);
$wxcfg = gettokthd($db, 1);
$aesKey = $wxcfg['v3key']; //v3秘钥
$associatedData = $json['resource']['associated_data'];
$nonceStr = $json['resource']['nonce'];
@ -229,7 +229,7 @@ class wxpay {
return self::errlog('回调JSON出错:' . $msg);
if (@$json['event_type'] != 'TRANSACTION.SUCCESS')
return self::errlog('支付失败:' . $msg);
$wxcfg = gettoken($db, 1);
$wxcfg = gettokthd($db, 1);
$aesKey = $wxcfg['v3key']; //v3秘钥
$associatedData = $json['resource']['associated_data'];
$nonceStr = $json['resource']['nonce'];
@ -290,7 +290,7 @@ class wxpay {
$bonus[] = array('percent' => 0.01, 'name' => '推荐奖金');
$bonus[] = array('percent' => 0.02, 'name' => '带新奖金');
$bonus[] = array('percent' => 0.03, 'name' => '领导奖金');
\web\cweb_ap::mlmbonus($db, $money, $userrow, $bonus);
\web\cwebcomon::mlmbonus($db, $money, $userrow, $bonus);
$db->commit();
} catch (\Exception $ex) {
$db->rollback();

View File

@ -9,7 +9,7 @@ class weixin {
function __construct($tokenid) {
global $db;
$this->token = null;
$ret = gettoken($db, $tokenid);
$ret = gettokthd($db, $tokenid);
if (is_string($ret))
return $this->err($ret);
$this->tokenid = $tokenid;
@ -150,7 +150,7 @@ class weixin {
$updata = array();
$updata['accesstoken'] = $accesstoken;
$updata['exptimes'] = $exptimes;
$ret = settoken($db, $this->tokenid, $updata);
$ret = settokthd($db, $this->tokenid, $updata);
if (is_string($ret))
return $this->err($ret);
return array('accesstoken' => $accesstoken);

View File

@ -1,81 +0,0 @@
<?php
namespace web;
class cweb_ap {
static function mlmbonus($db, $money, $userrow, $bonusset) {
if ($userrow['upid'] <= 0)
return;
if (!isset($bonusset[0]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userrow['upid']);
$uprow = $db->getone($csql);
if (!is_array($uprow))
return;
\web\cweb_ap::usercashoe($db, 20, $uprow['id'], $money * $bonusset[0]['percent'], $bonusset[0]['name']);
if ($uprow['upid'] <= 0)
return;
if (!isset($bonusset[1]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $uprow['upid']);
$up2row = $db->getone($csql);
if (!is_array($up2row))
return;
\web\cweb_ap::usercashoe($db, 21, $up2row['id'], $money * $bonusset[1]['percent'], $bonusset[1]['name']);
if ($up2row['upid'] <= 0)
return;
if (!isset($bonusset[2]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $up2row['upid']);
$up3row = $db->getone($csql);
if (!is_array($up3row))
return;
\web\cweb_ap::usercashoe($db, 22, $up3row['id'], $money * $bonusset[2]['percent'], $bonusset[2]['name']);
//最高三级代理
}
static function usercashie($db, $type, $userid, $money, $name = '') {
$updata = array();
if ($money > 0)
$updata['mymoney'] = array('mymoney+' . $money);
else
$updata['mymoney'] = array('mymoney' . $money);
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userid);
if ($db->update($csql, $updata) === false)
throw new \Exception('账户余额更新失败:' . $db->error);
//直接打款
$updata = array();
$updata['cashtype'] = $type;
$updata['iemoney'] = $money;
$updata['vuser'] = $userid;
$updata['name'] = $name;
$updata['addtimes'] = tostamp();
$csql = new \ciy\sql('ap_cash_ie');
if ($db->insert($csql, $updata) === false)
throw new \Exception('新建消费收支失败:' . $db->error);
}
static function usercashoe($db, $type, $userid, $money, $name = '') {
$updata = array();
if ($money > 0)
$updata['mycashmoney'] = array('mycashmoney+' . $money);
else
$updata['mycashmoney'] = array('mycashmoney' . $money);
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userid);
if ($db->update($csql, $updata) === false)
throw new \Exception('账户余额更新失败:' . $db->error);
//直接打款
$updata = array();
$updata['cashtype'] = $type;
$updata['oemoney'] = $money;
$updata['vuser'] = $userid;
$updata['name'] = $name;
$updata['addtimes'] = tostamp();
$csql = new \ciy\sql('ap_cash_oe');
if ($db->insert($csql, $updata) === false)
throw new \Exception('新建佣金收支失败:' . $db->error);
}
}

174
web/cwebcomon.php Normal file
View File

@ -0,0 +1,174 @@
<?php
namespace web;
class cwebcomon {
static function mlmbonus($db, $money, $userrow, $bonusset) {
if ($userrow['upid'] <= 0)
return;
if (!isset($bonusset[0]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userrow['upid']);
$uprow = $db->getone($csql);
if (!is_array($uprow))
return;
self::usercashoe($db, 20, $uprow['id'], $money * $bonusset[0]['percent'], $bonusset[0]['name']);
if ($uprow['upid'] <= 0)
return;
if (!isset($bonusset[1]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $uprow['upid']);
$up2row = $db->getone($csql);
if (!is_array($up2row))
return;
self::usercashoe($db, 21, $up2row['id'], $money * $bonusset[1]['percent'], $bonusset[1]['name']);
if ($up2row['upid'] <= 0)
return;
if (!isset($bonusset[2]))
return;
$csql = new \ciy\sql('ap_user');
$csql->where('id', $up2row['upid']);
$up3row = $db->getone($csql);
if (!is_array($up3row))
return;
self::usercashoe($db, 22, $up3row['id'], $money * $bonusset[2]['percent'], $bonusset[2]['name']);
//最高三级代理
}
static function usercashie($db, $type, $userid, $money, $name = '') {
$updata = array();
if ($money > 0)
$updata['mymoney'] = array('mymoney+' . $money);
else
$updata['mymoney'] = array('mymoney' . $money);
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userid);
if ($db->update($csql, $updata) === false)
throw new \Exception('账户余额更新失败:' . $db->error);
//直接打款
$updata = array();
$updata['cashtype'] = $type;
$updata['iemoney'] = $money;
$updata['vuser'] = $userid;
$updata['name'] = $name;
$updata['addtimes'] = tostamp();
$csql = new \ciy\sql('ap_cash_ie');
if ($db->insert($csql, $updata) === false)
throw new \Exception('新建消费收支失败:' . $db->error);
}
static function usercashoe($db, $type, $userid, $money, $name = '') {
$updata = array();
if ($money > 0)
$updata['mycashmoney'] = array('mycashmoney+' . $money);
else
$updata['mycashmoney'] = array('mycashmoney' . $money);
$csql = new \ciy\sql('ap_user');
$csql->where('id', $userid);
if ($db->update($csql, $updata) === false)
throw new \Exception('账户余额更新失败:' . $db->error);
//直接打款
$updata = array();
$updata['cashtype'] = $type;
$updata['oemoney'] = $money;
$updata['vuser'] = $userid;
$updata['name'] = $name;
$updata['addtimes'] = tostamp();
$csql = new \ciy\sql('ap_cash_oe');
if ($db->insert($csql, $updata) === false)
throw new \Exception('新建佣金收支失败:' . $db->error);
}
static function www_showpage($count, $pageno, $pagecount, $pageurl, $pagecb) {
if ($count <= 0) {
// 1...3,4,5,6,7,8
$isend = (-$count < $pagecount);
//if($pageno < 20) $isend = false;
$epage = $pageno + 2;
$spage = $pageno - 6;
if ($isend)
$epage = $pageno;
if ($spage < 1)
$spage = 1;
echo '<a ' . ($pageno <= 1 ? ' class="disabled"' : " href=\"" . $pageurl . $pagecb($pageno - 1) . "\"") . '>上页</a>';
if ($spage > 1)
echo '<a href="' . $pageurl . $pagecb(1) . '">1</a>';
if ($spage > 2)
echo '<span>...</span>';
for ($i = $spage; $i <= $epage; $i++)
echo '<a ' . ($i == $pageno ? ' class="active"' : " href=\"" . $pageurl . $pagecb($i) . "\"") . '>' . $i . '</a>';
echo '<a ' . ($isend ? ' class="disabled"' : " href=\"" . $pageurl . $pagecb($pageno + 1) . "\"") . '>下页</a>';
} else {
//1...3,4,5,6,7...n
$epage = $pageno + 6;
$spage = $pageno - 2;
$pagemax = ceil($count / $pagecount);
if ($spage < 1)
$spage = 1;
if ($epage > $pagemax)
$epage = $pagemax;
echo '<a ' . ($pageno <= 1 ? ' class="disabled"' : " href=\"" . $pageurl . $pagecb($pageno - 1) . "\"") . '>上页</a>';
if ($spage > 1)
echo '<a href="' . $pageurl . $pagecb(1) . '">1</a>';
if ($spage > 2)
echo '<span>...</span>';
for ($i = $spage; $i <= $epage; $i++)
echo '<a ' . ($i == $pageno ? ' class="active"' : " href=\"" . $pageurl . $pagecb($i) . "\"") . '>' . $i . '</a>';
if ($epage < $pagemax - 1)
echo '<span>...</span>';
if ($epage < $pagemax)
echo '<a href="' . $pageurl . $pagecb($pagemax) . '">' . $pagemax . '</a>';
echo '<a ' . ($pageno >= $pagemax ? ' class="disabled"' : " href=\"" . $pageurl . $pagecb($pageno + 1) . "\"") . '>下页</a>';
}
}
static function www_convertseoword($seowords, $content, $keystr = '') {
$seo = array();
$max = rand(2, 5);
shuffle($seowords);
foreach ($seowords as $row) {
if ($row['rank'] > rand(0, 100))
$seo[$row['name']] = $row['url'];
}
$repcnt = 0;
foreach ($seo as $key => $val) {
$ind = strpos($content, $key);
if ($ind === false)
continue;
$tmp = substr($content, 0, $ind);
$inda = strrpos($tmp, '<a ciy href=');
if ($inda !== false) {
$indb = strpos($tmp, '</a>', $inda);
if ($indb === false) //包含
continue;
}
$content = substr_replace($content, '<a ciy href="' . $val . '">' . $key . '</a>', $ind, strlen($key));
$repcnt++;
if ($repcnt >= $max)
break;
}
if (!empty($keystr)) {
$keystr = str_replace('', ',', $keystr);
$keystr = str_replace(';', ',', $keystr);
$keystr = str_replace('', ',', $keystr);
$keys = explode(',', $keystr);
foreach ($keys as $key) {
if (empty($key))
continue;
$ind = strpos($content, $key);
if ($ind === false)
continue;
$tmp = substr($content, 0, $ind);
$inda = strrpos($tmp, '<strong>');
if ($inda !== false) {
$indb = strpos($tmp, '</strong>', $inda);
if ($indb === false) //包含
continue;
}
$content = substr_replace($content, '<strong>' . $key . '</strong>', $ind, strlen($key));
}
}
return $content;
}
}

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<title>Ciyon(希央) - 众产全栈开发框架</title>
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
@ -102,8 +102,9 @@
Ciyon - 众产全栈开发框架
</div>
<div style="flex:1;text-align: right;padding:0.3em;">
<a class="btn" href="/indexweb" target="_blank">网站结构</a>
<a class="btn" href="/docs/" target="_blank">开发文档</a>
<a class="btn" href="/admin/" target="_blank">在线演示</a>
<a class="btn" href="/admin/" target="_blank">后台演示</a>
</div>
</div>
<nav>
@ -361,8 +362,8 @@
<div onclick="close_install()" style="position: absolute;top:0.5em;right:0.5em;font-size:1.5em;cursor:pointer;color:#000000;line-height: 1em;">×</div>
<div>nginx配置成功且加载正常</div>
<div>显示日期时间则PHP运行正常</div>
<div><iframe src="install.php?act=time" style="width:100%;border:none;"></iframe></div>
<div><iframe src="install.php?act=db" style="width:100%;height:100%;border:none;"></iframe></div>
<div><iframe src="install?act=time" style="width:100%;border:none;"></iframe></div>
<div><iframe src="install?act=db" style="width:100%;height:100%;border:none;"></iframe></div>
<div style="text-align:right;">
<label><input type="checkbox" name="non"/>不再显示</label>
</div>

25
web/indexweb.php Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$current_page = '/indexweb';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/indexweb.php</div>
<?php include_once("www/_footer.php");?>
</body>
</html>

View File

@ -11,8 +11,6 @@
if ($act == 'time')
echo date('Y-m-d H:i:s') . '  v' . phpversion();
if ($act == 'db') {
require '../zciyphp/comm.php';
$db = new \ciy\db();
$ret = $db->connect();
if (!$ret->isconnected)
die($ret->error);

View File

@ -1045,13 +1045,9 @@ ciyfn.callfunc = function (funcname, post, successfunc, opn) { //opn showload,m
window.ciy_vars = {};
if (ciy_vars.tokenfield)
opn.header['ciyauth'] = ciyfn.getstorage('_' + ciy_vars.tokenfield);
if (document.location.search)
funcname += '&' + document.location.search.substring(1);
if (opn.showload === undefined)
opn.showload = true;
if (funcname.indexOf('?') > -1 || funcname.indexOf('://') > -1)
opn.url = funcname;
else if (opn.method == 'get') {
if (opn.method == 'get' || funcname.indexOf('?') > -1 || funcname.indexOf('://') > -1) {
opn.url = funcname;
} else {
var ind = document.location.pathname.lastIndexOf('/');
@ -1065,7 +1061,7 @@ ciyfn.callfunc = function (funcname, post, successfunc, opn) { //opn showload,m
} else if (funcname.indexOf('/') == -1) {
funcname = path + funcname;
}
opn.url = "/z/?func=" + funcname;
opn.url = '/' + funcname;
}
opn.data = post || {};
@ -1145,6 +1141,12 @@ ciyfn.ajax = function (opn) { //IE8 OK
else
url += datastr;
}
if (document.location.search) {
if (url.indexOf('?') > -1)
url += '&' + document.location.search.substring(1);
else
url += document.location.search;
}
var request = new XMLHttpRequest();
request.withCredentials = true;
request.open(method, url, true);
@ -2436,11 +2438,14 @@ ciyclass.sse = function (opn) {
} else if (opn.url.indexOf('/') == -1) {
opn.url = path + opn.url;
}
opn.url = "/z/?sse=" + opn.url;
opn.url = "/" + opn.url;
}
if (isobj(opn.param)) {
for (var i in opn.param) {
opn.url += '&' + i + '=' + opn.param[i];
if (opn.url.indexOf('?') == -1)
opn.url += '?' + i + '=' + opn.param[i];
else
opn.url += '&' + i + '=' + opn.param[i];
}
}
var method = 'GET';
@ -2449,7 +2454,7 @@ ciyclass.sse = function (opn) {
opn.header = opn.header || {};
if (!ciy_vars)
console.log('nofind ciy_vars');
opn.header[ciy_vars.tokenfield] = ciyfn.getstorage('_' + ciy_vars.tokenfield);
opn.header['ciyauth'] = ciyfn.getstorage('_' + ciy_vars.tokenfield);
this.close = () => {
this.isaborted = true;

View File

@ -1 +0,0 @@
<?php

149
web/route.php Normal file
View File

@ -0,0 +1,149 @@
<?php
require '../zciyphp/comm.php'; //需要全局函数
function matchroute($str, $webpoint) {
$pathsplits = explode('/', $str);
$pathsplits = array_values(array_filter($pathsplits, 'strlen'));
$pathcount = count($pathsplits);
foreach ($webpoint as $key => $value) {
$keysplits = explode('/', $key);
$n = count($keysplits);
if ($n != $pathcount)
continue;
$macth = true;
for ($i = 0; $i < $n; $i++) {
if ($keysplits[$i][0] === '{') {
$_GET[substr($keysplits[$i], 1, -1)] = $pathsplits[$i];
} else if ($keysplits[$i] != $pathsplits[$i]) {
$macth = false;
break;
}
}
if (!$macth)
continue;
$idx = strpos($value, '?');
if ($idx !== false) {
$params = substr($value, $idx + 1);
$value = substr($value, 0, $idx);
parse_str($params, $paramsarr);
foreach ($paramsarr as $k => $v) {
$_GET[$k] = $v;
}
}
return $value;
}
return $str;
}
if (!isset($_SERVER['REQUEST_URI']))
die('nginx配置错误REQUEST_URI未设置');
$qstr = $_SERVER['REQUEST_URI']; // 例: admin/rig/user.list
$qstrarr = explode('.', $qstr);
$ms = timems();
if (count($qstrarr) < 2) {
if (!file_exists(PATH_ROOT . 'webpoint.php'))
die('无/webpoint.php文件');
$phpfile = $qstrarr[0];
$idx = strpos($phpfile, '?');
if ($idx !== false)
$phpfile = substr($phpfile, 0, $idx);
$phpfile = trim($phpfile, '/');
if (strtolower(substr($phpfile, 0, 3)) === 'www')
die('预留www开头目录不能使用');
$_webpoint_config = require PATH_ROOT . 'webpoint.php';
$phpfile = matchroute($phpfile, $_webpoint_config);
$phprequi = PATH_WEB . $phpfile . '.php';
if (!file_exists($phprequi)) {
$phprequi = PATH_WEB . $phpfile . '/index.php';
if (!file_exists($phprequi))
die('/web/' . $phpfile . '.php' . '文件不存在!');
}
if (strpos($phprequi, '..') !== false)
die('路径错误!');
$db = new ciy\db(); //默认数据库全局变量
require $phprequi;
die;
}
$qs0 = $qstrarr[0];
$qstrarr[0] = str_replace('\\\\', '\\', 'web\\' . str_replace('/', '\\', $qstrarr[0]));
if (!class_exists($qstrarr[0])){
$retarr = array('code' => 9, 'errmsg' => $qstrarr[0] . '无效类');
ciy_ouputJSON($retarr, timems() - $ms, $_SERVER['REQUEST_URI']);
}
$idx = strpos($qstrarr[1], '?');
if ($idx !== false)
$qstrarr[1] = substr($qstrarr[1], 0, $idx);
$db = new ciy\db(); //默认数据库全局变量
if (method_exists($qstrarr[0], 'json_' . $qstrarr[1])) {
$qs0 = substr($qs0, 0, strpos($qs0, '/', 1));
if (file_exists(PATH_WEB . $qs0 . '/common.php'))
require PATH_WEB . $qs0 . '/common.php'; //需要全局业务函数和全局变量
// $dbrd1 = new ciy\db('rd1');//读库 可实现注册中心取一个空闲实例 业务端判断
// $dbag = new ciy\db('ag');//独立ag库
// web\admin\autotask\task::json_run
$retarr = call_user_func($qstrarr[0] . '::json_' . $qstrarr[1]);
if (!is_array($retarr))
die('{"errmsg":"无succ返回值"}');
if ($retarr['code'] == 302) {
header('Location: ' . $retarr['redirect']);
die;
}
ciy_ouputJSON($retarr, timems() - $ms, $_SERVER['REQUEST_URI']);
} else if (method_exists($qstrarr[0], 'sse_' . $qstrarr[1])) {
//https://html.spec.whatwg.org/multipage/server-sent-events.html
$qs0 = substr($qs0, 1, strpos($qs0, '/', 1));
if (file_exists(PATH_WEB . $qs0 . '/common.php'))
require PATH_WEB . $qs0 . '/common.php'; //需要全局业务函数和全局变量
if (get('debug') == 'yes') {
call_user_func($qstrarr[0] . '::sse_' . $qstrarr[1], function ($data, $type = '') {
if ($type === true)
return;
//$data = '<code style="color:#199d01;">' . $data . '</code>';
else if ($type != '')
$data = '<kbd style="color:#ffffff;background:#000000;margin:0.2em 0.5em; padding:0.2em;">' . $type . '</kbd>' . $data;
echo $data . '<br/>';
});
} else {
set_time_limit(0);
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
while (@ob_end_flush()) {
}
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');
ob_start();
$retarr = call_user_func($qstrarr[0] . '::sse_' . $qstrarr[1], function ($data, $id = '') {
if (is_object($data) || is_array($data))
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
// if (strpos($data, "\n") !== false)
// $data = 'base64,' . base64_encode($data);
if (empty($id))
echo 'data: ' . $data . "\n\n";
else
echo 'data: ' . $data . "\n" . 'id: ' . $id . "\n\n";
ob_flush();
flush();
}, function ($data, $event = '_t_') {
echo 'data: ' . $data . "\n" . 'event: ' . $event . "\n\n";
ob_flush();
flush();
});
}
} else {
$csql = new \ciy\sql('zc_ymock');
$csql->where('ufunc', $qstr);
$csql->order('id desc');
$mockrow = $db->getone($csql);
if (!is_array($mockrow))
die('{"code":9,"errmsg":"' . $qstrarr[0] . '::' . $qstrarr[1] . '无效函数"}');
$updata = array();
$updata['lastrequest'] = $_SERVER['REQUEST_URI'] . '<br/>' . file_get_contents('php://input');
$updata['lasttimes'] = time();
$csql = new \ciy\sql('zc_ymock');
$csql->where('id', $mockrow['id']);
$db->update($csql, $updata);
echo $mockrow['mockjson'];
}

45
web/wwpage/art.php Normal file
View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$cate = 2;
$id = getint('id');
$current_page = '/wwpage/art?id=435';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/wwpage/art.php</div>
<div>
<?php
$csql = new \ciy\sql('www_list_cate');
$csql->where('id', $cate);
$row = $db->getone($csql);
clog($row);
$csql = new \ciy\sql('www_list_art');
$csql->where('cateid', $cate);
$csql->where('id', $id);
$artrow = $db->getone($csql);
clog($artrow);
$updata = array();
$updata['clickcnt'] = array('clickcnt+1');
$csql = new \ciy\sql('www_list_art');
$csql->where('id', $id);
$db->update($csql, $updata);
?>
</div>
<?php include_once("www/_footer.php"); ?>
</body>
</html>

59
web/wwpage/index.php Normal file
View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$cate = 2;
$pageno = getint('pageno');
$pagecount = 5;
$current_page = '/wwpage/';
if ($pageno > 1)
$current_page = '/wwpage/?pageno=2';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/wwpage/index.php</div>
<div>
<?php
$csql = new \ciy\sql('www_list_cate');
$csql->where('id', $cate);
$row = $db->getone($csql);
clog($row);
$csql = new \ciy\sql('www_list_art');
$csql->where('cateid', $cate);
$csql->where('bshow', 1);
$csql->limit($pageno, $pagecount);
$csql->order('id desc');
$csql->column('id,name');
$count = -1;
$rows = $db->get($csql, $count);
foreach ($rows as $row) {
echo '  <a href="/wwpage/art?id=' . $row['id'] . '">' . $row['name'] . '</a><br>';
}
clog('总条数: ' . $count);
?>
</div>
<div class="vpage">
<?php
\web\cwebcomon::www_showpage($count, $pageno, $pagecount, '/wwpage/', function ($pageno) {
if ($pageno < 2)
return '';
return '?pageno=' . $pageno;
});
?>
</div>
<?php include_once("www/_footer.php"); ?>
</body>
</html>

43
web/wwtour.php Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$current_page = '/wwtour/';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/wwtour.php</div>
<div>
<?php
$csql = new \ciy\sql('www_single');
$csql->where('id', 3);
$artrow = $db->getone($csql);
if (!is_array($artrow)) {
echo "单页不存在";
} else {
$content = $artrow['content'];
unset($artrow['content']);
clog($artrow);
$csql = new \ciy\sql('www_seoword');
$csql->where('isuse', 1);
$seowordrows = $db->get($csql);
echo \web\cwebcomon::www_convertseoword($seowordrows, \ciy\web::markdown_convert($content), $artrow['keys']);
}
?>
</div>
<?php include_once("www/_footer.php");?>
</body>
</html>

6
web/www/_footer.php Normal file
View File

@ -0,0 +1,6 @@
<div style="position: fixed; z-index:7;right:0;top:0;">
<div title="转到白天模式" class="mode-light" onclick="ciy_chgtheme(true)"></div>
<div title="转到暗夜模式" class="mode-dark" onclick="ciy_chgtheme(false)"></div>
</div>
<div class="bgbtm"></div>
<script src="/jscss/web.js"></script>

38
web/www/_header.php Normal file
View File

@ -0,0 +1,38 @@
<?php
$_header_nav1 = array();
$_header_nav1[] = '/about/';
$_header_nav1[] = '/wlist/2';
$_header_nav1[] = '/wlist/2/2';
$_header_nav1[] = '/wlist/2/art/435';
$_header_nav2 = array();
$_header_nav2[] = '/wwtour/';
$_header_nav2[] = '/wwpage/';
$_header_nav2[] = '/wwpage/?pageno=2';
$_header_nav2[] = '/wwpage/art?id=435';
?>
<div style="font-size: 1.2em;font-weight: bold;padding-left: 1em;">
Ciyon - <?php echo $current_page;?>
</div>
<div style="flex:1;padding:0.3em;">
 <a<?php if ($current_page == '/indexweb') echo ' style="color:var(--man6);"';?> href="/indexweb">首页</a>
<br/>
配置webpoint.php路由(推荐)
<?php
foreach ($_header_nav1 as $nav) {
echo '<br/> <a';
if ($current_page == $nav)
echo ' style="color:var(--man6);"';
echo ' href="'.$nav.'">'.$nav.'</a>';
}
?>
<br/><br/>不配置路由,单独建立文件
<?php
foreach ($_header_nav2 as $nav) {
echo '<br/> <a';
if ($current_page == $nav)
echo ' style="color:var(--man6);"';
echo ' href="'.$nav.'">'.$nav.'</a>';
}
?>
</div>

56
web/www/listart.php Normal file
View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$cate = getint('cate');
$id = getint('id');
$current_page = '/wlist/2/art/435';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/www/listart.php</div>
<div>
<?php
$csql = new \ciy\sql('www_list_cate');
$csql->where('id', $cate);
$row = $db->getone($csql);
clog($row);
$csql = new \ciy\sql('www_list_art');
$csql->where('cateid', $cate);
$csql->where('id', $id);
$artrow = $db->getone($csql);
if (!is_array($artrow)) {
echo "文章不存在";
} else {
$content = $artrow['content'];
unset($artrow['content']);
clog($artrow);
$csql = new \ciy\sql('www_seoword');
$csql->where('isuse', 1);
$seowordrows = $db->get($csql);
echo \web\cwebcomon::www_convertseoword($seowordrows, $content, $artrow['keys']);
}
$updata = array();
$updata['clickcnt'] = array('clickcnt+1');
$csql = new \ciy\sql('www_list_art');
$csql->where('id', $id);
$db->update($csql, $updata);
?>
</div>
<?php include_once("www/_footer.php"); ?>
</body>
</html>

59
web/www/listpage.php Normal file
View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$cate = getint('cate');
$pageno = getint('pageno');
$pagecount = 5;
$current_page = '/wlist/2';
if ($pageno > 1)
$current_page = '/wlist/2/2';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/www/listpage.php</div>
<div>
<?php
$csql = new \ciy\sql('www_list_cate');
$csql->where('id', $cate);
$row = $db->getone($csql);
clog($row);
$csql = new \ciy\sql('www_list_art');
$csql->where('cateid', $cate);
$csql->where('bshow', 1);
$csql->limit($pageno, $pagecount);
$csql->order('id desc');
$csql->column('id,name');
$count = -1;
$rows = $db->get($csql, $count);
foreach ($rows as $row) {
echo '  <a href="/wlist/' . $cate . '/art/' . $row['id'] . '">' . $row['name'] . '</a><br>';
}
clog('总条数: ' . $count);
?>
</div>
<div class="vpage">
<?php
\web\cwebcomon::www_showpage($count, $pageno, $pagecount, '/wlist/' . $cate, function ($pageno) {
if ($pageno < 2)
return '';
return '/' . $pageno;
});
?>
</div>
<?php include_once("www/_footer.php"); ?>
</body>
</html>

43
web/www/signpage.php Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Ciyon - 众产全栈开发框架</title>
<meta name="keywords" content="全栈开发框架,Golang开发框架,PHP开发框架,移动端开发框架,Vue3开发框架" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<link rel="stylesheet" href="/jscss/web.css" />
<script src="/jscss/theme.js"></script>
</head>
<body>
<div class="title">
<?php
$current_page = '/about/';
include_once("www/_header.php");
?>
</div>
<div class="vtitle">/web/www/signpage.php</div>
<div>
<?php
$csql = new \ciy\sql('www_single');
$csql->where('id', get('id'));
$artrow = $db->getone($csql);
if (!is_array($artrow)) {
echo "单页不存在";
} else {
$content = $artrow['content'];
unset($artrow['content']);
clog($artrow);
$csql = new \ciy\sql('www_seoword');
$csql->where('isuse', 1);
$seowordrows = $db->get($csql);
echo \web\cwebcomon::www_convertseoword($seowordrows, \ciy\web::markdown_convert($content), $artrow['keys']);
}
?>
</div>
<?php include_once("www/_footer.php");?>
</body>
</html>

View File

@ -1,117 +0,0 @@
<?php
require '../../zciyphp/comm.php'; //需要全局函数
require '../projectcomm.php';
$qstr = get('func'); // 例: admin/rig/user.list
if (!empty($qstr)) {
$qstrarr = explode('.', $qstr);
$ms = timems();
if (count($qstrarr) != 2) {
echo '{"errmsg":"' . $qstr . '格式错误"}';
die;
}
$qs0 = $qstrarr[0];
$qstrarr[0] = str_replace('\\\\', '\\', 'web\\' . str_replace('/', '\\', $qstrarr[0]));
//先找fun没有找mock最后提示错误
$retarr = null;
if (!class_exists($qstrarr[0])) {
$retarr = array('code' => 9, 'errmsg' => $qstrarr[0] . '无效类');
} else if (!method_exists($qstrarr[0], 'json_' . $qstrarr[1])) {
$retarr = array('code' => 9, 'errmsg' => $qstr . '无效函数');
}
$db = new ciy\db(); //默认数据库全局变量
if ($retarr === null) {
$qs0 = substr($qs0, 0, strpos($qs0, '/'));
if (file_exists(PATH_WEB . $qs0 . '/common.php'))
require PATH_WEB . $qs0 . '/common.php'; //需要全局业务函数和全局变量
// $dbrd1 = new ciy\db('rd1');//读库 可实现注册中心取一个空闲实例 业务端判断
// $dbag = new ciy\db('ag');//独立ag库
// web\admin\autotask\task::json_run
$retarr = call_user_func($qstrarr[0] . '::json_' . $qstrarr[1]);
} else {
$csql = new \ciy\sql('zc_ymock');
$csql->where('ufunc', $qstr);
$csql->order('id desc');
$mockrow = $db->getone($csql);
if (is_array($mockrow)) {
$updata = array();
$updata['lastrequest'] = $_SERVER['REQUEST_URI'] . '<br/>' . file_get_contents('php://input');
$updata['lasttimes'] = time();
$csql = new \ciy\sql('zc_ymock');
$csql->where('id', $mockrow['id']);
$db->update($csql, $updata);
echo $mockrow['mockjson'];
die;
}
}
if(!is_array($retarr))
die('{"errmsg":"无succ返回值"}');
if ($retarr['code'] == 302) {
header('Location: ' . $retarr['redirect']);
die;
}
ciy_ouputJSON($retarr, timems() - $ms, $_SERVER['REQUEST_URI']);
die;
}
$qstr = get('sse'); // 例: admin/rig/user.xxxsse
//https://html.spec.whatwg.org/multipage/server-sent-events.html
if (!empty($qstr)) {
$qstrarr = explode('.', $qstr);
$ms = timems();
if (count($qstrarr) < 2) {
echo '{"errmsg":"' . $qstr . '格式错误"}';
die;
}
$qs0 = $qstrarr[0];
$qstrarr[0] = 'web\\' . str_replace('/', '\\', $qstrarr[0]);
if (!class_exists($qstrarr[0]))
$retarr = array('code' => 9, 'errmsg' => $qstrarr[0] . '无效类');
else if (!method_exists($qstrarr[0], 'sse_' . $qstrarr[1]))
$retarr = array('code' => 9, 'errmsg' => $qstr . '无效函数');
else {
$qs0 = substr($qs0, 0, strpos($qs0, '/'));
require PATH_WEB . $qs0 . '/common.php'; //需要全局业务函数和全局变量
$db = new ciy\db(); //默认数据库全局变量
if (get('debug') == 'yes') {
call_user_func($qstrarr[0] . '::sse_' . $qstrarr[1], function ($data, $type = '') {
if ($type === true)
return;
//$data = '<code style="color:#199d01;">' . $data . '</code>';
else if ($type != '')
$data = '<kbd style="color:#ffffff;background:#000000;margin:0.2em 0.5em; padding:0.2em;">' . $type . '</kbd>' . $data;
echo $data . '<br/>';
});
} else {
set_time_limit(0);
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
while (@ob_end_flush()) {
}
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');
ob_start();
$retarr = call_user_func($qstrarr[0] . '::sse_' . $qstrarr[1], function ($data, $id = '') {
if (is_object($data) || is_array($data))
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
// if (strpos($data, "\n") !== false)
// $data = 'base64,' . base64_encode($data);
if (empty($id))
echo 'data: ' . $data . "\n\n";
else
echo 'data: ' . $data . "\n" . 'id: ' . $id . "\n\n";
ob_flush();
flush();
}, function ($data, $event = '_t_') {
echo 'data: ' . $data . "\n" . 'event: ' . $event . "\n\n";
ob_flush();
flush();
});
}
}
if (isset($retarr))
ciy_ouputJSON($retarr, timems() - $ms, $_SERVER['REQUEST_URI']);
die;
}
header('HTTP/1.1 488 Function Not Found');

7
webpoint.php Normal file
View File

@ -0,0 +1,7 @@
<?php
return [
'about' => 'www/signpage?id=3',
'wlist/{cate}' => 'www/listpage?pageno=1',
'wlist/{cate}/{pageno}' => 'www/listpage',
'wlist/{cate}/art/{id}' => 'www/listart',
];

View File

@ -22,10 +22,11 @@ func SSESend_data(w http.ResponseWriter, data string, argid ...any) bool {
id = Tostr(argid[0])
}
msg := ""
msg += "data: " + strings.Replace(data, "\n", "<br/>", -1) + "\n"
if id != "" {
msg += "id: " + id + "\n"
}
msg += "data: " + strings.Replace(data, "\n", "<br/>", -1) + "\n\n"
msg += "\n"
_, err := w.Write([]byte(msg))
if err != nil {
@ -40,7 +41,7 @@ func SSESend_event(w http.ResponseWriter, data string, argevent ...string) bool
if len(argevent) > 0 {
event = argevent[0]
}
msg := "event: " + event + "\ndata: " + strings.Replace(data, "\n", "<br/>", -1) + "\n\n"
msg := "data: " + strings.Replace(data, "\n", "<br/>", -1) + "\nevent: " + event + "\n\n"
_, err := w.Write([]byte(msg))
if err != nil {
return false

View File

@ -53,7 +53,7 @@ func NewCiyWebServer() (*CiyWebServer, error) {
web := &CiyWebServer{}
web.exts = map[string]int{}
web.pathfn = map[string]map[string]func(http.ResponseWriter, *http.Request) bool{}
http.HandleFunc("/z/", web.WithRequestContext(web.runMainPath))
http.HandleFunc("/", web.WithRequestContext(web.runMainPath))
http.HandleFunc("/ws/", web.runWebsocket)
return web, nil
}
@ -150,7 +150,7 @@ func (thos *CiyWebServer) execPHP(w http.ResponseWriter, r *http.Request) error
func (thos *CiyWebServer) execFunc(w http.ResponseWriter, r *http.Request) error {
defer func() {
if rc := recover(); rc != nil {
funname := GetQuery("func", r)
funname := r.URL.Path
if funname == "" {
funname = GetQuery("sse", r)
}
@ -160,13 +160,9 @@ func (thos *CiyWebServer) execFunc(w http.ResponseWriter, r *http.Request) error
}
}()
Clog("execFunc", r.URL.Path)
funname := GetQuery("func", r)
if funname == "" {
funname = GetQuery("sse", r)
}
clsmothod := strings.Split(funname, ".")
clsmothod := strings.Split(r.URL.Path, ".")
if len(clsmothod) != 2 {
return fmt.Errorf("RouterFunc format error:%v", funname)
return fmt.Errorf("RouterFunc format error:%v", r.URL.Path)
}
for path := range thos.pathfn {
if path == clsmothod[0] {
@ -251,7 +247,7 @@ func (thos *CiyWebServer) SetPHP(host string) {
Clog("WebRun support PHP:", host)
}
func (thos *CiyWebServer) execMockFile(w http.ResponseWriter, r *http.Request) error {
funname := GetQuery("func", r)
funname := r.URL.Path
mockfile := CiyWebDir + "/ud/mock/" + funname + ".json"
err := FileExist(mockfile)
if err != nil {

View File

@ -844,8 +844,15 @@ function ciy_ouputJSON($retarr, $ms = 0, $uri = '') {
$jsonstr = json_encode($retarr);
}
}
echo $jsonstr;
exit();
if (isset($_GET['jsonp'])) {
$callback = $_GET['jsonp'];
if (strlen($callback) < 128 && preg_match('/^[A-Za-z_][A-Za-z0-9_]*$/', $callback)) {
header('Content-Type: application/javascript; charset=utf-8');
die($callback . '(' . $jsonstr . ')');
}
}
header('Content-Type: application/json; charset=utf-8');
die($jsonstr);
}
//code=2 未登录3 未授权9 函数未加载
function errjson($error, $errcode = 0, $ext = null) {

View File

@ -9,411 +9,280 @@
*
* 页面相关
* diehtml 报错输出页面/跳转
* markdown_code
* markdown_convert Markdown转换为HTML
* inzone
*/
namespace ciy;
function diehtml($msg, $title = '提示信息') {
echo '<!DOCTYPE html><html><head><meta http-equiv="Content-type" content="text/html; charset=utf-8">';
echo '<title>' . $title . '</title><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0"/><meta name="format-detection" content="telephone=no,email=no"/>';
echo '<meta name="apple-mobile-web-app-capable" content="yes" /></head><body>';
$selfname = substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'], '/') + 1, -4);
echo '<fieldset style="margin:2em;border-radius: 0.5em;border: 1px solid #eeeeee;line-height:2em;"><legend style="font-size: 1.3em;padding: 0.2em 0.5em;">' . $title . '</legend><div style="padding:0 15px 15px 15px;"><b>来源: ' . str_replace('.php', '', $selfname) . '</b><br/>' . $msg . '</div></fieldset>';
echo '</body></html>';
die();
}
function markdown_convert($markdown) {
// #,!,`,@cr,[]
//行首: 标题# 对齐@ _HTML 无 独立div 图片!http://.jpg|ALT
//行中: `强调` \uhttp://xxx|链接字\u
if(substr($markdown,0, 4) != '[MD]')
return $markdown;
$mds = explode("\n", trim(substr($markdown,4)));
$html = '';
foreach ($mds as $mi) {
if (empty($mi)) {
$html .= '<br/>';
continue;
}
if ($mi[0] == '#') { //#一级标题 ##二级标题 ###三级标题
if (substr($mi,0, 3) == '###')
$html .= '<h3 class="md-h3">' . markdown_convertcode(substr($mi,3)) . '</h3>';
else if (substr($mi,0, 2) == '##')
$html .= '<h2 class="md-h2">' . markdown_convertcode(substr($mi,2)) . '</h2>';
else if ($mi[1] == 'c')
$html .= '<h1 class="md-h1" style="text-align:center;">' . markdown_convertcode(substr($mi,2)) . '</h1>';
else if ($mi[1] == 'r')
$html .= '<h1 class="md-h1" style="text-align:right;">' . markdown_convertcode(substr($mi,2)) . '</h1>';
else
$html .= '<h1 class="md-h1">' . markdown_convertcode(substr($mi,1)) . '</h1>';
} else if ($mi[0] == '@') {//c居中r靠右
if ($mi[1] == 'c')
$html .= '<div style="text-align:center;">' . markdown_convertcode(substr($mi,2)) . '</div>';
else if ($mi[1] == 'r')
$html .= '<div style="text-align:right;margin-right:1em;">' . markdown_convertcode(substr($mi,2)) . '</div>';
else
$html .= substr($mi,1);
} else if ($mi[0] == '!') { //!图片地址 !图片地址|ALT文字
$mis = explode('|',$mi);
$url = $mis[0];
$url = substr($url, 1);
$alt = '';
if(isset($mis[1]))
$alt = ' alt="' . str_replace('"',"",$mis[1]). '"';
$html .= '<div style="font-size:0"><img src="' . $url . '" style="max-width:100%;"'.$alt.'/></div>';
} else if ($mi[0] == '_') { //HTML
$html .= substr($mi, 1);
} else {
$html .= '<div class="md-content">' . markdown_convertcode($mi) . '</div>';
}
class web {
public static function diehtml($msg, $title = '提示信息') {
echo '<!DOCTYPE html><html><head><meta http-equiv="Content-type" content="text/html; charset=utf-8">';
echo '<title>' . $title . '</title><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0"/><meta name="format-detection" content="telephone=no,email=no"/>';
echo '<meta name="apple-mobile-web-app-capable" content="yes" /></head><body>';
$selfname = substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'], '/') + 1, -4);
echo '<fieldset style="margin:2em;border-radius: 0.5em;border: 1px solid #eeeeee;line-height:2em;"><legend style="font-size: 1.3em;padding: 0.2em 0.5em;">' . $title . '</legend><div style="padding:0 15px 15px 15px;"><b>来源: ' . str_replace('.php', '', $selfname) . '</b><br/>' . $msg . '</div></fieldset>';
echo '</body></html>';
die();
}
return $html;
}
function markdown_convertcode($md) {
$bcode = false;
$md = str_replace(' ',' ',$md);
$md = str_replace(' ','&nbsp;',$md);
while (true) {
$ind = strpos($md,'`');
if ($ind === false)
break;
$el = '<code class="md-code">';
if ($bcode) {
$bcode = false;
$el = '</code>';
}
else
$bcode = true;
$md = substr($md,0, $ind) . $el . substr($md,$ind + 1);
}
if ($bcode)
$md .= '</code>';
while (true) {
$ind = strpos($md,'\\u');
if ($ind === false)
break;
$ind2 = strpos($md,'\\u', $ind+1);
if ($ind2 === false)
break;
$mis = explode('|',substr($md,$ind + 2, $ind2-$ind-2));
$url = $mis[0];
$text = $url;
if(isset($mis[1]))
$text = $mis[1];
if($text[0] == '!'){
$html = '<a href="'.$url.'" target="_blank" nofollow><img src="' . substr($text,1) . '" style="max-width:100%;"/></a>';
}else{
$html = '<a href="'.$url.'" target="_blank" nofollow>' . $text . '</a>';
}
$md = substr($md,0,$ind) . $html . substr($md,$ind2+2);
}
return $md;
}
function convertseowords($db, $content, $keystr = '') {
$csql = new sql('a_web_word');
$seowords = $db->get($csql);
$seo = array();
$max = rand(2, 5);
shuffle($seowords);
foreach ($seowords as $row) {
if ($row['rank'] > rand(0, 100))
$seo[$row['name']] = $row['url'];
}
$repcnt = 0;
foreach ($seo as $key => $val) {
$keyind = 0;
for($i=0;$i<5;$i++){
$ind = strpos($content, $key,$keyind);
if ($ind === false)
break;
$tmp = substr($content, 0, $ind);
$inda = strrpos($tmp, '<a ciy href=');
if ($inda !== false) {
$indb = strpos($tmp, '</a>', $inda);
if ($indb === false){ //包含
$keyind = $ind + 1;
continue;
}
}
$inda = strrpos($tmp, ' alt="');
if ($inda !== false) {
$indb = strpos($tmp, '"', $inda+6);
if ($indb === false){ //包含
$keyind = $ind + 1;
continue;
}
}
break;
}
if ($ind === false)
continue;
$content = substr_replace($content, '<a ciy href="' . $val . '">' . $key . '</a>', $ind, strlen($key));
$repcnt++;
if ($repcnt >= $max)
break;
}
if (!empty($keystr)) {
$keystr = str_replace('', ',', $keystr);
$keystr = str_replace(';', ',', $keystr);
$keystr = str_replace('', ',', $keystr);
$keys = explode(',', $keystr);
foreach ($keys as $key) {
if (empty($key))
public static function markdown_convert($markdown) {
if (substr($markdown, 0, 4) == '[MD]')
$markdown = substr($markdown, 4);
$mds = explode("\n", trim($markdown));
$html = '';
foreach ($mds as $mi) {
if (empty($mi)) {
$html .= '<br/>';
continue;
$keyind = 0;
for($i=0;$i<5;$i++){
$ind = strpos($content, $key,$keyind);
if ($ind === false)
break;
$tmp = substr($content, 0, $ind);
$inda = strrpos($tmp, '<strong>');
if ($inda !== false) {
$indb = strpos($tmp, '</strong>', $inda);
if ($indb === false){ //包含
$keyind = $ind + 1;
continue;
}
}
$inda = strrpos($tmp, ' alt="');
if ($inda !== false) {
$indb = strpos($tmp, '"', $inda+6);
if ($indb === false){ //包含
$keyind = $ind + 1;
continue;
}
}
break;
}
if ($ind === false)
continue;
$content = substr_replace($content, '<strong>' . $key . '</strong>', $ind, strlen($key));
}
}
return $content;
}
function getwebtitle($db, $id) {
$csql = new sql('a_web_seo');
$csql->where('url', $_SERVER['REQUEST_URI']);
$webtitrow = $db->getone($csql);
if (is_array($webtitrow)) {
if ($webtitrow['pagecount'] < 1)
$webtitrow['pagecount'] = 20;
return $webtitrow;
}
$csql = new sql('a_web_seo');
$csql->where('id', $id);
$webtitrow = $db->getone($csql);
if (is_array($webtitrow)) {
if ($webtitrow['pagecount'] < 1)
$webtitrow['pagecount'] = 20;
return $webtitrow;
}
$webtitrow = array();
$webtitrow['name'] = '众产平台';
$webtitrow['keys'] = '众产平台,众产事业';
$webtitrow['desc'] = '众产事业网站';
$webtitrow['pagecount'] = 30;
return $webtitrow;
}
function titrep($str, $dat, $content = '') {
foreach ($dat as $key => $val) {
$str = str_replace('{' . $key . '}', $val, $str);
}
$str = str_replace('农业农业', '农业', $str);
if (empty($content))
return $str;
$ind = strpos($str, '{content');
if ($ind === false)
return $str;
$ind2 = strpos($str, '}', $ind);
if ($ind2 === false)
return $str;
if ($ind2 - $ind == 8) {
return str_replace('{content}', leftchinese($content), $str);
} else {
$len = substr($str, $ind + 8, $ind2 - $ind - 8);
return str_replace(substr($str, $ind, $ind2 - $ind + 1), leftchinese($content, $len), $str);
}
}
function leftchinese($content, $len = 0) {
$content = htmlspecialchars_decode($content);
$content = str_replace(" ", "", $content);
$content = str_replace("\n", "", $content);
$content = str_replace("\r", "", $content);
$content = str_replace("\t", "", $content);
$content = strip_tags($content);
$content = trim($content);
if ($len <= 0)
return $content;
if (mb_strlen($content, 'utf-8') > $len)
return mb_substr($content, 0, $len, "utf-8");
return $content;
}
function showpage($count, $pageno, $pagecount, $pageurl) {
if ($count <= 0) {
// 1...3,4,5,6,7,8
$isend = (-$count < $pagecount);
//if($pageno < 20) $isend = false;
$epage = $pageno + 2;
$spage = $pageno - 6;
if ($isend)
$epage = $pageno;
if ($spage < 1)
$spage = 1;
echo '<a ' . ($pageno <= 1 ? ' class="disabled"' : " href=\"" . $pageurl . ($pageno - 1) . "/\"") . '>上页</a>';
echo '<a ' . ($isend ? ' class="disabled"' : " href=\"" . $pageurl . ($pageno + 1) . "/\"") . '>下页</a>';
if ($spage > 1)
echo '<a href="' . $pageurl . '1/">1</a>';
if ($spage > 2)
echo '<span>...</span>';
for ($i = $spage; $i <= $epage; $i++)
echo '<a ' . ($i == $pageno ? ' class="active"' : " href=\"" . $pageurl . $i . "/\"") . '>' . $i . '</a>';
} else {
//1...3,4,5,6,7...n
$epage = $pageno + 4;
$spage = $pageno - 4;
$pagemax = ceil($count / $pagecount);
if ($spage < 1)
$spage = 1;
if ($epage > $pagemax)
$epage = $pagemax;
echo '<a ' . ($pageno <= 1 ? ' class="disabled"' : " href=\"" . $pageurl . ($pageno - 1) . "/\"") . '>上页</a>';
echo '<a ' . ($pageno >= $pagemax ? ' class="disabled"' : " href=\"" . $pageurl . ($pageno + 1) . "/\"") . '>下页</a>';
if ($spage > 1)
echo '<a href="' . $pageurl . '1/">1</a>';
if ($spage > 2)
echo '<span>...</span>';
for ($i = $spage; $i <= $epage; $i++)
echo '<a ' . ($i == $pageno ? ' class="active"' : " href=\"" . $pageurl . $i . "/\"") . '>' . $i . '</a>';
if ($epage < $pagemax - 1)
echo '<span>...</span>';
if ($epage < $pagemax)
echo '<a href="' . $pageurl . $pagemax . '/">' . $pagemax . '</a>';
}
}
function fillsource($str) {
$source = explode('|', $str);
if (!isset($source[1]))
return $source[0];
else
return '<a href="' . $source[1] . '" target="_blank" nofollow>' . '转自' . $source[0] . '</a>';
}
function showh1($webtit, $artrow) {
$h1 = titrep($webtit['h1'], $artrow);
$htip = titrep($webtit['htip'], $artrow);
if (empty($h1))
echo '';
else if ($h1[0] == '<')
echo $h1;
else
echo '<h1>' . $h1 . '</h1>';
if (empty($htip))
echo '';
else if ($htip[0] == '<')
echo $htip;
else
echo '<div class="vhtip">' . $htip . '</div>';
}
function markdown_fromhtml($content, $baseurl) {
$html = html::str_get_html($content);
if ($html === false || $html === null)
return '';
$md = '';
_html2md_child($baseurl, $html->childNodes(), $md);
return $md;
}
function _html2md_child($baseurl, $childs, &$md) {
if ($childs === null)
return;
foreach ($childs as $child) {
if ($child->tag == 'table') {
$md .= '_' . str_replace("\n", "", $child->outertext) . "\n";
} else if ($child->tag == 'img') {
if (empty(@$child->attr['src']))
continue;
$md .= '!' . urljoin($child->attr['src'], $baseurl) . '|' . @$child->attr['alt'] . "\n";
} else if ($child->tag == 'ul') {
//clog('find ul');
} else {
$divps = $child->find('div,p');
if (count($divps) > 0) {
$txt = trim($child->plaintext);
_html2md_child($baseurl, $child->childNodes(), $md);
if ($mi[0] == '#') { //#一级标题 ##二级标题 ###三级标题
if (substr($mi, 0, 3) == '###')
$html .= '<h3 class="md-h3">' . self::markdown_convertcode(substr($mi, 3)) . '</h3>';
else if (substr($mi, 0, 2) == '##')
$html .= '<h2 class="md-h2">' . self::markdown_convertcode(substr($mi, 2)) . '</h2>';
else if ($mi[1] == 'c')
$html .= '<h1 class="md-h1" style="text-align:center;">' . self::markdown_convertcode(substr($mi, 2)) . '</h1>';
else if ($mi[1] == 'r')
$html .= '<h1 class="md-h1" style="text-align:right;">' . self::markdown_convertcode(substr($mi, 2)) . '</h1>';
else
$html .= '<h1 class="md-h1">' . self::markdown_convertcode(substr($mi, 1)) . '</h1>';
} else if ($mi[0] == '@') { //c居中r靠右
if ($mi[1] == 'c')
$html .= '<div style="text-align:center;">' . self::markdown_convertcode(substr($mi, 2)) . '</div>';
else if ($mi[1] == 'r')
$html .= '<div style="text-align:right;margin-right:1em;">' . self::markdown_convertcode(substr($mi, 2)) . '</div>';
else
$html .= substr($mi, 1);
} else if ($mi[0] == '!') { //!图片地址 !图片地址|ALT文字
$mis = explode('|', $mi);
$url = $mis[0];
$url = substr($url, 1);
$alt = '';
if (isset($mis[1]))
$alt = ' alt="' . str_replace('"', "", $mis[1]) . '"';
$html .= '<div style="font-size:0"><img src="' . $url . '" style="max-width:100%;"' . $alt . '/></div>';
} else if ($mi[0] == '_') { //HTML
$html .= substr($mi, 1);
} else {
$divimgs = $child->find('img');
foreach ($divimgs as $divimg) {
if (empty(@$divimg->attr['src']))
continue;
$md .= '!' . urljoin($divimg->attr['src'], $baseurl) . '|' . @$divimg->attr['alt'] . "\n";
}
$txtpre = '';
$txt = $child->plaintext;
$txt = str_replace('&nbsp;', '', $txt);
$txt = trim($txt);
$style = @$child->attr['style'] . ',' . @$child->attr['align'];
if (strpos($style, 'right') !== false)
$txtpre = '@r';
else if (strpos($style, 'center') !== false)
$txtpre = '@c';
if (!empty($txt)) {
$txts = explode("\n", $txt);
foreach ($txts as $tx) {
$tx = trim($tx);
while (true) {
if (substr($tx, 0, 3) != ' ')
break;
$tx = substr($tx, 3);
}
if (empty($tx))
$html .= '<div class="md-content">' . self::markdown_convertcode($mi) . '</div>';
}
}
return $html;
}
private static function markdown_convertcode($md) {
$bcode = false;
$md = str_replace(' ', ' ', $md);
$md = str_replace(' ', '&nbsp;', $md);
while (true) {
$ind = strpos($md, '`');
if ($ind === false)
break;
$el = '<code class="md-code">';
if ($bcode) {
$bcode = false;
$el = '</code>';
} else
$bcode = true;
$md = substr($md, 0, $ind) . $el . substr($md, $ind + 1);
}
if ($bcode)
$md .= '</code>';
while (true) {
$ind = strpos($md, '\\u');
if ($ind === false)
break;
$ind2 = strpos($md, '\\u', $ind + 1);
if ($ind2 === false)
break;
$mis = explode('|', substr($md, $ind + 2, $ind2 - $ind - 2));
$url = $mis[0];
$text = $url;
if (isset($mis[1]))
$text = $mis[1];
if ($text[0] == '!') {
$html = '<a href="' . $url . '" target="_blank" nofollow><img src="' . substr($text, 1) . '" style="max-width:100%;"/></a>';
} else {
$html = '<a href="' . $url . '" target="_blank" nofollow>' . $text . '</a>';
}
$md = substr($md, 0, $ind) . $html . substr($md, $ind2 + 2);
}
return $md;
}
public static function getwebtitle($db, $id) {
$csql = new sql('a_web_seo');
$csql->where('url', $_SERVER['REQUEST_URI']);
$webtitrow = $db->getone($csql);
if (is_array($webtitrow)) {
if ($webtitrow['pagecount'] < 1)
$webtitrow['pagecount'] = 20;
return $webtitrow;
}
$csql = new sql('a_web_seo');
$csql->where('id', $id);
$webtitrow = $db->getone($csql);
if (is_array($webtitrow)) {
if ($webtitrow['pagecount'] < 1)
$webtitrow['pagecount'] = 20;
return $webtitrow;
}
$webtitrow = array();
$webtitrow['name'] = '众产平台';
$webtitrow['keys'] = '众产平台,众产事业';
$webtitrow['desc'] = '众产事业网站';
$webtitrow['pagecount'] = 30;
return $webtitrow;
}
public static function titrep($str, $dat, $content = '') {
foreach ($dat as $key => $val) {
$str = str_replace('{' . $key . '}', $val, $str);
}
$str = str_replace('农业农业', '农业', $str);
if (empty($content))
return $str;
$ind = strpos($str, '{content');
if ($ind === false)
return $str;
$ind2 = strpos($str, '}', $ind);
if ($ind2 === false)
return $str;
if ($ind2 - $ind == 8) {
return str_replace('{content}', self::leftchinese($content), $str);
} else {
$len = substr($str, $ind + 8, $ind2 - $ind - 8);
return str_replace(substr($str, $ind, $ind2 - $ind + 1), self::leftchinese($content, $len), $str);
}
}
private static function leftchinese($content, $len = 0) {
$content = htmlspecialchars_decode($content);
$content = str_replace(" ", "", $content);
$content = str_replace("\n", "", $content);
$content = str_replace("\r", "", $content);
$content = str_replace("\t", "", $content);
$content = strip_tags($content);
$content = trim($content);
if ($len <= 0)
return $content;
if (mb_strlen($content, 'utf-8') > $len)
return mb_substr($content, 0, $len, "utf-8");
return $content;
}
public static function fillsource($str) {
$source = explode('|', $str);
if (!isset($source[1]))
return $source[0];
else
return '<a href="' . $source[1] . '" target="_blank" nofollow>' . '转自' . $source[0] . '</a>';
}
public static function showh1($webtit, $artrow) {
$h1 = self::titrep($webtit['h1'], $artrow);
$htip = self::titrep($webtit['htip'], $artrow);
if (empty($h1))
echo '';
else if ($h1[0] == '<')
echo $h1;
else
echo '<h1>' . $h1 . '</h1>';
if (empty($htip))
echo '';
else if ($htip[0] == '<')
echo $htip;
else
echo '<div class="vhtip">' . $htip . '</div>';
}
public static function markdown_fromhtml($content, $baseurl) {
$html = html::str_get_html($content);
if ($html === false || $html === null)
return '';
$md = '';
self::_html2md_child($baseurl, $html->childNodes(), $md);
return $md;
}
private static function _html2md_child($baseurl, $childs, &$md) {
if ($childs === null)
return;
foreach ($childs as $child) {
if ($child->tag == 'table') {
$md .= '_' . str_replace("\n", "", $child->outertext) . "\n";
} else if ($child->tag == 'img') {
if (empty(@$child->attr['src']))
continue;
$md .= '!' . self::urljoin($child->attr['src'], $baseurl) . '|' . @$child->attr['alt'] . "\n";
} else if ($child->tag == 'ul') {
//clog('find ul');
} else {
$divps = $child->find('div,p');
if (count($divps) > 0) {
$txt = trim($child->plaintext);
self::_html2md_child($baseurl, $child->childNodes(), $md);
} else {
$divimgs = $child->find('img');
foreach ($divimgs as $divimg) {
if (empty(@$divimg->attr['src']))
continue;
$md .= $txtpre . $tx . "\n";
$md .= '!' . self::urljoin($divimg->attr['src'], $baseurl) . '|' . @$divimg->attr['alt'] . "\n";
}
$txtpre = '';
$txt = $child->plaintext;
$txt = str_replace('&nbsp;', '', $txt);
$txt = trim($txt);
$style = @$child->attr['style'] . ',' . @$child->attr['align'];
if (strpos($style, 'right') !== false)
$txtpre = '@r';
else if (strpos($style, 'center') !== false)
$txtpre = '@c';
if (!empty($txt)) {
$txts = explode("\n", $txt);
foreach ($txts as $tx) {
$tx = trim($tx);
while (true) {
if (substr($tx, 0, 3) != ' ')
break;
$tx = substr($tx, 3);
}
if (empty($tx))
continue;
$md .= $txtpre . $tx . "\n";
}
}
}
}
}
}
}
//相对网址转绝对网址
function urljoin($srcurl, $baseurl) {
$srcinfo = parse_url($srcurl);
if (isset($srcinfo['scheme'])) {
return $srcurl;
}
$baseinfo = parse_url($baseurl);
$url = $baseinfo['scheme'] . '://' . $baseinfo['host'];
if (substr($srcinfo['path'], 0, 1) == '/') {
$path = $srcinfo['path'];
} else {
$path = dirname($baseinfo['path']) . '/' . $srcinfo['path'];
}
$rst = array();
$path_array = explode('/', $path);
if (!$path_array[0]) {
$rst[] = '';
}
foreach ($path_array as $key => $dir) {
if ($dir == '..') {
if (end($rst) == '..') {
$rst[] = '..';
} elseif (!array_pop($rst)) {
$rst[] = '..';
}
} elseif ($dir && $dir != '.') {
$rst[] = $dir;
//相对网址转绝对网址
public static function urljoin($srcurl, $baseurl) {
$srcinfo = parse_url($srcurl);
if (isset($srcinfo['scheme'])) {
return $srcurl;
}
$baseinfo = parse_url($baseurl);
$url = $baseinfo['scheme'] . '://' . $baseinfo['host'];
if (substr($srcinfo['path'], 0, 1) == '/') {
$path = $srcinfo['path'];
} else {
$path = dirname($baseinfo['path']) . '/' . $srcinfo['path'];
}
$rst = array();
$path_array = explode('/', $path);
if (!$path_array[0]) {
$rst[] = '';
}
foreach ($path_array as $key => $dir) {
if ($dir == '..') {
if (end($rst) == '..') {
$rst[] = '..';
} elseif (!array_pop($rst)) {
$rst[] = '..';
}
} elseif ($dir && $dir != '.') {
$rst[] = $dir;
}
}
if (!end($path_array)) {
$rst[] = '';
}
$url .= implode('/', $rst);
return str_replace('\\', '/', $url);
}
if (!end($path_array)) {
$rst[] = '';
}
$url .= implode('/', $rst);
return str_replace('\\', '/', $url);
}
}