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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ build
electron

.local.env

.vs/
74 changes: 74 additions & 0 deletions database/graphql/homework_reply.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 作业三:聊天室消息的单层回复

# 1. 发一条回复消息:reply_to 指向被回复的消息
mutation replyMessage(
$user_uuid: uuid!,
$room_uuid: uuid!,
$content: String!,
$reply_to: uuid!
) {
insert_message_one(object: {
user_uuid: $user_uuid,
room_uuid: $room_uuid,
content: $content,
reply_to: $reply_to
}) {
uuid
content
# 自引用外键的对象关系名:Hasura 中为目标表名 message
message {
uuid
content
}
}
}

# 2. 查询某个会议的消息,并带出每条消息回复的目标(单层)
query messagesWithReply($room_uuid: uuid!) {
message(
where: { room_uuid: { _eq: $room_uuid } },
order_by: { created_at: asc }
) {
uuid
content
created_at
user {
username
}
# 回复目标(通过 message.reply_to 外键的对象关系)
message {
uuid
content
user {
username
}
}
}
}

# 3. 查询某条消息收到了哪些回复
query messageReplies($uuid: uuid!) {
message(where: { reply_to: { _eq: $uuid } }) {
uuid
content
user {
username
}
message {
uuid
content
}
}
}

# 4. 订阅某个会议的新消息(含回复关系),方便聊天室实时更新
subscription messagesByRoomWithReply($room_uuid: uuid!) {
message(where: { room_uuid: { _eq: $room_uuid } }) {
uuid
content
message {
uuid
content
}
}
}
14 changes: 14 additions & 0 deletions database/sql/homework_reply.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- 作业三:聊天室消息支持回复之前的某条消息(单层回复)
-- 设计:给 message 增加可空的 reply_to 列,自引用 message.uuid。
-- 被回复的消息删除时 reply_to 置空,避免出现悬空引用。

alter table public.message
add column if not exists reply_to uuid;

alter table public.message
drop constraint if exists message_reply_to_fkey;

alter table public.message
add constraint message_reply_to_fkey
foreign key (reply_to) references public.message (uuid)
on delete set null;
1 change: 1 addition & 0 deletions database/sql/message.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ insert into public.message (user_uuid, room_uuid, content) values
('00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-100000000003', '好了,今天就到这里吧');

update public.message set created_at = '2021-01-01 00:00:00' where room_uuid = '00000000-0000-0000-0000-100000000002';
-- 信息由AI生成
75 changes: 75 additions & 0 deletions frontend/public/about-me.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/png" sizes="32x32" href="./favicon.png" />
<title>关于我</title>
<link rel="stylesheet" href="./index.css" />
<script src="./about-me.js" defer></script>
</head>
<body>
<div id="about-me-frame">
<div class="card about-me-card" id="about-me-header">
<button id="theme-toggle" class="theme-toggle" type="button">切换到暗色模式</button>
<div id="about-me-avatar">我</div>
<h1>关于我</h1>
</div>

<div id="about-me-grid">
<div class="card about-me-card about-me-col">
<h2>基本信息</h2>
<table class="styled-table">
<tr>
<th>姓名</th>
<td>赵奕然</td>
</tr>
<tr>
<th>班级</th>
<td>无56</td>
</tr>
</table>

<hr />

<h2>我的爱好</h2>
<ul class="styled-list">
<li>弹琴</li>
<li>打游戏</li>
<li>刷<a href="https://www.bilibili.com/video/BV1GJ411x7h7/?">视频</a></li>
</ul>
</div>

<div class="card about-me-card about-me-col">
<h2>一些趣事</h2>
<ol class="styled-list">
<li>你被骗了</li>
</ol>
<blockquote class="about-me-quote">永不放弃你</blockquote>

<hr />

<h2>联系方式</h2>
<p>
邮箱:
<a href="mailto:zhaoyr25@mails.tsinghua.edu.cn">zhaoyr25@mails.tsinghua.edu.cn</a>
</p>
<p>
<a href="./index.html">返回首页</a>
</p>
</div>
</div>

<div class="card about-me-card" id="about-me-github">
<h2>GitHub</h2>
<div id="github-profile">
<img id="github-avatar" alt="GitHub 头像" hidden />
<div id="github-info">
<p id="github-name">加载中...</p>
<p id="github-repos"></p>
</div>
<p id="github-error" hidden></p>
</div>
</div>
</div>
</body>
</html>
46 changes: 46 additions & 0 deletions frontend/public/about-me.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const themeToggle = document.getElementById("theme-toggle");

