[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"getwebinfo":3,"news-item-11":4},null,{"classListRes":-1,"articleRes":5},{"code":6,"msg":3,"data":7,"total":3},200,{"id":8,"dwo_html":9,"dwo_name":10,"dwo_image":11,"dwo_time":12,"dwo_brief":13,"dwo_keywords":14,"dwo_cid":15,"dwo_show":16,"dwo_uid":17,"dwo_status":15,"dwo_comment_count":18,"dwo_status_reason":3,"dwo_status_time":3,"status_text":19},11,"\u003Cblockquote>本文档为CansCode API管理系统开发手册，适用于系统二次开发人员、模板开发者及插件开发工程师。文档系统梳理了开发过程中核心的技术要点，涵盖内置钩子、数据库操作函数及模板开发规范三大核心模块。其中，内置钩子部分详细说明支付、上传、系统相关钩子的类型、权重及使用场景，并提供注册实例；数据库函数部分包含函数引入方式与查询、新增、修改、删除等常用操作示例；模板规范部分则针对Typecho模板（兼容Joe主题），明确目录结构、核心文件功能、配置页面开发及关键注意事项。通过本文档，开发者可快速掌握系统开发的基础规范与核心能力，提升开发效率并保障开发质量。\u003C\u002Fblockquote>\u003Ch2>内置钩子文档\u003C\u002Fh2>\u003Ch3>支付相关\u003C\u002Fh3>\u003Cul>\u003Cli>Pay_Create_qq类型：执行钩子权重：1-100说明：创建支付订单时，QQ支付，可执行钩子，返回订单所有数据。\u003C\u002Fli>\u003Cli>Pay_Create_wx类型：执行钩子说明：创建支付订单时，微信支付，可执行钩子，返回订单所有数据。\u003C\u002Fli>\u003Cli>Pay_Create_ali类型：执行钩子说明：创建支付订单时，支付宝，可执行钩子，返回订单所有数据。\u003C\u002Fli>\u003Cli>Pay_Create_balance类型：执行钩子（非必要请勿使用！）说明：创建支付订单时，余额支付，可执行钩子，返回订单所有数据。\u003C\u002Fli>\u003Cli>Pay_Create类型：数据钩子说明：创建支付订单时，可返回数据钩子，用于创建后对订单数据进行编辑和返回。\u003C\u002Fli>\u003Cli>Pay_CallBack类型：执行钩子说明：支付成功回调钩子，返回所有回调数据。注意：发起支付若需要跳转链接而不是html，请确保code = 522 并且链接在 data中。\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>上传相关\u003C\u002Fh3>\u003Cul>\u003Cli>Update_File_Start类型：执行钩子权重：1-100说明：上传文件开始，返回$_FILES[\"file\"]。\u003C\u002Fli>\u003Cli>Update_Image_Start类型：执行钩子说明：上传图片开始，返回$_FILES[\"file\"]。\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>系统相关\u003C\u002Fh3>\u003Cul>\u003Cli>WebNotification类型：数据钩子权重：1-100说明：后台系统通知。\u003C\u002Fli>\u003Cli>AdminNav_Left类型：数据钩子说明：后台导航栏左侧。\u003C\u002Fli>\u003Cli>AdminNav_Chen类型：数据钩子说明：后台导航栏子栏目。\u003C\u002Fli>\u003Cli>\u003Cstrong>注意\u003C\u002Fstrong>：内置钩子请勿重复注册，否则可能出现插件异常，权重越小，越先执行。\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>注册实例\u003C\u002Fh3>\u003Cp>提供两种类型的钩子注册示例：执行类钩子和数据处理类钩子。\u003C\u002Fp>\u003Cp>执行类钩子注册实例：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">use Logic\\Important\\Hooks;\n\u002F\u002F 注册支付创建后，QQ支付处理钩子\nHooks::Register(\"Pay_Create_qq\", 1, function($parameter) {\n    echo \"Pay_Create_qq\";\n    var_dump($parameter);\n    exit();\n}, 10);\n数据处理类钩子注册实例：\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">use Logic\\Important\\Hooks;\n\u002F\u002F 支付创建后，处理数据，并将数据返回\nHooks::Register(\"Pay_Create\", 2, function($parameter) {\n    $parameter['payname'] = \"我爱你\";\n    return $parameter;\n}, 10);\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>内置函数\u003C\u002Fh3>\u003Cp>返回数据函数：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">use Logic\\Important\\Tos;\n\n\u002F\u002F 返回状态\nTos::sendmsg(200);\n\n\u002F\u002F 返回单个数据\nTos::sendmsg(200, \"\", $data);\n\n\u002F\u002F 返回列表数据\nTos::sendmsg(200, \"\", $data, $total);\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2>数据库内置函数\u003C\u002Fh2>\u003Ch3>一、引入函数\u003C\u002Fh3>\u003Cp>使用SqlFun库来处理数据库操作。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">use Logic\\Important\\SqlFun;\n\npublic function __construct()\n{\n   \u002F\u002F 获取数据库实例\n   $this-&gt;db = SqlFun::getInstance();\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>二、函数使用示例\u003C\u002Fh3>\u003Cp>1. 普通查询数据\u003C\u002Fp>\u003Cp>执行一个简单的查询操作以获取数据。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">$result = $this-&gt;db-&gt;query(\"SELECT * FROM xxx WHERE id = ?\", [$id]);\n2. 修改数据\n更新表中的特定记录。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">$this-&gt;db-&gt;update(\"xxxxx\", [\n    \"xu_fans\" =&gt; $merinfo[0]['xu_fans'] - 1,\n], 'id = ?', [$merinfo[0]['id']]);\n3. 删除数据\n从指定表中删除一条记录。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">$this-&gt;db-&gt;delete(\"xu_merfans\", \"id = ?\", [$res[0]['id']]);\n4. 写入数据\n向指定表中插入新数据。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">$this-&gt;db-&gt;insert(\"xu_keyapi\", [\n    \"xu_aid\" =&gt; $aidlist[$a],\n    \"xu_kid\" =&gt; $ids\n]);\n5. 数据库语句拼接\n使用SqlFun提供的方法构建复杂的SQL查询。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">$sql = SqlFun::SqlBuilderAdd(\"xu_name\", $pre['search'], 'like')\n            -&gt;SqlBuilderAdd(\"xu_mid\", $pre['mid'])\n            -&gt;SqlBuilderAdd(\"xu_status\", 1)\n            -&gt;SqlBuilderBuild();\n            6. 数据库查询语句（分页查询）\n            执行分页查询，并返回结果。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-php\">$result = $this-&gt;db-&gt;getPaginatedData(\"xu_api\", $sql, [$pre['sortname'], $pre['sorttype']], $pagination, [\n    \"xu_queryper\", \"xu_bodyper\", \"xu_headerper\", \"xu_cookies\", \"xu_errlist\", \"xu_bodyjson\", \"xu_words\", \"xu_apisource\"\n]);\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2>模板规范\u003C\u002Fh2>\u003Ch3>Typecho 模板开发指南（Joe 主题兼容）\u003C\u002Fh3>\u003Ch4>一、目录结构\u003C\u002Fh4>\u003Cp>一个标准的 Typecho 模板目录结构如下：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-Plain Text\">mytemplate\u002F\n├── user\u002F                  # 用户中心页面（自动判断登录）\n├── Main.php               # 主逻辑文件\n├── package.json           # 模板描述信息文件\n├── ConfigurationPage.php  # 模板配置页面\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch4>二、Main.php —— 主逻辑文件\u003C\u002Fh4>\u003Cp>该文件定义模板的核心行为和生命周期钩子。\u003C\u002Fp>\u003Cp>示例代码：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">&lt;?php\n\nnamespace Resource\\Template\\default;\n\nuse Logic\\Important\\Rote;\nuse Logic\\Important\\Tos;\nuse Resource\\Template\\default\\cp;\n\nclass Main\n{\n    public function CallBack($parameter)\n    {\n        if ($parameter['status'] == 1) {\n            cp::setteP($data);\n            Tos::sendmsg(200);\n        }\n\n        if ($parameter['status'] == 2) {\n            cp::checkUpdate(3);\n        }\n    }\n\n    public function init(): void\n    {\n        $this-&gt;getAuthCert();\n    }\n\n    public function Userinit(): void\n    {\n        $this-&gt;getAuthCert();\n    }\n\n    public function Admininit(): void\n    {\n        \u002F\u002F 检查模板是否存在新版本\n        cp::checkUpdate();\n    }\n\n    public function getAuthCert()\n    {\n        \u002F\u002F 授权验证示例（可选）\n        \u002F\u002F $auth = new Rote();\n        \u002F\u002F $res = $auth-&gt;appCertificate('5a6e619c-29d1-2890-1776-14078b36b4c3');\n        \u002F\u002F if ($res['code'] !== '5200') {\n        \u002F\u002F     error_log('未授权');\n        \u002F\u002F } else {\n        \u002F\u002F     error_log('已授权');\n        \u002F\u002F }\n    }\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch4>三、package.json —— 模板描述文件\u003C\u002Fh4>\u003Cp>用于存储模板的基本信息，便于管理与更新。\u003C\u002Fp>\u003Cp>示例内容：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"tep_name\": \"默认模板\",\n  \"tep_version\": \"0.0.1\",\n  \"tep_image\": \"https:\u002F\u002Fimgsbad.semoun.com\u002Fuploads\u002F2025\u002F03\u002F19\u002F67da24298292e.jpg\",\n  \"tep_brief\": \"自带的默认模板\",\n  \"tep_cansid\": \"default\",\n  \"tep_page\": true,\n  \"tep_PagePath\": \"ConfigurationPage.php\",\n  \"tep_code\": \"5a6e619c-29d1-2890-1776-14078b36b4c3\",\n  \"author_name\": \"CansCode\"\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch4>四、ConfigurationPage.php —— 模板配置页面\u003C\u002Fh4>\u003Cp>用于提供后台可视化配置界面，支持用户自定义设置。\u003C\u002Fp>\u003Cp>示例代码片段（HTML + Vue.js）：\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-php\">&lt;?php\n\nuse Logic\\Function\\MainControl\\WebInfo;\nuse Resource\\Template\\default\\cp;\n\n$config = cp::gettep();\n$pack = cp::getpack();\n$info = new WebInfo();\n$webinfo = $info-&gt;getWebInfo(2);\n\n\u002F\u002F 获取版本\n$type = $_GET['type'] ?? 1;\n\n$upinfo = cp::checkUpdate(2);\n?&gt;\n&lt;link rel=\"stylesheet\" href=\"\u002FResource\u002FTemplate\u002Fdefault\u002Fassets\u002Fcss\u002Fpage.min.css\"&gt;\n&lt;link rel=\"stylesheet\" href=\"\u002FResource\u002FTemplate\u002Fdefault\u002Fassets\u002Fcss\u002FXuZhiGlobal.min.css\"&gt;\n&lt;style&gt;\n    .WebPagesPg{\n        background-color: #fff;\n        min-height: 100vh;\n    }\n    .tab-header {\n        display: flex;\n        border-bottom: 1px solid #eee;\n        margin-bottom: 20px;\n    }\n\n    .tab-header div {\n        padding: 10px 20px;\n        cursor: pointer;\n        font-size: 16px;\n        border-bottom: 2px solid transparent;\n    }\n\n    .tab-header .active {\n        border-color: #1890ff;\n        font-weight: bold;\n        color: #1890ff;\n    }\n\n    .tabpanel {\n        display: none;\n    }\n\n    .tabpanel.active {\n        display: block;\n    }\n\n    .update-box {\n        border: 1px solid #ddd;\n        padding: 16px;\n        background: #f9f9f9;\n        border-radius: 8px;\n    }\n\n    .update-log {\n        margin-top: 16px;\n    }\n\n    .download-box {\n        margin-top: 20px;\n    }\n\n    .download-btn {\n        display: inline-block;\n        padding: 10px 16px;\n        background-color: #1466ff;\n        color: #fff;\n        border-radius: 6px;\n        text-decoration: none;\n    }\n\n    .download-btn:hover {\n        background-color: #0056d2;\n    }\n&lt;\u002Fstyle&gt;\n\n&lt;div class=\"WebPagesPg\" id=\"WebPages\"&gt;\n    &lt;!-- 标签页 --&gt;\n    &lt;div class=\"tab-header\"&gt;\n        &lt;div :class=\"{tabbtn:true, active:showtag == 1}\" data-tab=\"update\" @click=\"showtag = 1\"&gt;模板配置&lt;\u002Fdiv&gt;\n        &lt;div :class=\"{tabbtn:true, active:showtag == 2}\" data-tab=\"config\" @click=\"showtag = 2\"&gt;模板更新&lt;\u002Fdiv&gt;\n    &lt;\u002Fdiv&gt;\n\n    &lt;div class=\"x_from\"&gt;\n        &lt;!-- 模板配置 --&gt;\n        &lt;div :class=\"{tabpanel:true, active:showtag == 1}\" id=\"tab-update\"&gt;\n            &lt;div class=\"x_from_item\"&gt;\n                &lt;p class=\"x_from_title\"&gt;站点简介&lt;\u002Fp&gt;\n                &lt;input type=\"text\" v-model=\"conform.desc\" class=\"x_input\" id=\"site_desc\" placeholder=\"请输入站点简介\"&gt;\n                &lt;trg class=\"x_from_trg\"&gt;Ps: 将显示在首页底部文字区域&lt;\u002Ftrg&gt;\n            &lt;\u002Fdiv&gt;\n            &lt;div class=\"x_from_item\"&gt;\n                &lt;p class=\"x_from_title\"&gt;底部二维码&lt;\u002Fp&gt;\n                &lt;input type=\"text\" class=\"x_input\" v-model=\"conform.qr_urla\" id=\"qr_urla\" placeholder=\"请输入二维码图片地址\"&gt;\n            &lt;\u002Fdiv&gt;\n            &lt;div class=\"x_from_item\"&gt;\n                &lt;p class=\"x_from_title\"&gt;底部二维码&lt;\u002Fp&gt;\n                &lt;input type=\"text\" class=\"x_input\" v-model=\"conform.qr_urlb\" id=\"qr_urlb\" placeholder=\"请输入二维码图片地址\"&gt;\n            &lt;\u002Fdiv&gt;\n            &lt;div class=\"x_from_item\"&gt;\n                &lt;button class=\"x_button\" @click=\"upconfig()\"&gt;确认修改配置&lt;\u002Fbutton&gt;\n            &lt;\u002Fdiv&gt;\n        &lt;\u002Fdiv&gt;\n        &lt;div :class=\"{tabpanel:true, active:showtag == 2}\" id=\"tab-config\"&gt;\n            &lt;div class=\"x_from_item\" style=\"display: flex; gap: 20px; align-items: flex-start;\"&gt;\n                &lt;div style=\"flex: 1;\"&gt;\n                    &lt;p class=\"\"&gt;模板名称：&lt;span id=\"tep_name\" style=\"color: #333;\"&gt;{{ tepInfo.tep_name}}&lt;\u002Fspan&gt;&lt;\u002Fp&gt;\n                    &lt;p class=\"\"&gt;模板标识：&lt;span id=\"tep_cansid\" style=\"color: #888;\"&gt;{{ tepInfo.tep_cansid}}&lt;\u002Fspan&gt;&lt;\u002Fp&gt;\n                    &lt;p class=\"\"&gt;模板版本：&lt;span id=\"tep_version\" style=\"color: #007bff;\"&gt;v{{ tepInfo.tep_version}}&lt;\u002Fspan&gt; -- &lt;span id=\"tep_version\" style=\"color: #007bff;\"&gt;v{{upinfo.NewVersion}}&lt;\u002Fspan&gt;&lt;\u002Fp&gt;\n                    &lt;p class=\"\"&gt;作者：&lt;span id=\"author_name\" style=\"color: #555;\"&gt;{{tepInfo.author_name}}&lt;\u002Fspan&gt;&lt;\u002Fp&gt;\n                &lt;\u002Fdiv&gt;\n            &lt;\u002Fdiv&gt;\n            &lt;button class=\"x_button\" @click=\"update()\" style=\"margin-bottom: 20px;\"&gt;更新至最新版&lt;\u002Fbutton&gt;\n            &lt;div v-if=\"upinfo && upinfo.data?.length\"&gt;\n                &lt;div class=\"update-box\"&gt;\n                    &lt;h2 style=\"font-size: 16px\"&gt;版本更新说明&lt;\u002Fh2&gt;\n                    &lt;p style=\"margin-top: 10px\"&gt;&lt;strong&gt;最新版本：&lt;\u002Fstrong&gt; {{ upinfo.NewVersion }}&lt;\u002Fp&gt;\n                    &lt;div v-html=\"upinfo.data[0].x_word\" class=\"update-log\"&gt;&lt;\u002Fdiv&gt;\n                &lt;\u002Fdiv&gt;\n            &lt;\u002Fdiv&gt;\n        &lt;\u002Fdiv&gt;\n    &lt;\u002Fdiv&gt;\n&lt;\u002Fdiv&gt;\n&lt;img style=\"display: none;\" src=\"\u002FPublic\u002FAssets\u002Fimages\u002Floadw.png\" alt=\"\"&gt;\n&lt;script src=\"\u002FPublic\u002FAssets\u002Fjs\u002Faxios.js\"&gt;&lt;\u002Fscript&gt;\n&lt;script src=\"\u002FPublic\u002FAssets\u002Fjs\u002Fvue.js\"&gt;&lt;\u002Fscript&gt;\n&lt;script&gt;\n    const {\n        ref,\n        createApp\n    } = Vue;\n    const App = {\n        data() {\n            const showtag = ref(1);\n            const config = ref(JSON.parse('&lt;?= json_encode($config, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?&gt;'));\n            const tepInfo = ref(JSON.parse('&lt;?= json_encode($pack, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?&gt;'));\n            const upinfo = ref(&lt;?= json_encode($upinfo, JSON_UNESCAPED_UNICODE) ?&gt;);\n\n            const conform = ref({\n                type: 'TempCallBack',\n                status: 1,\n                desc: config.value.footer_text,\n                qr_urla: config.value.footer_qrlist?.[0]?.url || \"\",\n                qr_urlb: config.value.footer_qrlist?.[1]?.url || \"\",\n            })\n\n            const upconfig = () =&gt; {\n                window.parent.postMessage(JSON.parse(JSON.stringify(conform.value)))\n            }\n            const update = () =&gt; {\n                window.parent.postMessage({\n                    type: 'TempCallBack',\n                    status: 2\n                })\n            }\n\n            return {\n                config,\n                tepInfo,\n                conform,\n                showtag,\n                upinfo,\n                upconfig,\n                update\n            }\n        }\n    }\n    const app = Vue.createApp(App);\n    window.vm = app.mount(\"#WebPages\");\n&lt;\u002Fscript&gt;\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch4>五、功能说明\u003C\u002Fh4>\u003Cp>\u003Cbr>\u003C\u002Fp>\u003Ctable style=\"width: auto;\">\u003Ctbody>\u003Ctr>\u003Cth colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: left;\">功能模块\u003C\u002Fth>\u003Cth colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: left;\">描述\u003C\u002Fth>\u003C\u002Ftr>\u003Ctr>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">CallBack()\u003C\u002Ftd>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">处理来自系统的回调事件（如配置更新、版本升级）\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">init()\u003C\u002Ftd>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">初始化函数，在前台加载时执行\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">Userinit()\u003C\u002Ftd>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">用户中心初始化函数\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">Admininit()\u003C\u002Ftd>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">后台初始化函数，可用于检查模板更新\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">getAuthCert()\u003C\u002Ftd>\u003Ctd colSpan=\"1\" rowSpan=\"1\" width=\"auto\">可选的授权验证逻辑\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>六、注意事项\u003C\u002Fh4>\u003Cul>\u003Cli>所有模板页面需放置在 \u002Fusr\u002Fthemes\u002F 目录下。\u003C\u002Fli>\u003Cli>若模板包含用户中心页面，请放入 user\u002F 文件夹，并确保系统会自动进行登录验证。\u003C\u002Fli>\u003Cli>使用 Vue.js 前端框架时，确保引入了对应的 JS 库（如 vue.js, axios.js）。\u003C\u002Fli>\u003Cli>所有数据交互应使用 window.parent.postMessage() 发送至主窗口处理。\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cbr>\u003C\u002Fp>","CansCodeAPI开发文档","https:\u002F\u002Foss4liview.moji.com\u002Fthd_file\u002F2025\u002F12\u002F16\u002F72d96811fa32a1b296f46e5bafd760db.png","2025-06-05 18:53:34","本文档为CansCode API管理系统开发手册，适用于系统二次开发人员、模板开发者及插件开发工程师。","API开发手册,钩子文档,数据库操作,模板开发规范,二次开发指南,插件开发,开发教程",1,"1",16,0,"已上架"]