使用TFPHP开发TFUMS项目的标签模块的回收站功能【20210703】

发表于 2021-07-04
阅读 18

介绍

介绍

上一课福哥带着大家使用TFPHP框架给TFUMS项目增加了全套的标签模块的增、删、改、查功能,标签的删除功能福哥使用的是状态删除方式而不是物理删除方式,为的就是那些误删除的标签可以通过恢复功能找回来,今天福哥要带着大家来实现这个恢复功能。

标签模块的恢复功能和删除功能相对的,删除功能是把标签状态改为T_STATE_LOCKED,恢复功能是把标签状态改回T_STATE_NORMAL。

为了实现标签模块的恢复功能,福哥建立了一个标签模块的回收站,里面可以查到已经删除掉的标签信息。

结构

模型

WEB-APP/Model/tag.inc.php

控制器

WEB-APP/Controller/admin/tag/recycle.inc.php
WEB-APP/Controller/api/admin/tag.inc.php
WEB-APP/Controller/api/admin/tag/.mapping.inc.php
WEB-APP/Controller/api/resource/tag.inc.php
WEB-APP/Controller/api/resource/tag/.mapping.inc.php

视图

WEB-APP/View/Template/admin/tag/recycle.html
js/pages/admin/tag/recycle.js

删除(Delete)

错误码

1012031 - 错误请求
1012032 - 标签不存在
1012033 - 保存失败
1012034 - 恢复失败

模型

WEB-APP/Model/tag.inc.php

public function restore(int $userID, int $tagID):int {
    // check exist
    $tagInfo = $this->getByTable("tag", array(tag::T_TYPE, $tagID));
    if($tagInfo == null){

        return 1;
    }

    // mod
    $ret = $this->update("tag", array(
        'cTypeId'=>tag::T_TYPE,
        'cId'=>$tagID,
        'cStat'=>tag::T_STATE_NORMAL,
        'updateDT'=>date("Y-m-d H:i:s"),
    ));
    if(!$ret){

        return 2;
    }

    return 0;
}

控制器

WEB-APP/Controller/api/admin/tag/.mapping.inc.php

private function doRestore(){
    $pathVars = $this->tfphp->getRequest()->server->get("PATH_VARIABLE");
    $tag = new tag($this->tfphp);
    $tagId = $pathVars['tag'];

    try{
        if(!($tagId > 0)) {
            $this->tfphp->getResponse()->responseJSON_CM(200, 1012031, "错误请求");
        }

        // delete
        $ret = $tag->restore($this->login->getLoginStatus()->mId,
            $tagId);
        switch ($ret){
            case 1:
                $this->tfphp->getResponse()->responseJSON_CM(200, 1012032, "标签不存在");
                break;
            case 2:
                $this->tfphp->getResponse()->responseJSON_CM(200, 1012033, "保存失败");
                break;
        }
    }
    catch(\Exception $e){
        TFLog::getDefault($this->tfphp)->error($e->getMessage());

        $this->tfphp->getResponse()->responseJSON_CM(200, 1012034, "恢复失败");
    }

    // output
    $this->tfphp->getResponse()->responseJSON_CM(200, 0, "OK", array(
        'tagid'=>$tagId,
    ));
}

视图

HTML

<!-- restore form -->
<div class="dlg-box dlg-restore-form">
    <form class="form restore-form">
        <div class="dlg-header">
            <div class="dlg-tool-box">
                <i class="btn-close">X</i>
            </div>
            <div class="dlg-title">
                恢复标签
            </div>
        </div>
        <div class="dlg-content">
            <div class="form-group">
                <label>标签名称</label>
                <span class="form-text" name="title"></span>
            </div>
        </div>
        <div class="dlg-footer">
            <button class="btn btn-primary btn-sm">恢复</button>
        </div>
    </form>
</div>

JS

_startRestoreForm: function(id) {
    var ex=this;
    var formOpts;

    formOpts = {
        url: this.baseUri + "api/admin/tag/" + id + "/_restore",
        method: "post",
        dataUrl: this.baseUri + "api/resource/tag/" + id + "/_detail",
        dataMethod: "post",
        onSuccess: function (d) {
            if(d.errcode == 0){
                ex._dlg_restore_form.close();
                ex._list.refresh(null, true);
            }
            else{
                $('form.restore-form').tips({
                    text:d.errmsg
                });
            }
        },
        onError: function (d) {
            $('form.restore-form').tips({
                text:"服务器响应错误"
            });
        },
        onDataSuccess: function (d) {
            $('form.restore-form').find('[name="title"]').text(d.cName);
        },
        onValidationError: function (form, name, msg) {
            $('form.restore-form').tips({
                text:msg
            });
            $('form.restore-form').find('[name="'+ name +'"]').focus();
        }
    };
    this._mod_form = $('form.restore-form').form(formOpts);
},

查询(Retreive)

模型

WEB-APP/Model/tag.inc.php

public function loadDeletedTags(int $parentID, string $keyword, int $pageSize, int $pageNum, array $states=null):array {
    $tfdo = $this->tfphp->getDatabase()->getTFDO();

    $sql = "SELECT a.cId, a.cName FROM tfart_categories a
        WHERE a.cPId = @int
            AND a.cStat = @int";
    if($keyword != ""){
        $sql .= " AND a.cName LIKE '%". str_replace("'", "\'", $keyword). "%'";
    }
    $sql .= " ORDER BY a.cId DESC";
    $params = array($parentID, tag::T_STATE_LOCKED);
    $total = $tfdo->fetchTotal($sql, $params);
    $page = new TFDataPage($this->tfphp, $total, $pageSize, $pageNum);
    $page->makeTeamlinkRange(6);
    $pageArr = $page->toArray();
    $datas = $tfdo->fetchPart($sql, $pageArr['seekBegin'], $pageArr['fetchNums'], $params);

    if(is_array($datas)){
        foreach($datas as $k => $data){

        }
    }

    return array(
        'page'=>$pageArr,
        'data'=>$datas,
    );
}

