导航菜单
登录 注册

有人问到点赞功能,这里抽取代码分享一下,因为去掉了部分敏感信息,可能需要调试一下。
我的设计思路是使用自定义字段来存储点赞次数。和市面上的方案不一样,不过大同小异。

增加接口

首先要修改functions.phpthemeInit函数,加入点赞接口

function themeInit($archive)
{
    if ($archive->is('single')) {
        if ($archive->request->isPost()) {
            if ($archive->request->is('themeAction=promo')) {
                promo($archive);
            }
        }
    }
}

接着要加入点赞核心函数,下面的函数可以扩展

/**
 * Post Action AJAX接口
 *
 * @param Widget_Archive $widget
 * @return void
 * @date 2020-05-04
 */
function promo($widget)
{

    $user = $widget->widget('Widget_User');
    $db = Typecho_Db::get();
    $fields = unserialize($widget->fields);
    $allowOperates = array('get', 'set', 'inc', 'dec'); // 这里可以扩展操作,建议屏蔽get/set
    $allowFields = array('likes'); // 这里可以扩展修改字段

    // 获取操作
    $operate = $widget->request->get('operate');
    $field = $widget->request->get('field');
    $value = $widget->request->filter('int')->get('value');
    $value = $value === null ? 100 : $value; // 100 起步

    $result = array('cid' => $widget->cid);

    if ($operate === "get") {
        $result['operate'] = 'get';
        if (array_key_exists($field, $fields)) {
            $result[$field] = $fields[$field];
        } else {
            $result[$field] = -1;
        }
        $widget->response->throwJson(array('status' => 1, 'msg' => _t('已获取参数'), 'result' => json_encode($result)));
    } elseif ($operate === "set") {
        $result['operate'] = 'set';
        if ($value > 0) {
            $widget->setField($field, 'str', $value, $widget->cid);
        } else {
            $db->query($db->delete('table.fields')
                ->where('cid = ? AND name = ?', $widget->cid, $field));
        }
        $widget->response->throwJson(array('status' => 1, 'msg' => _t('已完成操作'), 'result' => json_encode($result)));
    } elseif ($operate === "inc") {
        $result['operate'] = 'inc';
        $value = intval($fields[$field]) + 1;
        $widget->setField($field, 'str', $value, $widget->cid);
        $result[$field] = $value;
        $widget->response->throwJson(array('status' => 1, 'msg' => _t('已完成操作'), 'result' => json_encode($result)));
    } elseif ($operate === "dec") {
        $result['operate'] = 'dec';
        $value = intval($fields[$field]) - 1;
        $result[$field] = $value;
        if ($value > 0) {
            $widget->setField($field, 'str', $value, $widget->cid);
        } else {
            $db->query($db->delete('table.fields')
                ->where('cid = ? AND name = ?', $widget->cid, $field));
        }
        $widget->response->throwJson(array('status' => 1, 'msg' => _t('已完成操作'), 'result' => json_encode($result)));
    }
}

Post 请求参数说明

operate:操作
field: 操作字段
value:操作值,inc/dec 操作用不到

前端方面

这里我给出我的参考 js 代码,实际建议自己写一下,使用 jq 也不复杂。

function likesCallback(count) {
    $("#likesPostCount").value(count);
}
$("#likesPost").click(function () {
    posturl = $(location).attr("href").split("?")[0] + "?themeAction=promo";
    $.ajax({
        url: posturl,
        type: "POST",
        data: { operate: "inc", field: "likes" },
        dataType: "json",
        success: function (result) {
            if (1 == result.status) {
                result = JSON.parse(result.result)
                likes =
                    undefined === result.likes ?
                        -1 :
                        result.likes;
                likesCallback(result.likes); 
            } else {
                // 提醒错误消息
                alert(
                    undefined === result.msg ?
                        '点赞失败' :
                        result.msg
                );
            }
        },
        error: function (xhr, ajaxOptions, thrownError) {
            alert('点赞失败' + ajaxOptions);
        },
    });
});

输出

因为使用自定义字段存储,所以输出和普通自定义字段一样

<?php echo $this->fields->likes; ?>
MyBatis的TypeHandler使用之 Java时间戳与PHP时间戳互转
上一篇
Typecho 无需插件集成 Sitemap(站点地图)
下一篇
广告