You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1662 lines
46 KiB

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聊天消息 - 青核 Youthome</title>
<link rel="stylesheet" href="../css/design-system.css">
<style>
/* ===== 页面变量 ===== */
:root {
--conv-list-width: 320px;
--info-panel-width: 280px;
--bubble-self: var(--primary);
--bubble-other: #F0F0F0;
}
/* ===== 全局布局 ===== */
.app {
width: 1920px
max-width: 100%;
overflow: hidden;;
min-height: 100vh;
margin: 0 auto;
display: flex;
position: relative;
background: var(--bg-page);
}
/* ===== 左侧边栏 ===== */
.sidebar {
width: var(--sidebar-width);
height: 100vh;
background: var(--bg-card);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
flex-shrink: 0;
z-index: 20;
position: sticky;
top: 0;
}
.sidebar-logo {
padding: 24px 20px;
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid var(--border-light);
cursor: pointer;
flex-shrink: 0;
}
.sidebar-logo-icon {
width: 36px;
height: 36px;
border-radius: 10px;
background: linear-gradient(135deg, var(--primary-light), var(--primary));
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 16px;
font-weight: 700;
flex-shrink: 0;
box-shadow: 0 4px 12px rgba(23, 176, 207, 0.25);
}
.sidebar-logo-text .main {
font-size: 16px;
font-weight: 700;
color: var(--text-primary);
}
.sidebar-logo-text .sub {
font-size: 11px;
color: var(--text-tertiary);
}
/* 发布按钮 */
.sidebar-publish {
padding: 16px 12px 8px;
flex-shrink: 0;
}
.publish-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
height: 44px;
background: var(--primary);
color: #fff;
border-radius: 12px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(23, 176, 207, 0.25);
}
.publish-btn:hover {
opacity: 0.92;
transform: translateY(-1px);
box-shadow: 0 6px 16px rgba(23, 176, 207, 0.35);
}
.publish-btn svg {
width: 20px;
height: 20px;
}
.publish-btn .publish-arrow {
width: 16px;
height: 16px;
opacity: 0.8;
transition: transform 0.2s;
}
.publish-btn:hover .publish-arrow {
transform: translateY(1px);
}
.publish-dropdown {
display: none;
margin-top: 6px;
background: var(--bg-card);
border: 1px solid var(--border-light);
border-radius: 12px;
padding: 6px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
.sidebar-publish:hover .publish-dropdown {
display: block;
}
.publish-option {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s;
}
.publish-option:hover {
background: var(--bg-hover);
}
.publish-option svg {
width: 22px;
height: 22px;
color: var(--primary);
flex-shrink: 0;
}
.publish-option-title {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
}
.publish-option-desc {
font-size: 11px;
color: var(--text-tertiary);
margin-top: 2px;
}
/* 导航 */
.sidebar-nav {
flex: 1;
padding: 8px 12px 24px 12px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 2px;
}
.nav-section-title {
font-size: 11px;
font-weight: 600;
color: var(--text-tertiary);
padding: 16px 12px 8px;
letter-spacing: 0.05em;
}
.nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.15s ease;
}
.nav-item:hover {
background: var(--bg-hover);
color: var(--text-primary);
}
.nav-item.active {
background: var(--primary-bg);
color: var(--primary);
font-weight: 600;
}
.nav-item svg {
width: 20px;
height: 20px;
flex-shrink: 0;
}
.nav-item-label {
display: flex;
align-items: center;
justify-content: space-between;
flex: 1;
}
.nav-badge {
min-width: 18px;
height: 18px;
padding: 0 5px;
background: #FF4D4F;
color: #fff;
font-size: 11px;
font-weight: 600;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
/* 底部用户卡片 */
.sidebar-footer {
padding: 16px;
border-top: 1px solid var(--border-light);
flex-shrink: 0;
}
.sidebar-user {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border-radius: 10px;
cursor: pointer;
transition: background 0.15s;
}
.sidebar-user:hover {
background: var(--bg-hover);
}
.sidebar-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
}
.sidebar-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.sidebar-user-info {
flex: 1;
min-width: 0;
}
.sidebar-user-name {
font-size: 13px;
font-weight: 600;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-user-desc {
font-size: 11px;
color: var(--text-tertiary);
margin-top: 1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* ===== 主区域 ===== */
.main-area {
flex: 1;
display: flex;
min-width: 0;
padding: 24px;
gap: 20px;
overflow: hidden;
}
/* ===== 会话列表 ===== */
.conv-list {
width: var(--conv-list-width);
background: var(--bg-card);
border-radius: 14px;
border: 1px solid var(--border-light);
box-shadow: var(--shadow-card);
display: flex;
flex-direction: column;
flex-shrink: 0;
overflow: hidden;
}
.conv-search {
padding: 16px;
border-bottom: 1px solid var(--border-light);
flex-shrink: 0;
}
.conv-search .input-wrap {
position: relative;
}
.conv-search .search-input {
width: 100%;
height: 40px;
padding: 0 14px 0 40px;
border: 1px solid var(--border);
border-radius: 10px;
font-size: 13px;
color: var(--text-primary);
background: var(--bg-page);
transition: all var(--transition-fast);
outline: none;
font-family: inherit;
}
.conv-search .search-input:focus {
border-color: var(--primary);
background: var(--bg-card);
box-shadow: 0 0 0 3px rgba(23, 176, 207, 0.12);
}
.conv-search .search-input::placeholder {
color: var(--text-placeholder);
}
.conv-search .search-icon {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
width: 18px;
height: 18px;
color: var(--text-tertiary);
pointer-events: none;
}
.conv-section {
padding: 12px 16px 8px;
font-size: 12px;
font-weight: 600;
color: var(--text-tertiary);
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
}
.conv-section-count {
font-size: 11px;
color: var(--text-tertiary);
font-weight: 500;
}
.conv-items {
flex: 1;
overflow-y: auto;
}
.conv-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
cursor: pointer;
transition: background 0.15s;
position: relative;
border-left: 3px solid transparent;
}
.conv-item:hover {
background: var(--bg-hover);
}
.conv-item.active {
background: var(--primary-bg);
border-left-color: var(--primary);
}
.conv-avatar {
width: 44px;
height: 44px;
border-radius: 50%;
flex-shrink: 0;
position: relative;
overflow: hidden;
}
.conv-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.conv-avatar.system {
background: var(--primary-bg);
display: flex;
align-items: center;
justify-content: center;
}
.conv-avatar.system svg {
width: 22px;
height: 22px;
color: var(--primary);
}
.conv-online-dot {
position: absolute;
bottom: 2px;
right: 2px;
width: 10px;
height: 10px;
background: #52C41A;
border: 2px solid #fff;
border-radius: 50%;
}
.conv-content {
flex: 1;
min-width: 0;
}
.conv-top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 4px;
}
.conv-name {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.conv-time {
font-size: 11px;
color: var(--text-tertiary);
flex-shrink: 0;
margin-left: 8px;
}
.conv-bottom {
display: flex;
align-items: center;
justify-content: space-between;
}
.conv-preview {
font-size: 12px;
color: var(--text-tertiary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.conv-unread {
min-width: 18px;
height: 18px;
padding: 0 5px;
background: #FF4D4F;
color: #fff;
font-size: 11px;
font-weight: 600;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
flex-shrink: 0;
margin-left: 8px;
}
/* ===== 聊天区域 ===== */
.chat-area {
flex: 1;
background: var(--bg-card);
border-radius: 14px;
border: 1px solid var(--border-light);
box-shadow: var(--shadow-card);
display: flex;
flex-direction: column;
min-width: 0;
overflow: hidden;
}
.chat-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
border-bottom: 1px solid var(--border-light);
flex-shrink: 0;
}
.chat-header-left {
display: flex;
align-items: center;
gap: 12px;
}
.chat-header-avatar {
width: 44px;
height: 44px;
border-radius: 50%;
flex-shrink: 0;
position: relative;
overflow: hidden;
}
.chat-header-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.chat-header-avatar .online-dot {
position: absolute;
bottom: 2px;
right: 2px;
width: 10px;
height: 10px;
background: #52C41A;
border: 2px solid #fff;
border-radius: 50%;
}
.chat-header-info .name {
font-size: 16px;
font-weight: 700;
color: var(--text-primary);
}
.chat-header-info .status {
font-size: 12px;
color: #52C41A;
margin-top: 2px;
display: flex;
align-items: center;
gap: 5px;
}
.chat-header-info .status-dot {
width: 6px;
height: 6px;
background: #52C41A;
border-radius: 50%;
}
.chat-header-right {
display: flex;
align-items: center;
gap: 8px;
}
.chat-header-btn {
width: 36px;
height: 36px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.15s;
}
.chat-header-btn:hover {
background: var(--bg-hover);
color: var(--primary);
}
.chat-header-btn svg {
width: 20px;
height: 20px;
}
/* 消息区域 */
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 24px;
display: flex;
flex-direction: column;
gap: 20px;
}
.date-separator {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.date-separator::before,
.date-separator::after {
content: '';
flex: 1;
height: 1px;
background: var(--border-light);
}
.date-separator span {
font-size: 12px;
color: var(--text-tertiary);
padding: 4px 12px;
background: var(--bg-page);
border-radius: 10px;
font-weight: 500;
}
.msg-row {
display: flex;
gap: 10px;
max-width: 70%;
}
.msg-row.self {
align-self: flex-end;
flex-direction: row-reverse;
}
.msg-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
flex-shrink: 0;
overflow: hidden;
}
.msg-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.msg-body {
display: flex;
flex-direction: column;
gap: 4px;
}
.msg-row.self .msg-body {
align-items: flex-end;
}
.msg-meta {
display: flex;
align-items: center;
gap: 8px;
font-size: 11px;
color: var(--text-tertiary);
}
.msg-bubble {
padding: 10px 14px;
border-radius: 14px;
font-size: 14px;
line-height: 1.6;
word-break: break-word;
position: relative;
}
.msg-row.other .msg-bubble {
background: var(--bubble-other);
color: var(--text-primary);
border-bottom-left-radius: 4px;
}
.msg-row.self .msg-bubble {
background: var(--bubble-self);
color: #fff;
border-bottom-right-radius: 4px;
}
.msg-time {
font-size: 11px;
color: var(--text-tertiary);
}
.msg-row.self .msg-time {
text-align: right;
}
/* 输入区域 */
.chat-input-area {
border-top: 1px solid var(--border-light);
padding: 16px 20px 20px;
flex-shrink: 0;
}
.chat-toolbar {
display: flex;
align-items: center;
gap: 4px;
margin-bottom: 12px;
}
.chat-toolbar-btn {
width: 32px;
height: 32px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-tertiary);
cursor: pointer;
transition: all 0.15s;
}
.chat-toolbar-btn:hover {
background: var(--primary-bg);
color: var(--primary);
}
.chat-toolbar-btn svg {
width: 20px;
height: 20px;
}
.chat-input-wrapper {
display: flex;
gap: 12px;
align-items: flex-end;
}
.chat-textarea {
flex: 1;
min-height: 64px;
max-height: 160px;
padding: 12px 14px;
border: 1px solid var(--border);
border-radius: 12px;
font-size: 14px;
line-height: 1.6;
color: var(--text-primary);
background: var(--bg-page);
resize: none;
font-family: inherit;
transition: all var(--transition-fast);
outline: none;
}
.chat-textarea:focus {
border-color: var(--primary);
background: var(--bg-card);
box-shadow: 0 0 0 3px rgba(23, 176, 207, 0.12);
}
.chat-textarea::placeholder {
color: var(--text-placeholder);
}
.send-btn {
height: 44px;
padding: 0 24px;
background: var(--primary);
color: #fff;
border-radius: 12px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 12px rgba(23, 176, 207, 0.25);
flex-shrink: 0;
}
.send-btn:hover {
background: var(--primary-hover);
transform: translateY(-1px);
box-shadow: 0 6px 16px rgba(23, 176, 207, 0.35);
}
.send-btn svg {
width: 18px;
height: 18px;
}
/* ===== 右侧信息面板 ===== */
.info-panel {
width: var(--info-panel-width);
background: var(--bg-card);
border-radius: 14px;
border: 1px solid var(--border-light);
box-shadow: var(--shadow-card);
display: flex;
flex-direction: column;
flex-shrink: 0;
overflow-y: auto;
}
.info-profile {
padding: 28px 20px 20px;
text-align: center;
border-bottom: 1px solid var(--border-light);
}
.info-avatar {
width: 72px;
height: 72px;
border-radius: 50%;
margin: 0 auto 14px;
overflow: hidden;
position: relative;
}
.info-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.info-name {
font-size: 18px;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 4px;
}
.info-school {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
}
.info-bio {
font-size: 12px;
color: var(--text-tertiary);
line-height: 1.6;
}
.info-actions {
display: flex;
justify-content: center;
gap: 10px;
padding: 16px 20px;
border-bottom: 1px solid var(--border-light);
}
.info-action-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 10px 14px;
border-radius: 10px;
cursor: pointer;
transition: all 0.15s;
color: var(--text-secondary);
}
.info-action-btn:hover {
background: var(--primary-bg);
color: var(--primary);
}
.info-action-btn .icon-circle {
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--bg-page);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.15s;
}
.info-action-btn:hover .icon-circle {
background: var(--primary);
}
.info-action-btn:hover .icon-circle svg {
color: #fff;
}
.info-action-btn .icon-circle svg {
width: 18px;
height: 18px;
color: var(--text-secondary);
transition: color 0.15s;
}
.info-action-btn span {
font-size: 11px;
font-weight: 500;
}
.info-section {
padding: 16px 20px;
border-bottom: 1px solid var(--border-light);
}
.info-section-title {
font-size: 13px;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 12px;
display: flex;
align-items: center;
justify-content: space-between;
}
.info-section-title .count {
font-size: 11px;
color: var(--text-tertiary);
font-weight: 500;
}
.file-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s;
margin-bottom: 4px;
}
.file-item:last-child {
margin-bottom: 0;
}
.file-item:hover {
background: var(--bg-hover);
}
.file-icon {
width: 36px;
height: 36px;
border-radius: 8px;
background: var(--primary-bg);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.file-icon.pdf { background: #FFF1F0; }
.file-icon.pdf svg { color: #F5222D; }
.file-icon.img { background: var(--primary-bg); }
.file-icon.img svg { color: var(--primary); }
.file-icon.doc { background: #E6F4FF; }
.file-icon.doc svg { color: #4A90FF; }
.file-icon svg {
width: 18px;
height: 18px;
}
.file-info {
flex: 1;
min-width: 0;
}
.file-name {
font-size: 13px;
color: var(--text-primary);
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.file-meta {
font-size: 11px;
color: var(--text-tertiary);
margin-top: 2px;
}
.group-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s;
margin-bottom: 4px;
}
.group-item:last-child {
margin-bottom: 0;
}
.group-item:hover {
background: var(--bg-hover);
}
.group-avatar {
width: 36px;
height: 36px;
border-radius: 8px;
background: linear-gradient(135deg, var(--primary-light), var(--primary));
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 12px;
font-weight: 700;
flex-shrink: 0;
}
.group-info {
flex: 1;
min-width: 0;
}
.group-name {
font-size: 13px;
color: var(--text-primary);
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.group-member {
font-size: 11px;
color: var(--text-tertiary);
margin-top: 2px;
}
body.web-embed .sidebar,
body.web-embed .web-topbar,
body.web-embed .web-drawer-backdrop,
body.web-embed .web-menu-button { display: none !important; }
body.web-embed .app { margin-left: 0 !important; padding-top: 0 !important; height: 100vh !important; width: 100% !important; }
body.web-embed .main-area { padding: 0 !important; height: 100vh !important; width: 100% !important; gap: 0 !important; }
body.web-embed .conv-list { width: 260px !important; border-radius: 0 !important; }
body.web-embed .chat-area { border-radius: 0 !important; }
</style>
<link rel="stylesheet" href="../css/web-refresh.css?v=20261020-brand-color">
</head>
<body>
<div class="app">
<!-- ===== 左侧边栏 ===== -->
<aside class="sidebar">
<div class="sidebar-logo">
<div class="sidebar-logo-icon">青</div>
<div class="sidebar-logo-text">
<div class="main">青核 Youthome</div>
<div class="sub">校园社交平台</div>
</div>
</div>
<!-- 发布按钮 -->
<div class="sidebar-publish">
<div class="publish-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 5v14M5 12h14"/>
</svg>
<span>发布</span>
<svg class="publish-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</div>
<div class="publish-dropdown">
<div class="publish-option">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14.5 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V9.5L14.5 3z"/>
<path d="M14 3v6h6"/>
</svg>
<div>
<div class="publish-option-title">发布动态</div>
<div class="publish-option-desc">分享你的校园生活</div>
</div>
</div>
<div class="publish-option">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M23 7l-7 5 7 5V7z"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
<div>
<div class="publish-option-title">发布视频</div>
<div class="publish-option-desc">上传精彩视频内容</div>
</div>
</div>
<div class="publish-option">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V4a2 2 0 00-2-2h-2"/>
<path d="M9 18h6"/>
</svg>
<div>
<div class="publish-option-title">发起活动</div>
<div class="publish-option-desc">组织有趣的校园活动</div>
</div>
</div>
</div>
</div>
<!-- 导航菜单 -->
<nav class="sidebar-nav">
<div class="nav-section-title">探索</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/>
<path d="M9 22V12h6v10"/>
</svg>
<span>首页</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/>
<path d="M21 21l-4.35-4.35"/>
</svg>
<span>发现</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="23 7 16 12 23 17 23 7"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
<span>视频</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
<path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
<span>活动</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 00-3-3.87"/>
<path d="M16 3.13a4 4 0 010 7.75"/>
</svg>
<span>校园圈</span>
</div>
<div class="nav-section-title">我的</div>
<div class="nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/>
</svg>
<div class="nav-item-label">
<span>聊天消息</span>
<span class="nav-badge">3</span>
</div>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/>
<path d="M13.73 21a2 2 0 01-3.46 0"/>
</svg>
<span>通知</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21l-7-5-7 5V5a2 2 0 012-2h10a2 2 0 012 2z"/>
</svg>
<span>收藏</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
<span>我的主页</span>
</div>
<div class="nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
</svg>
<span>设置</span>
</div>
</nav>
<!-- 底部用户卡片 -->
<div class="sidebar-footer">
<div class="sidebar-user">
<div class="sidebar-avatar">
<img src="../assets/avatar-02-male-short-medium.jpg" alt="用户头像">
</div>
<div class="sidebar-user-info">
<div class="sidebar-user-name">李青禾</div>
<div class="sidebar-user-desc">青山大学 · 计算机学院</div>
</div>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color: var(--text-tertiary); flex-shrink: 0;">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
</svg>
</div>
</div>
</aside>
<!-- ===== 主区域 ===== -->
<main class="main-area">
<!-- 会话列表 -->
<div class="conv-list">
<div class="conv-search">
<div class="input-wrap">
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/>
<path d="M21 21l-4.35-4.35"/>
</svg>
<input type="text" class="search-input" placeholder="搜索聊天记录或联系人">
</div>
</div>
<div class="conv-section">
<span>系统通知</span>
<span class="conv-section-count">1</span>
</div>
<div class="conv-items" style="flex-shrink: 0;">
<div class="conv-item">
<div class="conv-avatar system">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/>
<path d="M13.73 21a2 2 0 01-3.46 0"/>
</svg>
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">系统通知</span>
<span class="conv-time">09:30</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">你的活动报名已通过审核</span>
<span class="conv-unread">3</span>
</div>
</div>
</div>
</div>
<div class="conv-section">
<span>私信</span>
<span class="conv-section-count">5</span>
</div>
<div class="conv-items">
<!-- 林小夏 - 活跃 -->
<div class="conv-item active">
<div class="conv-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
<span class="conv-online-dot"></span>
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">林小夏</span>
<span class="conv-time">刚刚</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">好的,那我们明天图书馆见!</span>
<span class="conv-unread">2</span>
</div>
</div>
</div>
<!-- 张子轩 -->
<div class="conv-item">
<div class="conv-avatar">
<img src="../assets/avatar-04-male-curly-light.jpg" alt="张子轩">
<span class="conv-online-dot"></span>
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">张子轩</span>
<span class="conv-time">10:42</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">[图片]</span>
<span class="conv-unread">1</span>
</div>
</div>
</div>
<!-- 王思琪 -->
<div class="conv-item">
<div class="conv-avatar">
<img src="../assets/avatar-03-female-long-dark.jpg" alt="王思琪">
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">王思琪</span>
<span class="conv-time">昨天</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">作业我已经写完了,需要参考吗?</span>
</div>
</div>
</div>
<!-- 前端学习小组 -->
<div class="conv-item">
<div class="conv-avatar" style="background: linear-gradient(135deg, #73D3E6, #17B0CF); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 13px; font-weight: 700;">
前端
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">前端学习小组</span>
<span class="conv-time">昨天</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">陈雨桐: 大家周末有时间一起刷题吗</span>
<span class="conv-unread">5</span>
</div>
</div>
</div>
<!-- 陈雨桐 -->
<div class="conv-item">
<div class="conv-avatar">
<img src="../assets/avatar-07-female-twintails-light.jpg" alt="陈雨桐">
</div>
<div class="conv-content">
<div class="conv-top">
<span class="conv-name">陈雨桐</span>
<span class="conv-time">周一</span>
</div>
<div class="conv-bottom">
<span class="conv-preview">好的,收到~</span>
</div>
</div>
</div>
</div>
</div>
<!-- 聊天区域 -->
<div class="chat-area">
<!-- 聊天头部 -->
<div class="chat-header">
<div class="chat-header-left">
<div class="chat-header-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
<span class="online-dot"></span>
</div>
<div class="chat-header-info">
<div class="name">林小夏</div>
<div class="status">
<span class="status-dot"></span>
在线
</div>
</div>
</div>
<div class="chat-header-right">
<button class="chat-header-btn" title="语音通话">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 16.92z"/>
</svg>
</button>
<button class="chat-header-btn" title="视频通话">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="23 7 16 12 23 17 23 7"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
</button>
<button class="chat-header-btn" title="更多">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="1"/>
<circle cx="19" cy="12" r="1"/>
<circle cx="5" cy="12" r="1"/>
</svg>
</button>
</div>
</div>
<!-- 消息区域 -->
<div class="chat-messages">
<div class="date-separator">
<span>今天</span>
</div>
<!-- 对方消息 -->
<div class="msg-row other">
<div class="msg-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>林小夏</span>
<span>09:15</span>
</div>
<div class="msg-bubble">
嗨,青禾!你上次说的那个前端学习资源可以发我一下吗?我最近在学 React,想找一些好的教程。
</div>
</div>
</div>
<!-- 自己消息 -->
<div class="msg-row self">
<div class="msg-avatar">
<img src="../assets/avatar-02-male-short-medium.jpg" alt="我">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>09:18</span>
</div>
<div class="msg-bubble">
当然可以!我整理了一份学习清单,包括官方文档和几个优质课程。
</div>
</div>
</div>
<!-- 自己消息 -->
<div class="msg-row self">
<div class="msg-avatar">
<img src="../assets/avatar-02-male-short-medium.jpg" alt="我">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>09:18</span>
</div>
<div class="msg-bubble">
我等下把文件发给你,你可以先从基础部分开始看。
</div>
</div>
</div>
<!-- 对方消息 -->
<div class="msg-row other">
<div class="msg-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>林小夏</span>
<span>09:20</span>
</div>
<div class="msg-bubble">
太棒了,谢谢你!对了,明天图书馆的学习局你还来吗?我们准备一起刷算法题。
</div>
</div>
</div>
<!-- 自己消息 -->
<div class="msg-row self">
<div class="msg-avatar">
<img src="../assets/avatar-02-male-short-medium.jpg" alt="我">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>09:22</span>
</div>
<div class="msg-bubble">
来呀,几点开始?我上午有节课,可能要晚点到。
</div>
</div>
</div>
<!-- 对方消息 -->
<div class="msg-row other">
<div class="msg-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
</div>
<div class="msg-body">
<div class="msg-meta">
<span>林小夏</span>
<span>刚刚</span>
</div>
<div class="msg-bubble">
好的,那我们明天图书馆见!下午两点三楼自习区,不见不散~
</div>
</div>
</div>
</div>
<!-- 输入区域 -->
<div class="chat-input-area">
<div class="chat-toolbar">
<button class="chat-toolbar-btn" title="表情">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M8 14s1.5 2 4 2 4-2 4-2"/>
<line x1="9" y1="9" x2="9.01" y2="9"/>
<line x1="15" y1="9" x2="15.01" y2="9"/>
</svg>
</button>
<button class="chat-toolbar-btn" title="图片">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
<circle cx="8.5" cy="8.5" r="1.5"/>
<path d="M21 15l-5-5L5 21"/>
</svg>
</button>
<button class="chat-toolbar-btn" title="文件">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/>
</svg>
</button>
</div>
<div class="chat-input-wrapper">
<textarea class="chat-textarea" placeholder="输入消息... 按 Enter 发送"></textarea>
<button class="send-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="22" y1="2" x2="11" y2="13"/>
<polygon points="22 2 15 22 11 13 2 9 22 2"/>
</svg>
发送
</button>
</div>
</div>
</div>
<!-- 右侧信息面板 -->
<div class="info-panel">
<div class="info-profile">
<div class="info-avatar">
<img src="../assets/avatar-01-female-short-light.jpg" alt="林小夏">
</div>
<div class="info-name">林小夏</div>
<div class="info-school">青山大学 · 计算机学院</div>
<div class="info-bio">热爱编程和设计的大三学姐,喜欢探索新技术,也喜欢分享学习心得~</div>
</div>
<div class="info-actions">
<div class="info-action-btn">
<div class="icon-circle">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="23 7 16 12 23 17 23 7"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
</div>
<span>视频通话</span>
</div>
<div class="info-action-btn">
<div class="icon-circle">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 16.92z"/>
</svg>
</div>
<span>语音通话</span>
</div>
<div class="info-action-btn">
<div class="icon-circle">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="1"/>
<circle cx="19" cy="12" r="1"/>
<circle cx="5" cy="12" r="1"/>
</svg>
</div>
<span>更多</span>
</div>
</div>
<div class="info-section">
<div class="info-section-title">
聊天文件
<span class="count">3</span>
</div>
<div class="file-item">
<div class="file-icon pdf">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
</svg>
</div>
<div class="file-info">
<div class="file-name">前端学习资源.pdf</div>
<div class="file-meta">2.4MB · 今天 09:18</div>
</div>
</div>
<div class="file-item">
<div class="file-icon img">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
<circle cx="8.5" cy="8.5" r="1.5"/>
<path d="M21 15l-5-5L5 21"/>
</svg>
</div>
<div class="file-info">
<div class="file-name">课程笔记截图.png</div>
<div class="file-meta">1.1MB · 昨天</div>
</div>
</div>
<div class="file-item">
<div class="file-icon doc">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
</svg>
</div>
<div class="file-info">
<div class="file-name">React入门指南.docx</div>
<div class="file-meta">856KB · 周一</div>
</div>
</div>
</div>
<div class="info-section">
<div class="info-section-title">
共同群聊
<span class="count">2</span>
</div>
<div class="group-item">
<div class="group-avatar">前端</div>
<div class="group-info">
<div class="group-name">前端学习小组</div>
<div class="group-member">12 人</div>
</div>
</div>
<div class="group-item">
<div class="group-avatar" style="background: linear-gradient(135deg, #FFD4A3, #FF9F45);">算法</div>
<div class="group-info">
<div class="group-name">算法刷题小分队</div>
<div class="group-member">8 人</div>
</div>
</div>
</div>
</div>
</main>
</div>
<script src="../js/web-local-data.js?v=20261016-local" defer></script>
<script src="../js/web-api.js?v=20261020-api" defer></script>
<script src="../js/web-shell.js" defer></script>
<script>
if (new URLSearchParams(location.search).has('embed')) document.body.classList.add('web-embed');
</script>
</body>
</html>