mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 09:20:18 +08:00
update:添加apm与普通商店双支持
This commit is contained in:
@@ -17,10 +17,22 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-1 overflow-hidden">
|
||||
<div
|
||||
class="truncate text-base font-semibold text-slate-900 dark:text-white"
|
||||
>
|
||||
{{ app.name || "" }}
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="truncate text-base font-semibold text-slate-900 dark:text-white"
|
||||
>
|
||||
{{ app.name || "" }}
|
||||
</div>
|
||||
<span
|
||||
:class="[
|
||||
'rounded-md px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wider shadow-sm',
|
||||
app.origin === 'spark'
|
||||
? 'bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400'
|
||||
: 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400',
|
||||
]"
|
||||
>
|
||||
{{ app.origin === "spark" ? "Spark" : "APM" }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm text-slate-500 dark:text-slate-400">
|
||||
{{ app.pkgname || "" }} · {{ app.version || "" }}
|
||||
@@ -52,7 +64,12 @@ const loadedIcon = ref(
|
||||
);
|
||||
|
||||
const iconPath = computed(() => {
|
||||
return `${APM_STORE_BASE_URL}/${window.apm_store.arch}/${props.app.category}/${props.app.pkgname}/icon.png`;
|
||||
const arch = window.apm_store.arch || "amd64-apm";
|
||||
const finalArch =
|
||||
props.app.origin === "spark"
|
||||
? arch.replace("-apm", "-store")
|
||||
: arch.replace("-store", "-apm");
|
||||
return `${APM_STORE_BASE_URL}/${finalArch}/${props.app.category}/${props.app.pkgname}/icon.png`;
|
||||
});
|
||||
|
||||
const description = computed(() => {
|
||||
|
||||
@@ -36,7 +36,17 @@
|
||||
<p class="text-2xl font-bold text-slate-900 dark:text-white">
|
||||
{{ app?.name || "" }}
|
||||
</p>
|
||||
<!-- Close button for mobile layout could be considered here if needed, but for now sticking to desktop layout logic mainly -->
|
||||
<span
|
||||
v-if="app"
|
||||
:class="[
|
||||
'rounded-md px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wider shadow-sm',
|
||||
app.origin === 'spark'
|
||||
? 'bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400'
|
||||
: 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400',
|
||||
]"
|
||||
>
|
||||
{{ app.origin === "spark" ? "Spark" : "APM" }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm text-slate-500 dark:text-slate-400">
|
||||
{{ app?.pkgname || "" }} · {{ app?.version || "" }}
|
||||
@@ -269,7 +279,12 @@ const installBtnText = computed(() => {
|
||||
});
|
||||
const iconPath = computed(() => {
|
||||
if (!props.app) return "";
|
||||
return `${APM_STORE_BASE_URL}/${window.apm_store.arch}/${props.app.category}/${props.app.pkgname}/icon.png`;
|
||||
const arch = window.apm_store.arch || "amd64-apm";
|
||||
const finalArch =
|
||||
props.app.origin === "spark"
|
||||
? arch.replace("-apm", "-store")
|
||||
: arch.replace("-store", "-apm");
|
||||
return `${APM_STORE_BASE_URL}/${finalArch}/${props.app.category}/${props.app.pkgname}/icon.png`;
|
||||
});
|
||||
|
||||
const downloadCount = ref<string>("");
|
||||
@@ -281,7 +296,12 @@ watch(
|
||||
if (newApp) {
|
||||
downloadCount.value = "";
|
||||
try {
|
||||
const url = `${APM_STORE_BASE_URL}/${window.apm_store.arch}/${newApp.category}/${newApp.pkgname}/download-times.txt`;
|
||||
const arch = window.apm_store.arch || "amd64-apm";
|
||||
const finalArch =
|
||||
newApp.origin === "spark"
|
||||
? arch.replace("-apm", "-store")
|
||||
: arch.replace("-store", "-apm");
|
||||
const url = `${APM_STORE_BASE_URL}/${finalArch}/${newApp.category}/${newApp.pkgname}/download-times.txt`;
|
||||
const resp = await axios.get(url, { responseType: "text" });
|
||||
if (resp.status === 200) {
|
||||
downloadCount.value = String(resp.data).trim();
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
</div>
|
||||
|
||||
<ThemeToggle :theme-mode="themeMode" @toggle="toggleTheme" />
|
||||
<StoreModeSwitcher />
|
||||
|
||||
<div class="flex-1 space-y-2 overflow-y-auto scrollbar-muted pr-2">
|
||||
<button
|
||||
@@ -88,6 +89,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ThemeToggle from "./ThemeToggle.vue";
|
||||
import StoreModeSwitcher from "./StoreModeSwitcher.vue";
|
||||
import amberLogo from "../assets/imgs/spark-store.svg";
|
||||
|
||||
defineProps<{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
:title="link.more"
|
||||
>
|
||||
<img
|
||||
:src="computedImgUrl(link.imgUrl)"
|
||||
:src="computedImgUrl(link)"
|
||||
class="h-20 w-full object-contain"
|
||||
loading="lazy"
|
||||
/>
|
||||
@@ -62,10 +62,14 @@ defineEmits<{
|
||||
(e: "open-detail", app: Record<string, unknown>): void;
|
||||
}>();
|
||||
|
||||
const computedImgUrl = (imgUrl: string) => {
|
||||
if (!imgUrl) return "";
|
||||
// imgUrl is like /home/links/bbs.png -> join with base
|
||||
return `${APM_STORE_BASE_URL}/${window.apm_store.arch}${imgUrl}`;
|
||||
const computedImgUrl = (link: Record<string, any>) => {
|
||||
if (!link.imgUrl) return "";
|
||||
const arch = window.apm_store.arch || "amd64-apm";
|
||||
const finalArch =
|
||||
link.origin === "spark"
|
||||
? arch.replace("-apm", "-store")
|
||||
: arch.replace("-store", "-apm");
|
||||
return `${APM_STORE_BASE_URL}/${finalArch}${link.imgUrl}`;
|
||||
};
|
||||
|
||||
const onLinkClick = (link: Record<string, unknown>) => {
|
||||
|
||||
38
src/components/StoreModeSwitcher.vue
Normal file
38
src/components/StoreModeSwitcher.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-2 p-4 rounded-2xl bg-slate-50 dark:bg-slate-800/50 border border-slate-200/70 dark:border-slate-700/70">
|
||||
<span class="text-xs font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400 px-1">商店模式</span>
|
||||
<div class="grid grid-cols-3 gap-1 p-1 bg-slate-200/50 dark:bg-slate-900/50 rounded-xl">
|
||||
<button
|
||||
v-for="mode in modes"
|
||||
:key="mode.id"
|
||||
type="button"
|
||||
class="flex flex-col items-center justify-center py-2 px-1 rounded-lg text-[10px] font-medium transition-all duration-200"
|
||||
:class="currentStoreMode === mode.id
|
||||
? 'bg-white dark:bg-slate-700 text-brand shadow-sm scale-105 z-10'
|
||||
: 'text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200'"
|
||||
@click="setMode(mode.id as StoreMode)"
|
||||
>
|
||||
<i :class="mode.icon" class="mb-1 text-xs"></i>
|
||||
{{ mode.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { currentStoreMode } from "../global/storeConfig";
|
||||
import type { StoreMode } from "../global/typedefinition";
|
||||
|
||||
const modes = [
|
||||
{ id: "spark", label: "星火", icon: "fas fa-fire" },
|
||||
{ id: "apm", label: "APM", icon: "fas fa-box-open" },
|
||||
{ id: "hybrid", label: "混合", icon: "fas fa-layer-group" },
|
||||
];
|
||||
|
||||
const setMode = (mode: StoreMode) => {
|
||||
currentStoreMode.value = mode;
|
||||
localStorage.setItem("store_mode", mode);
|
||||
// Reload page to re-fetch data based on new mode
|
||||
window.location.reload();
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user