{collapse-item label="内置钩子文档" open}
内置钩子文档
支付相关
Pay_Create_qq
- 类型:执行钩子
- 权重:1-100
- 说明:创建支付订单时,QQ支付,可执行钩子,返回订单所有数据。
Pay_Create_wx
- 类型:执行钩子
- 说明:创建支付订单时,微信支付,可执行钩子,返回订单所有数据。
Pay_Create_ali
- 类型:执行钩子
- 说明:创建支付订单时,支付宝,可执行钩子,返回订单所有数据。
Pay_Create_balance
- 类型:执行钩子(非必要请勿使用!)
- 说明:创建支付订单时,余额支付,可执行钩子,返回订单所有数据。
Pay_Create
- 类型:数据钩子
- 说明:创建支付订单时,可返回数据钩子,用于创建后对订单数据进行编辑和返回。
Pay_CallBack
- 类型:执行钩子
- 说明:支付成功回调钩子,返回所有回调数据。
- 注意:发起支付若需要跳转链接而不是html,请确保code = 522 并且链接在 data中。
上传相关
Update_File_Start
- 类型:执行钩子
- 权重:1-100
- 说明:上传文件开始,返回
$_FILES["file"]。
Update_Image_Start
- 类型:执行钩子
- 说明:上传图片开始,返回
$_FILES["file"]。
系统相关
WebNotification
- 类型:数据钩子
- 权重:1-100
- 说明:后台系统通知。
AdminNav_Left
- 类型:数据钩子
- 说明:后台导航栏左侧。
AdminNav_Chen
- 类型:数据钩子
- 说明:后台导航栏子栏目。
注意:内置钩子请勿重复注册,否则可能出现插件异常,权重越小,越先执行。
注册实例
提供两种类型的钩子注册示例:执行类钩子和数据处理类钩子。
执行类钩子注册实例:
use Logic\Important\Hooks; // 注册支付创建后,QQ支付处理钩子 Hooks::Register("Pay_Create_qq", 1, function($parameter) { echo "Pay_Create_qq"; var_dump($parameter); exit(); }, 10);数据处理类钩子注册实例:
use Logic\Important\Hooks; // 支付创建后,处理数据,并将数据返回 Hooks::Register("Pay_Create", 2, function($parameter) { $parameter['payname'] = "我爱你"; return $parameter; }, 10);
内置函数
返回数据函数:
use Logic\Important\Tos; // 返回状态 Tos::sendmsg(200); // 返回单个数据 Tos::sendmsg(200, "", $data); // 返回列表数据 Tos::sendmsg(200, "", $data, $total);
{/collapse-item}
{collapse-item label="数据库内置函数"}
一、引入函数
使用SqlFun库来处理数据库操作。
use Logic\Important\SqlFun;
public function __construct()
{
// 获取数据库实例
$this->db = SqlFun::getInstance();
}二、函数使用示例
1. 普通查询数据
执行一个简单的查询操作以获取数据。
$result = $this->db->query("SELECT * FROM xxx WHERE id = ?", [$id]);2. 修改数据
更新表中的特定记录。
$this->db->update("xxxxx", [
"xu_fans" => $merinfo[0]['xu_fans'] - 1,
], 'id = ?', [$merinfo[0]['id']]);3. 删除数据
从指定表中删除一条记录。
$this->db->delete("xu_merfans", "id = ?", [$res[0]['id']]);4. 写入数据
向指定表中插入新数据。
$this->db->insert("xu_keyapi", [
"xu_aid" => $aidlist[$a],
"xu_kid" => $ids
]);5. 数据库语句拼接
使用SqlFun提供的方法构建复杂的SQL查询。
$sql = SqlFun::SqlBuilderAdd("xu_name", $pre['search'], 'like')
->SqlBuilderAdd("xu_mid", $pre['mid'])
->SqlBuilderAdd("xu_status", 1)
->SqlBuilderBuild();6. 数据库查询语句(分页查询)
执行分页查询,并返回结果。
$result = $this->db->getPaginatedData("xu_api", $sql, [$pre['sortname'], $pre['sorttype']], $pagination, [
"xu_queryper", "xu_bodyper", "xu_headerper", "xu_cookies", "xu_errlist", "xu_bodyjson", "xu_words", "xu_apisource"
]);{/collapse-item}
{collapse-item label="模板规范"}
Typecho 模板开发指南(Joe 主题兼容)
一、目录结构
一个标准的 Typecho 模板目录结构如下:
mytemplate/
├── user/ # 用户中心页面(自动判断登录)
├── Main.php # 主逻辑文件
├── package.json # 模板描述信息文件
├── ConfigurationPage.php # 模板配置页面二、Main.php —— 主逻辑文件
该文件定义模板的核心行为和生命周期钩子。
示例代码:
<?php
namespace Resource\Template\default;
use Logic\Important\Rote;
use Logic\Important\Tos;
use Resource\Template\default\cp;
class Main
{
public function CallBack($parameter)
{
if ($parameter['status'] == 1) {
cp::setteP($data);
Tos::sendmsg(200);
}
if ($parameter['status'] == 2) {
cp::checkUpdate(3);
}
}
public function init(): void
{
$this->getAuthCert();
}
public function Userinit(): void
{
$this->getAuthCert();
}
public function Admininit(): void
{
// 检查模板是否存在新版本
cp::checkUpdate();
}
public function getAuthCert()
{
// 授权验证示例(可选)
// $auth = new Rote();
// $res = $auth->appCertificate('5a6e619c-29d1-2890-1776-14078b36b4c3');
// if ($res['code'] !== '5200') {
// error_log('未授权');
// } else {
// error_log('已授权');
// }
}
}三、package.json —— 模板描述文件
用于存储模板的基本信息,便于管理与更新。
示例内容:
{
"tep_name": "默认模板",
"tep_version": "0.0.1",
"tep_image": "https://imgsbad.semoun.com/uploads/2025/03/19/67da24298292e.jpg",
"tep_brief": "自带的默认模板",
"tep_cansid": "default",
"tep_page": true,
"tep_PagePath": "ConfigurationPage.php",
"tep_code": "5a6e619c-29d1-2890-1776-14078b36b4c3",
"author_name": "CansCode"
}四、ConfigurationPage.php —— 模板配置页面
用于提供后台可视化配置界面,支持用户自定义设置。
示例代码片段(HTML + Vue.js):
<?php
use Logic\Function\MainControl\WebInfo
;
use Resource\Template\default\cp
;
$config = cp::gettep
();
$pack = cp::getpack
();
$info = new WebInfo
();
$webinfo = $info->getWebInfo(2
);
// 获取版本
$type = $_GET['type'] ?? 1
;
$upinfo = cp::checkUpdate(2
);
?>
<link rel=
"stylesheet" href="/Resource/Template/default/assets/css/page.min.css"
>
<link rel=
"stylesheet" href="/Resource/Template/default/assets/css/XuZhiGlobal.min.css"
>
<style>
.WebPagesPg{
background-color:
#fff;
min-height:
100
vh;
}
.tab-header {
display: flex;
border-bottom:
1px solid #eee;
margin-bottom:
20
px;
}
.tab-header div {
padding:
10px 20
px;
cursor: pointer;
font-size:
16
px;
border-bottom:
2
px solid transparent;
}
.tab-header .active {
border-color:
#1890ff;
font-weight: bold;
color:
#1890ff;
}
.tabpanel {
display: none;
}
.tabpanel.active {
display: block;
}
.update-box {
border:
1px solid #ddd;
padding:
16
px;
background:
#f9f9f9;
border-radius:
8
px;
}
.update-log {
margin-top:
16
px;
}
.download-box {
margin-top:
20
px;
}
.download-btn {
display: inline-block;
padding:
10px 16
px;
background-color:
#1466ff;
color:
#fff;
border-radius:
6
px;
text-decoration: none;
}
.download-btn:hover {
background-color:
#0056d2;
}
</style>
<div
class="WebPagesPg" id="WebPages
">
<!-- 标签页 -->
<
div class="tab-header
">
<
div :class="{tabbtn:true, active:showtag == 1}" data-tab="update" @click="showtag = 1
">模板配置</div>
<div :class="
{tabbtn:true, active:showtag == 2}" data-tab="config" @click="showtag = 2
">模板更新</div>
</div>
<div class="
x_from
">
<!-- 模板更新 -->
<!-- 模板配置 -->
<div :class="
{tabpanel:true, active:showtag == 1}" id="tab-update
">
<div class="
x_from_item
">
<p class="
x_from_title
">站点简介</p>
<input type="
text" v-model="conform.desc" class="x_input" id="site_desc" placeholder="请输入站点简介
">
<trg class="
x_from_trg
">Ps: 将显示在首页底部文字区域</trg>
</div>
<div class="
x_from_item
">
<p class="
x_from_title
">底部二维码</p>
<input type="
text" class="x_input" v-model="conform.qr_urla" id="qr_urla" placeholder="请输入二维码图片地址
">
</div>
<div class="
x_from_item
">
<p class="
x_from_title
">底部二维码</p>
<input type="
text" class="x_input" v-model="conform.qr_urlb" id="qr_urlb" placeholder="请输入二维码图片地址
">
</div>
<div class="
x_from_item
">
<button class="
x_button" @click="upconfig()
">确认修改配置</button>
</div>
</div>
<div :class="
{tabpanel:true, active:showtag == 2}" id="tab-config
">
<div class="
x_from_item" style="display: flex; gap: 20px; align-items: flex-start;
">
<div style="
flex: 1;
">
<p class="
">模板名称:<span id="tep_name" style="color: #333;">{{ tepInfo.tep_name}}</span></p>
<p
class="">模板标识:<span id="tep_cansid" style="color: #888;">
{{ tepInfo.tep_cansid}}</span></p>
<p
class="">模板版本:<span id="tep_version" style="color: #007bff;">v{{ tepInfo.tep_version}}</span> -- <span id="tep_version" style="color: #007bff;"
>v{{upinfo.NewVersion}}</span></p>
<p
class="">作者:<span id="author_name" style="color: #555;">
{{tepInfo.author_name}}</span></p>
</div>
</div>
<button
class="x_button" @click="update()" style="margin-bottom: 20px;">更新至最新版</button
>
<
div v-if="upinfo && upinfo.data?.length
">
<
div class="update-box
">
<
h2 style="font-size: 16px">版本更新说明</h2
>
<
p style="margin-top: 10px"><strong>最新版本:</strong>
{{ upinfo.NewVersion }}</p>
<div v-html=
"upinfo.data[0].x_word" class="update-log"></div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
img style="display: none;" src="/Public/Assets/images/loadw.png" alt
="">
<
script src="/Public/Assets/js/axios.js"></script
>
<
script src="/Public/Assets/js/vue.js"></script
>
<
script
>
const
{
ref,
createApp
} = Vue;
const App
= {
data
() {
const showtag = ref(1
);
const config = ref(JSON.parse('<?= json_encode($config, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>'
));
const tepInfo = ref(JSON.parse('<?= json_encode($pack, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>'
));
const upinfo = ref(<?= json_encode($upinfo
, JSON_UNESCAPED_UNICODE) ?>);
const conform = ref
({
type: 'TempCallBack'
,
status: 1
,
desc
: config.value.footer_text,
qr_urla: config.value.footer_qrlist?.[0]?.url || ""
,
qr_urlb: config.value.footer_qrlist?.[1]?.url || ""
,
})
const upconfig
= () => {
window.
parent.postMessage(JSON.parse(JSON.stringify
(conform.value)))
}
const update
= () => {
window.
parent.postMessage
({
type: 'TempCallBack'
,
status: 2
})
}
// 检查版本
return
{
config,
tepInfo,
conform,
showtag,
upinfo,
upconfig,
update
}
}
}
const app = Vue.createApp
(App);
window.vm = app.
mount("#WebPages"
);
</script>五、功能说明
| 功能模块 | 描述 |
|---|---|
CallBack() | 处理来自系统的回调事件(如配置更新、版本升级) |
init() | 初始化函数,在前台加载时执行 |
Userinit() | 用户中心初始化函数 |
Admininit() | 后台初始化函数,可用于检查模板更新 |
getAuthCert() | 可选的授权验证逻辑 |
六、注意事项
- 所有模板页面需放置在
/usr/themes/目录下。 - 若模板包含用户中心页面,请放入
user/文件夹,并确保系统会自动进行登录验证。 - 使用 Vue.js 前端框架时,确保引入了对应的 JS 库(如
vue.js,axios.js)。 - 所有数据交互应使用
window.parent.postMessage()发送至主窗口处理。
{/collapse-item}
由阿里云ECS服务器支持
由多吉云提供CDN支持
我来讲讲 (0)