feat(about): add version info and contact section to about page
This commit is contained in:
+121
-15
@@ -3,6 +3,25 @@
|
|||||||
<h2 class="mb-1 text-lg font-semibold">{{ t("about.title") }}</h2>
|
<h2 class="mb-1 text-lg font-semibold">{{ t("about.title") }}</h2>
|
||||||
<p class="mb-6 text-xs opacity-60">{{ t("about.subtitle") }}</p>
|
<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">
|
<section class="mb-6">
|
||||||
<div class="mb-2 text-sm font-medium">{{ t("about.introTitle") }}</div>
|
<div class="mb-2 text-sm font-medium">{{ t("about.introTitle") }}</div>
|
||||||
@@ -42,30 +61,57 @@
|
|||||||
|
|
||||||
<a-divider class="!my-5" />
|
<a-divider class="!my-5" />
|
||||||
|
|
||||||
<!-- 版本信息 / 检查更新 -->
|
<!-- 联系方式:邮箱可唤起邮件客户端并支持一键复制,微信以二维码图片展示(可点击放大) -->
|
||||||
<section>
|
<section>
|
||||||
<div class="mb-3 text-sm font-medium">{{ t("about.versionTitle") }}</div>
|
<div class="mb-3 text-sm font-medium">{{ t("about.contactTitle") }}</div>
|
||||||
<div class="flex flex-wrap items-center gap-3">
|
<a-card class="glass-card" size="small" :body-style="{ padding: '14px 16px' }">
|
||||||
<span class="text-xs opacity-60">{{ t("about.currentVersion") }}</span>
|
<div class="flex items-center gap-3">
|
||||||
<a-tag color="purple" class="!me-0">v{{ version }}</a-tag>
|
<MailOutlined class="text-2xl" />
|
||||||
<a-badge :dot="updateStore.hasUpdate">
|
<div class="min-w-0 flex-1">
|
||||||
<a-button size="small" :loading="updateStore.checking" @click="onCheckUpdate">
|
<div class="text-xs opacity-60">{{ t("about.email") }}</div>
|
||||||
{{ t("about.checkUpdate") }}
|
<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-button>
|
||||||
</a-badge>
|
</div>
|
||||||
<span v-if="updateStore.hasUpdate" class="text-xs text-[#6366f1]">
|
|
||||||
{{ t("about.newVersion", { version: updateStore.info?.version }) }}
|
<a-divider class="!my-3" />
|
||||||
</span>
|
|
||||||
</div>
|
<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>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { h } from "vue"
|
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 { 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"
|
import { useUpdateStore } from "@/stores/update"
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -75,6 +121,9 @@ const version = ref("")
|
|||||||
|
|
||||||
const stack = ["Tauri 2", "Vue 3", "TypeScript", "Rust", "Vite"]
|
const stack = ["Tauri 2", "Vue 3", "TypeScript", "Rust", "Vite"]
|
||||||
|
|
||||||
|
/** 作者邮箱:展示、复制、唤起邮件客户端共用同一份常量 */
|
||||||
|
const CONTACT_EMAIL = "wu434425608@163.com"
|
||||||
|
|
||||||
const flowItems = computed(() => [
|
const flowItems = computed(() => [
|
||||||
{ title: t("about.flow.step1Title"), description: t("about.flow.step1Desc") },
|
{ title: t("about.flow.step1Title"), description: t("about.flow.step1Desc") },
|
||||||
{ title: t("about.flow.step2Title"), description: t("about.flow.step2Desc") },
|
{ title: t("about.flow.step2Title"), description: t("about.flow.step2Desc") },
|
||||||
@@ -93,4 +142,61 @@ function onOpenRepo() {
|
|||||||
function onCheckUpdate() {
|
function onCheckUpdate() {
|
||||||
void updateStore.checkForUpdate(false)
|
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>
|
</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>
|
||||||
|
|||||||
Reference in New Issue
Block a user