✨ Finish solar network product page
This commit is contained in:
parent
1f2c4f33cb
commit
9726d8f805
@ -99,5 +99,21 @@
|
||||
"solarNetworkReadDialog": "Read Error Messages",
|
||||
"solarNetworkReadDialogDescription": "When encountering an error message, do not immediately take a screenshot and complain. Try to understand why the issue occurred. Then, seek help in the development channel or on GitHub instead of making complaint posts.",
|
||||
"solarNetworkToS": "And, if you continue registering, means you accept our Terms & Conditions",
|
||||
"solarNetworkToSCheck": "Check them out"
|
||||
"solarNetworkToSCheck": "Check them out",
|
||||
"solarNetworkFeat": "Features",
|
||||
"solarNetworkFeatDescription": "Explore the core features of Solar Network",
|
||||
"solarNetworkFeatDashboard": "Dashboard",
|
||||
"solarNetworkFeatDashboardDescription": "A single place to information around the site, anytime, anywhere.",
|
||||
"solarNetworkFeatExplore": "Explore",
|
||||
"solarNetworkFeatExploreDescription": "Enjoy what you love, free from ads and algorithmic noise.",
|
||||
"solarNetworkFeatChat": "Chat",
|
||||
"solarNetworkFeatChatDescription": "Bridge distances, stay connected with friends and communities effortlessly.",
|
||||
"solarNetworkFeatNews": "News",
|
||||
"solarNetworkFeatNewsDescription": "Even without traveling afar, stay informed about the world's stories.",
|
||||
"solarNetworkFeatStickers": "Stickers",
|
||||
"solarNetworkFeatStickersDescription": "Express yourself beyond words with playful and vivid stickers.",
|
||||
"solarNetworkFeatCompose": "Compose",
|
||||
"solarNetworkFeatComposeDescription": "Write freely, speak boldly—your voice deserves to be heard.",
|
||||
"solarNetworkJumpIn": "Jump into the community",
|
||||
"solarNetworkNeedHelp": "Need help?"
|
||||
}
|
||||
|
@ -99,5 +99,25 @@
|
||||
"solarNetworkReadDialog": "阅读错误提示",
|
||||
"solarNetworkReadDialogDescription": "遇到报错提示不要第一时间截图抱怨,尝试理解为什么这件事情发生。其次在开发频道或 GitHub 寻求帮助,不要发帖抱怨。",
|
||||
"solarNetworkToS": "还有,如果你继续注册 Solarpass 帐号,这意味着你同意我们的各项条款",
|
||||
"solarNetworkToSCheck": "阅读这些条款"
|
||||
"solarNetworkToSCheck": "阅读这些条款",
|
||||
"solarNetworkFeat": "特色功能",
|
||||
"solarNetworkFeatDescription": "浏览 Solar Network 的一些核心功能",
|
||||
"solarNetworkFeatDashboard": "冲浪板",
|
||||
"solarNetworkFeatDashboardDescription": "一处汇聚万千动向,随时捕捉站内资讯。",
|
||||
"solarNetworkFeatExplore": "探索",
|
||||
"solarNetworkFeatExploreDescription": "不受广告与算法羁绊,纯粹欣赏你热爱的风景。",
|
||||
"solarNetworkFeatChat": "聊天",
|
||||
"solarNetworkFeatChatDescription": "超越时空阻隔,与朋友和社群自在畅谈,情感相连。",
|
||||
"solarNetworkFeatNews": "新闻",
|
||||
"solarNetworkFeatNewsDescription": "纵然足不出户,依然洞悉世间冷暖,知晓天下风云。",
|
||||
"solarNetworkFeatStickers": "贴图",
|
||||
"solarNetworkFeatStickersDescription": "一枚贴图,胜过千言万语,趣味横生,情感尽现。",
|
||||
"solarNetworkFeatCompose": "撰写",
|
||||
"solarNetworkFeatComposeDescription": "在无拘无束的天地间,自由书写,勇敢表达,世界在倾听。",
|
||||
"solarNetworkHighlightPosts": "Solar Favorite",
|
||||
"solarNetworkHighlightPostsDescription": "Solar Network 社区用户中精选出来的精华帖",
|
||||
"solarNetworkJumpIn": "现在加入",
|
||||
"solarNetworkNeedHelp": "需要寻求帮助?",
|
||||
"askHelpContactUs": "联系我们",
|
||||
"askHelpReadTheDocs": "阅读文档"
|
||||
}
|
||||
|
@ -69,10 +69,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
alias: ["/posts/:area/:id"],
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
@ -80,17 +76,9 @@ const attachments = ref<any[]>([])
|
||||
const firstImage = ref<string | null>()
|
||||
const firstVideo = ref<string | null>()
|
||||
|
||||
const slug = computed(() => {
|
||||
if (route.params.area) {
|
||||
return `${route.params.area}:${route.params.id}`
|
||||
} else {
|
||||
return route.params.id
|
||||
}
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { data: post } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/co/posts/${slug.value}`)
|
||||
const { data: post } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/co/posts/${route.params.id}`)
|
||||
|
||||
if (!post.value) {
|
||||
const { data: publisher } = await $fetch<any>(`${config.public.solarNetworkApi}/cgi/co/publishers/${route.params.id}`)
|
||||
@ -154,7 +142,7 @@ useSeoMeta({
|
||||
ogSiteName: "Solsynth Capital",
|
||||
})
|
||||
|
||||
const externalOpenLink = computed(() => `${config.public.solianUrl}/posts/view/${slug.value}`)
|
||||
const externalOpenLink = computed(() => `${config.public.solianUrl}/posts/${route.params.id.toString().replace('/', ':')}`)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<v-container class="flex flex-col my-2 px-12 gap-[4rem]">
|
||||
<section class="content-section flex flex-col items-center justify-center text-center px-4" id="intro">
|
||||
<section class="content-section flex flex-col items-center justify-center text-center" id="intro">
|
||||
<div class="pt-1/3 mb-4 w-full relative">
|
||||
<img :src="AlphaScreenshot" class="absolute bottom-2 left-0 right-0" />
|
||||
<img
|
||||
@ -23,12 +23,67 @@
|
||||
<div>
|
||||
<h1 class="text-4xl font-bold">Solar Network</h1>
|
||||
<p class="mt-2 text-lg">{{ t("solarNetworkDescription") }}</p>
|
||||
<v-btn class="mt-4" color="primary" prepend-icon="mdi-arrow-down" href="#products">{{ t("learnMore") }}</v-btn>
|
||||
<v-btn class="mt-4" color="primary" prepend-icon="mdi-arrow-down" href="#features">{{ t("learnMore") }}</v-btn>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section flex flex-col items-center justify-center text-center px-4" id="reminders">
|
||||
<h1 class="text-3xl font-bold">{{ t("solarNetworkBeforeYouStart") }}</h1>
|
||||
<section class="content-section flex flex-col items-center justify-center text-center" id="features">
|
||||
<h2 class="text-3xl font-bold">{{ t("solarNetworkFeat") }}</h2>
|
||||
<p class="text-lg mb-4">{{ t("solarNetworkFeatDescription") }}</p>
|
||||
|
||||
<v-card class="w-full">
|
||||
<v-tabs v-model="featuresTab" align-tabs="center" color="primary">
|
||||
<v-tab
|
||||
:prepend-icon="feat.icon"
|
||||
:text="feat.title"
|
||||
:value="feat.icon"
|
||||
v-for="feat in features"
|
||||
@mouseover="featuresTab = feat.icon"
|
||||
/>
|
||||
</v-tabs>
|
||||
|
||||
<v-tabs-window v-model="featuresTab">
|
||||
<v-tabs-window-item :value="feat.icon" v-for="feat in features">
|
||||
<v-card flat>
|
||||
<v-img :aspect-ratio="16 / 9" :src="feat.image" cover></v-img>
|
||||
|
||||
<v-card-text>
|
||||
<p class="text-lg mb-1">
|
||||
{{ feat.description }}
|
||||
</p>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-tabs-window-item>
|
||||
</v-tabs-window>
|
||||
</v-card>
|
||||
</section>
|
||||
|
||||
<section class="content-section flex flex-col items-center justify-center" id="highlight-posts">
|
||||
<v-row class="w-full" dense>
|
||||
<v-col cols="12" md="6">
|
||||
<div
|
||||
class="max-h-[500px] overflow-y-auto posts-container"
|
||||
ref="highlight-posts"
|
||||
v-if="highlightPosts.status.value === 'success'"
|
||||
>
|
||||
<div v-for="post in highlightPosts.data.value">
|
||||
<post-item :post="post" force-show-content class="mx-0" />
|
||||
</div>
|
||||
</div>
|
||||
<v-progress-circular v-else indeterminate />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6" class="text-right">
|
||||
<h2 class="text-3xl font-bold">{{ t("solarNetworkHighlightPosts") }}<sup>®</sup></h2>
|
||||
<p>{{ t("solarNetworkHighlightPostsDescription") }}</p>
|
||||
<v-btn variant="text" color="white" slim prepend-icon="mdi-plus" href="#reminders">{{
|
||||
t("solarNetworkJumpIn")
|
||||
}}</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</section>
|
||||
|
||||
<section class="content-section flex flex-col items-center justify-center text-center" id="reminders">
|
||||
<h2 class="text-3xl font-bold">{{ t("solarNetworkBeforeYouStart") }}</h2>
|
||||
<p class="text-lg">{{ t("solarNetworkBeforeYouStartDescription") }}</p>
|
||||
|
||||
<div class="max-h-[500px] w-full mt-4 text-left">
|
||||
@ -63,8 +118,8 @@
|
||||
<nuxt-link class="underline text-sm" to="/terms">{{ t("solarNetworkToSCheck") }}</nuxt-link>
|
||||
</section>
|
||||
|
||||
<section class="content-section flex flex-col items-center justify-center text-center px-4" id="downloads">
|
||||
<h1 class="text-3xl font-bold">{{ t("download") }}</h1>
|
||||
<section class="content-section flex flex-col items-center justify-center text-center" id="downloads">
|
||||
<h3 class="text-3xl font-bold">{{ t("download") }}</h3>
|
||||
<p class="text-lg">
|
||||
File-hosting & versioning by
|
||||
<nuxt-link class="underline" to="https://github.com/Solsynth/HyperNet.Surface" target="_blank">GitHub</nuxt-link
|
||||
@ -82,8 +137,8 @@
|
||||
>
|
||||
{{ showPrerelease ? t("downloadSwitchRelease") : t("downloadSwitchPrerelease") }}
|
||||
</v-btn>
|
||||
<div class="max-h-[500px] w-full mt-4 text-left">
|
||||
<v-row dense>
|
||||
<div class="w-full mt-4 text-left">
|
||||
<v-row dense class="flex-1">
|
||||
<v-col cols="12" md="6">
|
||||
<v-card
|
||||
prepend-icon="mdi-alert-decagram"
|
||||
@ -152,19 +207,101 @@
|
||||
</v-row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section flex flex-col items-center justify-center" id="help">
|
||||
<h2 class="text-2xl font-bold text-center mb-4">{{ t("solarNetworkNeedHelp") }}</h2>
|
||||
<div class="flex flex-col gap-2 w-[480px] max-w-screen">
|
||||
<v-card :title="t('askHelpContactUs')" prepend-icon="mdi-email-fast" density="comfortable">
|
||||
<v-card-text>
|
||||
Contact our customer server at
|
||||
<nuxt-link to="mailto:lily@solsynth.dev" class="underline">
|
||||
<address>lily@solsynth.dev</address>
|
||||
</nuxt-link>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-card :title="t('askHelpReadTheDocs')" prepend-icon="mdi-page-next" density="comfortable">
|
||||
<v-card-text class="flex flex-col">
|
||||
<nuxt-link to="https://kb.solsynth.dev" class="underline">Visit Goatpedia</nuxt-link>
|
||||
<nuxt-link to="https://github.com/Solsynth/HyperNet.Surface/issues" class="underline"
|
||||
>Visit GitHub Issue Tracker</nuxt-link
|
||||
>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<copyright :service="['capital', 'roadsign']" />
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Icon from "~/assets/products/solar-network/icon.png"
|
||||
import AlphaScreenshot from "~/assets/products/solar-network/alpha.webp"
|
||||
import ScreenshotDashboard from "~/assets/products/solar-network/ft-dashboard.png"
|
||||
import ScreenshotExplore from "~/assets/products/solar-network/ft-explore.png"
|
||||
import ScreenshotChat from "~/assets/products/solar-network/ft-chat.png"
|
||||
import ScreenshotNews from "~/assets/products/solar-network/ft-news.png"
|
||||
import ScreenshotStickers from "~/assets/products/solar-network/ft-stickers.png"
|
||||
import ScreenshotCompose from "~/assets/products/solar-network/ft-posting.png"
|
||||
import AppStoreDownload from "~/assets/products/app-store-download.svg"
|
||||
|
||||
useHead({
|
||||
title: "Solar Network",
|
||||
})
|
||||
|
||||
import { formatBytes } from "~/utils/format"
|
||||
import { Octokit } from "@octokit/rest"
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const featuresTab = ref()
|
||||
|
||||
interface FeatureItem {
|
||||
title: string
|
||||
description: string
|
||||
icon: string
|
||||
image: string
|
||||
}
|
||||
|
||||
const features: FeatureItem[] = [
|
||||
{
|
||||
title: t("solarNetworkFeatDashboard"),
|
||||
description: t("solarNetworkFeatDashboardDescription"),
|
||||
icon: "mdi-view-dashboard",
|
||||
image: ScreenshotDashboard,
|
||||
},
|
||||
{
|
||||
title: t("solarNetworkFeatExplore"),
|
||||
description: t("solarNetworkFeatExploreDescription"),
|
||||
icon: "mdi-compass",
|
||||
image: ScreenshotExplore,
|
||||
},
|
||||
{
|
||||
title: t("solarNetworkFeatChat"),
|
||||
description: t("solarNetworkFeatChatDescription"),
|
||||
icon: "mdi-chat",
|
||||
image: ScreenshotChat,
|
||||
},
|
||||
{
|
||||
title: t("solarNetworkFeatNews"),
|
||||
description: t("solarNetworkFeatNewsDescription"),
|
||||
icon: "mdi-newspaper",
|
||||
image: ScreenshotNews,
|
||||
},
|
||||
{
|
||||
title: t("solarNetworkFeatStickers"),
|
||||
description: t("solarNetworkFeatStickersDescription"),
|
||||
icon: "mdi-sticker",
|
||||
image: ScreenshotStickers,
|
||||
},
|
||||
{
|
||||
title: t("solarNetworkFeatCompose"),
|
||||
description: t("solarNetworkFeatComposeDescription"),
|
||||
icon: "mdi-pencil",
|
||||
image: ScreenshotCompose,
|
||||
},
|
||||
]
|
||||
|
||||
const latestRelease = useAsyncData("sn-latest-release", async () => {
|
||||
const octo = new Octokit({})
|
||||
const resp = await octo.repos.getLatestRelease({
|
||||
@ -183,17 +320,97 @@ const latestPrerelease = useAsyncData("sn-latest-prerelease", async () => {
|
||||
return resp.data[0]
|
||||
})
|
||||
|
||||
const highlightPosts = useAsyncData("sn-highlight-posts", async () => {
|
||||
const resp = await solarFetch("/cgi/co/recommendations")
|
||||
const data = await resp.json()
|
||||
return data
|
||||
})
|
||||
|
||||
const showPrerelease = ref(false)
|
||||
|
||||
const currentRelease = computed(() => (showPrerelease.value ? latestPrerelease : latestRelease))
|
||||
const hasPrerelease = computed<boolean>(
|
||||
() => latestPrerelease.data?.value?.tag_name != latestRelease.data?.value?.tag_name,
|
||||
)
|
||||
|
||||
const highlightPostContainer = useTemplateRef("highlight-posts")
|
||||
|
||||
function autoScroll() {
|
||||
console.log("Auto scroll is called.")
|
||||
|
||||
const scrollSpeed = 1
|
||||
let animationFrameId: number
|
||||
let isScrolling = true
|
||||
|
||||
function scroll() {
|
||||
if (!isScrolling) return
|
||||
const container = highlightPostContainer.value!
|
||||
|
||||
if (container.scrollTop + container.clientHeight >= container.scrollHeight) {
|
||||
container.scroll(0, 0)
|
||||
} else {
|
||||
container.scrollBy(0, scrollSpeed)
|
||||
}
|
||||
animationFrameId = requestAnimationFrame(scroll)
|
||||
}
|
||||
|
||||
scroll()
|
||||
|
||||
const container = highlightPostContainer.value!
|
||||
container.addEventListener("mouseenter", () => {
|
||||
isScrolling = false
|
||||
cancelAnimationFrame(animationFrameId)
|
||||
})
|
||||
container.addEventListener("mouseleave", () => {
|
||||
if (!isScrolling) {
|
||||
isScrolling = true
|
||||
scroll()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
highlightPostContainer,
|
||||
(data) => {
|
||||
if (data != null) {
|
||||
autoScroll()
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.posts-container {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
position: relative;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
scrollbar-width: none;
|
||||
mask-image: linear-gradient(
|
||||
to bottom,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 80%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to bottom,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 80%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.posts-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content-section {
|
||||
min-height: calc(100vh - 80px);
|
||||
height: auto;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user