Merge branch 'camera-2018:master' into master

This commit is contained in:
柏喵Sakura
2023-08-21 00:03:49 +08:00
committed by GitHub
198 changed files with 7133 additions and 3797 deletions

View File

@@ -0,0 +1,65 @@
<script setup>
import confetti from 'canvas-confetti'
import { watch } from 'vue'
const props = defineProps(
{
passed: {
type: Boolean,
required: true,
},
},
['passed'],
)
function congrats() {
const defaults = {
colors: [
'#5D8C7B',
'#F2D091',
'#F2A679',
'#D9695F',
'#8C4646',
],
shapes: ['square'],
ticks: 500,
}
confetti({
...defaults,
particleCount: 80,
spread: 100,
origin: { y: 0 },
})
setTimeout(() => {
confetti({
...defaults,
particleCount: 50,
angle: 60,
spread: 80,
origin: { x: 0 },
})
}, 250)
setTimeout(() => {
confetti({
...defaults,
particleCount: 50,
angle: 120,
spread: 80,
origin: { x: 1 },
})
}, 400)
}
watch(
() => props.passed,
(v) => {
if (v)
setTimeout(congrats, 300)
},
{ flush: 'post' },
)
</script>
<template>
<div />
</template>

View File

@@ -0,0 +1,111 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { withBase } from 'vitepress'
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import { useLangs } from 'vitepress/dist/client/theme-default/composables/langs'
import Sweep from './sweep.vue';
const { site, theme } = useData()
const { localeLinks } = useLangs({ removeCurrent: false })
const root = ref('/')
onMounted(() => {
const path = window.location.pathname
.replace(site.value.base, '')
.replace(/(^.*?\/).*$/, '/$1')
if (localeLinks.value.length) {
root.value =
localeLinks.value.find(({ link }) => link.startsWith(path))?.link ||
localeLinks.value[0].link
}
})
</script>
<template>
<div class="NotFound">
<p class="code">{{ theme.notFound?.code ?? '404' }}</p>
<h1 class="title">{{ theme.notFound?.title ?? 'PAGE NOT FOUND' }}</h1>
<div class="divider" />
<div class="action">
<a
class="link"
:href="withBase(root)"
:aria-label="theme.notFound?.linkLabel ?? 'go to home'"
>
{{ theme.notFound?.linkText ?? 'Take me home' }}
</a>
</div>
<blockquote class="quote">
{{
theme.notFound?.quote ??
"虽然你迷路了,但是这是一个扫雷小游戏"
}}
</blockquote>
<Sweep />
</div>
</template>
<style scoped>
.NotFound {
padding: 64px 24px 96px;
text-align: center;
}
@media (min-width: 768px) {
.NotFound {
padding: 96px 32px 168px;
}
}
.code {
line-height: 128px;
font-size: 128px;
font-weight: 500;
}
.title {
padding-top: 12px;
letter-spacing: 2px;
line-height: 20px;
font-size: 35px;
font-weight: 700;
}
.divider {
margin: 24px auto 1px;
width: 64px;
height: 1px;
background-color: var(--vp-c-divider);
}
.quote {
margin: 0 auto;
padding-top: 20px;
max-width: 256px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
}
.action {
padding-top: 20px;
}
.link {
display: inline-block;
border: 1px solid var(--vp-c-brand);
border-radius: 16px;
padding: 3px 16px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-brand);
transition:
border-color 0.25s,
color 0.25s;
}
.link:hover {
border-color: var(--vp-c-brand-dark);
color: var(--vp-c-brand-dark);
}
</style>

View File

