阿里云云开发活动#笔记 Day7

Seele.Clover 发布于


文章总访问次数:

阿里云云开发活动#笔记 Day7

——Midway Serverless一体化应用开发实战

今日作业:在云开发平台使用MySQL或者OTS模板创建应用,使用自己的对应数据库实现一个注册和登陆系统

1、为了简化操作,本次作业将在第5天作业的基础上完成。若要从零开始开发,请先完成第5天的操作步骤。(点击下方链接跳转第5天的作业笔记)

阿里云云开发活动#笔记 Day5
阿里云云开发活动#笔记 Day5

2、打开表格存储的“管理控制台”,打开我们在第5天创建的那个实例(我这里的实例名是lesson)

阿里云-表格存储
阿里云-表格存储

我们需要在这个实例中再创建一张数据表,信息填写如下图所示(数据表名称:user,表主键:id,下拉选择:字符串;这里的信息原则上不能变动)
Day7-1

3、进入CloudIDE,今天我们一共需要改动以下4个文件(你可以选择直接复制这里的代码粘贴过去):
Day7-2

其中2个文件为增添,1个文件为修改,1个文件为新建;改动部分会在代码高亮框中标出,代码内容讲解直接在写在注释中

本节课程源码
本节课程源码

f.yml(增添)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
service: serverless-hello-world

provider:
name: aliyun
runtime: nodejs10

functions:
render:
handler: render.handler
events:
- apigw:
path: /*
list:
handler: todo.list
events:
- apigw:
path: /api/list
update:
handler: todo.update
events:
- apigw:
path: /api/update
remove:
handler: todo.remove
events:
- apigw:
path: /api/remove
add:
handler: todo.add
events:
- apigw:
path: /api/add
# 增添部分开始
register:
handler: user.register
events:
- apigw:
path: /api/register
login:
handler: user.login
events:
- apigw:
path: /api/login
# 增添部分结束

package:
include:
- build
artifact: code.zip

public/index.html(增添)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Todo List</title>
<!--增添部分开始-->
<link href="https://cdn.bootcdn.net/ajax/libs/tailwindcss/1.6.2/tailwind.min.css" rel="stylesheet">
<!--增添部分结束-->
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

src/index.tsx(修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import React, { useEffect, useState } from 'react'
import ReactDOM from 'react-dom';

import './index.css';
import 'todomvc-app-css/index.css'
import { AddTodoEntry } from './components/entry'
import Footer from './components/footer'
import Todos from './components/todos'

/*修改部分开始*/
export default function App() {
const [name, setName] = useState('')
const [password, setPassword] = useState('')

const handleRegister = () => {
console.log('name is', name)
console.log('password is', password)

fetch(`/api/register?name=${name}&password=${password}`)
.then(resp => resp.json())
.then(resp => {
if (resp.success === true) {
alert('注册成功')
}
})
}

const handleLogin = () => {
console.log('name is', name)
console.log('password is', password)

fetch(`/api/login?name=${name}&password=${password}`)
.then(resp => resp.json())
.then(resp => {
if (resp.success === true) {
alert(`登录成功,用户名:${resp.user.name}`)
} else {
alert(`登录失败,提示信息:${resp.message}`)
}
})
}

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
onChange={e => {
console.log('当前输入的账号是:', e.target.value)
setName(e.target.value)
}}
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
onChange={e => {
setPassword(e.target.value)
}}
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" onClick={handleRegister} 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" onClick={handleLogin} 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')
);

src/apis/user.ts(新建)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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 },
{ status: '1' }
]
};
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
});
}
});
});
}
}

4、最后启动Dev Server

1
$ npm run dev

Day7-3

这时CloudIDE会自动生成一个预览网址,我们访问这个网址可以看到一个“注册或登录页面”
Day7-4

5、我们先往其中填入信息进行注册,注册成功会有弹出提示
Day7-5

一旦注册成功,在表格存储的“管理控制台”——“lesson”实例——“user”数据表——“数据管理”中可以看到写入的注册信息(账户与密码)
Day7-6

然后我们再进行登录操作,登录成功会有弹出提示
Day7-7