feat(about): add version info and contact section to about page

This commit is contained in:
Yuhang Wu
2026-10-20 10:22:23 +08:00
parent bba146fd1a
commit 8eac325b75
+121 -15
View File
@@ -3,6 +3,25 @@
<h2 class="mb-1 text-lg font-semibold">{{ t("about.title") }}</h2>
<p class="mb-6 text-xs opacity-60">{{ t("about.subtitle") }}</p>
<!-- 版本信息 / 检查更新:最常用的信息放在最前面 -->
<section class="mb-6">
<div class="mb-3 text-sm font-medium">{{ t("about.versionTitle") }}</div>
<div class="flex flex-wrap items-center gap-3">
<span class="text-xs opacity-60">{{ t("about.currentVersion") }}</span>
<a-tag color="purple" class="!me-0">v{{ version }}</a-tag>
<a-badge :dot="updateStore.hasUpdate">
<a-button size="small" :loading="updateStore.checking" @click="onCheckUpdate">
{{ t("about.checkUpdate") }}
</a-button>
</a-badge>
<span v-if="updateStore.hasUpdate" class="text-xs text-[#6366f1]">
{{ t("about.newVersion", { version: updateStore.info?.version }) }}
</span>
</div>
</section>
<a-divider class="!my-5" />
<!-- 项目介绍 -->
<section class="mb-6">
<div class="mb-2 text-sm font-medium">{{ t("about.introTitle") }}</div>
@@ -42,30 +61,57 @@
<a-divider class="!my-5" />
<!-- 版本信息 / 检查更新 -->
<!-- 联系方式:邮箱可唤起邮件客户端并支持一键复制,微信以二维码图片展示(可点击放大) -->
<section>
<div class="mb-3 text-sm font-medium">{{ t("about.versionTitle") }}</div>
<div class="flex flex-wrap items-center gap-3">
<span class="text-xs opacity-60">{{ t("about.currentVersion") }}</span>
<a-tag color="purple" class="!me-0">v{{ version }}</a-tag>
<a-badge :dot="updateStore.hasUpdate">
<a-button size="small" :loading="updateStore.checking" @click="onCheckUpdate">
{{ t("about.checkUpdate") }}
<div class="mb-3 text-sm font-medium">{{ t("about.contactTitle") }}</div>
<a-card class="glass-card" size="small" :body-style="{ padding: '14px 16px' }">
<div class="flex items-center gap-3">
<MailOutlined class="text-2xl" />
<div class="min-w-0 flex-1">
<div class="text-xs opacity-60">{{ t("about.email") }}</div>
<a
class="contact-value"
:href="`mailto:${CONTACT_EMAIL}`"
@click.prevent="onOpenEmail"
>
{{ CONTACT_EMAIL }}
</a>
</div>
<a-button size="small" :icon="h(CopyOutlined)" @click="onCopy(CONTACT_EMAIL)">
{{ t("common.copy") }}
</a-button>
</a-badge>
<span v-if="updateStore.hasUpdate" class="text-xs text-[#6366f1]">
{{ t("about.newVersion", { version: updateStore.info?.version }) }}
</span>
</div>
</div>
<a-divider class="!my-3" />
<div class="flex items-center gap-3">
<WechatOutlined class="text-2xl" />
<div class="min-w-0 flex-1">
<div class="text-xs opacity-60">{{ t("about.wechat") }}</div>
<div class="truncate text-sm font-medium">{{ t("about.wechatTip") }}</div>
</div>
<!-- 微信二维码:点击可用 a-image 内置的预览放大,方便用手机扫码 -->
<a-image :src="wechatQr" :width="100" class="wechat-qr" />
</div>
</a-card>
<p class="mt-2 text-xs opacity-60">{{ t("about.contactDesc") }}</p>
</section>
</div>
</template>
<script setup lang="ts">
import { h } from "vue"
import { GithubOutlined, LinkOutlined } from "@ant-design/icons-vue"
import { message } from "ant-design-vue"
import {
CopyOutlined,
GithubOutlined,
LinkOutlined,
MailOutlined,
WechatOutlined,
} from "@ant-design/icons-vue"
import { useI18n } from "vue-i18n"
import { getAppVersion, openProjectRepo, PROJECT_GITHUB_URL } from "@/api/updater"
import wechatQr from "@/assets/images/wx.webp"
import { getAppVersion, openExternal, openProjectRepo, PROJECT_GITHUB_URL } from "@/api/updater"
import { useUpdateStore } from "@/stores/update"
const { t } = useI18n()
@@ -75,6 +121,9 @@ const version = ref("")
const stack = ["Tauri 2", "Vue 3", "TypeScript", "Rust", "Vite"]
/** 作者邮箱:展示、复制、唤起邮件客户端共用同一份常量 */
const CONTACT_EMAIL = "wu434425608@163.com"
const flowItems = computed(() => [
{ title: t("about.flow.step1Title"), description: t("about.flow.step1Desc") },
{ title: t("about.flow.step2Title"), description: t("about.flow.step2Desc") },
@@ -93,4 +142,61 @@ function onOpenRepo() {
function onCheckUpdate() {
void updateStore.checkForUpdate(false)
}
/** 复制到剪贴板,失败时提示手动复制 */
async function onCopy(text: string) {
try {
await navigator.clipboard.writeText(text)
message.success(t("common.copySuccess"))
} catch {
message.error(t("common.copyFailed"))
}
}
/** 用系统默认邮件客户端写信;没有可用客户端时退化为复制邮箱 */
async function onOpenEmail() {
try {
await openExternal(`mailto:${CONTACT_EMAIL}`)
} catch {
await onCopy(CONTACT_EMAIL)
}
}
</script>
<style scoped>
/* 邮箱可点击:悬停时高亮,提示可以唤起邮件客户端 */
.contact-value {
display: block;
overflow: hidden;
font-size: 13px;
font-weight: 500;
line-height: 1.5;
text-overflow: ellipsis;
white-space: nowrap;
transition: color 0.2s ease;
}
.contact-value:hover {
color: #6366f1;
text-decoration: underline;
}
/* 微信二维码:白底圆角,深色模式下也保持足够对比度,便于手机扫描 */
.wechat-qr {
flex-shrink: 0;
padding: 4px;
cursor: zoom-in;
background-color: #fff;
border: 1px solid rgba(15, 23, 42, 0.08);
border-radius: 8px;
}
.wechat-qr :deep(img) {
display: block;
border-radius: 4px;
}
.dark .wechat-qr {
border-color: rgba(255, 255, 255, 0.16);
}
</style>