本节目标
- 编写 mutation 操作,登录、注册
- graphql 操作类加入异常处理
视频
https://www.bilibili.com/vide...
代码
https://github.com/ducafecat/...
strapi 运行环境网盘下载
- 网盘
链接:https://pan.baidu.com/s/13Ujy...
密码:yu82
- 运行
需要用 docker-compose 启动
账号 admin
密码 123456
# 启动
docker-compose up -d --remove-orphans
# 关闭
docker-compose down
正文
- 调试地址
http://localhost:1337/graphql
注册 graphql
- mutation
mutation UserRegister($username: String!, $email: String!, $password: String!) {
register(input: { username: $username, email: $email, password: $password }) {
jwt
user {
id
username
email
role {
id
name
description
type
}
blocked
confirmed
}
}
}
- variables
{
"username": "dbuser",
"email": "[email protected]",
"password": "12345678"
}
登录 graphql
mutation UserLogin($identifier: String!, $password: String!) {
login(input: { identifier: $identifier, password: $password }) {
jwt
user {
id
username
email
role {
id
name
description
type
}
blocked
confirmed
}
}
}
- variables
{
"identifier": "dbuser",
"password": "12345678"
}
identifier 可以是 username、email ,都是唯一的
Graphql 请求类加入异常处理
- lib/common/utils/graphql_client.dart
import 'package:flutter/material.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';
import 'package:flutter_ducafecat_news/common/values/values.dart';
import 'package:flutter_ducafecat_news/common/widgets/widgets.dart';
import 'package:flutter_ducafecat_news/global.dart';
import 'package:graphql/client.dart';
class GraphqlClientUtil {
static OptimisticCache cache = OptimisticCache(
dataIdFromObject: typenameDataIdFromObject,
);
static client() {
HttpLink _httpLink = HttpLink(
uri: '$SERVER_STRAPI_GRAPHQL_URL/graphql',
);
if (Global.profile?.jwt != null) {
final AuthLink _authLink = AuthLink(
getToken: () => 'Bearer ${Global.profile.jwt}',
);
final Link _link = _authLink.concat(_httpLink);
return GraphQLClient(
cache: cache,
link: _link,
);
} else {
return GraphQLClient(
cache: cache,
link: _httpLink,
);
}
}
/// 错误处理
static _formatException(BuildContext context, OperationException exception) {
var statusCode = '';
try {
statusCode = exception
.graphqlErrors[0]?.extensions["exception"]["output"]["statusCode"]
.toString();
if (statusCode == '') {
statusCode = exception.graphqlErrors[0]?.extensions["exception"]["code"]
.toString();
}
} catch (e) {}
switch (statusCode) {
case '400': // 重新登录
toastInfo(msg: "错误请求,提交数据错误!");
break;
case '401': // 没有认证
case '403': // 没有授权
toastInfo(msg: "账号无效、服务没有授权,请重新登录!");
return goLoginPage(context);
// break;
default:
toastInfo(msg: exception.toString());
}
throw exception;
}
// 查询
static Future query({
@required BuildContext context,
@required String schema,
Map variables,
}) async {
QueryOptions options = QueryOptions(
documentNode: gql(schema),
variables: variables,
);
QueryResult result = await client().query(options);
if (result.hasException) {
_formatException(context, result.exception);
}
return result;
}
// 操作
static Future mutate({
@required BuildContext context,
@required String schema,
Map variables,
}) async {
MutationOptions options = MutationOptions(
documentNode: gql(schema),
variables: variables,
);
QueryResult result = await client().mutate(options);
if (result.hasException) {
_formatException(context, result.exception);
}
return result;
}
}
- 常见错误码:
400 数据提交时间
401 需要登录认证
403 功能需要授权
Entity 用户
- lib/common/entitys/gql_user.dart
// 用户登录 - request
class GqlUserLoginRequestEntity {
GqlUserLoginRequestEntity({
this.identifier,
this.password,
});
String identifier;
String password;
factory GqlUserLoginRequestEntity.fromJson(Map json) =>
GqlUserLoginRequestEntity(
identifier: json["identifier"],
password: json["password"],
);
Map toJson() => {
"identifier": identifier,
"password": password,
};
}
// 用户登录 - request
class GqlUserRegisterRequestEntity {
GqlUserRegisterRequestEntity({
this.username,
this.email,
this.password,
});
String username;
String email;
String password;
factory GqlUserRegisterRequestEntity.fromJson(Map json) =>
GqlUserRegisterRequestEntity(
username: json["username"],
email: json["email"],
password: json["password"],
);
Map toJson() => {
"username": username,
"email": email,
"password": password,
};
}
//////////////////////////////////////////////////////////////////
// 用户登录 - response
class GqlUserLoginResponseEntity {
GqlUserLoginResponseEntity({
this.jwt,
this.user,
});
String jwt;
UserEntity user;
factory GqlUserLoginResponseEntity.fromJson(Map json) =>
GqlUserLoginResponseEntity(
jwt: json["jwt"],
user: UserEntity.fromJson(json["user"]),
);
Map toJson() => {
"jwt": jwt,
"user": user.toJson(),
};
}
// 注册新用户 - response
class GqlUserRegisterResponseEntity {
GqlUserRegisterResponseEntity({
this.jwt,
this.user,
});
String jwt;
UserEntity user;
factory GqlUserRegisterResponseEntity.fromJson(Map json) =>
GqlUserRegisterResponseEntity(
jwt: json["jwt"],
user: UserEntity.fromJson(json["user"]),
);
Map toJson() => {
"jwt": jwt,
"user": user.toJson(),
};
}
// 用户
class UserEntity {
UserEntity({
this.id,
this.username,
this.email,
this.role,
this.blocked,
this.confirmed,
});
String id;
String username;
String email;
RoleEntity role;
bool blocked;
bool confirmed;
factory UserEntity.fromJson(Map json) => UserEntity(
id: json["id"],
username: json["username"],
email: json["email"],
role: RoleEntity.fromJson(json["role"]),
blocked: json["blocked"],
confirmed: json["confirmed"],
);
Map toJson() => {
"id": id,
"username": username,
"email": email,
"role": role.toJson(),
"blocked": blocked,
"confirmed": confirmed,
};
}
// 角色
class RoleEntity {
RoleEntity({
this.id,
this.name,
this.description,
this.type,
});
String id;
String name;
String description;
String type;
factory RoleEntity.fromJson(Map json) => RoleEntity(
id: json["id"],
name: json["name"],
description: json["description"],
type: json["type"],
);
Map toJson() => {
"id": id,
"name": name,
"description": description,
"type": type,
};
}
API 用户注册、登录
- lib/common/apis/gql_user.dart
import 'package:flutter/material.dart';
import 'package:flutter_ducafecat_news/common/entitys/entitys.dart';
import 'package:flutter_ducafecat_news/common/graphql/graphql.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';
import 'package:graphql/client.dart';
/// 新闻
class GqlUserAPI {
/// 登录
static Future login({
@required BuildContext context,
@required GqlUserLoginRequestEntity variables,
}) async {
QueryResult response = await GraphqlClientUtil.mutate(
context: context,
schema: GQL_USER_LOGIN,
variables: variables.toJson());
return GqlUserLoginResponseEntity.fromJson(response.data["login"]);
}
/// 注册
static Future register({
@required BuildContext context,
@required GqlUserRegisterRequestEntity variables,
}) async {
QueryResult response = await GraphqlClientUtil.mutate(
context: context,
schema: GQL_USER_REGISTER,
variables: variables.toJson());
return GqlUserRegisterResponseEntity.fromJson(response.data["register"]);
}
}
资源
设计稿蓝湖预览
https://lanhuapp.com/url/lYuz1
密码: gSKl
蓝湖现在收费了,所以查看标记还请自己上传 xd 设计稿
商业设计稿文件不好直接分享, 可以加微信联系 ducafecat
© 猫哥