Implement structure for code changes with placeholders for future updates

This commit is contained in:
zhangyuheng
2026-03-02 17:30:59 +08:00
parent 326f30b70e
commit 8318355475
6 changed files with 1765 additions and 1 deletions

888
css/pages/join.css Normal file
View File

@@ -0,0 +1,888 @@
:root {
--step-active-bg: #0071e3;
--sidebar-bg: #f5f5f7;
--sidebar-width: 280px;
--content-padding: 60px;
--card-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
--transition-smooth: all 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
body {
background-color: #fbfbfd;
color: #1d1d1f;
}
/* Minimal Header */
.join-header-minimal {
padding: 120px 20px 40px;
text-align: center;
background: transparent;
}
.join-header-minimal h1 {
font-size: 3rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 10px;
background: linear-gradient(135deg, #1d1d1f 0%, #434344 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.join-header-minimal p {
color: #86868b;
font-size: 1.25rem;
font-weight: 400;
}
/* Modern Wizard Container */
.wizard-container-modern {
display: flex;
max-width: 1200px;
margin: 20px auto 80px;
background: #fff;
border-radius: 24px;
box-shadow: 0 20px 40px rgba(0,0,0,0.08);
overflow: hidden;
min-height: 600px;
border: 1px solid rgba(0,0,0,0.04);
}
/* Sidebar */
.wizard-sidebar {
width: var(--sidebar-width);
background: var(--sidebar-bg);
padding: 60px 40px;
border-right: 1px solid rgba(0,0,0,0.05);
display: flex;
flex-direction: column;
}
.wizard-progress-vertical {
position: relative;
display: flex;
flex-direction: column;
gap: 40px;
}
.progress-step {
padding-left: 20px;
position: relative;
color: #86868b;
transition: var(--transition-smooth);
opacity: 0.6;
cursor: default;
}
.progress-step::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 4px;
background: #d2d2d7;
border-radius: 50%;
transition: var(--transition-smooth);
}
.progress-step.active,
.progress-step.completed {
opacity: 1;
color: #1d1d1f;
}
.progress-step.active::before {
background: var(--step-active-bg);
height: 24px;
border-radius: 2px;
}
.progress-step.completed::before {
background: #34c759;
}
.step-label {
display: block;
font-weight: 600;
font-size: 1.1rem;
margin-bottom: 4px;
}
.step-sub {
font-size: 0.85rem;
color: #86868b;
}
/* Content Area */
.wizard-content-area {
flex: 1;
padding: var(--content-padding);
background: #fff;
display: flex;
flex-direction: column;
position: relative;
}
.step-content {
display: none;
animation: fadeIn 0.5s ease;
flex: 1;
flex-direction: column;
}
.step-content.active {
display: flex;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.content-header {
margin-bottom: 40px;
}
.content-header h2 {
font-size: 2rem;
font-weight: 700;
margin-bottom: 8px;
}
.content-header p {
color: #86868b;
font-size: 1.1rem;
}
/* Footer & Buttons */
.step-footer {
margin-top: auto;
padding-top: 40px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid rgba(0,0,0,0.05);
}
.btn-clean {
background: none;
border: none;
color: #86868b;
font-size: 1rem;
cursor: pointer;
transition: color 0.2s;
font-weight: 500;
padding: 10px 20px;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-clean:hover {
color: #1d1d1f;
}
.btn-clean:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.btn-primary-large {
background: #0071e3;
color: white;
border: none;
padding: 14px 32px;
border-radius: 980px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition-smooth);
display: inline-flex;
align-items: center;
gap: 8px;
text-decoration: none;
}
.btn-primary-large:hover {
background: #0077ed;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 113, 227, 0.3);
}
.step-action-group {
display: flex;
gap: 16px;
align-items: center;
}
.step-action-group .hidden {
display: none !important;
}
.step-action-group .final-actions {
display: flex;
align-items: center;
gap: 12px;
}
/* Device Cards */
.card-content {
flex: 1;
}
.device-selection-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.device-card {
border: 2px solid #f5f5f7;
border-radius: 16px;
padding: 30px 20px;
text-align: center;
cursor: pointer;
transition: var(--transition-smooth);
position: relative;
background: #fff;
}
.device-card:hover {
border-color: #d2d2d7;
transform: translateY(-2px);
}
.device-card.selected {
border-color: #0071e3;
background: rgba(0, 113, 227, 0.03);
}
.icon-circle {
width: 60px;
height: 60px;
background: #f5f5f7;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin: 0 auto 16px;
color: #1d1d1f;
transition: var(--transition-smooth);
}
.device-card.selected .icon-circle {
background: #0071e3;
color: white;
}
.check-mark {
position: absolute;
top: 16px;
right: 16px;
color: #0071e3;
opacity: 0;
transform: scale(0.5);
transition: var(--transition-smooth);
}
.device-card.selected .check-mark {
opacity: 1;
transform: scale(1);
font-size: 1.2rem;
}
.device-info h3 {
margin: 0 0 4px;
font-size: 1.1rem;
}
.device-info p {
margin: 0;
font-size: 0.9rem;
color: #86868b;
}
/* Playstyle Cards */
.playstyle-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.playstyle-card {
display: flex;
align-items: center;
padding: 24px;
border-radius: 16px;
background: #f5f5f7;
gap: 20px;
transition: var(--transition-smooth);
border: 1px solid transparent;
}
.playstyle-card:hover {
background: #fff;
box-shadow: 0 4px 12px rgba(0,0,0,0.08); /* Fixed shadow var */
transform: translateY(-2px);
}
.playstyle-visual {
width: 64px;
height: 64px;
border-radius: 12px;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: #1d1d1f;
flex-shrink: 0;
}
/* Convention */
.convention-wrapper {
background: #f5f5f7;
border-radius: 12px;
padding: 6px;
margin-bottom: 24px;
}
.markdown-content {
background: #fff;
border-radius: 8px;
padding: 30px;
height: 400px;
overflow-y: auto;
font-size: 0.95rem;
line-height: 1.6;
color: #333;
}
/* Custom Checkbox */
.agreement-area {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
cursor: pointer;
border-radius: 8px;
transition: background 0.2s;
}
.agreement-area:hover {
background: #f5f5f7;
}
.custom-checkbox {
position: relative;
width: 24px;
height: 24px;
border: 2px solid #d2d2d7;
border-radius: 6px;
display: flex; /* Flex to center content */
align-items: center;
justify-content: center;
transition: var(--transition-smooth);
background: #fff;
}
.custom-checkbox input {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.checkmark {
display: none;
color: white;
font-size: 14px;
}
/* When the checkbox input inside is checked */
.custom-checkbox:has(input:checked) {
background-color: #0071e3;
border-color: #0071e3;
}
.custom-checkbox:has(input:checked) .checkmark {
display: block;
}
/* Launcher Recommendation */
.launcher-box {
margin-top: 30px;
padding: 24px;
background: #f0f9ff;
border-radius: 16px;
border: 1px solid #bae6fd;
}
.hidden {
display: none;
}
/* Final Message */
.final-message {
text-align: center;
margin-top: 30px;
color: #86868b;
font-style: italic;
}
@media (max-width: 800px) {
.wizard-container-modern {
flex-direction: column;
margin: 20px;
}
.wizard-sidebar {
width: 100%;
padding: 20px;
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid rgba(0,0,0,0.05);
gap: 20px;
}
.wizard-progress-vertical {
flex-direction: row;
width: 100%;
gap: 30px;
}
.progress-step {
padding-left: 0;
}
.progress-step::before {
display: none;
}
.step-sub { display: none; }
.wizard-content-area {
padding: 30px;
}
.device-selection-grid, .playstyle-grid {
grid-template-columns: 1fr;
}
.step-footer {
flex-direction: column-reverse;
gap: 20px;
}
.btn-clean {
width: 100%;
justify-content: center;
}
.step-action-group {
width: 100%;
flex-direction: column;
}
.btn-primary-large {
width: 100%;
justify-content: center;
}
}
.step-dot { display: none; }
/* Tutorial Steps */
.tutorial-steps {
display: flex;
flex-direction: column;
gap: 20px;
}
.tutorial-step {
display: flex;
gap: 20px;
padding: 20px;
background: #f5f5f7;
border-radius: 12px;
align-items: flex-start;
}
.step-badge {
width: 32px;
height: 32px;
background: #0071e3;
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
flex-shrink: 0;
}
.step-text h4 {
margin: 0 0 4px;
font-size: 1.1rem;
color: #1d1d1f;
}
.step-text p {
margin: 0;
color: #86868b;
font-size: 0.95rem;
line-height: 1.5;
}
.step-text code {
background: #e8e8ed;
padding: 2px 6px;
border-radius: 4px;
font-family: monospace;
color: #1d1d1f;
}
/* Enhanced Device Selection Styles */
.launcher-box {
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid rgba(0,0,0,0.05);
transition: opacity 0.4s ease, transform 0.4s ease;
}
.recommendation-header {
text-align: center;
margin-bottom: 30px;
}
.recommendation-header h3 {
font-size: 1.4rem;
color: #1d1d1f;
margin-bottom: 8px;
}
.recommendation-header p {
color: #86868b;
font-size: 1rem;
}
.launcher-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.launcher-card {
display: flex;
align-items: center;
padding: 24px;
background: #fbfbfd;
border: 1px solid rgba(0,0,0,0.05);
border-radius: 16px;
text-decoration: none;
color: inherit;
transition: all 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
position: relative;
overflow: hidden;
}
.launcher-card:hover {
background: #fff;
box-shadow: 0 8px 24px rgba(0,0,0,0.06);
transform: translateY(-2px);
border-color: rgba(0,0,0,0.08);
}
.launcher-card.primary {
background: #fff;
border: 1px solid rgba(0, 113, 227, 0.2);
box-shadow: 0 4px 12px rgba(0, 113, 227, 0.05);
}
.launcher-card.primary:hover {
box-shadow: 0 8px 24px rgba(0, 113, 227, 0.12);
border-color: rgba(0, 113, 227, 0.4);
}
.launcher-icon {
width: 54px;
height: 54px;
background: #ffffff;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: #1d1d1f;
margin-right: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
flex-shrink: 0;
}
.launcher-card.primary .launcher-icon {
background: #0071e3;
color: white;
}
.launcher-details {
flex: 1;
}
.launcher-details h4 {
margin: 0 0 4px;
font-size: 1.1rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.badge-rec {
font-size: 0.75rem;
background: #e1f0ff;
color: #0071e3;
padding: 2px 8px;
border-radius: 6px;
font-weight: 500;
}
.launcher-details p {
margin: 0;
font-size: 0.9rem;
color: #86868b;
line-height: 1.4;
}
.launcher-action {
color: #0071e3;
opacity: 0;
transform: translateX(-10px);
transition: all 0.3s ease;
}
.launcher-card:hover .launcher-action {
opacity: 1;
transform: translateX(0);
}
/* Server Address Box */
.server-address-box {
background: #e8e8ed;
padding: 8px 12px;
border-radius: 8px;
display: inline-flex;
align-items: center;
gap: 12px;
margin: 8px 0;
font-family: monospace;
color: #1d1d1f;
border: 1px solid rgba(0,0,0,0.05);
}
.server-address-box code {
background: none;
padding: 0;
font-size: 1rem;
font-weight: 600;
}
.btn-copy {
background: #fff;
border: 1px solid #d2d2d7;
border-radius: 6px;
padding: 4px 10px;
font-size: 0.8rem;
cursor: pointer;
transition: all 0.2s;
color: #1d1d1f;
display: flex;
align-items: center;
gap: 4px;
}
.btn-copy:hover {
background: #f5f5f7;
border-color: #86868b;
}
.btn-copy:active {
transform: scale(0.95);
}
.highlight-text {
color: #0071e3;
font-weight: 600;
}
/* --- Added for Step 4 Interactive Enhancement --- */
/* Interactive Playstyle Cards */
.playstyle-card {
cursor: pointer;
transition: var(--transition-smooth);
border: 2px solid transparent; /* Prepare for border change */
/* Ensure existing styles don't conflict, but we assume they are basic cards */
}
.playstyle-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.playstyle-card.selected {
border-color: #0071e3;
background-color: rgba(0, 113, 227, 0.04);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 113, 227, 0.2);
}
.icon-check-wrapper {
position: absolute;
top: 10px;
right: 10px;
color: #0071e3;
opacity: 0;
transform: scale(0.5);
transition: var(--transition-smooth);
}
.playstyle-card.selected .icon-check-wrapper {
opacity: 1;
transform: scale(1);
}
/* Details Section */
.playstyle-details-container {
margin-top: 40px;
opacity: 0;
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.playstyle-details-container.visible {
opacity: 1;
max-height: 1000px; /* Arbitrary large height */
margin-bottom: 20px;
}
.details-card {
background: #fbfbfd;
border-radius: 16px;
padding: 30px;
border: 1px solid rgba(0,0,0,0.06);
box-shadow: inset 0 0 20px rgba(0,0,0,0.02);
}
.details-header {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid rgba(0,0,0,0.08);
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.details-header h3 {
margin: 0;
font-size: 1.5rem;
color: #1d1d1f;
}
.badge-subtitle {
background: #e8e8ed;
color: #6e6e73;
padding: 4px 12px;
border-radius: 980px;
font-size: 0.85rem;
font-weight: 500;
}
.details-body {
display: flex;
flex-direction: column;
gap: 24px;
}
.detail-section h4 {
margin: 0 0 8px 0;
font-size: 1rem;
color: #1d1d1f;
display: flex;
align-items: center;
gap: 8px;
}
.detail-section h4 i {
color: #0071e3;
}
.detail-section p {
margin: 0;
color: #424245;
line-height: 1.6;
}
.detail-grid-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
@media (max-width: 768px) {
.detail-grid-row {
grid-template-columns: 1fr;
}
}
.detail-section ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.detail-section ul li {
padding-left: 24px;
position: relative;
margin-bottom: 8px;
color: #424245;
line-height: 1.5;
}
.detail-section ul li::before {
content: "•";
position: absolute;
left: 8px;
color: #86868b;
}
.detail-section.check-list ul li::before {
content: "✓";
color: #34c759; /* Green */
font-weight: bold;
}
.detail-section.warn-list ul li::before {
content: "!";
color: #ff9f0a; /* Orange */
font-weight: bold;
left: 8px; /* Adjust if needed */
}
/* --- Added for Step 4 Interactive Enhancement - Fix --- */
/* Details Section */
.playstyle-details-container {
margin-top: 0;
opacity: 0;
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.playstyle-details-container.visible {
opacity: 1;
max-height: 1000px;
margin-top: 40px;
margin-bottom: 20px;
}

96
data/convention.md Normal file
View File

@@ -0,0 +1,96 @@
## 一、根基
白鹿原是一个在中国大陆运营的**非官方我的世界公益纯净生存服务器**。白鹿原始终坚持以中华人民共和国法律为基准,始终坚持 **《中华人民共和国网络安全法》**、**《二十四字社会主义核心价值观》**、**《网络游戏行业防沉迷自律公约》**。我们反对一切违反法律的行为,白鹿原玩家公约的编写充分遵循了上述法律及社会公共道德的要求,请玩家务必遵守。
白鹿原服务器完全遵守Mojang Studios 发布的 [EULA协议](https://account.mojang.com/documents/minecraft_eula)拒绝向任何玩家提供游戏的副本不将Mojiang Studio创建的任何内容用于商业通途、不允许其他人以不公平或不合理的方式访问Mojiang Studio创建的任何内容、不通过Mojiang Studio创建的任何内容产生盈利。
## 二、服务器公约
1. 禁止作弊,如被证实为作弊,**所有参与者处予永久封禁**
2. 禁止破坏游戏氛围与交流环境的行为,**处罚措施根据以下情况按严重程度决定**
1. 恶意带节奏:所有参与者视严重程度处予 1\~3 天的临时封禁;
2. 恶意寻衅滋事:所有参与者视严重程度处予 1\~30 天的临时封禁,极其严重者处予永久封禁;
3. 恶意PVP所有参与者视严重程度处予 1\~5 天的临时封禁,极其严重者处予永久封禁;
4. 恶意人身攻击:所有参与者视严重程度处予 3\~10 天的临时封禁,极其严重者处予永久封禁;
5. 恶意拉帮结派:所有参与者处予永久封禁;
3. 禁止恶意偷盗、破坏服务器公共财产或使用不正当手段破坏其他玩家私有财产,**处罚措施根据以下情况按严重程度决定**
1. 恶意偷盗、破坏如主城等官方公共设施:所有参与者处予永久封禁;
2. 恶意偷盗、破坏由玩家组织建立的内部性\[^1\]公共设施:如有玩家组织非普世性公约,则首先根据玩家组织非普世性公约进行处罚,玩家组织有有权利要求 白鹿原管理组按照2.3.4相关条例进行进一步处罚;
3. 恶意偷盗、破坏由玩家组织建立的非内部性\[^2\]公共设施:所有参与者视严重程度处予 5\~30 天的临时封禁,极其严重者处予永久封禁;
4. 恶意偷盗、破坏其他玩家已圈地保护的私人财产:所有参与者视严重程度处予 5\~30 天的临时封禁,极其严重者处予永久封禁;
5. **恶意偷盗、破坏其他玩家未圈地保护的私人财产如该财产未明确标明为公共财产则白鹿原管理组不进行处理反之则按2.3.4进行处罚;**
6. 请着重注意:因未及时圈地或权限管理不当导致财产损失的,白鹿原管理组**不进行处理**
4. 每一名 白鹿原玩家都有义务为保持良好的游戏环境进行自我约束与监督,当发现其他玩家进行违反玩家公约所规定的行为时,请向白鹿原管理组检举;
5. 玩家组织有权利设置门槛以限制玩家加入,有对成员进行管理的权利,同时也有设置玩家组织内部规则(服务器非普世性公约)的权利。玩家有权利向白鹿原管理组举报玩家组织的恶意行为;
6. 任何因非管理员操作\[^3\]发生的动物、盔甲架、展示框等物品的丢失都不予以补偿;
7. 服务器**允许制作与使用**涉及到高频红石的机械装置,但是如果因此导致服务器产生明显的卡顿,请自觉**暂时停止使用相关装置**
8. 禁止恶意圈地造成他人的不便,对于特殊资源(如女巫塔、神殿等)**不开发请不要随意圈地占有**。圈地遵循用多少圈多大的原则,**禁止一次性圈下过大的区域**
9. 当玩家进入服务器时,白鹿原管理组已经默认玩家同意了《服务器公约》的全部内容。如玩家不同意《公约》的全部内容,白鹿原管理组有权利禁止玩家进入服务器。
## 三、QQ群公约
1. 群名片中需包含自己的游戏ID
2. 禁止发布以下暴力低俗内容,**所有参与者处予禁言 1\~5 天**,极其严重者将踢出群聊:
1. 令人不适的重口内容;
2. 使用带有生殖器含义及其谐音的词语;
3. 过度暴露的、露点的色情图片与儿童色情;
4. 由同性恋内容发展而来的低俗梗(如:野兽先辈、大鸟转转转等);
5. 含有违法、低俗内容的群名片;
6. 其他可能引起多数人不适的内容;
3. 严禁讨论以下敏感话题及关键字,**所有参与者将踢出群聊**
1. 散布谣言;
2. 讨论与指点国家政策;
3. 制作和发布包含国家领导人头像的表情包;
4. 讨论和发布与科学上网相关的话题和软件;
5. 反动、暴恐、宗教、邪教等扰乱社会治安的内容;
4. 严禁破坏游戏与交流环境的行为,**所有参与者处予禁言 3\~10 天,极其严重者将踢出群聊**
1. 无理取闹的杠精;
2. 辱骂管理员;
3. 阴阳怪气引起多数人不适;
4. 刷屏、影响他人正常聊天;
5. 发送具有整蛊性质的、虚假的XML消息
6. 虚假广告(包括但不限于办证刷单招打字员等);
5. 禁止多次、重复提问群公告已有的内容,从第二次提问开始禁言(提问次数-1分钟
## 四、处理流程
> 该版块将详细罗列白鹿原管理组如何处理部分违反《白鹿原玩家公约》的玩家的流程,欢迎各位白鹿原玩家进行监督。
### 1.《白鹿服务器公约》中第二条的处理流程
当服务器内出现了破坏游戏氛围与交流环境的行为,管理组将会按照以下流程进行处理:
* 接受玩家举报,开始调查,通过服务器日志,聊天截图,现场截图等收集证据;
* 在白鹿原玩家交流群内公开询问当事人与受害者听取双方证词。如双方中的一方或多方不在玩家交流群内直接按照《公约》中相关条例进行处理。非当事人或受害者在询问期间公然恶意带节奏的处予1小时禁言处罚
* 白鹿原管理组首先根据双方态度,进行调解。要求当事人向受害者进行道歉;
* 若双方无法接受调解,则按照《玩家公约》中相关条例进行处理。同时将发布处理公告与相关证据以供公开查阅;
* 如对结果有异议的,管理组不接受再审;
### 2.《白鹿原服务器公约》中第三条的处理流程
当服务器内出现了恶意偷盗、破坏服务器公共财产或使用不正当手段破坏其他玩家私有财产的行为,管理组将会按照以下流程进行处理:
* 玩家需凭借截图证据向白鹿原管理组举报,管理组接受玩家举报,开始调查,通过服务器日志,聊天截图,现场截图等收集证据;
* 在白鹿原玩家交流群内公开询问当事人与受害者听取双方证词。如双方中的一方或多方不在玩家交流群内直接按照《公约》中相关条例进行处理。非当事人或受害者在询问期间公然恶意带节奏的处予1小时禁言处罚
* 白鹿原管理组首先根据双方态度,进行调解,要求当事人在期限内赔偿受害者的损失;
* 若双方无法接受调解,则按照《公约》中相关条例进行处理。同时将发布处理公告与相关证据以供公开查阅,同时管理组将代替当事人向受害者进行赔偿相关损失;
* 如对结果有异议的,管理组不接受再审;

246
join.html Normal file
View File

@@ -0,0 +1,246 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>加入游戏指引 - 白鹿原 Minecraft 服务器</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/pages/join.css">
<!-- Font Awesome for icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Marked.js for Markdown parsing -->
<script src="js/marked.min.js"></script>
</head>
<body>
<!-- Navigation Bar -->
<div id="navbar-component"></div>
<div class="join-page-wrapper">
<div class="join-header-minimal">
<h1>开启您的冒险</h1>
</div>
<main class="wizard-container-modern">
<div class="wizard-sidebar">
<div class="wizard-progress-vertical">
<div class="progress-step active" data-step="1">
<div class="step-dot"></div>
<div class="step-text">
<span class="step-title">公约</span>
<span class="step-desc">阅读须知</span>
</div>
</div>
<div class="progress-step" data-step="2">
<div class="step-dot"></div>
<div class="step-text">
<span class="step-title">设备</span>
<span class="step-desc">选择平台</span>
</div>
</div>
<div class="progress-step" data-step="3">
<div class="step-dot"></div>
<div class="step-text">
<span class="step-title">启动</span>
<span class="step-desc">配置教程</span>
</div>
</div>
<div class="progress-step" data-step="4">
<div class="step-dot"></div>
<div class="step-text">
<span class="step-title">出发</span>
<span class="step-desc">选择玩法</span>
</div>
</div>
</div>
</div>
<div class="wizard-content-area">
<!-- Step 1: Convention -->
<div id="step-1" class="step-content">
<div class="content-header">
<h2>服务器公约</h2>
<p>为了维护良好的游戏环境,请务必阅读并遵守以下规则。</p>
</div>
<div class="convention-wrapper">
<div class="markdown-content" id="convention-content">
<!-- Content will be loaded from data/convention.md -->
<div class="loading-state">
<i class="fas fa-circle-notch fa-spin"></i>
<span>正在加载公约内容...</span>
</div>
</div>
</div>
<div class="agreement-area" onclick="document.getElementById('agree-checkbox').click()">
<div class="custom-checkbox">
<input type="checkbox" id="agree-checkbox">
<span class="checkmark"><i class="fas fa-check"></i></span>
</div>
<label for="agree-checkbox" class="agreement-label">我已认真阅读并承诺遵守《服务器公约》</label>
</div>
</div>
<!-- Step 2: Device Selection -->
<div id="step-2" class="step-content">
<div class="content-header">
<h2>选择您的设备</h2>
<p>工欲善其事,必先利其器。</p>
</div>
<div class="card-content">
<div class="device-selection-grid">
<div class="device-card" data-device="pc">
<div class="icon-circle"><i class="fas fa-desktop"></i></div>
<div class="device-info">
<h3>电脑版</h3>
<p>Win / Mac / Linux</p>
</div>
<div class="check-mark"><i class="fas fa-check"></i></div>
</div>
<div class="device-card" data-device="ios">
<div class="icon-circle"><i class="fab fa-apple"></i></div>
<div class="device-info">
<h3>iOS 设备</h3>
<p>iPhone / iPad</p>
</div>
<div class="check-mark"><i class="fas fa-check"></i></div>
</div>
<div class="device-card" data-device="android">
<div class="icon-circle"><i class="fab fa-android"></i></div>
<div class="device-info">
<h3>安卓设备</h3>
<p>Android 手机 / 平板</p>
</div>
<div class="check-mark"><i class="fas fa-check"></i></div>
</div>
</div>
<div id="launcher-recommendation" class="launcher-box hidden">
<div id="recommendation-content"></div>
</div>
</div>
</div>
<!-- Step 3: Tutorial -->
<div id="step-3" class="step-content">
<div class="content-header">
<h2>配置与启动</h2>
<p>只需几步简单操作即可进入游戏。</p>
</div>
<div class="card-content" id="tutorial-content">
<!-- Content will be injected based on device selection -->
</div>
</div>
<!-- Step 4: Gameplay Guide -->
<div id="step-4" class="step-content">
<div class="content-header">
<h2>选择您的玩法</h2>
<p>这里有无限可能,你想成为什么样的玩家?(点击卡片查看详情)</p>
</div>
<div class="card-content">
<div class="playstyle-grid">
<!-- Style 1: Large Towns -->
<div class="playstyle-card" data-style="large-town">
<div class="playstyle-visual town-bg">
<i class="fas fa-city"></i>
</div>
<div class="playstyle-text">
<h3>融入大型城镇</h3>
<p>快速启航,共建繁华</p>
</div>
</div>
<!-- Style 2: Small Towns -->
<div class="playstyle-card" data-style="small-town">
<div class="playstyle-visual village-bg">
<i class="fas fa-home"></i>
</div>
<div class="playstyle-text">
<h3>加入小型城镇</h3>
<p>共同成长,见证历史</p>
</div>
</div>
<!-- Style 3: Friends -->
<div class="playstyle-card" data-style="friends">
<div class="playstyle-visual friends-bg">
<i class="fas fa-users"></i>
</div>
<div class="playstyle-text">
<h3>与朋友共建</h3>
<p>白手起家,开创时代</p>
</div>
</div>
<!-- Style 4: Solo -->
<div class="playstyle-card" data-style="solo">
<div class="playstyle-visual solo-bg">
<i class="fas fa-user-ninja"></i>
</div>
<div class="playstyle-text">
<h3>独狼求生</h3>
<p>自力更生,隐于山林</p>
</div>
</div>
</div>
<!-- Details Section (Initially Hidden) -->
<div id="playstyle-details" class="playstyle-details-container">
<div class="details-card">
<div class="details-header">
<h3 id="detail-title">玩法标题</h3>
<span id="detail-subtitle" class="badge-subtitle">副标题</span>
</div>
<div class="details-body">
<div class="detail-section">
<h4><i class="fas fa-user-tag"></i> 适合人群</h4>
<p id="detail-target">...</p>
</div>
<div class="detail-grid-row">
<div class="detail-section check-list">
<h4><i class="fas fa-thumbs-up"></i> 优势</h4>
<ul id="detail-pros"></ul>
</div>
<div class="detail-section warn-list">
<h4><i class="fas fa-exclamation-circle"></i> 注意事项</h4>
<ul id="detail-cons"></ul>
</div>
</div>
</div>
</div>
</div>
<div class="final-message">
<p>无论你选择哪条路,都别忘了多探索世界,结识他人。我们期待看到你的故事在这里展开!</p>
</div>
</div>
</div>
<div class="step-footer">
<button id="btn-prev" class="btn-clean" disabled>Back</button>
<div class="step-action-group">
<button id="btn-next" class="btn-primary-large">
下一步 <i class="fas fa-arrow-right"></i>
</button>
<div id="step4-buttons" class="hidden final-actions">
<a href="doc.html" class="btn-clean"><i class="fas fa-book"></i> 查看文档</a>
<a href="index.html" class="btn-primary-large"><i class="fas fa-home"></i> 回到首页</a>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- Footer -->
<div id="footer-component"></div>
<script src="js/components.js"></script>
<script src="js/join_script.js"></script>
</body>
</html>

View File

@@ -20,7 +20,7 @@ const Components = {
<a href="https://qm.qq.com/q/9izlHDoef6" target="_blank">群聊</a> <a href="https://qm.qq.com/q/9izlHDoef6" target="_blank">群聊</a>
</div> </div>
<div class="nav-cta-container"> <div class="nav-cta-container">
<a href="https://outline.lunadeer.cn/s/447e5db6-8af4-468e-b7c5-cdb7b48aa439/doc/5yqg5ywl5pyn5yqh5zmo-WE4jkTxRmM" class="nav-cta" target="_blank">加入游戏</a> <a href="join.html" class="nav-cta">加入游戏</a>
</div> </div>
</div> </div>
</nav> </nav>
@@ -34,6 +34,7 @@ const Components = {
<a href="/stats.html">数据</a> <a href="/stats.html">数据</a>
<a href="/sponsor.html">赞助</a> <a href="/sponsor.html">赞助</a>
<a href="https://qm.qq.com/q/9izlHDoef6" target="_blank">群聊</a> <a href="https://qm.qq.com/q/9izlHDoef6" target="_blank">群聊</a>
<a href="join.html">加入游戏</a>
</div> </div>
</div> </div>
`, `,

464
js/join_script.js Normal file
View File

@@ -0,0 +1,464 @@
document.addEventListener('DOMContentLoaded', () => {
// State
let currentStep = 1;
let selectedDevice = null;
const totalSteps = 4;
// Elements
const prevBtn = document.getElementById('btn-prev');
const nextBtn = document.getElementById('btn-next');
// Updated selector for new sidebar structure
const stepIndicators = document.querySelectorAll('.progress-step');
const stepContents = document.querySelectorAll('.step-content');
const conventionContent = document.getElementById('convention-content');
if (!conventionContent) {
console.error('Critical Error: Element #convention-content not found in DOM');
return;
}
const agreeCheckbox = document.getElementById('agree-checkbox');
const deviceCards = document.querySelectorAll('.device-card');
const recommendationSection = document.getElementById('launcher-recommendation');
const recommendationContent = document.getElementById('recommendation-content');
const tutorialContent = document.getElementById('tutorial-content');
const step4Buttons = document.getElementById('step4-buttons');
const mainWizardActions = document.querySelector('.wizard-actions');
console.log('DOM Elements loaded. Step contents found:', stepContents.length);
// Fallback if marked is not loading correctly
if (typeof marked === 'undefined') {
console.warn("Marked not defined globally, checking for window.marked");
if (window.marked) {
console.log("Found window.marked");
// Assign to local variable if needed or just use window.marked
}
}
// --- Step 1: Convention Loading ---
console.log('Fetching convention from data/convention.md ...');
fetch('data/convention.md')
.then(response => {
console.log('Response status:', response.status);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.text();
})
.then(markdown => {
console.log('Convention loaded, length:', markdown.length);
let parser = null;
if (typeof marked !== 'undefined') {
if (typeof marked.parse === 'function') parser = marked.parse;
else if (typeof marked === 'function') parser = marked;
} else if (window.marked) {
if (typeof window.marked.parse === 'function') parser = window.marked.parse;
else if (typeof window.marked === 'function') parser = window.marked;
}
if (parser) {
try {
const result = parser(markdown);
if (result instanceof Promise) {
result.then(html => conventionContent.innerHTML = html);
} else {
conventionContent.innerHTML = result;
}
} catch (e) {
console.error('Parse error:', e);
conventionContent.innerHTML = '<pre>' + markdown + '</pre>';
}
} else {
console.error('No markdown parser found');
conventionContent.innerHTML = '<pre>' + markdown + '</pre>';
}
})
.catch(error => {
console.error('Convention fetch error:', error);
conventionContent.innerHTML = `<p style="color:red">无法加载公约内容: ${error.message}</p>`;
});
// --- Navigation Logic ---
function updateWizard() {
console.log('UpdateWizard called, step:', currentStep);
// Update Indicators
stepIndicators.forEach(indicator => {
const step = parseInt(indicator.dataset.step);
if (step === currentStep) {
indicator.classList.add('active');
indicator.classList.remove('completed');
} else if (step < currentStep) {
indicator.classList.add('completed');
indicator.classList.remove('active');
} else {
indicator.classList.remove('active', 'completed');
}
});
// Update Progress Bar Fill
const progressFill = document.getElementById('progress-fill');
if (progressFill) {
const progress = ((currentStep - 1) / (totalSteps - 1)) * 100;
progressFill.style.width = `${progress}%`;
}
// Update Content visibility with Animation timeout
stepContents.forEach(content => {
if (content.id === `step-${currentStep}`) {
content.classList.add('active');
// Optional: ensure display block if handled by CSS alone or JS
} else {
content.classList.remove('active');
}
});
// Buttons State
updateButtons();
}
function updateButtons() {
// Prev Button
if (prevBtn) prevBtn.disabled = currentStep === 1;
// Next Button logic
if (currentStep === 1) {
// Step 1: Checkbox required
if (nextBtn) nextBtn.disabled = !agreeCheckbox.checked;
} else if (currentStep === 2) {
// Step 2: Device selection required
if (nextBtn) nextBtn.disabled = !selectedDevice;
} else {
if (nextBtn) nextBtn.disabled = false;
}
// Step 4 special buttons visibility
if (currentStep === totalSteps) {
if (nextBtn) nextBtn.style.display = 'none';
if (step4Buttons) step4Buttons.classList.remove('hidden');
} else {
if (nextBtn) nextBtn.style.display = 'inline-flex';
if (step4Buttons) step4Buttons.classList.add('hidden');
}
}
if (prevBtn) {
prevBtn.addEventListener('click', () => {
if (currentStep > 1) {
currentStep--;
updateWizard();
}
});
}
if (nextBtn) {
nextBtn.addEventListener('click', () => {
if (currentStep < totalSteps) {
if (currentStep === 2) {
renderTutorial(); // Generate step 3 content before showing
// Also scroll to top for better ux
window.scrollTo({ top: 0, behavior: 'smooth' });
}
currentStep++;
updateWizard();
window.scrollTo({ top: 0, behavior: 'smooth' });
}
});
}
// Step 1 Checkbox
if (agreeCheckbox) {
agreeCheckbox.addEventListener('change', updateButtons);
}
// --- Step 2: Device Selection ---
const deviceData = {
pc: {
title: "电脑版 (Java Edition)",
recommendations: [
{
name: "PCL2",
icon: "fas fa-cube",
desc: "界面精美功能强大的现代化启动器仅Win",
url: "https://afdian.net/p/0164034c016c11ebafcb52540025c377",
primary: true
},
{
name: "HMCL",
icon: "fas fa-horse-head",
desc: "历史悠久,跨平台支持好 (Win/Mac/Linux)",
url: "https://hmcl.huangyuhui.net/",
primary: false
}
],
note: "推荐使用 PCL2 或 HMCL均支持极大改善游戏体验。"
},
ios: {
title: "iOS 设备",
recommendations: [
{
name: "PojavLauncher",
icon: "fab fa-app-store-ios",
desc: "iOS 上运行 Java 版的唯一选择",
url: "https://apps.apple.com/us/app/pojavlauncher/id6443526546",
primary: true
}
],
note: "需要 iOS 14.0 或更高版本。若未越狱,请保持 JIT 开启以获得最佳性能(部分版本可能需要)。"
},
android: {
title: "安卓设备",
recommendations: [
{
name: "FCL 启动器",
icon: "fab fa-android",
desc: "基于 FoldCraft 的高性能启动器",
url: "https://github.com/FoldCraftLauncher/FoldCraftLauncher/releases",
primary: true
},
{
name: "PojavLauncher",
icon: "fas fa-gamepad",
desc: "经典的移动端 Java 版启动器",
url: "https://play.google.com/store/apps/details?id=net.kdt.pojavlaunch",
primary: false
}
],
note: "建议设备拥有至少 4GB 运存以流畅运行 1.21 版本。"
}
};
deviceCards.forEach(card => {
card.addEventListener('click', () => {
// UI Update
deviceCards.forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
const deviceType = card.dataset.device;
selectedDevice = deviceType; // Correctly update state
// Show Recommendation
showRecommendation(deviceType);
// Re-enable next button
updateButtons();
});
});
function showRecommendation(device) {
const data = deviceData[device];
if (!data) return;
if (recommendationSection) {
recommendationSection.classList.remove('hidden');
// Little fade-in effect
recommendationSection.style.opacity = '0';
setTimeout(() => recommendationSection.style.opacity = '1', 50);
}
let cardsHtml = data.recommendations.map(req => `
<a href="${req.url}" target="_blank" class="launcher-card ${req.primary ? 'primary' : ''}">
<div class="launcher-icon">
<i class="${req.icon}"></i>
</div>
<div class="launcher-details">
<h4>${req.name} ${req.primary ? '<span class="badge-rec">推荐</span>' : ''}</h4>
<p>${req.desc}</p>
</div>
<div class="launcher-action">
<i class="fas fa-download"></i>
</div>
</a>
`).join('');
const html = `
<div class="recommendation-header">
<h3>为 ${data.title} 准备启动器</h3>
<p>${data.note}</p>
</div>
<div class="launcher-grid">
${cardsHtml}
</div>
`;
if (recommendationContent) recommendationContent.innerHTML = html;
}
// --- Step 3: Tutorial Rendering ---
const deviceTutorials = {
pc: [
{
title: '登录账号',
desc: '打开启动器PCL2/HMCL选择“添加账号”。推荐使用 Microsoft 账号登录拥有正版 Minecraft 的账户。'
},
{
title: '安装游戏',
desc: '在启动器中创建一个新游戏配置,选择游戏版本 <strong>1.21.x</strong>。强烈建议安装 <a href="https://fabricmc.net/" target="_blank">Fabric</a> 加载器以获得更好的模组支持和性能优化。'
},
{
title: '启动游戏',
desc: '等待游戏资源文件下载完成,点击启动游戏直到看到 Minecraft 主界面。'
},
{
title: '加入服务器',
desc: `点击“多人游戏” -> “添加服务器”。<br>
服务器名称:<span class="highlight-text">白鹿原</span><br>
服务器地址:
<div class="server-address-box">
<code id="server-address">mcpure.lunadeer.cn</code>
<button class="btn-copy" onclick="navigator.clipboard.writeText('mcpure.lunadeer.cn').then(() => { this.innerHTML = '<i class=\\'fas fa-check\\'></i> 已复制'; setTimeout(() => this.innerHTML = '<i class=\\'fas fa-copy\\'></i> 复制', 2000); })">
<i class="fas fa-copy"></i> 复制
</button>
</div>
点击“完成”并双击服务器即可加入。`
}
],
ios: [
{
title: '准备环境',
desc: '打开 PojavLauncher。若您的设备未越狱请确保已启用 JITJust-In-Time以获得可玩的帧率。'
},
{
title: '登录账号',
desc: '点击“添加账户”选择“Microsoft 账户”并完成登录流程。'
},
{
title: '下载并启动',
desc: '点击“创建新配置”,选择版本 <strong>1.21.x</strong>。建议调整内存分配至设备总内存的 50% 左右,然后点击“启动”。'
},
{
title: '加入服务器',
desc: `进入主界面后,选择 Multiplayer多人游戏 -> Add Server添加服务器。<br>
Address地址
<div class="server-address-box">
<code id="server-address-ios">mcpure.lunadeer.cn</code>
<button class="btn-copy" onclick="navigator.clipboard.writeText('mcpure.lunadeer.cn').then(() => { this.innerHTML = '<i class=\\'fas fa-check\\'></i> 已复制'; setTimeout(() => this.innerHTML = '<i class=\\'fas fa-copy\\'></i> 复制', 2000); })">
<i class="fas fa-copy"></i>
</button>
</div>
点击 Done 并加入。`
}
],
android: [
{
title: '配置启动器',
desc: '打开 FCL 或 PojavLauncher。给予必要的存储权限。'
},
{
title: '登录账号',
desc: '在账户设置中添加 Microsoft 账户。'
},
{
title: '安装版本',
desc: '下载 <strong>1.21.x</strong> 游戏核心。FCL 用户可直接使用内置下载源加速下载。建议安装 OptiFine 或 Fabric+Sodium 以提升帧率。'
},
{
title: '加入服务器',
desc: `启动游戏后,点击 Multiplayer多人游戏 -> Add Server添加服务器。<br>
Address地址
<div class="server-address-box">
<code id="server-address-android">mcpure.lunadeer.cn</code>
<button class="btn-copy" onclick="navigator.clipboard.writeText('mcpure.lunadeer.cn').then(() => { this.innerHTML = '<i class=\\'fas fa-check\\'></i> 已复制'; setTimeout(() => this.innerHTML = '<i class=\\'fas fa-copy\\'></i> 复制', 2000); })">
<i class="fas fa-copy"></i> 复制
</button>
</div>
点击 Done 并加入。`
}
]
};
function renderTutorial() {
const device = selectedDevice || 'pc'; // default to pc if somehow null
const steps = deviceTutorials[device] || deviceTutorials['pc'];
let content = '<div class="tutorial-steps">';
steps.forEach((step, index) => {
content += `
<div class="tutorial-step">
<div class="step-badge">${index + 1}</div>
<div class="step-text">
<h4>${step.title}</h4>
<p>${step.desc}</p>
</div>
</div>
`;
});
content += '</div>';
if (tutorialContent) {
tutorialContent.innerHTML = content;
}
}
// --- Step 4: Playstyle Selection ---
const playstyleCards = document.querySelectorAll('.playstyle-card');
const playstyleDetails = document.getElementById('playstyle-details');
const playstyleData = {
'large-town': {
title: '融入大型城镇',
subtitle: '快速启航,共建繁华 (10+人)',
target: '希望跳过艰难的初期积累,快速投入大规模建造与合作的玩家。',
pros: ['资源无忧:可直接从公共仓库获取建材与工具。', '工业完善:享受成熟的自动化生产带来的便利。'],
cons: ['为了整体美观与规划,可能需要遵守城镇的建筑风格与管理安排,自由度相对受限。']
},
'small-town': {
title: '加入小型城镇',
subtitle: '共同成长,见证历史 (3-10人)',
target: '喜欢参与从零到一的建设过程,享受亲手打造家园成就感的玩家。',
pros: ['发展参与感:亲身参与城镇的规划与扩张。', '自由度较高:在发展初期通常有更多的个人发挥空间。'],
cons: ['初期资源相对有限,需要与同伴共同努力。']
},
'friends': {
title: '与朋友共建家园',
subtitle: '白手起家,开创时代 (1-3人)',
target: '拥有固定小团体,渴望一片完全属于自己的领地的玩家。',
pros: ['绝对自由:从选址到规划,一切由你定义。', '纯粹体验:体验最原始的协作与创造乐趣。'],
cons: ['这是一条充满挑战的道路,但从无到有建立的一切都将格外珍贵。']
},
'solo': {
title: '独狼求生',
subtitle: '自力更生,隐于山林',
target: '享受孤独,崇尚一切亲力亲为的硬核生存玩家。',
pros: ['极致的自由与独立,你的世界只属于你。', '可尝试与其他玩家进行贸易换取无法独自获得的资源。'],
cons: ['一切都需要亲力亲为,生存挑战较大。']
}
};
if (playstyleCards.length > 0 && playstyleDetails) {
playstyleCards.forEach(card => {
card.addEventListener('click', () => {
// UI Visual Selection
playstyleCards.forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
// Get Data
const styleKey = card.dataset.style;
const data = playstyleData[styleKey];
if (data) {
// Populate Details
document.getElementById('detail-title').textContent = data.title;
document.getElementById('detail-subtitle').textContent = data.subtitle;
document.getElementById('detail-target').textContent = data.target;
const prosList = document.getElementById('detail-pros');
const consList = document.getElementById('detail-cons');
prosList.innerHTML = data.pros.map(p => `<li>${p}</li>`).join('');
consList.innerHTML = data.cons.map(c => `<li>${c}</li>`).join('');
// Show Details
playstyleDetails.classList.add('visible');
// Optional: scroll into view gently if needed, or stick to bottom
playstyleDetails.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
});
});
}
// Initial check
updateWizard();
});

69
js/marked.min.js vendored Normal file

File diff suppressed because one or more lines are too long