strapi实现接口自由
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
,所以选用自定义安装:
安装过程中可能会出现sharp
安装失败,解决办法可参考npm或者yarn安装sharp太慢、失败等问题。
数据库连接中可能会出现问题,解决办法可参考Linux CentOS 7 安装mysql的两种方式、mysql连接失败。
安装完成后来将它运行起来:
npm run develop
浏览器会自动打开一个选项卡,让我们创建账户,完成后,你将成为该 Strapi 应用的第一个管理员用户。
登录进去之后,可以看到我们的主界面:
界面都是英文的,我们可以将其设置成中文界面:
1、在src/admin
下面新建一个app.js
:
export default {
config: {
locales: [
'zh-Hans',
],
},
};
2、重启我们的项目,打开页面,选择“中文(简体)”:
新建接口
本文要实现的是一个小说管理后台,需要以下接口:小说列表的增删改查接口,小说目录的增删改查接口、小说内容的增删改查接口。
1、先让我们来新建小说列表的接口:
选择旁边的“高级设置”,勾选“草稿&发布”,会让我们在新建内容保存后先存为草稿然后再点击发布,如果不勾选的话,内容保存即发布:
点击右下角的“继续”按钮,会跳转到新增字段弹窗,选择字段的类型:
类型选择好之后,设置字段的名称和属性:
选择“高级设置”,可以设置该字段的属性:
如果还有其它的字段需要添加,可以点击右下角的“添加另一个字段”,没有则点击完成。
点击右上角的“保存”按钮,服务会自动重启,该接口创建成功。后续如还要新增字段,右上角有“添加一个新字段”按钮。
Strapi
内置有用户权限系统,我们来配置下列表接口的权限:
默认有两种角色,Authenticated
是需要登录的,Public
是不需要登录的,我们的接口都是需要登录才能访问的,所以选择Authenticated
:
可以看到原本我们新建的list
接口,下面有增删改查,鼠标放到某个接口上,点击旁边的小图标,右侧可以看到该接口的请求方式和请求地址。勾选上list
所有接口,然后点击右上角的“保存”按钮,接口权限就配置好了。
2、新建目录接口
新建及权限配置方法同list
接口,有一点不同的是,我们需要把目录和小说关联上,哪些目录属于同一本小说,所以我们需要建立下目录和小说的关联。
添加一个新字段,类型选择“引用”:
关联关系选择多对一,多个catalogue
对一个list
,也就是一个list
下面可以有多个catalogue
:
3、新建内容接口
新建及权限配置方法同catalogue
接口,同理,内容需要和目录关联上,该目录下有啥内容,属于一对一的关系:
接口调用
接口请求参数及返回数据格式可见文档 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, "获取小说目录失败")
}
}
参考文章
转载自:https://juejin.cn/post/7303702670320746536