<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Aliso&apos; Blog</title><description>Like Water. Like Code. Always Evolving</description><link>https://visa-aliso.github.io/</link><language>zh_CN</language><item><title>从 Hexo 迁移到 Astro</title><link>https://visa-aliso.github.io/posts/migrate-to-astro/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/migrate-to-astro/</guid><description>把旧 Hexo 博客快照保留下来，并把日常写作迁移到基于 Astro 的 Fuwari</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;为什么迁移&lt;/h1&gt;
&lt;p&gt;最开始搭建这个博客的时候，我还是一个刚接触前端的新手。那时候对于静态博客框架并没有太多了解，最后看教程直接选择了 Hexo 作为博客框架，使用的是 Vivia 主题，也陆续根据自己的需求对博客做了不少修改。&lt;/p&gt;
&lt;p&gt;前段时间，我偶然发现 Vivia 已经推出了基于 Astro 的版本，而且项目一直保持着持续维护。然后发现自己以前花了不少时间手动实现的很多功能，在新版本中都已经得到了原生支持，整体的设计和开发体验也更加现代化。不仅如此，Astro 本身在性能、构建速度以及内容管理方面也比当初的 Hexo 更有优势。&lt;/p&gt;
&lt;p&gt;于是现在我把博客从 Hexo 迁移到 Astro。一方面可以摆脱过去自己改的主题的各种丑陋的代码，另一方面也能借着这次迁移重新整理博客的结构和配置，让后续的维护更加轻松。&lt;/p&gt;
&lt;h1&gt;保留旧站&lt;/h1&gt;
&lt;p&gt;迁移不是为了丢弃过去。旧的 Hexo 站点被整树保留下来，作为可点开浏览的「时间胶囊」快照，搬进新站的 public/legacy/ 目录，随构建产物一起发布到 /legacy/ 路径下。&lt;/p&gt;
&lt;p&gt;这样既不丢历史内容，也让新站保持干净——旧站是只读快照，新内容只写在 Astro 这边。&lt;/p&gt;
&lt;h1&gt;改路径让旧站自洽&lt;/h1&gt;
&lt;p&gt;旧站所有链接都是根路径，举例如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/css/style.css
/archives
/tags/Linux/
/2025/09/02/无限进步/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;放进 /legacy/ 子路径后，这些链接会全部指到新站根，样式断、跳转断。&lt;/p&gt;
&lt;p&gt;写了一个脚本 scripts/prepare-legacy.js，递归遍历旧站所有 HTML，把根路径属性重写成 /legacy/ 开头，举例如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 改动前
src=&quot;/js/script.js&quot;
href=&quot;/archives&quot;