@@ -0,0 +1,183 @@
<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue'
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import { APPEARANCE_KEY } from 'vitepress/dist/client/shared'
import VPSwitch from 'vitepress/dist/client/theme-default/components/VPSwitch.vue'
import VPIconSun from 'vitepress/dist/client/theme-default/components/icons/VPIconSun.vue'
import VPIconMoon from 'vitepress/dist/client/theme-default/components/icons/VPIconMoon.vue'
const { site, isDark } = useData()
const checked = ref(false)
const toggle = typeof localStorage !== 'undefined' ? useAppearance() : () => {}
onMounted(() => {
checked.value = document.documentElement.classList.contains('dark')
})
// @ts-expect-error: Transition API
const isAppearanceTransition = document.startViewTransition &&
!window.matchMedia(`(prefers-reduced-motion: reduce)`).matches
function useAppearance() {
const query = window.matchMedia('(prefers-color-scheme: dark)')
const classList = document.documentElement.classList
let userPreference = localStorage.getItem(APPEARANCE_KEY)
let isDark =
(site.value.appearance === 'dark' && userPreference == null) ||
(userPreference === 'auto' || userPreference == null
? query.matches
: userPreference === 'dark')
query.onchange = (e) => {
if (userPreference === 'auto') {
setClass((isDark = e.matches))
}
}
function toggle(event: MouseEvent) {
if (!isAppearanceTransition) {
setClass((isDark = !isDark))
userPreference = isDark
? query.matches ? 'auto' : 'dark'
: query.matches ? 'light' : 'auto'
localStorage.setItem(APPEARANCE_KEY, userPreference)
return
}
const x = event.clientX
const y = event.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)
// @ts-expect-error: Transition API
const transition = document.startViewTransition(() => {
setClass((isDark = !isDark))
userPreference = isDark
? query.matches ? 'auto' : 'dark'
: query.matches ? 'light' : 'auto'
localStorage.setItem(APPEARANCE_KEY, userPreference)
})
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
]
document.documentElement.animate(
{
clipPath: isDark ? clipPath : [...clipPath].reverse(),
},
{
duration: 300,
easing: 'ease-in',
pseudoElement: isDark ? '::view-transition-new(root)' : '::view-transition-old(root)',
},
)
})
}
function setClass(dark: boolean): void {
const css = document.createElement('style')
css.type = 'text/css'
css.appendChild(
document.createTextNode(
`:not(.VPSwitchAppearance):not(.VPSwitchAppearance *) {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}`
)
)
document.head.appendChild(css)
checked.value = dark
classList[dark ? 'add' : 'remove']('dark')
const _ = window.getComputedStyle(css).opacity
document.head.removeChild(css)
}
return toggle
}
watch(checked, (newIsDark) => {
isDark.value = newIsDark
})
</script>
<template>
<label title="toggle dark mode">
<VPSwitch
class="VPSwitchAppearance"
:class="{ 'VPSwitchAppearanceTransition': isAppearanceTransition }"
:aria-checked="checked"
@click="toggle"
>
<VPIconSun class="sun" />
<VPIconMoon class="moon" />
</VPSwitch>
</label>
</template>
<style scoped>
.sun {
opacity: 1;
}
.moon {
opacity: 0;
}
.dark .sun {
opacity: 0;
}
.dark .moon {
opacity: 1;
}
.VPSwitchAppearance.VPSwitchAppearanceTransition {
width: 22px;
}
.dark .VPSwitchAppearance:not(.VPSwitchAppearanceTransition) :deep(.check) {
/*rtl:ignore*/
transform: translateX(18px);
}
</style>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 9999;
}
::view-transition-new(root) {
z-index: 1;
}
.dark::view-transition-old(root) {
z-index: 1;
}
.dark::view-transition-new(root) {
z-index: 9999;
}
</style>

View File