// ===== 功能 1:亮色 / 暗色模式 =====
const applyTheme = (dark) => {
document.body.classList.toggle("dark", dark);
themeToggle.textContent = dark ? "切换到亮色模式" : "切换到暗色模式";
};

const savedTheme = localStorage.getItem("about-me-theme");
applyTheme(savedTheme === "dark");

themeToggle.addEventListener("click", () => {
const dark = !document.body.classList.contains("dark");
applyTheme(dark);
localStorage.setItem("about-me-theme", dark ? "dark" : "light");
});

// ===== 功能 2:拉取 GitHub 公开资料(网络资源) =====
const githubAvatar = document.getElementById("github-avatar");
const githubName = document.getElementById("github-name");
const githubRepos = document.getElementById("github-repos");
const githubError = document.getElementById("github-error");

const loadGithubProfile = async () => {
try {
const response = await fetch("https://api.github.com/users/Victor-692");
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const user = await response.json();

githubAvatar.src = user.avatar_url;
githubAvatar.hidden = false;
githubName.textContent = user.name || user.login;
githubRepos.textContent = `公开仓库数:${user.public_repos}`;
githubError.hidden = true;
} catch (err) {
console.error(err);
githubName.textContent = "GitHub 资料加载失败";
githubRepos.textContent = "";
githubError.hidden = false;
githubError.textContent = "请检查网络后刷新页面。";
}
};

loadGithubProfile();
141 changes: 132 additions & 9 deletions frontend/public/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,140 @@
line-height: 2em;
}

#clock {
position: absolute;
bottom: 0;
left: 12px;
width: 40vw;
/* ===== 关于我页面 ===== */
#about-me-frame {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
padding: 32px 16px;
box-sizing: border-box;
background: linear-gradient(135deg, #fbc2eb 0%, #a6c1ee 100%);
}

#motto {
.about-me-card {
background-color: rgba(255, 255, 255, 0.35);
}

#about-me-header {
width: min(640px, 92vw);
text-align: center;
}

#about-me-avatar {
width: 88px;
height: 88px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-size: 40px;
color: #ffffff;
background: linear-gradient(135deg, #6a82fb 0%, #fc5c7d 100%);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

.about-me-subtitle {
color: rgba(0, 0, 0, 0.65);
}

#about-me-grid {
width: min(920px, 94vw);
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16px;
}

.about-me-col {
flex: 1 1 320px;
max-width: 460px;
}

.about-me-quote {
margin: 12px 0;
padding: 8px 16px;
border-left: 4px solid #6a82fb;
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.35);
color: rgba(0, 0, 0, 0.75);
}

#about-me-header {
position: relative;
}

.theme-toggle {
position: absolute;
bottom: 0;
top: 12px;
right: 12px;
text-align: right;
width: 40vw;
padding: 6px 12px;
border: none;
border-radius: 16px;
cursor: pointer;
color: #ffffff;
background: linear-gradient(135deg, #6a82fb 0%, #fc5c7d 100%);
}

#about-me-github {
width: min(450px, 94vw);
}

#github-profile {
display: flex;
align-items: center;
gap: 16px;
}

#github-avatar {
width: 72px;
height: 72px;
border-radius: 50%;
}

#github-info p {
margin: 4px 0;
}

#github-error {
color: #b00020;
}

/* ===== 暗色模式 ===== */
body.dark #about-me-frame {
background: linear-gradient(135deg, #23272f 0%, #30384a 100%);
}

body.dark .about-me-card {
background-color: rgba(255, 255, 255, 0.08);
color: #e8e8e8;
}

body.dark .about-me-quote {
background-color: rgba(255, 255, 255, 0.08);
color: #cfd3dc;
}

body.dark .styled-table th,
body.dark .styled-table td,
body.dark #about-me-github a {
color: #d7dbe3;
}

#clock {
position: absolute;
bottom: 0;
left: 12px;
width: 40vw;
}

#motto {
position: absolute;
bottom: 0;
right: 12px;
text-align: right;
width: 40vw;
}
2 changes: 2 additions & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ <h1 style="color: purple;">这是一个趣味会议软件</h1>
<a href="./main.html">进入主页</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="./about.html" target="_blank">关于这个工程</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="./about-me.html">关于我</a>
</div>
<p id="clock">当前时间加载中... ...</p>
<p id="motto">每日一句加载中... ...</p>
Expand Down