likes
comments
collection
share

strapi实现接口自由

作者站长头像
站长
· 阅读数 18

CMS

我们先来了解下CMS(Content Management System,内容管理系统),它是一种用于管理和发布网站内容的软件工具或平台。通过CMS,用户可以方便地创建、修改和发布网站内容,包括文章、图片、视频等各种形式的信息。CMS的主要目标是使网站管理和维护过程变得更加简单和高效,使非技术人员也能轻松地创建、编辑和发布内容,无需编写代码或了解复杂的技术知识。

常见的CMS系统有:wordpress、drupal、joomla。CMS有很多种类型,具体的可见什么是内容管理系统 (CMS)?,如果我们只需要它的内容管理功能,而不需要它的内容展示功能怎么办呢?这个时候我们可以使用无头CMS。

无头CMS

无头CMS是一种内容管理系统,它将前端和后端分离,只关注内容的创建和管理,而不处理呈现内容的前端界面。传统的CMS通常将内容管理和展示耦合在一起,即内容的创建、编辑和展示都依赖于特定的前端界面和模板。而无头CMS则将内容与前端逻辑完全解耦,提供了一种更加灵活的方式来处理内容。

无头CMS的工作原理是,通过提供API来让开发者获取和管理内容,而不是通过特定的模板和页面来展示内容。这样,开发者可以使用任何前端技术或框架来构建用户界面,而不受CMS制约。

无头CMS有以下的一些好处:

  • 它允许开发人员将网站的后端和前端解耦,从而更容易管理和更新内容。
  • 多渠道发布,内容可以轻松地在不同平台和设备上展示。
  • 它可以提高网站性能,因为后端不负责渲染页面。
  • 无头 CMS 通常比传统 CMS 更具可扩展性,因为它可以处理大量流量而无需额外资源。

无头CMS有很多,我们今天要实践的是strapi

Strapi

Strapi 是一款开源无头 CMS,它使开发者可以自由选择自己喜欢的工具和框架,并允许编辑人员使用应用的管理面板来管理和分发其内容。 Strapi 基于插件系统,是一个灵活的 CMS,其管理面板和 API 是可扩展的 - 并且每个部分都可以定制以匹配任何用例。 Strapi 还具有内置用户系统,可详细管理管理员和终端用户有权访问的内容。

安装

安装文档可见从 CLI 安装

npx create-strapi-app@4.14.5 my-project

本文使用的数据库是mysql,所以选用自定义安装:

strapi实现接口自由

安装过程中可能会出现sharp安装失败,解决办法可参考npm或者yarn安装sharp太慢、失败等问题。 数据库连接中可能会出现问题,解决办法可参考Linux CentOS 7 安装mysql的两种方式mysql连接失败

安装完成后来将它运行起来:

npm run develop

浏览器会自动打开一个选项卡,让我们创建账户,完成后,你将成为该 Strapi 应用的第一个管理员用户。

登录进去之后,可以看到我们的主界面:

strapi实现接口自由

界面都是英文的,我们可以将其设置成中文界面:

1、在src/admin下面新建一个app.js

export default {
  config: {
    locales: [
      'zh-Hans',
    ],
  },
};

2、重启我们的项目,打开页面,选择“中文(简体)”:

strapi实现接口自由

新建接口

本文要实现的是一个小说管理后台,需要以下接口:小说列表的增删改查接口,小说目录的增删改查接口、小说内容的增删改查接口。

1、先让我们来新建小说列表的接口:

strapi实现接口自由

选择旁边的“高级设置”,勾选“草稿&发布”,会让我们在新建内容保存后先存为草稿然后再点击发布,如果不勾选的话,内容保存即发布:

strapi实现接口自由

点击右下角的“继续”按钮,会跳转到新增字段弹窗,选择字段的类型:

strapi实现接口自由

类型选择好之后,设置字段的名称和属性:

strapi实现接口自由

选择“高级设置”,可以设置该字段的属性:

strapi实现接口自由

如果还有其它的字段需要添加,可以点击右下角的“添加另一个字段”,没有则点击完成。

点击右上角的“保存”按钮,服务会自动重启,该接口创建成功。后续如还要新增字段,右上角有“添加一个新字段”按钮。

Strapi内置有用户权限系统,我们来配置下列表接口的权限:

