阿里云七天云开发校园合伙人创造营 Day 7

云开发7天训练营学习计划

在这里插入图片描述

阿里云云开发平台校园合伙人招募 主要提供了 云开发平台 进行 Web 开发的体验,包括以下内容:

完结撒花 🎉 ,点击上面的链接可以回顾这七天的内容哦~

Day 7: 在 Midway Serverless 数据库示例模板中实现一个注册和登陆系统

关于 Midway Serverless

关于 Midway Serverless 的相关介绍,请参考 Day2 的文章

每日任务

今日任务为使用 Midway Serverless 数据库示例模板实现一个注册和登录系统,展示注册和登录功能。

本次任务原理跟 Day5 相似,请先阅读 Day5 文章每日任务 部分

1. 准备开发环境

登入云开发平台,进入到应用列表,点击 创建新应用,新建一个 WEB 实验室解决方案的 Midway Serverless OTS数据库示例

创建好后,进入 开发部署

在这里插入图片描述

进入 IDE 后,先在终端执行:

npm i --registry=https://registry.npm.taobao.org

安装 npm 依赖,因为依赖包很多,这里用了淘宝的镜像源,安装会更快。

2. 开发调试

本次任务是直接在 ToDo List 示例的基础上修改,先附上需要改动的地方:

.
├── f.yml                          # 修改函数定义文件
├── public
|   └── index.html                 # 修改前端 HTML 主页
└── src
	├── index.tsx                  # 修改 React 前端代码
   	└── apis
		├── user.ts                # 增加函数文件
		└── config
			└── config.default.ts  # 部署环境变量配置

同时,我将全部代码上传到 GitHub,可以用于覆盖原来的代码,具体上传代码到远程仓库的方法在 Day1 文章每日任务 第三部分有提及。

2.1 修改代码

按照开发逻辑,首先修改后端代码,在 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.ymlfunctions 下声明定义注册、登录这两个函数,增加代码:

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>
2.2 连接数据库

要实现功能,需要开通阿里云 OTS 数据库,创建数据表,以及申请一个 AccessKey。具体请回顾 Day5 文章 每日任务 的第二部分。

与 Day5 文章中不同的是,这里只需要创建一个名为 user 的数据表,表主键为 id

在这里插入图片描述

2.3 调试

修改好环境变量后,可以执行 npm run dev 运行项目,点击生成的链接查看页面。

在这里插入图片描述

尝试注册一个新账号,注册成功时会弹窗提示:

在这里插入图片描述

尝试使用此账号登录,登录成功时会弹窗提示:

在这里插入图片描述

登录异常情况示例:

  1. 用户不存在

在这里插入图片描述

  1. 密码错误

在这里插入图片描述

3. 部署上线

正式部署上线前记得将 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。

七天创造营就到此结束了,对后续 项目实战 内容感兴趣的朋友们记得 关注我 哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值