mirror of
https://github.com/sendevia/website.git
synced 2026-03-08 08:44:15 +08:00
Compare commits
9 Commits
26.3.5(323
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c5628d1661 | |||
| 8795c219ac | |||
| c856ce009d | |||
| b87a0d2918 | |||
| b4c6347538 | |||
| 3b17ade7f7 | |||
| b81d7fd415 | |||
| 206cf373a3 | |||
| 9677ac1367 |
6
.github/workflows/docker-build.yml
vendored
6
.github/workflows/docker-build.yml
vendored
@@ -29,8 +29,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
with:
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v4
|
||||||
@@ -63,5 +61,5 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
no-cache: true
|
||||||
cache-to: type=gha,mode=max
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import { anchor } from "./theme/utils/mdCustomAnchor";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: "/",
|
base: "/",
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
|
rewrites: {
|
||||||
|
"posts/index.md": "index.md",
|
||||||
|
},
|
||||||
lang: "zh_CN",
|
lang: "zh_CN",
|
||||||
title: "sendevia 的小站",
|
title: "sendevia 的小站",
|
||||||
titleTemplate: ":title",
|
titleTemplate: ":title",
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ import { useGlobalData } from "../composables/useGlobalData";
|
|||||||
const postsStore = usePostStore();
|
const postsStore = usePostStore();
|
||||||
const { theme } = useGlobalData();
|
const { theme } = useGlobalData();
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** 预设分类筛选 */
|
||||||
|
presetCategory?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
presetCategory: "",
|
||||||
|
});
|
||||||
|
|
||||||
/** 设置面板是否打开 */
|
/** 设置面板是否打开 */
|
||||||
const isSettingsOpen = ref(false);
|
const isSettingsOpen = ref(false);
|
||||||
/** 设置面板的 DOM 引用 */
|
/** 设置面板的 DOM 引用 */
|
||||||
@@ -14,7 +23,7 @@ const settingsPanelRef = ref<HTMLElement | null>(null);
|
|||||||
/** 触发按钮的 DOM 引用 */
|
/** 触发按钮的 DOM 引用 */
|
||||||
const settingsTriggerRef = ref<HTMLElement | null>(null);
|
const settingsTriggerRef = ref<HTMLElement | null>(null);
|
||||||
/** 选中的分类(单选,空字符串代表全部) */
|
/** 选中的分类(单选,空字符串代表全部) */
|
||||||
const selectedCategory = ref("");
|
const selectedCategory = ref(props.presetCategory);
|
||||||
/** 选中的标签(多选,空数组代表全部) */
|
/** 选中的标签(多选,空数组代表全部) */
|
||||||
const selectedTags = ref<string[]>([]);
|
const selectedTags = ref<string[]>([]);
|
||||||
/** 排序字段: `date` | `title` */
|
/** 排序字段: `date` | `title` */
|
||||||
@@ -81,7 +90,7 @@ const columnCount = computed(() => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取仅经过筛选(未排序)的文章列表
|
* 获取仅经过筛选(未排序)的文章列表
|
||||||
* 逻辑:筛选分类和标签
|
* 筛选分类和标签
|
||||||
*/
|
*/
|
||||||
const filteredRawList = computed(() => {
|
const filteredRawList = computed(() => {
|
||||||
let posts = [...(postsStore.posts || [])];
|
let posts = [...(postsStore.posts || [])];
|
||||||
@@ -101,9 +110,36 @@ const filteredRawList = computed(() => {
|
|||||||
return posts;
|
return posts;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前分类下的文章标签
|
||||||
|
* 如果当前有选中的分类,则只返回该分类下的文章所出现的标签
|
||||||
|
*/
|
||||||
|
const currentCategoryTags = computed(() => {
|
||||||
|
if (!selectedCategory.value) {
|
||||||
|
return postsStore.allTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagSet = new Set<string>();
|
||||||
|
postsStore.posts.forEach((post) => {
|
||||||
|
if (post.categories.includes(selectedCategory.value)) {
|
||||||
|
post.tags.forEach((tag) => tagSet.add(tag));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Array.from(tagSet);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有预设分类
|
||||||
|
* 如果有预设分类,则分类section应该隐藏
|
||||||
|
*/
|
||||||
|
const hasPresetCategory = computed(() => {
|
||||||
|
return props.presetCategory !== "";
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对筛选后的列表进行排序
|
* 对筛选后的列表进行排序
|
||||||
* 逻辑:根据 sortField 和 sortOrder 排序
|
* 根据 sortField 和 sortOrder 排序
|
||||||
*/
|
*/
|
||||||
const sortedArticlesList = useSorted(filteredRawList, (a, b) => {
|
const sortedArticlesList = useSorted(filteredRawList, (a, b) => {
|
||||||
let comparison = 0;
|
let comparison = 0;
|
||||||
@@ -310,7 +346,7 @@ const clearTags = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div v-if="!hasPresetCategory" class="section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h6>分类 <span v-if="selectedCategory" @click="selectedCategory = ''">clear</span></h6>
|
<h6>分类 <span v-if="selectedCategory" @click="selectedCategory = ''">clear</span></h6>
|
||||||
</div>
|
</div>
|
||||||
@@ -333,7 +369,7 @@ const clearTags = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="chip-container">
|
<div class="chip-container">
|
||||||
<MaterialChip
|
<MaterialChip
|
||||||
v-for="tag in postsStore.allTags"
|
v-for="tag in currentCategoryTags"
|
||||||
:key="tag"
|
:key="tag"
|
||||||
:color="selectedTags.includes(tag) ? 'tonal' : 'outlined'"
|
:color="selectedTags.includes(tag) ? 'tonal' : 'outlined'"
|
||||||
:icon="selectedTags.includes(tag) ? 'check' : ''"
|
:icon="selectedTags.includes(tag) ? 'check' : ''"
|
||||||
|
|||||||
@@ -233,6 +233,10 @@
|
|||||||
transition: opacity var(--md-sys-motion-spring-fast-effect-duration) var(--md-sys-motion-spring-fast-effect);
|
transition: opacity var(--md-sys-motion-spring-fast-effect-duration) var(--md-sys-motion-spring-fast-effect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.scroll {
|
&.scroll {
|
||||||
@@ -246,10 +250,8 @@
|
|||||||
&.hidden {
|
&.hidden {
|
||||||
top: -64px;
|
top: -64px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 840px) {
|
@media screen and (max-width: 840px) {
|
||||||
.AppBar {
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
&:nth-of-type(1) {
|
&:nth-of-type(1) {
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
filter: url(#noise-filter);
|
filter: url(#noise-filter);
|
||||||
mask-image: linear-gradient(to right, black 0%, transparent 60%);
|
mask-image: linear-gradient(to right, black 0%, transparent 100%);
|
||||||
mix-blend-mode: screen;
|
mix-blend-mode: screen;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
@@ -133,12 +133,6 @@
|
|||||||
&:nth-of-type(2) {
|
&:nth-of-type(2) {
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 840px) {
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
mask-image: linear-gradient(to right, black 0%, transparent 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,10 +344,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
&:nth-of-type(1) {
|
|
||||||
transition: 5s var(--md-sys-motion-spring-slow-effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-of-type(2) {
|
&:nth-of-type(2) {
|
||||||
transition: var(--md-sys-motion-spring-slow-effect-duration) var(--md-sys-motion-spring-default-effect)
|
transition: var(--md-sys-motion-spring-slow-effect-duration) var(--md-sys-motion-spring-default-effect)
|
||||||
var(--md-sys-motion-spring-fast-effect-duration);
|
var(--md-sys-motion-spring-fast-effect-duration);
|
||||||
@@ -380,11 +370,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
&:nth-of-type(1) {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-25%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-of-type(2) {
|
&:nth-of-type(2) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(1.005);
|
transform: scale(1.005);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y git \
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 拉取项目代码
|
# 拉取项目代码
|
||||||
RUN git clone https://github.com/sendevia/website .
|
RUN git clone https://github.com/sendevia/website . --depth=1
|
||||||
|
|
||||||
# 安装依赖并构建
|
# 安装依赖并构建
|
||||||
RUN npm i && npm run docs:build
|
RUN npm i && npm run docs:build
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "26.3.5(323)",
|
"version": "26.3.8.332",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"update-version": "bash ./scripts/update-version.sh",
|
"update-version": "bash ./scripts/update-version.sh",
|
||||||
"docs:dev": "vitepress dev",
|
"docs:dev": "vitepress dev",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ tags:
|
|||||||
- osu!
|
- osu!
|
||||||
- 示例文章
|
- 示例文章
|
||||||
- 作品介绍
|
- 作品介绍
|
||||||
date: 2022-07-04T04:00:00Z
|
date: 2022-07-04T04:00:00+08
|
||||||
external_links:
|
external_links:
|
||||||
- type: download
|
- type: download
|
||||||
label: 直连下载
|
label: 直连下载
|
||||||
@@ -29,7 +29,7 @@ external_links:
|
|||||||
|
|
||||||
1. 本皮肤通过游戏补丁的方式,做到了覆盖几乎全部的 osu! 界面元素。
|
1. 本皮肤通过游戏补丁的方式,做到了覆盖几乎全部的 osu! 界面元素。
|
||||||
2. 结合更现代的设计,扩展了《刀剑神域》中出现的界面设计。
|
2. 结合更现代的设计,扩展了《刀剑神域》中出现的界面设计。
|
||||||
:::
|
:::
|
||||||
|
|
||||||
# 优点
|
# 优点
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ external_links:
|
|||||||
- 本皮肤所提供的 dll 文件仅替换了图像资源,未做其他修改。如果不放心,你可以使用 dnSpy 自行替换文件
|
- 本皮肤所提供的 dll 文件仅替换了图像资源,未做其他修改。如果不放心,你可以使用 dnSpy 自行替换文件
|
||||||
|
|
||||||
[^1]: 通过修改 osu! 的资源 dll。
|
[^1]: 通过修改 osu! 的资源 dll。
|
||||||
|
|
||||||
[^2]: 此为估计得出。
|
[^2]: 此为估计得出。
|
||||||
|
|
||||||
# 皮肤预览
|
# 皮肤预览
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ categories:
|
|||||||
- 博客主题
|
- 博客主题
|
||||||
tags:
|
tags:
|
||||||
- readme
|
- readme
|
||||||
date: 2026-02-25T21:44:00Z
|
date: 2026-02-25T21:44:00+08
|
||||||
external_links:
|
external_links:
|
||||||
- type: download
|
- type: download
|
||||||
icon: rocket_launch
|
icon: rocket_launch
|
||||||
|
|||||||
144
posts/components/ButtonGroup.md
Normal file
144
posts/components/ButtonGroup.md
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
title: "Button group"
|
||||||
|
description: "按钮组组件"
|
||||||
|
color: "#42b883"
|
||||||
|
categories:
|
||||||
|
- 组件
|
||||||
|
tags:
|
||||||
|
- Vue 3
|
||||||
|
- 开发文档
|
||||||
|
- UI
|
||||||
|
date: 2026-02-25T21:20:00+08
|
||||||
|
---
|
||||||
|
|
||||||
|
# ButtonGroup 按钮组组件
|
||||||
|
|
||||||
|
`ButtonGroup` 是一个用于聚合多个 `MaterialButton` 的容器组件。它支持灵活的布局切换、统一的属性默认值配置以及全局事件委托监听。
|
||||||
|
|
||||||
|
## 核心特性
|
||||||
|
|
||||||
|
- **布局自适应**:支持水平(Horizontal)和垂直(Vertical)两种排列方式。
|
||||||
|
- **属性继承与覆盖**:可以在组级别设置默认的尺寸、颜色、图标等,也可以在具体的按钮项中进行个性化覆盖。
|
||||||
|
- **智能类型识别**:内置了对 `download` 和 `normal` 类型的样式及图标自动匹配逻辑。
|
||||||
|
- **事件委托**:支持统一监听 `@click` 事件,便捷获取点击的项信息及索引。
|
||||||
|
|
||||||
|
## 组件属性 (Props)
|
||||||
|
|
||||||
|
| 属性名 | 类型 | 默认值 | 可选值 | 说明 |
|
||||||
|
| :---------- | :--------------- | :------------- | :---------------------------------- | :--------------- |
|
||||||
|
| `links` | `ExternalLink[]` | `[]` | - | 按钮配置数组 |
|
||||||
|
| `layout` | `string` | `"horizontal"` | `"horizontal"`, `"vertical"` | 布局方向 |
|
||||||
|
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 默认按钮尺寸 |
|
||||||
|
| `color` | `string` | - | - | 默认按钮颜色样式 |
|
||||||
|
| `icon` | `string` | - | - | 默认按钮图标 |
|
||||||
|
| `target` | `string` | - | - | 默认链接打开方式 |
|
||||||
|
| `ariaLabel` | `string` | - | - | 组的无障碍标签 |
|
||||||
|
|
||||||
|
## 组件事件 (Emits)
|
||||||
|
|
||||||
|
| 事件名 | 回调参数 | 说明 |
|
||||||
|
| :------- | :-------------------------------------------------- | :------------------------- |
|
||||||
|
| `@click` | `(event: Event, item: ExternalLink, index: number)` | 当组内任意按钮被点击时触发 |
|
||||||
|
|
||||||
|
## 按钮配置项 (ExternalLink)
|
||||||
|
|
||||||
|
每一项 `links` 中的对象支持以下配置:
|
||||||
|
|
||||||
|
| 属性名 | 类型 | 说明 |
|
||||||
|
| :---------- | :--------- | :------------------------------------------------------ |
|
||||||
|
| `label` | `string` | 按钮显示的文本内容 |
|
||||||
|
| `id` | `string` | (可选) 自定义标识符,方便在事件处理中识别 |
|
||||||
|
| `link` | `string` | (可选) 点击跳转的链接地址 |
|
||||||
|
| `type` | `string` | (可选) 预设类型:`download` (充满色), `normal` (色调色) |
|
||||||
|
| `icon` | `string` | (可选) 覆盖组设置的图标 |
|
||||||
|
| `color` | `string` | (可选) 覆盖组设置的颜色 |
|
||||||
|
| `size` | `string` | (可选) 覆盖组设置的尺寸 |
|
||||||
|
| `target` | `string` | (可选) 覆盖组设置的打开方式 |
|
||||||
|
| `ariaLabel` | `string` | (可选) 按钮的无障碍标签 |
|
||||||
|
| `onClick` | `Function` | (可选) 单体独立的点击回调函数 |
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 1. 基础用法 (水平排列)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<ButtonGroup
|
||||||
|
:links="[
|
||||||
|
{ label: '查看详情', id: 'detail' },
|
||||||
|
{ label: '下载资源', id: 'download', type: 'download' },
|
||||||
|
]"
|
||||||
|
@click="(e, item) => console.log('点击了:', item.id)"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
<ButtonGroup
|
||||||
|
:links="[
|
||||||
|
{ label: '查看详情', id: 'detail' },
|
||||||
|
{ label: '下载资源', id: 'download', type: 'download' }
|
||||||
|
]"
|
||||||
|
@click="(e, item) => console.log('点击了:', item.id)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
### 2. 垂直排列与尺寸控制
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<ButtonGroup
|
||||||
|
layout="vertical"
|
||||||
|
size="l"
|
||||||
|
:links="[
|
||||||
|
{ label: '选项一', icon: 'settings' },
|
||||||
|
{ label: '选项二', icon: 'person' },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
<ButtonGroup
|
||||||
|
layout="vertical"
|
||||||
|
size="l"
|
||||||
|
:links="[
|
||||||
|
{ label: '选项一', icon: 'settings' },
|
||||||
|
{ label: '选项二', icon: 'person' }
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
### 3. 混合图标与文本
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<ButtonGroup
|
||||||
|
size="m"
|
||||||
|
:links="[
|
||||||
|
{ id: 'prev', icon: 'chevron_left', ariaLabel: '上一页' },
|
||||||
|
{ id: 'index', label: '1 / 5', color: 'tonal' },
|
||||||
|
{ id: 'next', icon: 'chevron_right', ariaLabel: '下一页' },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
<ButtonGroup
|
||||||
|
size="m"
|
||||||
|
:links="[
|
||||||
|
{ id: 'prev', icon: 'chevron_left', ariaLabel: '上一页' },
|
||||||
|
{ id: 'index', label: '1 / 5', color: 'tonal' },
|
||||||
|
{ id: 'next', icon: 'chevron_right', ariaLabel: '下一页' }
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
### 4. 链接跳转
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<ButtonGroup
|
||||||
|
target="_blank"
|
||||||
|
:links="[
|
||||||
|
{ label: 'GitHub', link: 'https://github.com', icon: 'code' },
|
||||||
|
{ label: '首页', link: '/', icon: 'home' },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
<ButtonGroup
|
||||||
|
target="_blank"
|
||||||
|
:links="[
|
||||||
|
{ label: 'GitHub', link: 'https://github.com', icon: 'code' },
|
||||||
|
{ label: '首页', link: '/', icon: 'home' }
|
||||||
|
]"
|
||||||
|
/>
|
||||||
@@ -8,7 +8,7 @@ tags:
|
|||||||
- markdown 语法
|
- markdown 语法
|
||||||
- 示例文章
|
- 示例文章
|
||||||
- 组件示例
|
- 组件示例
|
||||||
date: 2007-08-31T00:00:00Z
|
date: 2007-08-31T00:00:00+08
|
||||||
---
|
---
|
||||||
|
|
||||||
# 语法高亮
|
# 语法高亮
|
||||||
@@ -99,14 +99,14 @@ MaterialButton 组件是一个通用的按钮组件,支持多种样式和功
|
|||||||
|
|
||||||
#### 属性列表
|
#### 属性列表
|
||||||
|
|
||||||
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
||||||
| ---- | ---- | ---- | ---- | ---- |
|
| -------- | -------- | ---------- | ------------------------------------------------------------------------- | -------------------------- |
|
||||||
| `shape` | `string` | `"round"` | `"round"`, `"square"` | 按钮形状 |
|
| `shape` | `string` | `"round"` | `"round"`, `"square"` | 按钮形状 |
|
||||||
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 按钮尺寸 |
|
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 按钮尺寸 |
|
||||||
| `color` | `string` | `"filled"` | `"elevated"`, `"filled"`, `"tonal"`, `"outlined"`, `"standard"`, `"text"` | 按钮颜色样式 |
|
| `color` | `string` | `"filled"` | `"elevated"`, `"filled"`, `"tonal"`, `"outlined"`, `"standard"`, `"text"` | 按钮颜色样式 |
|
||||||
| `icon` | `string` | - | Material Icons 名称 | 按钮图标 |
|
| `icon` | `string` | - | Material Icons 名称 | 按钮图标 |
|
||||||
| `href` | `string` | - | 任意URL | 如果提供,按钮将渲染为链接 |
|
| `href` | `string` | - | 任意URL | 如果提供,按钮将渲染为链接 |
|
||||||
| `target` | `string` | `"_blank"` | `"_blank"`, `"_self"`, `"_parent"`, `"_top"` | 链接打开方式 |
|
| `target` | `string` | `"_blank"` | `"_blank"`, `"_self"`, `"_parent"`, `"_top"` | 链接打开方式 |
|
||||||
|
|
||||||
#### 使用示例
|
#### 使用示例
|
||||||
|
|
||||||
@@ -140,29 +140,25 @@ Card 组件用于展示内容卡片,支持多种变体和样式。
|
|||||||
|
|
||||||
#### 属性列表
|
#### 属性列表
|
||||||
|
|
||||||
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
||||||
| ---- | ---- | ---- | ---- | ---- |
|
| -------------- | ---------- | ---------- | -------------------------------------- | ------------ |
|
||||||
| `variant` | `string` | `"feed"` | `"feed"` | 卡片变体 |
|
| `variant` | `string` | `"feed"` | `"feed"` | 卡片变体 |
|
||||||
| `size` | `string` | `"m"` | `"s"`, `"m"`, `"l"` | 卡片尺寸 |
|
| `size` | `string` | `"m"` | `"s"`, `"m"`, `"l"` | 卡片尺寸 |
|
||||||
| `color` | `string` | `"filled"` | `"elevated"`, `"filled"`, `"outlined"` | 卡片颜色样式 |
|
| `color` | `string` | `"filled"` | `"elevated"`, `"filled"`, `"outlined"` | 卡片颜色样式 |
|
||||||
| `title` | `string` | - | 任意字符串 | 卡片标题 |
|
| `title` | `string` | - | 任意字符串 | 卡片标题 |
|
||||||
| `description` | `string` | - | 任意字符串 | 卡片描述 |
|
| `description` | `string` | - | 任意字符串 | 卡片描述 |
|
||||||
| `date` | `string` | - | 日期字符串 | 发布日期 |
|
| `date` | `string` | - | 日期字符串 | 发布日期 |
|
||||||
| `tags` | `string[]` | - | 字符串数组 | 标签列表 |
|
| `tags` | `string[]` | - | 字符串数组 | 标签列表 |
|
||||||
| `category` | `string[]` | - | 字符串数组 | 分类列表 |
|
| `category` | `string[]` | - | 字符串数组 | 分类列表 |
|
||||||
| `impression` | `string[]` | `[]` | 图片URL数组 | 印象图片 |
|
| `impression` | `string[]` | `[]` | 图片URL数组 | 印象图片 |
|
||||||
| `href` | `string` | - | 任意URL | 卡片链接 |
|
| `href` | `string` | - | 任意URL | 卡片链接 |
|
||||||
| `downloadable` | `boolean` | `false` | `true`, `false` | 是否可下载 |
|
| `downloadable` | `boolean` | `false` | `true`, `false` | 是否可下载 |
|
||||||
|
|
||||||
#### 使用示例
|
#### 使用示例
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- 基础卡片 -->
|
<!-- 基础卡片 -->
|
||||||
<Card
|
<Card title="文章标题" description="这是一段文章描述,简要介绍文章内容。" date="2023-10-01" />
|
||||||
title="文章标题"
|
|
||||||
description="这是一段文章描述,简要介绍文章内容。"
|
|
||||||
date="2023-10-01"
|
|
||||||
/>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
@@ -177,22 +173,12 @@ Card 组件用于展示内容卡片,支持多种变体和样式。
|
|||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- 可下载资源卡片 -->
|
<!-- 可下载资源卡片 -->
|
||||||
<Card
|
<Card title="资源下载" description="包含可下载的文件资源" downloadable tags="['资源', '下载']" category="['教程']" />
|
||||||
title="资源下载"
|
|
||||||
description="包含可下载的文件资源"
|
|
||||||
downloadable
|
|
||||||
tags="['资源', '下载']"
|
|
||||||
category="['教程']"
|
|
||||||
/>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- 不同样式卡片 -->
|
<!-- 不同样式卡片 -->
|
||||||
<Card
|
<Card title="轮廓样式" description="使用轮廓样式的卡片" color="outlined" />
|
||||||
title="轮廓样式"
|
|
||||||
description="使用轮廓样式的卡片"
|
|
||||||
color="outlined"
|
|
||||||
/>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### ButtonGroup 组件 (ButtonGroup.vue)
|
### ButtonGroup 组件 (ButtonGroup.vue)
|
||||||
@@ -201,19 +187,19 @@ ButtonGroup 组件用于将多个按钮组合在一起,支持水平和垂直
|
|||||||
|
|
||||||
#### 属性列表
|
#### 属性列表
|
||||||
|
|
||||||
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
| 属性 | 类型 | 默认值 | 可选值 | 描述 |
|
||||||
| ---- | ---- | ---- | ---- | ---- |
|
| -------- | ---------------- | -------------- | ----------------------------------- | ------------ |
|
||||||
| `links` | `ExternalLink[]` | `[]` | 链接对象数组 | 按钮链接列表 |
|
| `links` | `ExternalLink[]` | `[]` | 链接对象数组 | 按钮链接列表 |
|
||||||
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 按钮尺寸 |
|
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 按钮尺寸 |
|
||||||
| `layout` | `string` | `"horizontal"` | `"horizontal"`, `"vertical"` | 布局方向 |
|
| `layout` | `string` | `"horizontal"` | `"horizontal"`, `"vertical"` | 布局方向 |
|
||||||
|
|
||||||
#### ExternalLink 类型
|
#### ExternalLink 类型
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface ExternalLink {
|
interface ExternalLink {
|
||||||
type: string; // 链接类型:'download' 或 'normal'
|
type: string; // 链接类型:'download' 或 'normal'
|
||||||
label: string; // 按钮标签文本
|
label: string; // 按钮标签文本
|
||||||
link: string; // 链接地址
|
link: string; // 链接地址
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -225,7 +211,7 @@ interface ExternalLink {
|
|||||||
:links="[
|
:links="[
|
||||||
{ type: 'normal', label: '查看文档', link: '/docs' },
|
{ type: 'normal', label: '查看文档', link: '/docs' },
|
||||||
{ type: 'download', label: '下载资源', link: '/downloads/file.zip' },
|
{ type: 'download', label: '下载资源', link: '/downloads/file.zip' },
|
||||||
{ type: 'normal', label: 'GitHub', link: 'https://github.com/example' }
|
{ type: 'normal', label: 'GitHub', link: 'https://github.com/example' },
|
||||||
]"
|
]"
|
||||||
size="m"
|
size="m"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
@@ -236,26 +222,16 @@ interface ExternalLink {
|
|||||||
:links="[
|
:links="[
|
||||||
{ type: 'normal', label: '选项一', link: '/option1' },
|
{ type: 'normal', label: '选项一', link: '/option1' },
|
||||||
{ type: 'normal', label: '选项二', link: '/option2' },
|
{ type: 'normal', label: '选项二', link: '/option2' },
|
||||||
{ type: 'normal', label: '选项三', link: '/option3' }
|
{ type: 'normal', label: '选项三', link: '/option3' },
|
||||||
]"
|
]"
|
||||||
size="s"
|
size="s"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 不同尺寸按钮组 -->
|
<!-- 不同尺寸按钮组 -->
|
||||||
<ButtonGroup
|
<ButtonGroup :links="[{ type: 'download', label: '小尺寸下载', link: '/download' }]" size="xs" />
|
||||||
:links="[
|
|
||||||
{ type: 'download', label: '小尺寸下载', link: '/download' }
|
|
||||||
]"
|
|
||||||
size="xs"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ButtonGroup
|
<ButtonGroup :links="[{ type: 'normal', label: '大尺寸按钮', link: '/large' }]" size="xl" />
|
||||||
:links="[
|
|
||||||
{ type: 'normal', label: '大尺寸按钮', link: '/large' }
|
|
||||||
]"
|
|
||||||
size="xl"
|
|
||||||
/>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# 更多信息
|
# 更多信息
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ color: "#39c5bb"
|
|||||||
impression: "/assets/images/132307491_p0.webp"
|
impression: "/assets/images/132307491_p0.webp"
|
||||||
categories:
|
categories:
|
||||||
tags:
|
tags:
|
||||||
date: 2007-08-31T00:00:00Z
|
date: 2007-08-31T00:00:00+08
|
||||||
---
|
---
|
||||||
|
|
||||||
这只是一篇示例文章。
|
这只是一篇示例文章。
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Button group"
|
|
||||||
description: "按钮组组件"
|
|
||||||
color: "#42b883"
|
|
||||||
categories:
|
|
||||||
- 开发文档
|
|
||||||
tags:
|
|
||||||
- Vue 3
|
|
||||||
- 组件
|
|
||||||
- UI
|
|
||||||
date: 2026-02-25T21:20:00Z
|
|
||||||
---
|
|
||||||
|
|
||||||
# ButtonGroup 按钮组组件
|
|
||||||
|
|
||||||
`ButtonGroup` 是一个用于聚合多个 `MaterialButton` 的容器组件。它支持灵活的布局切换、统一的属性默认值配置以及全局事件委托监听。
|
|
||||||
|
|
||||||
## 核心特性
|
|
||||||
|
|
||||||
- **布局自适应**:支持水平(Horizontal)和垂直(Vertical)两种排列方式。
|
|
||||||
- **属性继承与覆盖**:可以在组级别设置默认的尺寸、颜色、图标等,也可以在具体的按钮项中进行个性化覆盖。
|
|
||||||
- **智能类型识别**:内置了对 `download` 和 `normal` 类型的样式及图标自动匹配逻辑。
|
|
||||||
- **事件委托**:支持统一监听 `@click` 事件,便捷获取点击的项信息及索引。
|
|
||||||
|
|
||||||
## 组件属性 (Props)
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 可选值 | 说明 |
|
|
||||||
| :--- | :--- | :--- | :--- | :--- |
|
|
||||||
| `links` | `ExternalLink[]` | `[]` | - | 按钮配置数组 |
|
|
||||||
| `layout` | `string` | `"horizontal"` | `"horizontal"`, `"vertical"` | 布局方向 |
|
|
||||||
| `size` | `string` | `"s"` | `"xs"`, `"s"`, `"m"`, `"l"`, `"xl"` | 默认按钮尺寸 |
|
|
||||||
| `color` | `string` | - | - | 默认按钮颜色样式 |
|
|
||||||
| `icon` | `string` | - | - | 默认按钮图标 |
|
|
||||||
| `target` | `string` | - | - | 默认链接打开方式 |
|
|
||||||
| `ariaLabel` | `string` | - | - | 组的无障碍标签 |
|
|
||||||
|
|
||||||
## 组件事件 (Emits)
|
|
||||||
|
|
||||||
| 事件名 | 回调参数 | 说明 |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `@click` | `(event: Event, item: ExternalLink, index: number)` | 当组内任意按钮被点击时触发 |
|
|
||||||
|
|
||||||
## 按钮配置项 (ExternalLink)
|
|
||||||
|
|
||||||
每一项 `links` 中的对象支持以下配置:
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 说明 |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `label` | `string` | 按钮显示的文本内容 |
|
|
||||||
| `id` | `string` | (可选) 自定义标识符,方便在事件处理中识别 |
|
|
||||||
| `link` | `string` | (可选) 点击跳转的链接地址 |
|
|
||||||
| `type` | `string` | (可选) 预设类型:`download` (充满色), `normal` (色调色) |
|
|
||||||
| `icon` | `string` | (可选) 覆盖组设置的图标 |
|
|
||||||
| `color` | `string` | (可选) 覆盖组设置的颜色 |
|
|
||||||
| `size` | `string` | (可选) 覆盖组设置的尺寸 |
|
|
||||||
| `target` | `string` | (可选) 覆盖组设置的打开方式 |
|
|
||||||
| `ariaLabel` | `string` | (可选) 按钮的无障碍标签 |
|
|
||||||
| `onClick` | `Function` | (可选) 单体独立的点击回调函数 |
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 1. 基础用法 (水平排列)
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<ButtonGroup
|
|
||||||
:links="[
|
|
||||||
{ label: '查看详情', id: 'detail' },
|
|
||||||
{ label: '下载资源', id: 'download', type: 'download' }
|
|
||||||
]"
|
|
||||||
@click="(e, item) => console.log('点击了:', item.id)"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
<ButtonGroup
|
|
||||||
:links="[
|
|
||||||
{ label: '查看详情', id: 'detail' },
|
|
||||||
{ label: '下载资源', id: 'download', type: 'download' }
|
|
||||||
]"
|
|
||||||
@click="(e, item) => console.log('点击了:', item.id)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### 2. 垂直排列与尺寸控制
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<ButtonGroup
|
|
||||||
layout="vertical"
|
|
||||||
size="l"
|
|
||||||
:links="[
|
|
||||||
{ label: '选项一', icon: 'settings' },
|
|
||||||
{ label: '选项二', icon: 'person' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
<ButtonGroup
|
|
||||||
layout="vertical"
|
|
||||||
size="l"
|
|
||||||
:links="[
|
|
||||||
{ label: '选项一', icon: 'settings' },
|
|
||||||
{ label: '选项二', icon: 'person' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### 3. 混合图标与文本
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<ButtonGroup
|
|
||||||
size="m"
|
|
||||||
:links="[
|
|
||||||
{ id: 'prev', icon: 'chevron_left', ariaLabel: '上一页' },
|
|
||||||
{ id: 'index', label: '1 / 5', color: 'tonal' },
|
|
||||||
{ id: 'next', icon: 'chevron_right', ariaLabel: '下一页' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
<ButtonGroup
|
|
||||||
size="m"
|
|
||||||
:links="[
|
|
||||||
{ id: 'prev', icon: 'chevron_left', ariaLabel: '上一页' },
|
|
||||||
{ id: 'index', label: '1 / 5', color: 'tonal' },
|
|
||||||
{ id: 'next', icon: 'chevron_right', ariaLabel: '下一页' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### 4. 链接跳转
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<ButtonGroup
|
|
||||||
target="_blank"
|
|
||||||
:links="[
|
|
||||||
{ label: 'GitHub', link: 'https://github.com', icon: 'code' },
|
|
||||||
{ label: '首页', link: '/', icon: 'home' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
<ButtonGroup
|
|
||||||
target="_blank"
|
|
||||||
:links="[
|
|
||||||
{ label: 'GitHub', link: 'https://github.com', icon: 'code' },
|
|
||||||
{ label: '首页', link: '/', icon: 'home' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
@@ -7,7 +7,7 @@ categories:
|
|||||||
- 随笔
|
- 随笔
|
||||||
tags:
|
tags:
|
||||||
- jekyll
|
- jekyll
|
||||||
date: 2024-07-11T04:00:00Z
|
date: 2024-07-11T04:00:00+08
|
||||||
---
|
---
|
||||||
|
|
||||||
::: info
|
::: info
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ YEAR=$(date +%y)
|
|||||||
MONTH=$(date +%-m)
|
MONTH=$(date +%-m)
|
||||||
DAY=$(date +%-d)
|
DAY=$(date +%-d)
|
||||||
|
|
||||||
NEW_VERSION="${YEAR}.${MONTH}.${DAY}(${NEXT_COMMIT_COUNT})"
|
NEW_VERSION="${YEAR}.${MONTH}.${DAY}.${NEXT_COMMIT_COUNT}"
|
||||||
|
|
||||||
echo "📝 更新版本号..."
|
echo "📝 更新版本号..."
|
||||||
# 使用 sed 更新 package.json 中的版本号
|
# 使用 sed 更新 package.json 中的版本号
|
||||||
|
|||||||
Reference in New Issue
Block a user