strapi实现接口自由

默认有两种角色,Authenticated是需要登录的,Public是不需要登录的,我们的接口都是需要登录才能访问的,所以选择Authenticated

strapi实现接口自由

可以看到原本我们新建的list接口,下面有增删改查,鼠标放到某个接口上,点击旁边的小图标,右侧可以看到该接口的请求方式和请求地址。勾选上list所有接口,然后点击右上角的“保存”按钮,接口权限就配置好了。

2、新建目录接口

新建及权限配置方法同list接口,有一点不同的是,我们需要把目录和小说关联上,哪些目录属于同一本小说,所以我们需要建立下目录和小说的关联。

添加一个新字段,类型选择“引用”:

strapi实现接口自由

关联关系选择多对一,多个catalogue对一个list,也就是一个list下面可以有多个catalogue

strapi实现接口自由

3、新建内容接口

新建及权限配置方法同catalogue接口,同理,内容需要和目录关联上,该目录下有啥内容,属于一对一的关系:

strapi实现接口自由

接口调用

接口请求参数及返回数据格式可见文档 REST API

新建一个前端项目,技术栈自选。

新建接口请求文件,utils/request.ts

import axios from "axios";

export const request = axios.create({
  baseURL: "http://localhost:1337", 
  timeout: 50000,
});
 
request.interceptors.request.use((config) => {
  const jwt = window.localStorage.getItem("jwt");
  if (jwt) {
    config!.headers!.Authorization = "Bearer " + jwt;
  }
  console.log(config);

  return config;
});

新建接口调用文件,api/index.ts

import { request } from "@/utils/request";

export interface LoginData {
  identifier?: string;
  password?: string;
}

export interface RegisterData {
  username?: string;
  email?: string;
  password?: string;
}

// 登录
export function login(data: LoginData) {
  return request.post("/api/auth/local", data);
}

// 注册
export function register(data: RegisterData) {
  return request.post("/api/auth/local/register", data);
}

// 获取小说列表
export function getLists(query: any) {
  return request.get(`/api/lists?${query}`);
}

// 获取小说目录
export function getCatalogues(query: any) {
  return request.get(`/api/catalogues?${query}`);
}

新建登录注册页,接口调用如下:

// 注册
const onRegister = async () => {
    try {
        await register({
          username: xxxx; // 用户名
          email: xxxx; // 邮箱
          password: xxxx; // 密码
        })
    } catch (error) {
        console.log(error, "注册失败")
    }
};

// 登录
const onLogin = async () => {
    try {
        const res = await login({
          identifier: xxxx; // 用户名
          password: xxxx; // 密码
        })
        const data = res.data;
        localStorage.setItem("jwt", data.jwt);
    } catch (error) {
        console.log(error, "登录失败")
    }
};

新建小说列表展示页,获取小说列表接口调用如下:

const handleSearch = async () => {
    try {
        const query = qs.stringify(
            {
                populate: ['catalogues'], // 数据中是否填充关联数据,不设置则返回的列表不会包含关联数据
                sort: "starNum:DESC", // 列表排序,可设置排序的字段和顺序
                pagination: { // 分页参数
                    page: current,
                    pageSize: pageSize,
                },
            },
            {
                encodeValuesOnly: true, // 仅对value进行编码
            }
        );
        const res = await getLists(query)
        const tableData = res?.data?.data?.map((item: any) => ({
            id: item.id,
            ...item.attributes
        })) || []
    } catch (error) {
        console.log(error, "获取列表失败")
    }
}

新建小说目录展示页,接口调用如下:

const handleSearch = async () => {
    try {
        let filters: any = undefined;
        if (id) {
            filters = {
                list: {
                    id: {
                        $eq: id, // 根据小说id去查该小说下的所有目录
                    },
                },
            };
        }
        const query = qs.stringify(
            {
                populate: "*", // 设置为“*”代表查出所有的关联数据
                sort: "catalogueNum:asc",
                filters,
                pagination: {
                    page: 1,
                    pageSize: 3000,
                },
            },
            {
                encodeValuesOnly: true, 
            }
        );
        const res = await getCatalogues(query)
        console.log(res)
    } catch (error) {
        console.log(error, "获取小说目录失败")
    }
}

参考文章