# 使用 Pocketbase 作为评论后端的可能性并简单尝试

> [使用 Pocketbase 作为评论后端的可能性并简单尝试](https://www.ftls.xyz/posts/20230804-pocketbase/)
> Penned by [恐咖兵糖](https://www.ftls.xyz/) on 2023-08-04

PocketBase 是一个 Golang 写的的简单后端。下面验证一下 PocketBase 作为评论系统后端的可能性。

<!--more-->

我使用的版本 PocketBase v0.17.1 ，在支持嵌入 js 之后，PocketBase 可以更加简单方便的自定义各种需要的功能。

## PocketBase 创建数据结构

评论系统建议配置好 OAuth2.0 和邮箱，PocketBase 支持的登录方式还是很多的。配置完成之后，调用提供的 js SDK 其中的登陆方法，会自动在 users 新建账户 ，并且绑定登录的方式，如 Github 。这些新建的账户并不能登录进入 Admin web UI ,是给普通用户使用的，需要自己写前端。

使用 Admin 账户登录，新建 collection ，我这里取名 dis 。以下是表的结构。

![](https://cdn.ftls.xyz/images/2023/06/20230804112335.png)

第一行是主要内容，最好限制一个长度，er 代表发布人，关系选择 users 表，replay 代表回复的评论。内容和发布人都不可以为空，回复则可以为空。

下面配置 API 访问规则：

![](https://cdn.ftls.xyz/images/2023/06/20230804113057.png)

```
List/Search 为空
View 为空
Create: @request.auth.id != "" && @request.auth.id = er.id  && text != ""
Update: @request.auth.id = er.id
Delete: @request.auth.id = er.id
```

这其中代表的含义是列出和查看,不需要任何的权限。而创建则需要使用一个账户进行创建并且字段中 er 代表的创建者的账户和请求者的账户 id 需要相同，并且新创建的文字并不能为空。更新和删除都需要请求 id 和字段中 er 代表的创建者的账户相同。

## PocketBase 嵌入 js

文档 [https://pocketbase.io/docs/js-overview](https://pocketbase.io/docs/js-overview)
创建一个回复之后我们还需要的功能就是给被回复的人发送一个邮件提醒。在 Pocketbase 运行目录下创建 pb\_hooks/main.pb.js

```javascript
onModelAfterCreate((e) => {
    try {
        let replay_id = e.model.getString("replay")
        if (replay_id != "") {
            let replay_record = $app.dao().findRecordById("dis", replay_id)
            // console.log(replay_record)
            let replay_userid = replay_record.getString("er")
            let user_record = $app.dao().findRecordById("users", replay_userid)
            let email = user_record.getString("email")
            console.log(email)
            if (email != "") {
                const message = new MailerMessage({
                    from: {
                        address: $app.settings().meta.senderAddress,
                        name: $app.settings().meta.senderName,
                    },
                    to: [{ address: user_record.email() }],
                    subject: "回复...",
                    html: "原留言： " + replay_record.getString("text") + "<br>回复： " + e.model.getString("text"),
                    // bcc, cc and custom headers are also supported...
                })

                $app.newMailClient().send(message)
            }
        }
    } catch (error) {
        console.error(error);
    }
}, "dis")
```

这段代码的功能就是监测 dis Collection , 如果回复了某一个消息，在创建完成后触发该函数，找到需要发送邮件的用户 id ，然后获取用户的 email ，然后调用内置的邮件发送功能进行提醒。

## 简单前端使用

外面贴一个我当时测试使用的代码。并没有详细的每一步进行测试。只是基本验证了登录显示等功能，发送邮件我是在 admin web上测试的。

```ts
<script setup lang="ts">
import { ref } from 'vue'
import PocketBase from 'pocketbase';


defineProps<{ msg: string }>()

const resultList:any = ref("xxx");
const input = ref("input");
const replay = ref("myanb0fbp7dyr00");


const pb = new PocketBase('https://pocketbase.example.com');


function Login() {
  pb.collection('users').authWithOAuth2({ provider: 'gitea' });
}

function Read() {
  let id = pb.authStore.model?.id;
  console.log(id);
  pb.collection('dis').getList(1, 50, {
    filter: `created >= "2022-01-01 00:00:00" && er = "${id}"`,
    expand: 'replay',
  },).then(res => {
    console.log(res);
    resultList.value =  res;
  })
}

function Send() {
  let id = pb.authStore.model?.id;
  const data = {
    "text": `${input.value}`,
    "er": `${id}`,
    "replay": `${replay.value}`
  };
  pb.collection('dis').create(data).then( res => {
    console.log(res);
    Read();
  })
}
</script>

<template>
  <div v-for="item in resultList.items">
    id: {{ item.id }} text: {{ item.text }} {{ item.er }} replay： {{ item.replay }}
  </div>
  <div class="card">
    <button type="button" @click="Login">Login</button>
    <button type="button" @click="Read">Read</button>
    <br>
    <br>
    {{  input  }}
    <input type="text" v-model="input"/>
    <br>
    <br>
    {{  replay  }}
    <input type="text" v-model="replay"/>
    <button type="button" @click="Send">Send</button>
  </div>
</template>

<style scoped>
.read-the-docs {
  color: #888;
}
</style>{% endraw %}
```

## 结论

基本软件在作为评论系统的可行性。然而实际上评论系统并不缺好用的方案，如 Artalk - 轻量、安全、易上手的自托管评论系统 ，或者是使用 Github Issues 。不过也算是在一定程度上可以快速搭建评论系统的前后端，而且自己写嵌入 js 脚本确实也挺方便的。