控制器

WEB-APP/Controller/api/admin/tag.inc.php

private function doListDeleted(){
    $req = $this->tfphp->getRequest();
    $tag = new tag($this->tfphp);
    $keyword = $req->post->get("keyword");

    $datas = $tag->loadDeletedTags(intval($req->get->get("pid")),
        strval($keyword),
        10,
        intval($req->get->get("pn")));

    // output
    $this->tfphp->getResponse()->responseJSON(200, $datas);
}

视图

HTML

<div class="row">
    <div class="col-12">
        <div class="tag-search">
            <form class="search-form form-horizontal">
                <div class="row">
                    <div class="col-12">
                        <div class="float-left">

                        </div>
                        <div class="float-right">
                            <div class="form-inline">
                                <span><label>关键词</label></span>
                                <span><input class="form-control" type="text" name="keyword" /></span>
                                <span><button class="btn btn-primary btn-sm form-control">搜索</button></span>
                            </div>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <div class="col-12">
        <div class="tag-list">
            <table class="table">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>标签</th>
                    <th>&nbsp;</th>
                </tr>
                </thead>
                <tbody>

                </tbody>
            </table>

            <ul class="pagination">
                <li><a>第一页</a></li>
                <li><a>前一页</a></li>
                <li class="active"><a>1</a></li>
                <li><a>2</a></li>
                <li><a>3</a></li>
                <li><a>4</a></li>
                <li><a>5</a></li>
                <li><a>6</a></li>
                <li><a>后一页</a></li>
                <li><a>最后页</a></li>
            </ul>
        </div>
    </div>
</div>

JS

_startTable: function (_pn) {
    var ex = this;
    var tableOpts;

    tableOpts = {
        dataUrl: this.baseUri + "api/admin/tag/_list_deleted?pn={pn}",
        dataMethod: "post",
        dataRenderType: "classic",
        pn: _pn,
        attachRowEvent: function (obj, id) {
            var item = obj.find('tr[dataid="' + id + '"]'), dataid = id;

            item.find('.btn-restore').click(function () {
                // restore
                ex._openRestoreForm(dataid);
            });
        },
        onRenderTable: function (data, table) {
            var obj = table.find(".table").find("tbody");

            obj.find("tr").remove();
        },
        onRenderRow: function (row, table) {
            var obj = table.find(".table").find("tbody"), extraBtns, extraClass;

            extraBtns = '';
            extraClass = '';
            obj.append('<tr dataid="' + row.cId + '">' +
                '       <td>' + row.cId + '</td>' +
                '       <td><a href="">' + row.cName + '</a></td>' +
                '       <td class="btns">' +
                '           <span class="btn btn-white btn-sm btn-restore">恢复</span>' +
                '       </td>' +
                '</tr>');

            this.attachRowEvent(obj, row.cId);
        },
        onRenderPage: function (page, table) {
            var obj = table.find(".pagination"), html = "";

            obj.html("");
            if (page.pageNum > 1) {
                obj.append('<li><a page-num="1">第一页</a></li>');
                obj.append('<li><a page-num="' + (page.pageNum - 1) + '">前一页</a></li>');
            }
            if (page.pageTeamlinkRange) {
                for (var p = page.pageTeamlinkRange.low; p <= page.pageTeamlinkRange.high; p++) {
                    obj.append('<li><a page-num="' + p + '">' + p + '</a></li>');
                }
                obj.find('[page-num="' + page.pageNum + '"]').parent().addClass("active");
            }
            if (page.pageNum < page.pageTotal) {
                obj.append('<li><a page-num="' + (page.pageNum + 1) + '">后一页</a></li>');
                obj.append('<li><a page-num="' + page.pageTotal + '">最后页</a></li>');
            }
        },
        onError: function (d) {

        }
    };
    this._list = $('.tag-list').table(tableOpts);
},

_startSearchForm: function() {
    var ex=this;
    var formOpts;

    formOpts = {
        method: "post",
        onSuccess: function (d) {
            if(d.page && d.data){

            }
            else{
                $('form.search').tips({
                    text:d.errmsg
                });
            }
        },
        onError: function (d) {
            $('form.search').tips({
                text:"服务器响应错误"
            });
        },
        onValidationError: function (form, name, msg) {
            $('form.search').tips({
                text:msg
            });
            $('form.search').find('[name="'+ name +'"]').focus();
        }
    };
    formOpts.table = this._list;
    this._search_form = $('form.search-form').form(formOpts);
},

效果

列表

home/topic/2021/0704/16/6fd4665d2adb7cf926c28080f7187550.png

表单

home/topic/2021/0704/16/ab7c56692a6cab3e1d594c4855152045.png

总结

今天福哥带着童鞋们给TFUMS项目的标签模块增加了恢复功能,通过恢复功能可以实现已删除标签的找回功能!大家可以看到标签的删除功能和恢复功能都是执行的update操作,这就是模块功能的状态删除的实现技巧!


鬼谷子叔叔

跟福哥学编程吧~~
日志
212
浏览
1626