@@ -0,0 +1,73 @@
<script setup>
defineProps(
{
block: {
type: Object,
required: true,
},
},
['block']
)
const numberColors = [
'text-transparent',
'text-blue-500',
'text-green-500',
'text-yellow-500',
'text-orange-500',
'text-red-500',
'text-purple-500',
'text-pink-500',
'text-teal-500',
]
function getBlockClass(block) {
if (block.flagged)
return 'bg-gray-500-10'
if (!block.revealed)
return 'bg-gray-500-10 hover:bg-gray-500-20'
return block.mine
? 'bg-red-500-50'
: numberColors[block.adjacentMines]
}
</script>
<style>
.text-transparent { color: transparent; }
.text-blue-500 { color: #3b82f6; }
.text-green-500 { color: #10b981; }
.text-yellow-500 { color: #f59e0b; }
.text-orange-500 { color: #f97316; }
.text-red-500 { color: #ef4444; }
.text-red { color: rgba(248, 113, 113); }
.text-purple-500 { color: #8b5cf6; }
.text-pink-500 { color: #ec4899; }
.text-teal-500 { color: #14b8a6; }
.bg-gray-500-10 { background-color: rgba(107, 114, 128, 0.1); }
.bg-gray-500-20 { background-color: rgba(107, 114, 128, 0.2); }
.bg-red-500-50 { background-color: rgba(239, 68, 68, 0.5); }
.font-600 { font-weight: 600; }
.button-block { width: 30px; height: 30px; }
</style>
<template>
<button
style="display: flex; align-items: center; justify-content: center; min-width: 2rem; min-height: 2rem; margin: 1px; border: 0.5px solid rgba(166, 166, 166, 0.1);"
:class="getBlockClass(block)"
>
<template v-if="block.flagged">
<div class="text-red button-block">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6h-5.6Z"/></svg>
</div>
</template>
<template v-else-if="block.revealed">
<div v-if="block.mine" class="button-block">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M23 13v-2h-3.07a7.988 7.988 0 0 0-1.62-3.9l2.19-2.17l-1.43-1.43l-2.17 2.19A7.988 7.988 0 0 0 13 4.07V1h-2v3.07c-1.42.18-2.77.74-3.9 1.62L4.93 3.5L3.5 4.93L5.69 7.1A7.988 7.988 0 0 0 4.07 11H1v2h3.07c.18 1.42.74 2.77 1.62 3.9L3.5 19.07l1.43 1.43l2.17-2.19c1.13.88 2.48 1.44 3.9 1.62V23h2v-3.07c1.42-.18 2.77-.74 3.9-1.62l2.17 2.19l1.43-1.43l-2.19-2.17a7.988 7.988 0 0 0 1.62-3.9H23M12 8a4 4 0 0 0-4 4H6a6 6 0 0 1 6-6v2Z"/></svg>
</div>
<div v-else class="font-600">
{{ block.adjacentMines }}
</div>
</template>
</button>
</template>

View File

@@ -0,0 +1,161 @@
<script setup>
import { GamePlay } from '../composables/logic.js'
import { useNow, useStorage } from '@vueuse/core'
import { watchEffect } from 'vue'
import MineBlock from './MineBlock.vue'
import Confetti from './Confetti.vue'
const play = new GamePlay(9, 9, 10)
const now = $(useNow())
const timerMS = $computed(() => Math.round(((play.state.value.endMS || +now) - play.state.value.startMS) / 1000))
useStorage('vuesweeper-state', play.state)
const state = $computed(() => play.board)
const mineRest = $computed(() => {
if (!play.state.value.mineGenerated)
return play.mines
return play.blocks.reduce((a, b) => a + (b.mine ? 1 : 0) - (b.flagged ? 1 : 0), 0)
})
function newGame(difficulty) {
switch (difficulty) {
case 'very easy':
play.reset(3, 3, 1)
break
case 'easy':
play.reset(9, 9, 10)
break
case 'medium':
play.reset(16, 16, 40)
break
case 'hard':
play.reset(16, 30, 99)
break
}
}
watchEffect(() => {
play.checkGameState()
})
</script>
<template>
<div>
<div class="flex gap1 justify-center p4">
<button class="btn" @click="play.reset()">
New Game
</button>
<button class="btn" @click="newGame('very easy')">
Very Easy
</button>
<button class="btn" @click="newGame('easy')">
Easy
</button>
<button class="btn" @click="newGame('medium')">
Medium
</button>
<button class="btn" @click="newGame('hard')">
Hard
</button>
</div>
<div class="flex gap-10 justify-center">
<div class="text-2xl flex gap-1 items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 32 32"><path fill="currentColor" d="M15 11h2v9h-2zm-2-9h6v2h-6z"/><path fill="currentColor" d="m28 9l-1.42-1.41l-2.25 2.25a10.94 10.94 0 1 0 1.18 1.65ZM16 26a9 9 0 1 1 9-9a9 9 0 0 1-9 9Z"/></svg>
{{ timerMS }}
</div>
<div class="text-2xl flex gap-1 items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M23 13v-2h-3.07a7.988 7.988 0 0 0-1.62-3.9l2.19-2.17l-1.43-1.43l-2.17 2.19A7.988 7.988 0 0 0 13 4.07V1h-2v3.07c-1.42.18-2.77.74-3.9 1.62L4.93 3.5L3.5 4.93L5.69 7.1A7.988 7.988 0 0 0 4.07 11H1v2h3.07c.18 1.42.74 2.77 1.62 3.9L3.5 19.07l1.43 1.43l2.17-2.19c1.13.88 2.48 1.44 3.9 1.62V23h2v-3.07c1.42-.18 2.77-.74 3.9-1.62l2.17 2.19l1.43-1.43l-2.19-2.17a7.988 7.988 0 0 0 1.62-3.9H23M12 8a4 4 0 0 0-4 4H6a6 6 0 0 1 6-6v2Z"/></svg>
{{ mineRest }}
</div>
</div>
<div class="p5 w-full overflow-auto">
<div
v-for="row, y in state"
:key="y"
class="flex items-center justify-center w-max ma"
>
<MineBlock
v-for="block, x in row" :key="x"
:block="block"
@click="play.onClick(block)"
@dblclick="play.autoExpand(block)"
@contextmenu.prevent="play.onRightClick(block)"
/>
</div>
</div>
<!-- <div flex="~ gap-1" justify-center>
<button btn @click="toggleDev()">
{{ isDev ? 'DEV' : 'NORMAL' }}
</button>
</div> -->
<Confetti :passed="play.state.value.status === 'won'" />
</div>
</template>
<style>
.gap1 {
gap: 0.25rem;
}
.gap-1 {
gap: 0.25rem;
}
.gap-10 {
gap: 2.5rem;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.items-center {
align-items: center;
}
.text-2xl {
font-size: 1.5rem;
}
.btn {
background-color: var(--vp-button-brand-bg);
border: 1px solid var(--vp-c-brand-light);
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
cursor: pointer;
color: #fff;
transition: all 0.1s ease-in-out;
}
.btn:hover {
background-color: var(--vp-c-brand-light);
border-color: var(--vp-c-brand-light);
transition: all 0.1s ease-in-out;
}
.btn:dark {
background-color: var(--vp-c-brand-dark);
border-color: var(--vp-c-brand-light);
transition: all 0.1s ease-in-out;
}
.p4 {
padding: 1rem;
}
.p5 {
padding: 1.25rem;
}
.w-full {
width: 100%;
}
.w-max {
width: max-content;
}
.overflow-auto {
overflow: auto;
}
.ma {
margin: auto;
}
</style>

View File

@@ -0,0 +1,210 @@
import { ref } from 'vue';
const directions = [
[1, 1],
[1, 0],
[1, -1],
[0, -1],
[-1, -1],
[-1, 0],
[-1, 1],
[0, 1],
];
export class GamePlay {
state = ref();
constructor(width, height, mines) {
this.width = width;
this.height = height;
this.mines = mines;
this.reset();
}
get board() {
return this.state.value.board;
}
get blocks() {
return this.state.value.board.flat();
}
reset(width = this.width, height = this.height, mines = this.mines) {
this.width = width;
this.height = height;
this.mines = mines;
this.state.value = {
startMS: +Date.now(),
endMS: undefined, // 确保结束时间戳被重置
mineGenerated: false,
status: 'play',
board: Array.from({ length: this.height }, (_, y) =>
Array.from({ length: this.width }, (_, x) => ({
x,
y,
mine: false, // 初始化 mine 属性
flagged: false, // 初始化 flagged 属性
adjacentMines: 0,
revealed: false,
}),
),
),
};
}
randomRange(min, max) {
return Math.random() * (max - min) + min;
}
randomInt(min, max) {
return Math.round(this.randomRange(min, max));
}
generateMines(state, initial) {
const placeRandom = () => {
const x = this.randomInt(0, this.width - 1);
const y = this.randomInt(0, this.height - 1);
const block = state[y][x];
if (Math.abs(initial.x - block.x) <= 1 && Math.abs(initial.y - block.y) <= 1)
return false;
if (block.mine)
return false;
block.mine = true;
return true;
};
Array.from({ length: this.mines }, () => null)
.forEach(() => {
let placed = false;
let attempts = 0;
const maxAttempts = 1000;
while (!placed) {
if (attempts++ > maxAttempts) {
this.reset();
break;
}
placed = placeRandom();
}
});
this.updateNumbers();
}
updateNumbers() {
this.board.forEach((raw) => {
raw.forEach((block) => {
if (block.mine)
return;
this.getSiblings(block)
.forEach((b) => {
if (b.mine)
block.adjacentMines += 1;
});
});
});
}
expendZero(block) {
if (block.adjacentMines)
return;
this.getSiblings(block)
.forEach((s) => {
if (!s.revealed) {
s.revealed = true;
this.expendZero(s);
}
});
}
onRightClick(block) {
if (this.state.value.status !== 'play')
return;
if (block.revealed)
return;
block.flagged = !block.flagged;
}
onClick(block) {
if (this.state.value.status !== 'play')
return;
if (!this.state.value.mineGenerated) {
this.generateMines(this.board, block);
this.state.value.mineGenerated = true;
}
block.revealed = true;
if (block.mine) {
this.onGameOver('lost');
return;
}
this.expendZero(block);
}
getSiblings(block) {
return directions.map(([dx, dy]) => {
const x2 = block.x + dx;
const y2 = block.y + dy;
if (x2 < 0 || x2 >= this.width || y2 < 0 || y2 >= this.height)
return undefined;
return this.board[y2][x2];
})
.filter(Boolean);
}
showAllMines() {
this.board.flat().forEach((i) => {
if (i.mine)
i.revealed = true;
});
}
checkGameState() {
if (!this.state.value.mineGenerated)
return;
const blocks = this.board.flat();
if (blocks.every(block => block.revealed || block.flagged || block.mine)) {
if (blocks.some(block => block.flagged && !block.mine))
this.onGameOver('lost');
else
this.onGameOver('won');
}
}
autoExpand(block) {
const siblings = this.getSiblings(block);
const flags = siblings.reduce((a, b) => a + (b.flagged ? 1 : 0), 0);
const notRevealed = siblings.reduce((a, b) => a + (!b.revealed && !b.flagged ? 1 : 0), 0);
if (flags === block.adjacentMines) {
siblings.forEach((i) => {
if (i.revealed || i.flagged)
return;
i.revealed = true;
this.expendZero(i);
if (i.mine)
this.onGameOver('lost');
});
}
const missingFlags = block.adjacentMines - flags;
if (notRevealed === missingFlags) {
siblings.forEach((i) => {
if (!i.revealed && !i.flagged)
i.flagged = true;
});
}
}
onGameOver(status) {
this.state.value.status = status;
this.state.value.endMS = +Date.now();
if (status === 'lost') {
this.showAllMines();
setTimeout(() => {
alert('lost');
}, 10);
}
}
}

View File

@@ -1,14 +1,12 @@
// import { defineConfig } from 'vitepress'
import { withMermaid } from "vitepress-plugin-mermaid";
import { withMermaid } from "vitepress-plugin-mermaid-xyxsw";
import mathjax3 from 'markdown-it-mathjax3';
import { main_sidebar, chapter2, chapter3, chapter4, chapter5, chapter6, chapter7, chapter8, chapter9 } from './sidebar.js';
import { nav } from './nav.js';
import PanguPlugin from 'markdown-it-pangu'
import { createWriteStream } from 'node:fs'
import { resolve } from 'node:path'
import { SitemapStream } from 'sitemap'
const links = []
import { fileURLToPath, URL } from 'node:url'
import VueMacros from 'unplugin-vue-macros/vite'
import Vue from '@vitejs/plugin-vue'
const customElements = [
'mjx-container',
@@ -104,8 +102,9 @@ const customElements = [
export default withMermaid({
lang: 'zh-CN',
title: "HDU-CS-WIKI",
description: "HDU计算机科学讲义",
description: "HDU 计算机科学讲义",
lastUpdated: true,
cleanUrls: true,
head: [['script', { async: "async", src: 'https://umami.hdu-cs.wiki/script.js', "data-website-id": "3f11687a-faae-463a-b863-6127a8c28301", "data-domains": "wiki.xyxsw.site,hdu-cs.wiki" }]],
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
@@ -156,24 +155,31 @@ export default withMermaid({
isCustomElement: (tag) => customElements.includes(tag),
},
},
},
transformHtml: (_, id, { pageData }) => {
if (!/[\\/]404\.html$/.test(id))
links.push({
// you might need to change this if not using clean urls mode
url: pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2'),
lastmod: pageData.lastUpdated
})
},
buildEnd: async ({ outDir }) => {
const sitemap = new SitemapStream({
hostname: 'https://hdu-cs.wiki/'
})
const writeStream = createWriteStream(resolve(outDir, 'sitemap.xml'))
sitemap.pipe(writeStream)
links.forEach((link) => sitemap.write(link))
sitemap.end()
await new Promise((r) => writeStream.on('finish', r))
sitemap: {
hostname: 'https://hdu-cs.wiki'
},
vite: {
plugins: [
VueMacros(),
],
resolve: {
alias: [
{
find: /^.*\/VPSwitchAppearance\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomSwitchAppearance.vue', import.meta.url)
)
},
{
find: /^.*\/NotFound\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNotFound.vue', import.meta.url)
)
}
]
}
}
})

View File

@@ -24,6 +24,7 @@ export function main_sidebar() {
{ text: '1.10如何读论文', link: '/1.杭电生存指南/1.10如何读论文' },
{ text: '1.11陷入虚无主义?进来看看吧', link: '/1.杭电生存指南/1.11陷入虚无主义?进来看看吧' },
{ text: '1.12选课原则与抢课技巧', link: '/1.杭电生存指南/1.12选课原则与抢课技巧' },
{ text: '1.13数学学习篇', link: '/1.杭电生存指南/1.13数学学习篇'},
]
},
{
@@ -224,6 +225,14 @@ export function chapter3() {
{ text: '3.6.4.5阶段五:迭代生成', link: '/3.编程思维体系构建/3.6.4.5阶段五:迭代生成' },
{ text: '3.6.4.6结语', link: '/3.编程思维体系构建/3.6.4.6结语' },
]
},
{
text: '3.6.5CS61A食用指南',
collapsed: true,
items: [
{ text: '3.6.5CS61A食用指南', link: '/3.编程思维体系构建/3.6.5CS61A食用指南' },
{ text: '3.6.5.1CS61A Sec1', link: '/3.编程思维体系构建/3.6.5.1CS61A Sec1' },
]
}
]
},
@@ -424,7 +433,8 @@ export function chapter4() {
{ text: '4.9如何做研究', link: '/4.人工智能/4.9如何做研究' },
{ text: '4.10科研论文写作', link: '/4.人工智能/4.10科研论文写作' },
{ text: '4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents', link: '/4.人工智能/4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents' },
{ text: '4.12本章节内容的局限性', link: '/4.人工智能/4.12本章节内容的局限性' },
{ text: '4.12LLM Agent之结构化输出', link: '/4.人工智能/4.12LLMAgent之结构化输出' },
{ text: '4.13本章节内容的局限性', link: '/4.人工智能/4.13本章节内容的局限性' },
{ text: 'SRT社团介绍', link: '/4.人工智能/SRT' },
{
text: 'FunRec',
@@ -583,6 +593,7 @@ export function chapter6() {
},
{ text: '6.3密码学', link: '/6.计算机安全/6.3密码学' },
{ text: '6.4安全杂项', link: '/6.计算机安全/6.4安全杂项' },
{ text: '6.5学习资料推荐', link: '/6.计算机安全/6.5学习资料推荐' },
]
},
]
@@ -660,4 +671,4 @@ export function chapter9() {
]
}
]
}
}

View File

@@ -10,7 +10,6 @@ import './rainbow.css'
let homePageStyle = undefined
export default {
...DefaultTheme,
Layout: () => {
@@ -27,7 +26,7 @@ export default {
watch(
() => ctx.router.route.data.relativePath,
() => updateHomePageStyle(location.pathname === '/' || location.pathname === '/contributors.html'),
() => updateHomePageStyle(location.pathname === '/' || location.pathname === '/contributors'),
{ immediate: true },
)
},

View File

@@ -5,6 +5,9 @@
/**
* Colors
* -------------------------------------------------------------------------- */
@import url('https://fonts.loli.net/css2?family=Noto+Sans+Mono:wght@400&family=Noto+Sans+SC:wght@400;500;700&display=swap');
@font-face {
font-family: 'Noto Color Emoji';
font-style: normal;
@@ -14,28 +17,19 @@
unicode-range: U+200d, U+261d, U+2620, U+2639-263a, U+2665, U+270a-270d, U+2728, U+2763-2764, U+2b50, U+fe0f, U+1f31a-1f31f, U+1f32b, U+1f383, U+1f389, U+1f3fb-1f3ff, U+1f440-1f450, U+1f463-1f465, U+1f479-1f47b, U+1f47d-1f480, U+1f485, U+1f48b-1f48c, U+1f493-1f49f, U+1f4a4-1f4a6, U+1f4a8-1f4ab, U+1f4af, U+1f525, U+1f573, U+1f590, U+1f595-1f596, U+1f5a4, U+1f5e3, U+1f600-1f644, U+1f648-1f64a, U+1f64c, U+1f64f, U+1f90c-1f925, U+1f927-1f92f, U+1f932-1f933, U+1f970-1f976, U+1f978-1f97a, U+1f9a0, U+1f9b4-1f9b7, U+1f9bb, U+1f9be-1f9bf, U+1f9d0, U+1f9e0-1f9e1, U+1fa75-1fa79, U+1fac0-1fac2, U+1fae0-1fae6, U+1fae8, U+1faf0-1faf8;
}
@font-face {
font-family: 'Noto Sans SC';
font-weight: 400;
src: url('./font/NotoSansSC-Regular.otf');
}
@font-face {
font-family: 'Noto Sans SC';
font-weight: 700;
src: url('./font/NotoSansSC-Bold.otf');
}
@font-face {
font-family: 'Noto Sans Mono';
font-weight: 400;
src: url('./font/NotoSansMono-Regular.ttf');
}
.dark .vp-doc a,#loading, .dark .vp-doc a>code, .dark .VPNavBarMenuLink.VPNavBarMenuLink:hover, .dark .VPNavBarMenuLink.VPNavBarMenuLink.active, .dark .link.link:hover, .dark .link.link.active, .dark .edit-link-button.edit-link-button, .dark .pager-link .title {
color: var(--vp-c-brand-lighter);
}
/**
* 这个版本可能有 bugbuild 后字体变不了还为 consolas 可能是我自己配的有问题 可能是这个版本拉了 总之就加个临时的
* -------------------------------------------------------------------------- */
code {
font-family: 'Noto Sans Mono', sans-serif, monospace, consolas !important;
font-weight: 400 !important;
font-size: 14px !important;
}
:root {
--vp-c-brand: #0dadc4;
--vp-c-brand-light: #1A9CED;
@@ -50,14 +44,6 @@
--vp-font-family-base: 'Noto Sans SC', 'Noto Color Emoji', sans-serif;
--vp-font-family-mono: 'Noto Sans Mono', sans-serif, monospace, consolas;
}
/**
* 这个版本可能有 bugbuild 后字体变不了还为 consolas 可能是我自己配的有问题 可能是这个版本拉了 总之就加个临时的
* -------------------------------------------------------------------------- */
code {
font-family: 'Noto Sans Mono', sans-serif, monospace, consolas !important;
font-weight: 400 !important;
font-size: 14px !important;
}
/**
* Component: Button