🎉 创世提交
This commit is contained in:
60
src/lib/api/app.ts
Normal file
60
src/lib/api/app.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { AppDetail, AppItem } from "@/types/app";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { retryOperation } from "../utils";
|
||||
|
||||
/**
|
||||
* 获取应用详细信息
|
||||
* @param category 应用分类
|
||||
* @param pkgname 应用包名
|
||||
* @returns Promise<AppInfoItem>
|
||||
*/
|
||||
export async function getAppInfo(category: string, pkgname: string): Promise<AppDetail> {
|
||||
try {
|
||||
return await retryOperation(async () => {
|
||||
const appInfo = await invoke<AppDetail>("get_app_info", {
|
||||
category,
|
||||
pkgname,
|
||||
});
|
||||
return appInfo;
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`获取应用信息失败: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索所有应用
|
||||
* @param query 搜索关键词
|
||||
* @returns Promise<AppItem[]>
|
||||
*/
|
||||
export async function searchAllApps(query: string): Promise<AppItem[]> {
|
||||
try {
|
||||
// 从后端获取数据并转换字段名称
|
||||
const rawApps = await retryOperation(async () => {
|
||||
return await invoke<Array<{
|
||||
More: string,
|
||||
Name: string,
|
||||
Pkgname: string,
|
||||
Tags?: string,
|
||||
Update: string,
|
||||
icon?: string,
|
||||
category?: string
|
||||
}>>("search_all_apps", { query });
|
||||
});
|
||||
|
||||
// 将后端返回的大写字段名转换为前端使用的小写格式
|
||||
return rawApps.map(app => ({
|
||||
more: app.More,
|
||||
name: app.Name,
|
||||
pkgname: app.Pkgname,
|
||||
tags: app.Tags,
|
||||
update: app.Update,
|
||||
icon: app.icon,
|
||||
category: app.category
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("搜索应用失败:", error);
|
||||
throw new Error(`搜索应用失败: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
46
src/lib/api/category.ts
Normal file
46
src/lib/api/category.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { Category } from "@/types/category";
|
||||
import { AppItem } from "@/types/app";
|
||||
import { retryOperation } from "../utils";
|
||||
|
||||
export const getAllCategories = async (): Promise<Category[]> => {
|
||||
try {
|
||||
return await retryOperation(async () => {
|
||||
return await invoke<Category[]>("get_all_categories");
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("获取分类列表失败:", error);
|
||||
throw new Error("获取分类列表失败");
|
||||
}
|
||||
};
|
||||
|
||||
export const getCategoryApps = async (categoryId: string): Promise<AppItem[]> => {
|
||||
// 从后端获取数据并转换字段名称
|
||||
try {
|
||||
const rawApps = await retryOperation(async () => {
|
||||
return await invoke<Array<{
|
||||
More: string,
|
||||
Name: string,
|
||||
Pkgname: string,
|
||||
Tags?: string,
|
||||
Update: string,
|
||||
icon?: string,
|
||||
category?: string
|
||||
}>>("get_category_apps", { categoryId });
|
||||
});
|
||||
|
||||
// 将后端返回的大写字段名转换为前端使用的小写格式
|
||||
return rawApps.map(app => ({
|
||||
more: app.More,
|
||||
name: app.Name,
|
||||
pkgname: app.Pkgname,
|
||||
tags: app.Tags,
|
||||
update: app.Update,
|
||||
icon: app.icon,
|
||||
category: app.category
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("获取分类应用列表失败:", error);
|
||||
throw new Error("获取分类应用列表失败");
|
||||
}
|
||||
};
|
||||
21
src/lib/api/home.ts
Normal file
21
src/lib/api/home.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { retryOperation } from "../utils";
|
||||
import { HomeLink, HomeLinkResponse } from "@/types/home";
|
||||
|
||||
export const getHomeLinks = async (): Promise<HomeLink[]> => {
|
||||
try {
|
||||
const links = await retryOperation(async () => {
|
||||
const result = await invoke<HomeLinkResponse[]>("get_home_links");
|
||||
// 将返回数据中的 url 字段转换为 linkUrl
|
||||
return result.map(link => ({
|
||||
...link,
|
||||
linkUrl: link.url,
|
||||
url: undefined
|
||||
}));
|
||||
});
|
||||
return links;
|
||||
} catch (error) {
|
||||
console.error("获取主页链接列表失败:", error);
|
||||
throw new Error("获取主页链接列表失败");
|
||||
}
|
||||
};
|
||||
50
src/lib/api/server.ts
Normal file
50
src/lib/api/server.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
// 存储服务器相关的全局变量
|
||||
let targetArchToStore: string;
|
||||
let jsonServerUrl: string;
|
||||
let imgServerUrl: string;
|
||||
|
||||
// 初始化函数,在应用启动时调用
|
||||
export async function initServerConfig() {
|
||||
targetArchToStore = await invoke('get_target_arch_to_store');
|
||||
jsonServerUrl = await invoke('get_json_server_url');
|
||||
imgServerUrl = await invoke('get_img_server_url');
|
||||
}
|
||||
|
||||
export function getTargetArchToStore(): string {
|
||||
if (!targetArchToStore) {
|
||||
throw new Error('服务器配置未初始化,请先调用 initServerConfig');
|
||||
}
|
||||
return targetArchToStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JSON服务器URL
|
||||
* @returns 返回JSON服务器的完整URL
|
||||
*/
|
||||
export function getJsonServerUrl(): string {
|
||||
if (!jsonServerUrl) {
|
||||
throw new Error('服务器配置未初始化,请先调用 initServerConfig');
|
||||
}
|
||||
return jsonServerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片服务器URL
|
||||
* @returns 返回图片服务器的完整URL
|
||||
*/
|
||||
export function getImgServerUrl(): string {
|
||||
if (!imgServerUrl) {
|
||||
throw new Error('服务器配置未初始化,请先调用 initServerConfig');
|
||||
}
|
||||
return imgServerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 User-Agent
|
||||
* @returns 返回应用的 User-Agent 字符串
|
||||
*/
|
||||
export async function getUserAgent(): Promise<string> {
|
||||
return await invoke('get_user_agent');
|
||||
}
|
||||
18
src/lib/icon.ts
Normal file
18
src/lib/icon.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Package, Code, Globe, Palette, MessageCircle, Gamepad2, Image, Music, FileText, Grid, type Icon } from 'lucide-solid';
|
||||
|
||||
const iconMap: Record<string, typeof Icon> = {
|
||||
'code': Code,
|
||||
'globe': Globe,
|
||||
'palette': Palette,
|
||||
'message-circle': MessageCircle,
|
||||
'gamepad-2': Gamepad2,
|
||||
'image': Image,
|
||||
'music': Music,
|
||||
'file-text': FileText,
|
||||
'grid': Grid
|
||||
};
|
||||
|
||||
export const getIconComponent = (iconName?: string): typeof Icon => {
|
||||
if (!iconName) return Package;
|
||||
return iconMap[iconName] || Package;
|
||||
};
|
||||
24
src/lib/share.ts
Normal file
24
src/lib/share.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
|
||||
export const getTargetArchToStore = async (): Promise<string> => {
|
||||
return await invoke<string>("get_target_arch_to_store");
|
||||
};
|
||||
|
||||
export const copy = async (text: string): Promise<void> => {
|
||||
console.log(text);
|
||||
await writeText(text);
|
||||
};
|
||||
|
||||
export const generateShareLinks = async (category: string, pkgname: string) => {
|
||||
const targetArch = await getTargetArchToStore();
|
||||
const spkLink = `spk://${targetArch}/${category}/${pkgname}`;
|
||||
const shareLink = `https://spk-resolv.spark-app.store/?spk=spk://${targetArch}/${category}/${pkgname}`;
|
||||
const shareIframe = `<iframe src="https://spk-resolv.spark-app.store/?spk=${encodeURIComponent(`spk://${targetArch}/${category}/${pkgname}`)}" height="350" width="100%" border="0"></iframe>`;
|
||||
|
||||
return {
|
||||
spkLink,
|
||||
shareLink,
|
||||
shareIframe
|
||||
};
|
||||
};
|
||||
26
src/lib/utils.ts
Normal file
26
src/lib/utils.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export const retryOperation = async <T>(
|
||||
operation: () => Promise<T>,
|
||||
maxRetries: number = 3
|
||||
): Promise<T> => {
|
||||
let lastError: any;
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (attempt === maxRetries) break;
|
||||
// 等待一小段时间后重试
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
};
|
||||
Reference in New Issue
Block a user