技术文献

Thinkphp3.2单页面自定义内容和后台维护

2026-04-20

应用网站:ktmchina.cn

1.添加数据库来保存单页面里面的内容

//sqlite数据库语法

CREATE TABLE contactconfig (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 key TEXT NOT NULL UNIQUE,
 contents TEXT
);

2.后台控制器

private $template='Home/View/Index/index.html';
private $mdbconfig="homeconfig";
public function index()
   {
       $list=gettemplate($this->template,$this->mdbconfig);
       $this->assign('list', $list);
       $this->display();
   }
public function save() {
       $result = savemdbconfig($this->mdbconfig);
       if ($result === true) {
           $this->success('保存成功');
       } else {
           $this->error('保存错误');
       }
   }

2.2后端视图

<form method="post" action="{:U('save')}">
    <volist name="list" id="vo">
        <div style="margin-bottom:20px;">
            <label style="font-weight:bold;display:block;margin-bottom:5px;">
                {$vo.key}
            </label>
            <textarea name="{$vo.key}" style="width:100%;height:100px;">{$vo.value}</textarea>
        </div>
    </volist>
    <button type="submit">保存</button>
</form>

3.Qwadmin\Common\function.php

//从template获得data-edit的数据到数据库的查询
function gettemplate($template,$mdbconfig){
   $html = file_get_contents(APP_PATH . $template);
   //echo $html;
   // 解析 HTML
   $fields = getEditableFields($html);
   //var_dump($fields);exit;
   // 取数据库数据
   $dbData = M($mdbconfig)->getField('key,contents');
   // 自动初始化(第一次用)
   foreach ($fields as $key => $value) {
       if (!isset($dbData[$key])) {
           M($mdbconfig)->add(array(
               'key' => $key,
               'contents' => $value
           ));
       }
   }
   // 再取一次(保证完整)
   $dbData = M($mdbconfig)->getField('key,contents');
   // 转成 list(给模板用)
   $list = array();
   foreach ($dbData as $key => $value) {
       $list[] = array(
           'key' => $key,
           'value' => $value
       );
   }
   return $list;
}
function getEditableFields($html) {
   libxml_use_internal_errors(true);
   $dom = new \DOMDocument();
   $dom->loadHTML('<?xml encoding="utf-8" ?>' . $html);
   $xpath = new \DOMXPath($dom);
   $nodes = $xpath->query('//*[@data-edit]');
   $fields = array();
   foreach ($nodes as $node) {
       $key = $node->getAttribute('data-edit');
       $innerHTML = '';
       foreach ($node->childNodes as $child) {
           $innerHTML .= $node->ownerDocument->saveHTML($child);
       }
       $fields[$key] = $innerHTML;
   }
   return $fields;
}
function savemdbconfig($mdbconfig){
   $model = M($mdbconfig);
   $model->startTrans();
   foreach ($_POST as $key => $value) {
       $res = $model->where(array('key'=>$key))->save(
           array('contents' => $value)
       );
       if ($res === false) {
           $model->rollback();
           return false;
       }
   }
   $model->commit();
   return true;
}

4.view视图中添加:data-edit="home_part1_title"属性

...
<span class="text-primary" data-edit="home_part1_title2">卓越精度的车辆管家</span>
<h3 class="font-bold" data-edit="home_part1_title6">极速办理</h3>
<p class="text-xs text-on-primary-container mt-2" data-edit="home_part1_title7">缩短50%以上等待周期</p>
...

5.前端视图控制器

private $template='Index/index';
private $mdbconfig='homeconfig';
public function index(){
       $this->renderAll($this->template,$this->mdbconfig);
   }

5.1renderAll函数在父类中定义:ComController.class.php

protected function renderAll($template,$mdbconfig)
{
    $html = $this->fetch($template);
    $data = M($mdbconfig)->getField('key,contents');
    $html = renderHtml($html, $data);
    echo $html;
}

6.Common/function.php

function renderHtml($html, $data) {
   libxml_use_internal_errors(true);
   // ✅ 正确初始化(指定编码)
   $dom = new \DOMDocument('1.0', 'UTF-8');
   // ✅ 不要再用 <?xml encoding...>
   $dom->loadHTML(
       mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')
   );
   $xpath = new \DOMXPath($dom);
   foreach ($data as $key => $value) {
       $nodes = $xpath->query("//*[@data-edit='$key']");
       foreach ($nodes as $node) {
           // 清空原内容
           while ($node->firstChild) {
               $node->removeChild($node->firstChild);
           }
           // 👇 判断是否纯文本
           if ($value == strip_tags($value)) {
               // ✅ 纯文本(不会出现 <p>)
               $node->appendChild($dom->createTextNode($value));
           } else {
               // ✅ HTML 内容处理
               $tmpDom = new \DOMDocument('1.0', 'UTF-8');
               libxml_use_internal_errors(true);
               $tmpDom->loadHTML(
                   mb_convert_encoding($value, 'HTML-ENTITIES', 'UTF-8')
               );
               $body = $tmpDom->getElementsByTagName('body')->item(0);
               if ($body) {
                   foreach ($body->childNodes as $child) {
                       $imported = $dom->importNode($child, true);
                       $node->appendChild($imported);
                   }
               }
           }
       }
   }
   // ✅ 输出 HTML
   $output = $dom->saveHTML();
   // ✅ 关键:还原中文(解决 &#xxx;)
   $output = html_entity_decode($output, ENT_QUOTES, 'UTF-8');
   return $output;
}