阿里云云开发平台校园合伙人招募 主要提供了 云开发平台 进行 Web 开发的体验,包括以下内容:
认识 Serverless 云开发 (8.3) :学习云开发平台的基本概念和操作、团队协同、应用的开发、部署
云函数 (8.4) :函数的基础概念,架构,调用方式、静态文件的托管方式
开发Web接口 (8.5):学习使用函数开发 Web 接口、多个函数的同时开发,资源复用
服务端渲染 (8.6):学习使用函数接入传统 koa 中间件,构建 Web 应用
数据库调用 (8.7):学习接入数据库,调用数据存储
多媒体托管和支付 (8.10):学习函数的文件多媒体托管和支持能力
一体化方案开发实战 (8.11):学习和前端 ( react / vue ) 代码一起开发的一体化方案
完结撒花 ,点击上面的链接可以回顾这七天的内容哦~
关于 Midway Serverless 的相关介绍,请参考 Day2 的文章
今日任务为使用 Midway Serverless 数据库示例模板实现一个注册和登录系统,展示注册和登录功能。
本次任务原理跟 Day5 相似,请先阅读 Day5 文章 的 每日任务 部分
登入云开发平台,进入到应用列表,点击 创建新应用
,新建一个 WEB 实验室解决方案的 Midway Serverless OTS数据库示例
。
创建好后,进入 开发部署
。
进入 IDE 后,先在终端执行:
npm i --registry=https://registry.npm.taobao.org
安装 npm 依赖,因为依赖包很多,这里用了淘宝的镜像源,安装会更快。
本次任务是直接在 ToDo List 示例的基础上修改,先附上需要改动的地方:
.
├── f.yml # 修改函数定义文件
├── public
| └── index.html # 修改前端 HTML 主页
└── src
├── index.tsx # 修改 React 前端代码
└── apis
├── user.ts # 增加函数文件
└── config
└── config.default.ts # 部署环境变量配置
同时,我将全部代码上传到 GitHub,可以用于覆盖原来的代码,具体上传代码到远程仓库的方法在 Day1 文章 的 每日任务
第三部分有提及。
按照开发逻辑,首先修改后端代码,在 src/apis
下新增文件 user.ts
,主要定义了注册、登录这两个函数,实现一些数据库操作,完整代码如下:
import { Func, Inject, Provide } from '@midwayjs/decorator';
import TableStore from 'tablestore';
import format from 'otswhere/format';
@Provide()
export class UserService {
@Inject()
ctx;
@Inject()
tb;
@Func('user.login')
async login() {
const { name, password } = this.ctx.query;
const params = {
tableName: 'user',
direction: TableStore.Direction.BACKWARD,
inclusiveStartPrimaryKey: [{ id: TableStore.INF_MAX }],
exclusiveEndPrimaryKey: [{ id: TableStore.INF_MIN }]
};
return new Promise(resolve => {
this.tb.getRange(params, (_, data) => {
const rows = format.rows(data, { email: true });
const userExists = rows.list.findIndex(user => user.name === name) !== -1
if (!userExists) {
resolve({
success: false,
message: '用户不存在'
})
return
}
const user = rows.list.find(user => user.name === name);
if (user.password !== password) {
resolve({
success: false,
message: '密码不正确'
})
return
}
resolve({
success: true,
user
});
});
})
}
@Func('user.register')
async register() {
const { name, password } = this.ctx.query;
const params = {
tableName: "user",
condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),
primaryKey: [
{ id: `${Date.now()}-${Math.random()}` }
],
attributeColumns: [
{ name },
{ password }
]
};
return new Promise(resolve => {
this.tb.putRow(params, async function (err, data) {
if (err) {
resolve({
success: false,
errmsg: err.message
});
} else {
resolve({
success: true,
data
});
}
});
});
}
}
下一步,在函数定义文件 f.yml
的 functions
下声明定义注册、登录这两个函数,增加代码:
register:
handler: user.register
events:
- apigw:
path: /api/register
login:
handler: user.login
events:
- apigw:
path: /api/login
接下来修改前端代码,重写 src/index.tsx
文件构造前端页面:
import React, { useEffect, useState } from 'react'
import ReactDOM from 'react-dom';
export default function App() {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full">
<div>
<img className="mx-auto h-12 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-on-white.svg" alt="Workflow" />
<h2 className="mt-6 text-center text-3xl leading-9 font-extrabold text-gray-900">
注册或者登录
</h2>
</div>
<form className="mt-8" action="#" method="POST">
<input type="hidden" name="remember" defaultValue="true" />
<div className="rounded-md shadow-sm">
<div>
<input
aria-label="Email address" name="email" type="email" required className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5" placeholder="Email address" />
</div>
<div className="-mt-px">
<input
aria-label="Password" name="password" type="password" required className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5" placeholder="Password" />
</div>
</div>
<div className="mt-6">
<button type="button" className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out">
<span className="absolute left-0 inset-y-0 flex items-center pl-3">
</span>
注册
</button>
</div>
<div className="mt-6">
<button type="button" className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out">
<span className="absolute left-0 inset-y-0 flex items-center pl-3">
</span>
登录
</button>
</div>
</form>
</div>
</div>
)
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
修改 public/index.html
文件,在 head
标签结束前引入 CSS :
<head>
<link href="https://cdn.bootcdn.net/ajax/libs/tailwindcss/1.6.2/tailwind.min.css" rel="stylesheet">
head>
要实现功能,需要开通阿里云 OTS 数据库,创建数据表,以及申请一个 AccessKey。具体请回顾 Day5 文章 每日任务
的第二部分。
与 Day5 文章中不同的是,这里只需要创建一个名为 user
的数据表,表主键为 id
。
修改好环境变量后,可以执行 npm run dev
运行项目,点击生成的链接查看页面。
尝试注册一个新账号,注册成功时会弹窗提示:
尝试使用此账号登录,登录成功时会弹窗提示:
登录异常情况示例:
正式部署上线前记得将 src/apis/config/config.default.ts
文件改回默认状态。
本次任务同样可以使用 MySQL 数据库,只需在 Midway Serverless MySQL数据库示例
中增加并修改函数文件 user.ts
,并在自己的数据库中新建如下一张数据表即可。
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
这个简单的注册、登录只能作学习、演示使用,重点是如何在 Midway Serverless 中使用阿里云 BaaS 服务进行数据的操作和调用。
这个 demo 可改进的地方很多,比如注册时用户名是要求 Email 的,可以增加判断语句限定用户名必须为 Email 地址;又如密码错误次数过多,可以增加尝试次数限制、填写验证码、账号暂时锁定等;也可以限定密码的规范,进行密码加密或者增强验证,将注册和登录分为两个页面,增加跳转路由等等。
由于时间关系需要准备项目实战的内容,以上的改进成为了遗憾,后续 [视情况]^(看心情) 更新完善,也欢迎大家上 GitHub 提 issue 和 PR。
七天创造营就到此结束了,对后续 项目实战 内容感兴趣的朋友们记得 关注我 哦~