Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,38 @@ app.use("/user", userRouter);
app.use("/file", fileRouter);
app.use("/email", emailRouter);

// 要添加的新接口
app.post("/sendMessage", async (req, res) => {
// 从 Hasura Action 的请求体中获取参数
const { user_uuid, room_uuid, content } = req.body.input;

// 输入验证
if (!content || content.trim() === "") {
return res.status(400).json({
message: "Content cannot be empty",
});
}

// 调用 Hasura GraphQL API 来插入数据
try {
const data = await sdk.addMessage({
user_uuid: user_uuid,
room_uuid: room_uuid,
content: content,
});

// 返回成功响应
return res.json({
uuid: data.insert_message_one?.uuid,
});
} catch (err) {
console.error(err);
return res.status(500).json({
message: "Failed to send message",
});
}
});

app.listen(port, () => {
console.log(`Server running at ${address}:${port}/`);
});
9 changes: 9 additions & 0 deletions backend/src/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ const router = express.Router();

router.post("/login", async (req, res) => {
const { username, password } = req.body;
if (username.length < 3 || username.length > 20) {
return res.status(400).json({
message: "Username must be between 3 and 20 characters",
extensions: {
code: "USER_INPUT_ERROR",
path: "$.args.username"
}
});
}
if (!username || !password) {
return res.status(422).send("422 Unprocessable Entity: Missing username or password");
}
Expand Down
11 changes: 11 additions & 0 deletions database/graphql/message.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,14 @@ subscription getMessagesByRoom($room_uuid: uuid!) {
created_at
}
}

query getMessagesByUser($user_uuid: uuid!) {
message(where: {user_uuid: {_eq: $user_uuid}}, order_by: {created_at: desc}) {
uuid
content
created_at
room {
name
}
}
}
11 changes: 11 additions & 0 deletions database/graphql/room.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,14 @@ mutation joinRoom($user_uuid: uuid!, $room_uuid: uuid!) {
room_uuid
}
}

mutation quitRoom($user_uuid: uuid!, $room_uuid: uuid!) {
delete_user_room(
where: {user_uuid: {_eq: $user_uuid}, room_uuid: {_eq: $room_uuid}}
) {
returning {
user_uuid
room_uuid
}
}
}
10 changes: 10 additions & 0 deletions database/graphql/user.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,13 @@ query getUsersByUsername($username: String!) {
password
}
}

mutation deleteUser($uuid: uuid!) {
delete_user(where: {uuid: {_eq: $uuid}}) {
returning {
uuid
username
}
}
}

24 changes: 24 additions & 0 deletions database/hasura/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: "3.6"
services:
postgres:
image: postgres:latest
container_name: postgres
restart: always
volumes:
- ~/data/postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgrespassword
graphql-engine:
image: hasura/graphql-engine:latest
container_name: hasura
ports:
- "23333:8080"
depends_on:
- "postgres"
restart: always
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
89 changes: 89 additions & 0 deletions frontend/public/about-me.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>关于我</title>
<style>
body {
background-color: #f0f8ff;
color: #333;
font-family: Arial, sans-serif;
text-align: center;
padding: 20px;
transition: background .3s, color .3s;
}
h1 { color: #2c3e50; }
img { border-radius: 10px; margin-top: 20px; }
a { color: #1e90ff; text-decoration: none; }

body.dark {
background-color: #121212 !important;
color: #e0e0e0 !important;
}
body.dark a { color: #81c784; }
body.dark img { filter: brightness(.8) contrast(1.2); }

#toggleBtn {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
padding: 6px 12px;
font-size: 14px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>关于我</h1>
<p>你好!我叫<strong>懒人</strong>,是电子系一名学生。</p>

<h2>我的爱好</h2>
<ul>
<li>睡懒觉!</li>
<li>睡懒觉!</li>
<li>睡懒觉!</li>
</ul>

<h2>一件趣事</h2>
<p>前天有个会要开,完全忘记了!</p>

<h2>个人照片</h2>
<img src="https://i.ibb.co/1tvkMhX5/c5b601e47c27c660243aeb20b2ee8b26.png" alt="我的照片">

<p>想回首页?<a href="index.html">点这里</a></p>

<button id="toggleBtn">🌓 切换暗色模式</button>
<section id="githubSec">
<h2>GitHub 实时数据</h2>
<p>加载中…</p>
</section>

<script>
const toggleBtn = document.getElementById('toggleBtn');
toggleBtn.addEventListener('click', () => {
document.body.classList.toggle('dark');
toggleBtn.textContent = document.body.classList.contains('dark')
? '☀️ 亮色模式'
: '🌓 切换暗色模式';
});

const githubUser = 'like017';
const box = document.getElementById('githubSec');
fetch(`https://api.github.com/users/${githubUser}`)
.then(r => r.json())
.then(d => {
box.innerHTML = `
<h2>GitHub 实时数据</h2>
<img src="${d.avatar_url}" width="80" style="border-radius:50%">
<p>用户名:${d.login}</p>
<p>公开仓库:${d.public_repos}</p>
<p>粉丝数:${d.followers}</p>
`;
})
.catch(() => {
box.innerHTML = '<h2>GitHub 实时数据</h2><p>获取失败,请检查网络</p>';
});
</script>
</body>
</html>
39 changes: 39 additions & 0 deletions frontend/public/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的首页</title>
<style>
html,body{height:100%;margin:0;}
body{
background:url('https://i.ibb.co/t1WZsMD/301e4a1856b68d86f90271f769c1c942.png') center/cover no-repeat fixed;
position:relative;
color:#fff;
font:32px/1.4 Arial,sans-serif;
text-align:center;
display:table;
width:100%;
}
body::before{
content:"";
position:absolute;
inset:0;
background:rgba(0,0,0,.5);
}
.center{
display:table-cell;
vertical-align:middle;
position:relative;
z-index:1;
}
a{color:#1e90ff;text-decoration:none;}
a:hover{text-decoration:underline;}
</style>
</head>
<body>
<div class="center">
<h1>欢迎来到我的主页</h1>
<p>点击这里查看 <a href="about-me.html">关于我</a></p>
</div>
</body>
</html>