# 改动后
src=&quot;/legacy/js/script.js&quot;
href=&quot;/legacy/archives&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;跳过 //cdn 和完整 URL，顺便给每个 body 标签加上 data-pagefind-ignore。跑一次后旧站就能在新站子路径里完整自洽浏览，导航、翻页、样式都不坏。&lt;/p&gt;
&lt;h1&gt;排除出新站索引&lt;/h1&gt;
&lt;p&gt;旧站快照不应该污染新站的搜索结果和 SEO：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pagefind&lt;/strong&gt;：靠脚本注入的 body[data-pagefind-ignore]，搜索索引自动跳过旧站整页。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sitemap&lt;/strong&gt;：在 astro.config.mjs 给 sitemap() 加了一行 filter，把含 /legacy/ 的 URL 排除出 sitemap。具体写法如下：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;filter: (page) =&amp;gt; !page.includes(&quot;/legacy/&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样搜索框只反映新内容，搜索引擎也只收录新站页面。&lt;/p&gt;
&lt;h1&gt;验证与小结&lt;/h1&gt;
&lt;p&gt;构建后访问博文里的链接跳到 /legacy/，旧站的首页、归档、分类、标签、文章内页都能正常导航，样式不崩、不跳回新站根。新旧两套互不干扰，迁移完成。&lt;/p&gt;
&lt;p&gt;如果你想看看这次迁移前是什么样子，可以点这里访问&lt;a href=&quot;/legacy/&quot;&gt;旧版博客&lt;/a&gt;，整个 Hexo 站点被原样保留下来作为快照。&lt;/p&gt;
</content:encoded></item><item><title>NoMaD项目复现</title><link>https://visa-aliso.github.io/posts/nomad-reproduction/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/nomad-reproduction/</guid><description>完成 NoMaD 模型的训练，并在不依赖实机平台的条件下，实现轨迹的生成。</description><pubDate>Wed, 04 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;NoMaD项目复现&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/2310.07896&quot;&gt;NoMaD: Goal Masked Diffusion Policies for Navigation and Exploration&lt;/a&gt;提出了一种基于 Transformer 与扩散模型的统一导航策略，能够在未知的环境中同时进行无目标探索和目标条件导航，并以更高效率实现更强泛化能力。&lt;/p&gt;
&lt;h2&gt;Train&lt;/h2&gt;
&lt;p&gt;最初训练模型是在本地电脑上进行，但是遇到训练速度过慢的问题，于是后续训练在服务器中进行。配置好环境之后，进行数据处理，此次训练采用 go_stanford 数据集（数据量小，适合学习用），但是因为 go_stanford 数据里的 yaw 和 position 在格式上不稳定（常见是多一维、不是标量、长度不够），而原始 _compute_actions 默认它们是形状固定的一维数组。结果在数据处理阶段做切片、拼接和 padding 时，yaw 会因为多出来的一维或类型不一致直接导致 shape 不匹配、np.concatenate / np.repeat 报错。所以要将以下文件的代码进行修改：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;file：train/vint_train/data/vint_dataset.py&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Original code:
    def _compute_actions(self, traj_data, curr_time, goal_time):
        start_index = curr_time
        end_index = curr_time + self.len_traj_pred * self.waypoint_spacing + 1
        yaw = traj_data[&quot;yaw&quot;][start_index:end_index:self.waypoint_spacing]
        positions = traj_data[&quot;position&quot;][start_index:end_index:self.waypoint_spacing]
        goal_pos = traj_data[&quot;position&quot;][min(goal_time, len(traj_data[&quot;position&quot;]) - 1)]

        if len(yaw.shape) == 2:
            yaw = yaw.squeeze(1)

        if yaw.shape != (self.len_traj_pred + 1,):
            const_len = self.len_traj_pred + 1 - yaw.shape[0]
            yaw = np.concatenate([yaw, np.repeat(yaw[-1], const_len)])
            positions = np.concatenate([positions, np.repeat(positions[-1][None], const_len, axis=0)], axis=0)

        assert yaw.shape == (self.len_traj_pred + 1,), f&quot;{yaw.shape} and {(self.len_traj_pred + 1,)} should be equal&quot;
        assert positions.shape == (self.len_traj_pred + 1, 2), f&quot;{positions.shape} and {(self.len_traj_pred + 1, 2)} should be equal&quot;

        waypoints = to_local_coords(positions, positions[0], yaw[0])
        goal_pos = to_local_coords(goal_pos, positions[0], yaw[0])

        assert waypoints.shape == (self.len_traj_pred + 1, 2), f&quot;{waypoints.shape} and {(self.len_traj_pred + 1, 2)} should be equal&quot;

        if self.learn_angle:
            yaw = yaw[1:] - yaw[0]
            actions = np.concatenate([waypoints[1:], yaw[:, None]], axis=-1)
        else:
            actions = waypoints[1:]
        
        if self.normalize:
            actions[:, :2] /= self.data_config[&quot;metric_waypoint_spacing&quot;] * self.waypoint_spacing
            goal_pos /= self.data_config[&quot;metric_waypoint_spacing&quot;] * self.waypoint_spacing

        assert actions.shape == (self.len_traj_pred, self.num_action_params), f&quot;{actions.shape} and {(self.len_traj_pred, self.num_action_params)} should be equal&quot;

        return actions, goal_pos

# Modified code:
    def _compute_actions(self, traj_data, curr_time, goal_time):
        start_index = curr_time
        end_index = curr_time + self.len_traj_pred * self.waypoint_spacing + 1

        yaw = np.array(traj_data[&quot;yaw&quot;][start_index:end_index:self.waypoint_spacing], dtype=np.float32).flatten()
        positions = np.array(traj_data[&quot;position&quot;][start_index:end_index:self.waypoint_spacing], dtype=np.float32)
        goal_pos = np.array(traj_data[&quot;position&quot;][min(goal_time, len(traj_data[&quot;position&quot;]) - 1)], dtype=np.float32)

        # 补齐长度
        if yaw.shape[0] != self.len_traj_pred + 1:
            const_len = self.len_traj_pred + 1 - yaw.shape[0]
            yaw = np.concatenate([yaw, np.repeat(yaw[-1], const_len)])
            positions = np.concatenate([positions, np.repeat(positions[-1][None], const_len, axis=0)], axis=0)

        # 确保都是 float32
        yaw = yaw.astype(np.float32)
        positions = positions.astype(np.float32)

        waypoints = to_local_coords(positions, positions[0], float(yaw[0]))
        goal_pos = to_local_coords(goal_pos, positions[0], float(yaw[0]))

        if self.learn_angle:
            yaw_delta = (yaw[1:] - yaw[0]).astype(np.float32)
            actions = np.concatenate([waypoints[1:], yaw_delta[:, None]], axis=-1)
        else:
            actions = waypoints[1:]

        # 标准化
        if self.normalize:
            actions[:, :2] /= self.data_config[&quot;metric_waypoint_spacing&quot;] * self.waypoint_spacing
            goal_pos /= self.data_config[&quot;metric_waypoint_spacing&quot;] * self.waypoint_spacing

        # 最终确保是 float32
        actions = np.asarray(actions, dtype=np.float32)
        goal_pos = np.asarray(goal_pos, dtype=np.float32)

        return actions, goal_pos
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在完成数据处理后，进行了模型训练，共训练 30 epochs，最终得到模型权重文件（.pth）。训练过程中，各项参数的变化情况均可在 Weights &amp;amp; Biases（wandb）中进行可视化查看。&lt;/p&gt;
&lt;h2&gt;Deployment&lt;/h2&gt;
&lt;p&gt;由于没有实机部署的条件，于是采用&lt;a href=&quot;https://github.com/Mrakas/nomad&quot;&gt;https://github.com/Mrakas/nomad&lt;/a&gt;的方案。&lt;/p&gt;
&lt;p&gt;配置好环境之后，需要导入权重文件（.pth）并将代码结构统一，主要是修改相关文件中的路径设置。需要注意的是，diffusion_policy 是通过直接 git clone 得到的：外层是一个大文件夹，里面又包含一个同名的 diffusion_policy 子文件夹，这种结构很容易导致路径重复或引用混乱。因此，可能需要在多个地方进行调整，包括 diffusion_policy 内部的文件以及 deployment 相关文件中的路径引用。&lt;/p&gt;
&lt;p&gt;相关代码完成之后，选择图片文件进行处理即可运行。目前程序最初的执行逻辑是：只取某一条轨迹中的某一个点，因此只会返回一个二维的 waypoint。需要对这部分逻辑进行如下修改：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;api_explore_RGB.py&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    # ...

    def navigate(self,
                 single_img = None,# priority
                 num_samples: int = 8, 
                 waypoint_index: int = 2,
                 return_traj: bool = False) -&amp;gt; np.ndarray:
        &quot;&quot;&quot;
        Main navigation method to generate navigation actions.

        Args:
            context_images (List[str]): List of image paths for context
            num_samples (int, optional): Number of action samples. Defaults to 8.
            waypoint_index (int, optional): Waypoint to use for navigation. Defaults to 2.
            return_traj (bool, optional): Whether to return full trajectory. Defaults to False.

        Returns:
            np.ndarray: Chosen navigation waypoint
        &quot;&quot;&quot;
        # Check context size
        
        # Load and transform images
        
        if len(self.context_queue) &amp;lt; 4:
            self.context_queue = [single_img,single_img,single_img,single_img] # 4imgs !!
        else:
            self.context_queue = self.context_queue[1:] + [single_img]

        context_queue = self.context_queue
        
        obs_images = transform_images(context_queue, self.model_params[&quot;image_size&quot;], center_crop=False)
        obs_images = obs_images.to(self.device)

        # Prepare goal and mask
        fake_goal = torch.randn((1, 3, *self.model_params[&quot;image_size&quot;])).to(self.device)
        mask = torch.ones(1).long().to(self.device)

        # Inference
        with torch.no_grad():
            # Encode vision features
            obs_cond = self.model(&apos;vision_encoder&apos;, obs_img=obs_images, goal_img=fake_goal, input_goal_mask=mask)
            
            # Repeat condition for multiple samples
            obs_cond = obs_cond.repeat(num_samples, 1) if len(obs_cond.shape) == 2 else obs_cond.repeat(num_samples, 1, 1)
            
            # Initialize noisy action
            noisy_action = torch.randn(
                (num_samples, self.model_params[&quot;len_traj_pred&quot;], 2), device=self.device)
            naction = noisy_action

            # Run noise scheduler
            self.noise_scheduler.set_timesteps(self.num_diffusion_iters)
            for k in self.noise_scheduler.timesteps[:]:
                noise_pred = self.model(
                    &apos;noise_pred_net&apos;,
                    sample=naction,
                    timestep=k,
                    global_cond=obs_cond
                )
                naction = self.noise_scheduler.step(
                    model_output=noise_pred,
                    timestep=k,
                    sample=naction
                ).prev_sample

        # Process actions
        naction = to_numpy(get_action(naction))

        if return_traj:
            return naction  # (num_samples, T, 2)

        naction = naction[0]  # Select first sample
        chosen_waypoint = naction[waypoint_index]

        # Normalize if required
        if self.model_params.get(&quot;normalize&quot;, False):
            chosen_waypoint *= (self.MAX_V / self.RATE)

        return chosen_waypoint

    # ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;api_test_RGB.py&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
sys.path.append(&apos;../vint_release/deployment&apos;)

from deployment.src.api_explore_RGB import VisualNavigationAPI
import PIL.Image as PILImage
import numpy as np

def main():
    single_img_path = &apos;path/to/0.jpg&apos;
    single_img = PILImage.open(single_img_path).convert(&quot;RGB&quot;)

    nav_api = VisualNavigationAPI(model_name=&quot;nomad&quot;)

    # 核心：返回整条轨迹
    naction = nav_api.navigate(
        single_img=single_img,
        num_samples=8,
        return_traj=True
    )

    print(&quot;naction shape:&quot;, naction.shape)  # (8, 8, 2)
    np.save(&quot;naction.npy&quot;, naction)
    print(&quot;saved naction.npy&quot;)

if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后，利用 show.py 生成轨迹。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import numpy as np
import matplotlib.pyplot as plt

naction = np.load(&quot;naction.npy&quot;)

plt.figure(figsize=(6, 6))
for i in range(naction.shape[0]):
    x = naction[i, :, 0]
    y = naction[i, :, 1]
    plt.plot(x, y, marker=&apos;o&apos;, alpha=0.8)

plt.axis(&quot;equal&quot;)
plt.grid(True)
plt.title(&quot;Predicted Trajectories&quot;)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;尽管代码改的十分丑陋，但好在是完成了 ಥ_ಥ 。&lt;/p&gt;
</content:encoded></item><item><title>服务器搭建代理环境</title><link>https://visa-aliso.github.io/posts/server-proxy/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/server-proxy/</guid><description>终于解决了服务器某些网络问题了QAQ</description><pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Clash 代理服务在服务器上快速部署&lt;/h2&gt;
&lt;h3&gt;上传文件到服务器主目录&lt;/h3&gt;
&lt;p&gt;将以下两个文件上传到服务器主目录：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/files/clash&quot;&gt;clash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/files/cache.db&quot;&gt;cache.db&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;准备配置文件&lt;/h3&gt;
&lt;p&gt;在本地的 Clash 客户端中找到你的代理配置文件（通常是 .yml 后缀），将其改名为 config.yaml，并上传到服务器主目录。&lt;/p&gt;
&lt;h3&gt;启动 Clash&lt;/h3&gt;
&lt;p&gt;在服务器终端执行以下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod +x clash
./clash -d .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果能够弹出代理节点，说明 Clash 启动成功。(不能退出这个终端)&lt;/p&gt;
&lt;h3&gt;在终端中使用代理&lt;/h3&gt;
&lt;p&gt;在需要使用代理的终端输入以下命令（根据实际 IP 和端口调整）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export https_proxy=127.0.0.1:7890
export http_proxy=127.0.0.1:7890
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;设置成功后，终端的网络请求就会通过 Clash 代理。&lt;/p&gt;
</content:encoded></item><item><title>搭建WSL</title><link>https://visa-aliso.github.io/posts/wsl-setup/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/wsl-setup/</guid><description>在Windows环境中搭建Linux环境</description><pubDate>Tue, 13 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Win11 下 WSL2 搭建记录&lt;/h1&gt;
&lt;p&gt;本文记录一次从零开始搭建 WSL2的完整过程，同时整理相关的关键命令。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;一、什么是 WSL？&lt;/h2&gt;
&lt;p&gt;WSL（Windows Subsystem for Linux）是 Windows 提供的 Linux 子系统，使我们可以在 Windows 下直接运行原生 Linux 环境。其中：&lt;/p&gt;
&lt;p&gt;WSL1：系统调用翻译层（已基本淘汰）&lt;/p&gt;
&lt;p&gt;WSL2：基于轻量虚拟机，完整 Linux 内核（当前主流）&lt;/p&gt;
&lt;p&gt;本文全部基于 WSL2 + Win11。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;二、先安装，再迁移至 D 盘&lt;/h2&gt;
&lt;h3&gt;2.1 安装 Ubuntu（默认在 C 盘）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;wsl --install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装完成后：首次启动会创建用户和密码&lt;/p&gt;
&lt;h3&gt;2.2 关闭 WSL&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.3 导出 Ubuntu（生成 tar 备份）&lt;/h3&gt;
&lt;p&gt;先查看发行版名称：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl -l -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后导出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --export Ubuntu D:\WSL\ubuntu_backup.tar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该 tar 文件包含：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-系统
-用户
-home 目录
-已安装的软件和配置
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.4 注销原有 Ubuntu（删除 C 盘那份）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;wsl --unregister Ubuntu
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;⚠️ 此操作会删除 C 盘里的 Ubuntu，但 tar 备份是完整的。&lt;/p&gt;
&lt;h3&gt;2.5 导入到 D 盘&lt;/h3&gt;
&lt;p&gt;先创建目标目录，例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;D:\WSL\Ubuntu
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --import Ubuntu D:\WSL\Ubuntu D:\WSL\ubuntu_backup.tar --version 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时：Ubuntu 被重新注册，ext4.vhdx 会生成在 D 盘&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;三、成功标志与环境说明&lt;/h2&gt;
&lt;p&gt;当你看到类似提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;username@HOSTNAME:~$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并伴随提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;To run a command as administrator (user &quot;root&quot;), use &quot;sudo &amp;lt;command&amp;gt;&quot;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明：Ubuntu 已正常启动，当前为普通用户，可通过 sudo 获取管理员权限&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;四、安装CUDA&lt;/h2&gt;
&lt;p&gt;在确认 WSL2 已正确启用、Ubuntu 子系统可正常运行，且 Windows 侧显卡驱动已支持 WSL GPU 后，下一步便是为 Linux 环境配置 CUDA 开发工具链。&lt;/p&gt;
&lt;p&gt;考虑到 稳定性、维护成本以及 WSL 环境的兼容性，本文选择 Ubuntu 官方仓库提供的 CUDA Toolkit，而非 NVIDIA 官方 runfile 安装方式。&lt;/p&gt;
&lt;h3&gt;4.1 更新系统软件源&lt;/h3&gt;
&lt;p&gt;在安装 CUDA 之前，建议先同步系统的软件索引并升级已有组件，以避免依赖冲突：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update

sudo apt upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该步骤不会影响 Windows 系统，只作用于 WSL 内部的 Ubuntu 文件系统。如果提示可升级大量基础库，属于正常现象，建议确认执行。&lt;/p&gt;
&lt;h3&gt;4.2 查询可用的 CUDA Toolkit 版本&lt;/h3&gt;
&lt;p&gt;Ubuntu 官方仓库并不会提供所有 NVIDIA 官网的 CUDA 版本，而是提供 经过适配与验证的稳定版本。可以通过以下命令查看当前可用的 CUDA Toolkit：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt search nvidia-cuda-toolkit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;典型输出如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nvidia-cuda-toolkit 12.0.x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这意味着当前系统可直接安装 CUDA 12.0，对大多数深度学习与科研项目已经完全足够。&lt;/p&gt;
&lt;h3&gt;4.3 安装 CUDA Toolkit&lt;/h3&gt;
&lt;p&gt;直接通过 apt 安装即可：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install nvidia-cuda-toolkit -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该命令会自动安装以下内容：&lt;/p&gt;
&lt;p&gt;CUDA 编译器（nvcc）&lt;/p&gt;
&lt;p&gt;CUDA Runtime 与开发库&lt;/p&gt;
&lt;p&gt;标准头文件与调试工具&lt;/p&gt;
&lt;p&gt;安装过程中无需手动配置环境变量，这是官方仓库方案的一个重要优势。&lt;/p&gt;
&lt;h3&gt;4.4 验证 CUDA 安装状态&lt;/h3&gt;
&lt;p&gt;安装完成后，首先检查 CUDA 编译器是否可用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nvcc --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;若输出类似以下内容，说明 CUDA Toolkit 已成功安装：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Cuda compilation tools, release 12.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着确认 nvcc 是否已加入系统 PATH：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;which nvcc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在官方仓库方案下，返回路径通常为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/bin/nvcc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是 完全正常且推荐的结果，无需额外修改 .bashrc 或手动添加环境变量。&lt;/p&gt;
&lt;h3&gt;4.6 小结&lt;/h3&gt;
&lt;p&gt;至此，WSL2 下的 CUDA 开发环境已经搭建完成：&lt;/p&gt;
&lt;p&gt;无需手动配置环境变量&lt;/p&gt;
&lt;p&gt;无需下载 NVIDIA runfile&lt;/p&gt;
&lt;p&gt;可直接用于 PyTorch、CUDA C++ 或科研项目开发&lt;/p&gt;
&lt;p&gt;后续只需根据具体项目需求，安装对应的深度学习框架或编译 CUDA 程序即可。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;五、WSL 使用&lt;/h2&gt;
&lt;h2&gt;推荐的长期结构：&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;内容
    -建议位置
Linux 系统
    D:\WSL\Ubuntu
项目代码
    /home/&amp;lt;user&amp;gt;/projects
大数据集
    /mnt/d/datasets
Python / Conda
    Linux 内部
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Windows 访问 Linux：&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;\\wsl$\Ubuntu\home\&amp;lt;user&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Linux 访问 Windows：&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;/mnt/c
/mnt/d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;WSL（Windows 侧）管理命令【PowerShell / CMD】&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ 以下命令 在 Windows 终端 / PowerShell / CMD 中执行&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;wsl --list --verbose
# 列出所有已安装的 WSL 发行版，并显示使用的是 WSL1 还是 WSL2

wsl -l -v
# 上一条命令的简写形式，效果完全一致

wsl -d Ubuntu
# 启动名为 Ubuntu 的 WSL 发行版

wsl --set-default Ubuntu
# 将 Ubuntu 设置为默认发行版（直接输入 wsl 时启动它）

wsl --set-version Ubuntu 2
# 将 Ubuntu 切换为 WSL2（需要系统支持虚拟化）

wsl --shutdown
# 强制关闭所有正在运行的 WSL 实例（解决 90% 的异常问题）
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;WSL 迁移到 D 盘的核心命令串（重点）&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
# 确保所有 WSL 实例已完全关闭，否则 vhdx 文件会被占用

wsl --export Ubuntu D:\WSL\ubuntu.tar
# 将 Ubuntu 发行版导出为一个 tar 包（不包含运行状态）

wsl --unregister Ubuntu
# 从 WSL 中注销 Ubuntu（不会影响刚刚导出的 tar 包）

wsl --import Ubuntu D:\WSL\Ubuntu D:\WSL\ubuntu.tar --version 2
# 将 Ubuntu 重新导入到 D 盘指定目录，并指定使用 WSL2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;📌 说明：&lt;/p&gt;
&lt;p&gt;D:\WSL\Ubuntu 下会生成 ext4.vhdx&lt;/p&gt;
&lt;p&gt;以后 Ubuntu 的所有 Linux 文件都物理存放在 D 盘&lt;/p&gt;
&lt;h2&gt;WSL 内 Ubuntu：系统与软件管理&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ 以下命令 在 Ubuntu 终端中执行&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update
# 更新软件包索引（不安装软件）

sudo apt upgrade -y
# 升级所有已安装的软件到最新版本

sudo apt install git vim curl wget -y
# 安装常用基础工具：git、vim、curl、wget

sudo apt autoremove
# 删除不再被依赖的软件包，释放空间
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;系统信息与资源查看&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;uname -a
# 查看 Linux 内核信息（WSL 内核版本）

lsb_release -a
# 查看 Ubuntu 发行版版本信息

df -h
# 查看磁盘使用情况（人类可读格式）

free -h
# 查看内存使用情况（单位自动换算）
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;目录与文件操作&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pwd
# 显示当前所在的完整路径

ls
# 列出当前目录下的文件和文件夹

ls -lah
# 以详细形式列出文件（含隐藏文件），并显示文件大小

cd /path/to/dir
# 切换到指定目录

cd ~
# 回到当前用户的 home 目录（/home/用户名）

mkdir project
# 创建名为 project 的文件夹

rm file.txt
# 删除文件 file.txt

rm -rf folder
# 强制递归删除 folder 目录（危险命令）

cp a.txt b.txt
# 复制文件 a.txt 为 b.txt

mv old new
# 重命名或移动文件/目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Windows 与 WSL 文件互通&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cd /mnt/c
# 进入 Windows 的 C 盘

cd /mnt/d/WSL
# 进入 Windows 的 D:\WSL 目录

explorer.exe .
# 用 Windows 资源管理器打开当前 Linux 目录

wsl
# 从 Windows 直接进入默认 WSL 发行版
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;权限与用户相关&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;whoami
# 显示当前登录的用户名

id
# 显示当前用户的 UID、GID 以及所属用户组

sudo command
# 以管理员（root）权限执行 command

sudo -i
# 切换到 root 用户（不建议长期使用）
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;开发常用（Git / Python）&lt;/h2&gt;
&lt;p&gt;Git&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/user/repo.git
# 克隆远程仓库到本地

git status
# 查看当前仓库状态

git pull
# 拉取远程更新

git add .
# 将所有改动加入暂存区

git commit -m &quot;message&quot;
# 提交代码并添加提交说明
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Python 虚拟环境&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 --version
# 查看 Python 版本

sudo apt install python3-venv -y
# 安装 Python 虚拟环境模块

python3 -m venv venv
# 创建名为 venv 的虚拟环境

source venv/bin/activate
# 激活虚拟环境

deactivate
# 退出虚拟环境
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;更新&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update
# 从软件源同步可用软件列表

apt list --upgradable
# 查看当前有哪些软件可以升级

sudo apt upgrade
# 安全升级已安装的软件，不删除也不新增依赖

sudo apt full-upgrade
# 在必要时允许新增或删除依赖完成升级

sudo apt autoremove
# 删除升级后不再需要的旧依赖，释放磁盘空间

sudo apt clean
# 清空已下载的软件包缓存，不影响已安装的软件

df -h
# 查看磁盘剩余空间，避免升级或安装过程中空间不足

sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
# 一条命令完成日常系统更新（不需要逐条确认）
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;进程 / 网络 / 排错&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;top
# 实时查看系统进程和资源占用

htop
# 更友好的进程查看工具（需提前安装）

ps aux | grep python
# 查找包含 python 的进程

ping google.com
# 测试网络连通性

ip a
# 查看网络接口和 IP 地址
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;WSL 救命级命令&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
# WSL 出现任何奇怪问题，第一步永远是它

df -h
# 检查磁盘是否已满（ext4.vhdx 满了会导致大量异常）

sudo apt --fix-broken install
# 修复损坏的软件依赖关系
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Blog搭建</title><link>https://visa-aliso.github.io/posts/blog-setup/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/blog-setup/</guid><description>迈出第一步</description><pubDate>Sat, 20 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;本网站基于 Hexo 构建，采用了 Vivia 主题，是一个风格简洁的个人博客模板。在当前版本中，“返回至顶端”、主页预览博客内容等功能尚不完善或者不符合我的使用习惯，这些都正在改进中改进。总体而言，在美观成都与易用性而言，这个模板表现非常不错。&lt;/p&gt;
&lt;p&gt;作为该方向的初学者，我在此次网站搭建过程中基本依赖 AI 协助完成。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;完成Blog基础功能的搭建&lt;/h1&gt;
&lt;p&gt;#2025年9月4日&lt;/p&gt;
&lt;p&gt;在移除“返回至顶端”按钮后，发现主题切换按钮因继承了原按钮的点击方式，导致无法在页面顶端正常使用。为修复此 bug，需要定位相关文件，并将其中的指定代码完全删除。&lt;/p&gt;
&lt;p&gt;以下为相关文件路径：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\layout\_partial\back-to-top.ejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以下为源文件代码（留着以防以后有用）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;back-to-top-wrapper&quot;&amp;gt;
    &amp;lt;button id=&quot;back-to-top-btn&quot; class=&quot;back-to-top-btn hide&quot; onclick=&quot;topFunction()&quot;&amp;gt;
        &amp;lt;i class=&quot;fa-solid fa-angle-up&quot;&amp;gt;&amp;lt;/i&amp;gt;
    &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
    function topFunction() {
        window.scroll({ top: 0, behavior: &apos;smooth&apos; });
    }
    let btn = document.getElementById(&apos;back-to-top-btn&apos;);
    function scrollFunction() {
        if (document.body.scrollTop &amp;gt; 600 || document.documentElement.scrollTop &amp;gt; 600) {
            btn.classList.remove(&apos;hide&apos;)
        } else {
            btn.classList.add(&apos;hide&apos;)
        }
    }
    window.onscroll = function() {
        scrollFunction();
    }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来将进行下一步的开发，希望一切顺利。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;主页展示方式的修改&lt;/h1&gt;
&lt;p&gt;#2025年9月8日&lt;/p&gt;
&lt;h2&gt;添加abstract&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\source\css\_partial
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在上述文件夹中，创建 abstract.styl 文件，文件中代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.abstract-box
  border-left 4px solid skyblue
  color #000
  padding-left 10px
  line-height 1.6
  margin 16px 0
  display block

html[theme=&quot;dark&quot;] .abstract-box
  color #fff
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;修改展示方式&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\layout\_partial\artical.ejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在上述文件中，将以下部分:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;e-content article-entry&quot; itemprop=&quot;articleBody&quot;&amp;gt;
  &amp;lt;% if (post.excerpt &amp;amp;&amp;amp; index){ %&amp;gt;
    &amp;lt;%- post.excerpt %&amp;gt;
  &amp;lt;% } else if (is_home() &amp;amp;&amp;amp; !post.excerpt &amp;amp;&amp;amp; theme.home.style != &apos;detail&apos;) { %&amp;gt;
    &amp;lt;div class=&quot;truncate-text&quot;&amp;gt;
     &amp;lt;% if(description){ %&amp;gt;
      &amp;lt;%- strip_html(post.description) %&amp;gt;
     &amp;lt;% } else{ %&amp;gt;
      &amp;lt;%- truncate(strip_html(post.content), {length: 500}) %&amp;gt;
     &amp;lt;% } %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;% } else { %&amp;gt;
    &amp;lt;%- post.content %&amp;gt;
  &amp;lt;% } %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;e-content article-entry&quot; itemprop=&quot;articleBody&quot;&amp;gt;
  &amp;lt;% if (is_home() &amp;amp;&amp;amp; post.abstract) { %&amp;gt;
    &amp;lt;div class=&quot;post-abstract abstract-box&quot;&amp;gt;
      &amp;lt;%= post.abstract %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;% } else if (post.excerpt &amp;amp;&amp;amp; index) { %&amp;gt;
    &amp;lt;%- post.excerpt %&amp;gt;
  &amp;lt;% } else if (is_home() &amp;amp;&amp;amp; !post.excerpt &amp;amp;&amp;amp; theme.home.style != &apos;detail&apos;) { %&amp;gt;
    &amp;lt;div class=&quot;truncate-text&quot;&amp;gt;
     &amp;lt;% if(description){ %&amp;gt;
      &amp;lt;%- strip_html(post.description) %&amp;gt;
     &amp;lt;% } else{ %&amp;gt;
      &amp;lt;%- truncate(strip_html(post.content), {length: 500}) %&amp;gt;
     &amp;lt;% } %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;% } else { %&amp;gt;
    &amp;lt;%- post.content %&amp;gt;
  &amp;lt;% } %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在修改之后，若加入了abstract，则会直接显示abstract；否则显示原文内容。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;修改About的显示方式&lt;/h1&gt;
&lt;p&gt;#2025年9月8日&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\layout\_partial\article.ejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在以上文件路径中，找到以下代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&apos;meta-info-bar&apos;&amp;gt;    
  &amp;lt;%- partial(&apos;post/date&apos;, {class_name: &apos;meta-info&apos;, date_format: null}) %&amp;gt;    
  &amp;lt;div class=&quot;need-seperator meta-info&quot;&amp;gt;    
    &amp;lt;%- partial(&apos;post/category&apos;) %&amp;gt;     
  &amp;lt;/div&amp;gt;    
  &amp;lt;div class=&quot;wordcount need-seperator meta-info&quot;&amp;gt;    
    &amp;lt;%- symbolsCount(post) %&amp;gt; &amp;lt;%- __(&apos;words&apos;) %&amp;gt;     
  &amp;lt;/div&amp;gt;    
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;% if (post.layout !== &apos;page&apos;) { %&amp;gt;
  &amp;lt;div class=&apos;meta-info-bar&apos;&amp;gt;    
    &amp;lt;%- partial(&apos;post/date&apos;, {class_name: &apos;meta-info&apos;, date_format: null}) %&amp;gt;    
    &amp;lt;div class=&quot;need-seperator meta-info&quot;&amp;gt;    
      &amp;lt;%- partial(&apos;post/category&apos;) %&amp;gt;     
    &amp;lt;/div&amp;gt;    
    &amp;lt;div class=&quot;wordcount need-seperator meta-info&quot;&amp;gt;    
      &amp;lt;%- symbolsCount(post) %&amp;gt; &amp;lt;%- __(&apos;words&apos;) %&amp;gt;     
    &amp;lt;/div&amp;gt;    
  &amp;lt;/div&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在修改之后，About界面就不再显示时间、分类与字数。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;完善Blog字数的计算&lt;/h1&gt;
&lt;p&gt;#2025年9月8日&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\languages\zh-CN.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上文件中把 words 中的“词”改为“字”，则主页显示的则为字而不是词。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\scripts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在以上文件夹中添加文件wordcount.js，以下为代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hexo.extend.helper.register(&apos;symbolsCount&apos;, function(post) {
  let content = post.content || &apos;&apos;;

  // 1. 去掉多行代码块 &amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
  content = content.replace(/&amp;lt;pre.*?&amp;gt;[\s\S]*?&amp;lt;\/pre&amp;gt;/g, &apos;&apos;);

  // 2. 去掉行内代码 &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt;
  content = content.replace(/&amp;lt;code.*?&amp;gt;[\s\S]*?&amp;lt;\/code&amp;gt;/g, &apos;&apos;);

  // 3. 去掉 HTML 标签
  content = content.replace(/&amp;lt;[^&amp;gt;]*&amp;gt;/g, &apos;&apos;);

  // 4. 去掉空格、换行、制表符
  content = content.replace(/\s+/g, &apos;&apos;);

  return content.length;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改之后，Blog计数统计就不会计算代码。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;PS：因为不支持ejs语法高亮，此处使用的html来添加代码高亮，实际为ejs.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;添加Blog评论功能&lt;/h1&gt;
&lt;p&gt;#2025年9月18日&lt;/p&gt;
&lt;p&gt;本功能基于giscus，简单实用。首先安装giscus app，并按照相关提示完成配置，得到配置代码。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\layout\_partial
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在以上路径中创建文件comment.ejs，加入giscus的相关配置代码。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Blog\node_modules\hexo-theme-vivia\layout\post.ejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后在以上文件中，加入以下代码:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;%- partial(&apos;_partial/comment&apos;) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置完成。&lt;/p&gt;
&lt;h1&gt;添加友链版块&lt;/h1&gt;
&lt;p&gt;#2025年9月20日&lt;/p&gt;
&lt;p&gt;很简单，在主题yaml文件中menu中添加Friends，在以下路径中：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\Blog\source\friends
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建index.md，以下为相关代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Friends
---


&amp;lt;div class=&quot;links-content&quot;&amp;gt;

  &amp;lt;div class=&quot;card&quot;&amp;gt;
    &amp;lt;img class=&quot;ava&quot; src=&quot;/images/example.png&quot; /&amp;gt;
    &amp;lt;div class=&quot;card-header&quot;&amp;gt;
      &amp;lt;a href=&quot;https://friend1.com&quot;&amp;gt;Friend One&amp;lt;/a&amp;gt;
      &amp;lt;div class=&quot;info&quot;&amp;gt;个人Blog&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;



&amp;lt;style&amp;gt;
.links-content {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  padding: 0 1rem;
}

/* 768px为moblile到tablet，1024为tablet到desktop */
@media screen and (min-width: 768px) {
  .links-content {
    grid-template-columns: repeat(2, 1fr);
  }
}

.card {
  display: flex;
  align-items: center;
  padding: 16px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  background-color: #ffffff;
  transition: transform 0.2s ease;
}

.card:hover {
  transform: scale(1.02);
}

.ava {
  width: 128px;
  height: 128px;
  border-radius: 50%;
  object-fit: cover;
  margin-right: 1rem;
  flex-shrink: 0;
}

.card-header {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  flex-grow: 1;
}

.card-header a {
  font-weight: bold;
  font-size: 1.1rem;
  color: #007acc;
  text-decoration: none;
}

.card-header a:hover {
  color: #005fa3;
}

.info {
  color: #666;
  font-size: 0.95rem;
  margin-top: 4px;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;完成。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;总结&lt;/h1&gt;
&lt;p&gt;完成Blog搭建，我对于这方面不够了解，所以整个Blog都是拆东墙补西墙的，缺乏作为一个项目的整体感（尽管尽量在主题上做出统一性）。&lt;/p&gt;
&lt;p&gt;事情告一段落，要开始摆烂了QAQ.&lt;/p&gt;
</content:encoded></item><item><title>配置ssh</title><link>https://visa-aliso.github.io/posts/ssh-setup/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/ssh-setup/</guid><description>配置ssh，以防以后需要</description><pubDate>Tue, 09 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Hexo 使用 SSH 部署到 GitHub 完整指南&lt;/h1&gt;
&lt;h2&gt;生成 SSH Key&lt;/h2&gt;
&lt;p&gt;在命令行（CMD、PowerShell 或 Git Bash）执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa -C &quot;GitHub-Email@example.com&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;测试ssh&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第一次连接时会提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The authenticity of host &apos;github.com (IP)&apos; can&apos;t be established.
Are you sure you want to continue connecting (yes/no)?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入yes并回车，如果显示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hi &amp;lt;用户名&amp;gt;! You&apos;ve successfully authenticated...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明SSH配置成功&lt;/p&gt;
&lt;h3&gt;注意事项&lt;/h3&gt;
&lt;p&gt;默认SSH端口会使用22端口，若22端口被墙，则用443端口。&lt;/p&gt;
&lt;p&gt;22端口格式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git@github.com:User/repo.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;443端口格式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh://git@ssh.github.com:443/User/repo.git
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>无限进步</title><link>https://visa-aliso.github.io/posts/infinite-progress/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/infinite-progress/</guid><pubDate>Tue, 02 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;/images/avatar.jpg&quot; alt=&quot;Aliso&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;技术宅拯救世界&lt;/h1&gt;
</content:encoded></item><item><title>Examples</title><link>https://visa-aliso.github.io/posts/examples/</link><guid isPermaLink="true">https://visa-aliso.github.io/posts/examples/</guid><description>Fuwari 所有功能示例合集：Markdown、扩展语法、代码块、视频等。</description><pubDate>Mon, 01 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本篇合并了 Fuwari 模板的所有示例文章，涵盖 Markdown 基础语法、扩展功能、Expressive Code 代码块、嵌入视频以及使用指南。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h1&gt;Markdown 基础语法&lt;/h1&gt;
&lt;h2&gt;标题与段落&lt;/h2&gt;
&lt;p&gt;Paragraphs are separated by a blank line.&lt;/p&gt;
&lt;p&gt;2nd paragraph. &lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, and &lt;code&gt;monospace&lt;/code&gt;. Itemized lists
look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this one&lt;/li&gt;
&lt;li&gt;that one&lt;/li&gt;
&lt;li&gt;the other one&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Block quotes are
written like so.&lt;/p&gt;
&lt;p&gt;They can span multiple paragraphs,
if you like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., &quot;it&apos;s all
in chapters 12--14&quot;). Three dots ... will be converted to an ellipsis.
Unicode is supported. ☺&lt;/p&gt;
&lt;h3&gt;有序列表&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;first item&lt;/li&gt;
&lt;li&gt;second item&lt;/li&gt;
&lt;li&gt;third item&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;代码块&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import time
# Quick, count to ten!
for i in range(10):
    # (but not *too* quick)
    time.sleep(0.5)
    print(i)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;表格&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;size&lt;/th&gt;
&lt;th&gt;material&lt;/th&gt;
&lt;th&gt;color&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;leather&lt;/td&gt;
&lt;td&gt;brown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;hemp&lt;/td&gt;
&lt;td&gt;canvas natural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;glass&lt;/td&gt;
&lt;td&gt;transparent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;数学公式&lt;/h3&gt;
&lt;p&gt;Inline math equations go in like so: $\omega = d\phi / dt$. Display
math should get its own line and be put in in double-dollarsigns:&lt;/p&gt;
&lt;p&gt;$$I = \int \rho R^{2} dV$$&lt;/p&gt;
&lt;p&gt;$$
\begin{equation*}
\pi = 3.1415926535 ; 8979323846 ; 2643383279 ; 5028841971 ; 6939937510 ; 5820974944
\end{equation*}
$$&lt;/p&gt;
&lt;h3&gt;脚注&lt;/h3&gt;
&lt;p&gt;Here&apos;s a footnote [^1].&lt;/p&gt;
&lt;p&gt;[^1]: Footnote text goes here.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Markdown 扩展功能&lt;/h1&gt;
&lt;h2&gt;GitHub 仓库卡片&lt;/h2&gt;
&lt;p&gt;::github{repo=&quot;Fabrizz/MMM-OnSpotify&quot;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;saicaca/fuwari&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Admonitions 提示框&lt;/h2&gt;
&lt;p&gt;:::note
Highlights information that users should take into account, even when skimming.
:::&lt;/p&gt;
&lt;p&gt;:::tip
Optional information to help a user be more successful.
:::&lt;/p&gt;
&lt;p&gt;:::important
Crucial information necessary for users to succeed.
:::&lt;/p&gt;
&lt;p&gt;:::warning
Critical content demanding immediate user attention due to potential risks.
:::&lt;/p&gt;
&lt;p&gt;:::caution
Negative potential consequences of an action.
:::&lt;/p&gt;
&lt;h3&gt;自定义标题&lt;/h3&gt;
&lt;p&gt;:::note[自定义标题]
This is a note with a custom title.
:::&lt;/p&gt;
&lt;h3&gt;GitHub 语法&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;a href=&quot;https://github.com/orgs/community/discussions/16925&quot;&gt;The GitHub syntax&lt;/a&gt; is also supported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Spoiler 剧透&lt;/h3&gt;
&lt;p&gt;The content :spoiler[is hidden &lt;strong&gt;ayyy&lt;/strong&gt;]!&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Expressive Code 代码块&lt;/h1&gt;
&lt;h2&gt;语法高亮&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;This code is syntax highlighted!&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;编辑器与终端框架&lt;/h2&gt;
&lt;h3&gt;代码编辑器框架&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Title attribute example&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;终端框架&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;This terminal frame has no title&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;覆盖框架类型&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Look ma, no frame!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;文本与行标记&lt;/h2&gt;
&lt;h3&gt;标记整行&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// Line 1 - targeted by line number
// Line 2
// Line 3
// Line 4 - targeted by line number
// Line 5
// Line 6
// Line 7 - targeted by range &quot;7-8&quot;
// Line 8 - targeted by range &quot;7-8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;选择标记类型&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;this line is marked as deleted&apos;)
  // This line and the next one are marked as inserted
  console.log(&apos;this is the second inserted line&apos;)

  return &apos;this line uses the neutral default marker type&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Diff 语法&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;+this line will be marked as inserted
-this line will be marked as deleted
this is a regular line
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  function thisIsJavaScript() {
    // This entire block gets highlighted as JavaScript,
    // and we can still add diff markers to it!
-   console.log(&apos;Old code to be removed&apos;)
+   console.log(&apos;New and shiny code!&apos;)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;可折叠区域&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// All this boilerplate setup code will be collapsed
import { someBoilerplateEngine } from &apos;@example/some-boilerplate&apos;
import { evenMoreBoilerplate } from &apos;@example/even-more-boilerplate&apos;

const engine = someBoilerplateEngine(evenMoreBoilerplate())

// This part of the code will be visible by default
engine.doSomething(1, 2, 3, calcFn)

function calcFn() {
  // You can have multiple collapsed sections
  const a = 1
  const b = 2
  const c = a + b

  // This will remain visible
  console.log(`Calculation result: ${a} + ${b} = ${c}`)
  return c
}

// All this code until the end of the block will be collapsed again
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: &apos;End of example boilerplate code&apos; })
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;行号&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// This code block will show line numbers
console.log(&apos;Greetings from line 2!&apos;)
console.log(&apos;I am on line 3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Greetings from line 5!&apos;)
console.log(&apos;I am on line 6&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;自动换行&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;嵌入视频&lt;/h1&gt;
&lt;p&gt;Just copy the embed code from YouTube or other platforms, and paste it in the markdown file.&lt;/p&gt;
&lt;h2&gt;YouTube&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bilibili&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;//player.bilibili.com/player.html?bvid=BV1fK4y1s7Qf&amp;amp;p=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Fuwari 使用指南&lt;/h1&gt;
&lt;h2&gt;文章 Front-matter&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: My First Blog Post
published: 2023-09-09
description: This is the first post of my new Astro blog.
image: ./cover.jpg
tags: [Foo, Bar]
category: Front-end
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The title of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The date the post was published.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short description of the post. Displayed on index page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The cover image path of the post.&amp;lt;br/&amp;gt;1. Start with &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;: Use web image&amp;lt;br/&amp;gt;2. Start with &lt;code&gt;/&lt;/code&gt;: For image in &lt;code&gt;public&lt;/code&gt; dir&amp;lt;br/&amp;gt;3. With none of the prefixes: Relative to the markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The tags of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The category of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If this post is still a draft, which won&apos;t be displayed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;文件放置位置&lt;/h2&gt;
&lt;p&gt;Your post files should be placed in &lt;code&gt;src/content/posts/&lt;/code&gt; directory. You can also create sub-directories to better organize your posts and assets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── post-1.md
└── post-2/
    ├── cover.png
    └── index.md
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;博客使用指南&lt;/h1&gt;
&lt;h2&gt;创建新文章&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;src/content/posts/&lt;/code&gt; 目录下新建 &lt;code&gt;.md&lt;/code&gt; 文件，文件头部使用以下 front-matter：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: 我的第一篇文章
published: 2025-09-20
description: 这是文章的简短描述，会显示在首页列表中。
image: ./cover.jpg   # 可选，文章封面图
tags: [学习, 教程]    # 可选，标签
category: 学习经历     # 可选，分类
draft: false         # 是否草稿（草稿不会显示）
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文章标题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;发布日期&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;简短描述，显示在首页&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;封面图路径。1. &lt;code&gt;http://&lt;/code&gt; 开头：网络图片 2. &lt;code&gt;/&lt;/code&gt; 开头：&lt;code&gt;public&lt;/code&gt; 目录 3. 无前缀：相对于 md 文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;标签数组&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;分类名称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是否为草稿&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;如何添加 Projects 项目&lt;/h2&gt;
&lt;p&gt;打开 &lt;code&gt;src/pages/projects.astro&lt;/code&gt;，在顶部的 &lt;code&gt;projects&lt;/code&gt; 数组中添加你的项目即可。&lt;/p&gt;
&lt;h3&gt;添加一个有 GitHub 链接的项目&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;{
    name: &quot;🏠 我的博客&quot;,
    description: &quot;基于 Astro + Fuwari 搭建的个人博客。&quot;,
    date: &quot;2025-09&quot;,
    primaryUrl: &quot;https://github.com/Visa-Aliso/Asipe&quot;,
    links: [
        { icon: &quot;fa6-brands:github&quot;, url: &quot;https://github.com/Visa-Aliso/Asipe&quot; },
    ],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;添加一个有多个链接的项目&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;{
    name: &quot;🤖 刷课机&quot;,
    description: &quot;自动选课脚本。&quot;,
    date: &quot;2025-08&quot;,
    primaryUrl: &quot;https://github.com/Visa-Aliso/AutoElective&quot;,
    links: [
        { icon: &quot;fa6-brands:github&quot;, url: &quot;https://github.com/Visa-Aliso/AutoElective&quot; },
        { icon: &quot;material-symbols:description-outline-rounded&quot;, url: &quot;https://docs.example.com&quot; },
        { icon: &quot;fa6-solid:flask&quot;, url: &quot;https://demo.example.com&quot; },
    ],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;添加一个占位项目&lt;/h3&gt;
&lt;p&gt;还没有内容时用占位卡片填充：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{ name: &quot;📐 Coming Soon&quot;, description: &quot;Work in progress, stay tuned.&quot;, date: &quot;&quot;, links: [], placeholder: true }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;字段说明&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;必填&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;项目名称，建议以 emoji 开头&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;一行描述&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;格式 &lt;code&gt;YYYY-MM&lt;/code&gt;，越新的越靠前；占位项目留空&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;primaryUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;点击项目名称跳转的链接&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;links&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;底部图标按钮数组；占位项目为空 &lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;placeholder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;设为 &lt;code&gt;true&lt;/code&gt; 表示占位卡片（虚线边框 + 半透明）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;排序与折叠规则&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;项目按 &lt;code&gt;date&lt;/code&gt; 从新到旧自动排序，占位项目排最后&lt;/li&gt;
&lt;li&gt;每个分区超过 4 个项目时自动折叠，点击「展开更多」展开&lt;/li&gt;
&lt;li&gt;分区只有 &lt;code&gt;Projects&lt;/code&gt; 和 &lt;code&gt;Learning&lt;/code&gt; 两个，不要随意增减&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;可用图标&lt;/h3&gt;
&lt;p&gt;图标来自 &lt;a href=&quot;https://icones.js.org&quot;&gt;Iconify&lt;/a&gt;，常用图标集：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;图标集&lt;/th&gt;
&lt;th&gt;前缀&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Material Symbols&lt;/td&gt;
&lt;td&gt;&lt;code&gt;material-symbols:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;material-symbols:description-outline-rounded&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FA6 Brands&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-brands:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-brands:github&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FA6 Solid&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-solid:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-solid:flask&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;前往 &lt;a href=&quot;https://icones.js.org&quot;&gt;icones.js.org&lt;/a&gt; 搜索图标，复制名称填入 &lt;code&gt;icon&lt;/code&gt; 字段即可。&lt;/p&gt;
&lt;h2&gt;添加友链&lt;/h2&gt;
&lt;p&gt;编辑 &lt;code&gt;src/pages/links.astro&lt;/code&gt; 文件顶部的 &lt;code&gt;friends&lt;/code&gt; 数组：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const friends = [
    {
        name: &quot;KiloxGo&quot;,
        description: &quot;Homepage&quot;,
        avatar: &quot;https://github.com/KiloxGo.png&quot;,  // 头像 URL
        url: &quot;https://profile.kilox.top&quot;,           // 站点链接
    },
    // 添加更多友链...
];
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;可用图标&lt;/h2&gt;
&lt;p&gt;本站使用 &lt;a href=&quot;https://icones.js.org&quot;&gt;Iconify&lt;/a&gt; 图标库，支持以下图标集：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;图标集&lt;/th&gt;
&lt;th&gt;前缀&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Material Symbols&lt;/td&gt;
&lt;td&gt;&lt;code&gt;material-symbols:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;material-symbols:home-outline-rounded&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Font Awesome 6 Brands&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-brands:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-brands:github&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Font Awesome 6 Regular&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-regular:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-regular:address-card&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Font Awesome 6 Solid&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-solid:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fa6-solid:star&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;前往 &lt;a href=&quot;https://icones.js.org&quot;&gt;icones.js.org&lt;/a&gt; 搜索图标，复制图标名称即可使用。&lt;/p&gt;
&lt;h3&gt;在 Projects 中使用图标&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;links: [
    { icon: &quot;fa6-brands:github&quot;, url: &quot;https://github.com/...&quot; },
    { icon: &quot;material-symbols:article-outline-rounded&quot;, url: &quot;https://docs.example.com&quot; },
    { icon: &quot;fa6-solid:flask&quot;, url: &quot;https://demo.example.com&quot; },
]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;在 Profile 侧栏使用图标&lt;/h3&gt;
&lt;p&gt;编辑 &lt;code&gt;src/config.ts&lt;/code&gt; 中的 &lt;code&gt;profileConfig.links&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;links: [
    { name: &quot;GitHub&quot;, icon: &quot;fa6-brands:github&quot;, url: &quot;https://github.com/Visa-Aliso&quot; },
    { name: &quot;Bilibili&quot;, icon: &quot;fa6-brands:bilibili&quot;, url: &quot;https://space.bilibili.com/...&quot; },
    { name: &quot;Email&quot;, icon: &quot;material-symbols:mail-outline-rounded&quot;, url: &quot;mailto:xxx@example.com&quot; },
]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;修改主题色&lt;/h2&gt;
&lt;h3&gt;在线调色&lt;/h3&gt;
&lt;p&gt;点击导航栏右侧的调色板图标 🎨，拖动滑块即可实时切换整站色相（0-360）。颜色会保存在浏览器的 &lt;code&gt;localStorage&lt;/code&gt; 中。&lt;/p&gt;
&lt;h3&gt;修改默认色相&lt;/h3&gt;
&lt;p&gt;编辑 &lt;code&gt;src/config.ts&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export const siteConfig: SiteConfig = {
    themeColor: {
        hue: 250,  // 0-360，250 = 青色，0 = 红色，300 = 紫色，345 = 粉色
        fixed: false,  // 设为 true 则隐藏调色器，锁定颜色
    },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;修改站点信息&lt;/h2&gt;
&lt;p&gt;编辑 &lt;code&gt;src/config.ts&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export const siteConfig: SiteConfig = {
    title: &quot;Aliso&apos; Blog&quot;,           // 站点标题
    subtitle: &quot;技术宅拯救世界&quot;,       // 副标题
    lang: &quot;zh_CN&quot;,                  // 语言
    banner: {
        enable: true,               // 是否显示横幅
        src: &quot;/images/seele.jpg&quot;,   // 横幅图片
    },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;评论系统配置&lt;/h2&gt;
&lt;p&gt;评论使用 Giscus（基于 GitHub Discussions）。编辑 &lt;code&gt;src/components/misc/Giscus.astro&lt;/code&gt; 顶部的默认参数，或前往 &lt;a href=&quot;https://giscus.app&quot;&gt;giscus.app&lt;/a&gt; 获取你的配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const {
    repo = &quot;Visa-Aliso/Visa-Aliso.github.io&quot;,
    repoId = &quot;R_kgDOPp3XLg&quot;,
    category = &quot;Announcements&quot;,
    categoryId = &quot;DIC_kwDOPp3XLs4Cvl5a&quot;,
} = Astro.props;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;评论会自动出现在每篇博客文章底部和友链页面，主题跟随 fuwari 的亮色/暗色模式切换。&lt;/p&gt;
</content:encoded></item></channel></rss>