Initial clean project import

This commit is contained in:
cat-shark
2026-06-19 18:41:41 +08:00
commit a13b804c7a
1306 changed files with 220568 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
<template>
<a-config-provider :locale="locale" :global="true">
<router-view></router-view>
<ResourcePreparingDialog />
</a-config-provider>
</template>
<script setup lang="ts">
import {onMounted, onUnmounted, ref, onErrorCaptured} from "vue";
import {onLocaleChange} from "./lang";
import {useRouter} from "vue-router";
import zhCN from "@arco-design/web-vue/es/locale/lang/zh-cn";
import enUS from "@arco-design/web-vue/es/locale/lang/en-us";
import {doCheckForUpdate} from "./components/common/util";
import ResourcePreparingDialog from "./components/common/ResourcePreparingDialog.vue";
const locales = {
"zh-CN": zhCN,
"en-US": enUS,
};
const locale = ref(zhCN);
onLocaleChange(newLocale => {
locale.value = locales[newLocale];
});
// 捕获所有 Vue 组件错误
onErrorCaptured((err, instance, info) => {
console.error('❌ Vue 组件错误:', err);
console.error('组件:', instance);
console.error('错误信息:', info);
// 如果是 $mapi 相关错误,给出友好提示
if (err.message && err.message.includes('$mapi')) {
console.error('💡 提示: $mapi 可能尚未初始化,请检查 preload 脚本');
}
// 返回 false 继续传播错误,返回 true 阻止传播
return false;
});
// 🔥 心跳检测:定时验证 token,被踢出时弹窗 + 跳转登录页
let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
const router = useRouter();
const startHeartbeat = () => {
// 每 60 秒检测一次
heartbeatTimer = setInterval(async () => {
try {
const token = localStorage.getItem('auth_token');
if (!token) return; // 未登录,不检测
// 直接调用后端验证
if (!window['$mapi']?.auth?.verifyToken) return;
const result = await window['$mapi'].auth.verifyToken(token);
if (result && !result.valid && result.kicked) {
// 被踢出!
console.warn('⚠️ 心跳检测:账号已在其他设备登录');
// 清除本地登录状态
localStorage.removeItem('auth_token');
localStorage.removeItem('auth_user');
localStorage.removeItem('auth_subscription');
// 停止心跳
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
// 弹窗提示
alert(result.message || '您的账号已在其他设备登录,当前会话已失效');
// 跳转登录页
router.push('/login');
}
} catch (e) {
// 网络错误等,静默忽略
}
}, 60000); // 60 秒
};
onMounted(() => {
// 启动心跳检测
startHeartbeat();
setTimeout(async () => {
if (!window.$mapi) {
return;
}
try {
const checkAtLaunch = await window.$mapi.config.get("updaterCheckAtLaunch", "yes");
if ("yes" !== checkAtLaunch) {
return;
}
doCheckForUpdate().then();
} catch (error) {
console.error('检查更新失败:', error);
}
}, 6000);
});
onUnmounted(() => {
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
});
</script>
+228
View File
@@ -0,0 +1,228 @@
import {CoverTemplate} from "../declarations/app";
import { useDevMode } from "../composables/useDevMode"; // ✅ 添加开发模式检测导入
// 生成UUID
function generateUUID(): string {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
// Fallback for older browsers
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* 保存封面模板
* @param template 模板配置
* @returns 模板ID
*/
export async function saveCoverTemplate(template: CoverTemplate): Promise<string> {
try {
// ✅ 获取开发模式状态
const { isDev } = useDevMode();
console.log('[saveCoverTemplate] 开始保存模板,详细信息:', {
id: template.id,
name: template.name,
hasTemplate: !!template,
idType: typeof template.id,
idValue: JSON.stringify(template.id),
isDev: isDev.value
});
// ✅ 修复:不嵌套 config,而是展开配置字段(排除元数据字段)
// 移除元数据字段(id, name, thumbnailPath, createdAt, updatedAt
const { id, name, thumbnailPath, createdAt, updatedAt, is_system, ...configFields } = template;
console.log('[saveCoverTemplate] 解构后的参数:', {
id: id,
idType: typeof id,
name: name,
configFieldsKeys: Object.keys(configFields).length,
thumbnailPath: !!thumbnailPath,
isDev: isDev.value
});
// 通过后端 IPC 保存模板
console.log('[saveCoverTemplate] 调用后端 IPC: ipAgent.saveCoverTemplate');
const result = await window.$mapi.ipAgent.saveCoverTemplate({
id: id || undefined, // ✅ 确保空字符串变为 undefined
name,
config: configFields, // ✅ 只传配置部分,不嵌套整个对象
thumbnailPath,
isDev: isDev.value // ✅ 传递开发模式标志给后端
});
console.log('[saveCoverTemplate] 后端返回结果:', {
success: result.success,
id: result.id,
message: result.message
});
if (result.success) {
const returnId = result.id || template.id || generateUUID();
console.log('[saveCoverTemplate] ✅ 模板保存成功,返回ID:', returnId);
return returnId;
} else {
console.error('[saveCoverTemplate] ❌ 后端返回失败:', result.message);
throw new Error(result.message || '保存模板失败');
}
} catch (error) {
console.error('[saveCoverTemplate] ❌ 捕获异常:', {
message: (error as Error).message,
stack: (error as Error).stack
});
throw error;
}
}
/**
* 获取所有封面模板列表(最多24个,按创建时间倒序)
* @returns 模板列表
*/
export async function getCoverTemplates(): Promise<CoverTemplate[]> {
try {
console.log('[getCoverTemplates] 调用后端获取模板列表');
// 通过后端 IPC 获取模板
const result = await window.$mapi.ipAgent.getCoverTemplates({ metadataOnly: false });
if (result.success && result.templates) {
console.log('[getCoverTemplates] 获取成功,模板数:', result.templates.length);
return result.templates;
} else {
console.error('[getCoverTemplates] 获取失败:', result.message);
return [];
}
} catch (error) {
console.error('[getCoverTemplates] 调用失败:', error);
return [];
}
}
/**
* 删除封面模板
* @param templateId 模板ID
*/
export async function deleteCoverTemplate(templateId: string): Promise<void> {
try {
const { isDev } = useDevMode();
console.log('[deleteCoverTemplate] 删除模板:', {
id: templateId,
isDev: isDev.value
});
// ✅ 调用后端 IPC API,后端会检查权限
const result = await window.$mapi.ipAgent.deleteCoverTemplate({
id: templateId,
isDev: isDev.value // 传递开发模式标志给后端
});
if (!result.success) {
throw new Error(result.message || '删除模板失败');
}
console.log('[deleteCoverTemplate] ✅ 模板删除成功');
} catch (error) {
console.error('[deleteCoverTemplate] ❌ 删除失败:', error);
throw error;
}
}
/**
* 更新封面模板
* @param templateId 模板ID
* @param template 模板配置
*/
export async function updateCoverTemplate(templateId: string, template: CoverTemplate): Promise<void> {
try {
const { isDev } = useDevMode();
console.log('[updateCoverTemplate] 更新模板:', {
id: templateId,
name: template.name,
isDev: isDev.value
});
// ✅ 调用后端 IPC API,后端会检查权限
const result = await window.$mapi.ipAgent.updateCoverTemplate({
id: templateId,
name: template.name,
description: template.description,
config: template,
thumbnailPath: template.thumbnailPath,
isDev: isDev.value // 传递开发模式标志给后端
});
if (!result.success) {
throw new Error(result.message || '更新模板失败');
}
console.log('[updateCoverTemplate] ✅ 模板更新成功');
} catch (error) {
console.error('[updateCoverTemplate] ❌ 更新失败:', error);
throw error;
}
}
/**
* 获取单个封面模板
* @param templateId 模板ID
* @returns 模板配置
*/
export async function getCoverTemplate(templateId: string): Promise<CoverTemplate> {
try {
console.log('[getCoverTemplate] 调用后端获取模板:', templateId);
// 通过后端 IPC 获取模板
const result = await window.$mapi.ipAgent.getCoverTemplate({ id: templateId });
if (result.success && result.template) {
console.log('[getCoverTemplate] 获取成功');
return result.template;
} else {
throw new Error(result.message || `模板 ${templateId} 不存在`);
}
} catch (error) {
console.error('[getCoverTemplate] 获取失败:', error);
throw error;
}
}
/**
* 复制封面模板
* @param templateId 源模板ID
* @param newName 新模板名称(可选)
* @returns 新模板ID
*/
export async function duplicateCoverTemplate(templateId: string, newName?: string): Promise<string> {
try {
console.log('[duplicateCoverTemplate] 开始复制模板:', {
sourceId: templateId,
newName
});
// 调用后端 IPC API
const result = await window.$mapi.ipAgent.duplicateCoverTemplate({
id: templateId,
newName
});
if (result.success && result.id) {
console.log('[duplicateCoverTemplate] ✅ 复制成功:', {
newId: result.id,
newName: result.name
});
return result.id;
} else {
throw new Error(result.message || '复制模板失败');
}
} catch (error) {
console.error('[duplicateCoverTemplate] ❌ 复制失败:', error);
throw error;
}
}
+293
View File
@@ -0,0 +1,293 @@
import { SubtitleTemplate } from "../types/smartSubtitle";
/**
* 保存字幕模板
* @param template 模板配置
* @returns 模板ID
*/
export async function saveSubtitleTemplate(template: SubtitleTemplate): Promise<string> {
try {
console.log('[saveSubtitleTemplate] 开始保存字幕模板:', {
id: template.id,
name: template.name
});
const result = await window.$mapi.ipAgent.saveSubtitleTemplate({
id: template.id || undefined,
name: template.name,
description: template.description,
config: template.config
});
console.log('[saveSubtitleTemplate] 后端返回结果:', {
success: result.success,
id: result.id,
message: result.message
});
if (result.success) {
return result.id || template.id || '';
} else {
throw new Error(result.message || '保存模板失败');
}
} catch (error) {
console.error('[saveSubtitleTemplate] 保存失败:', error);
throw error;
}
}
/**
* 获取所有字幕模板
* @returns 模板列表
*/
export async function getSubtitleTemplates(): Promise<SubtitleTemplate[]> {
try {
console.log('[getSubtitleTemplates] 调用后端获取字幕模板列表');
const result = await window.$mapi.ipAgent.getSubtitleTemplates();
if (result.success && result.templates) {
console.log('[getSubtitleTemplates] 获取成功,模板数:', result.templates.length);
return result.templates;
} else {
console.error('[getSubtitleTemplates] 获取失败:', result.message);
return [];
}
} catch (error) {
console.error('[getSubtitleTemplates] 调用失败:', error);
return [];
}
}
/**
* 获取单个字幕模板
* @param templateId 模板ID
* @returns 模板配置
*/
export async function getSubtitleTemplate(templateId: string): Promise<SubtitleTemplate | null> {
try {
console.log('[getSubtitleTemplate] 调用后端获取模板:', templateId);
const result = await window.$mapi.ipAgent.getSubtitleTemplate({ id: templateId });
if (result.success && result.template) {
console.log('[getSubtitleTemplate] 获取成功');
return result.template;
} else {
throw new Error(result.message || `模板 ${templateId} 不存在`);
}
} catch (error) {
console.error('[getSubtitleTemplate] 获取失败:', error);
return null;
}
}
/**
* 删除字幕模板
* @param templateId 模板ID
*/
export async function deleteSubtitleTemplate(templateId: string): Promise<boolean> {
try {
console.log('[deleteSubtitleTemplate] 开始删除模板:', templateId);
const result = await window.$mapi.ipAgent.deleteSubtitleTemplate({
id: templateId
});
if (result.success) {
console.log('[deleteSubtitleTemplate] 删除成功');
return true;
} else {
console.error('[deleteSubtitleTemplate] 删除失败:', result.message);
return false;
}
} catch (error) {
console.error('[deleteSubtitleTemplate] 删除异常:', error);
return false;
}
}
/**
* 更新字幕模板
* @param templateId 模板ID
* @param template 模板配置
*/
export async function updateSubtitleTemplate(templateId: string, template: SubtitleTemplate): Promise<boolean> {
try {
console.log('[updateSubtitleTemplate] 开始更新模板:', templateId);
const result = await window.$mapi.ipAgent.updateSubtitleTemplate({
id: templateId,
name: template.name,
description: template.description,
config: template.config
});
if (result.success) {
console.log('[updateSubtitleTemplate] 更新成功');
return true;
} else {
console.error('[updateSubtitleTemplate] 更新失败:', result.message);
return false;
}
} catch (error) {
console.error('[updateSubtitleTemplate] 更新异常:', error);
return false;
}
}
/**
* 导出所有字幕模板
* @param includeSystemOnly 是否仅导出系统模板
* @returns 导出结果
*/
export async function exportSubtitleTemplates(includeSystemOnly: boolean = false): Promise<any> {
try {
console.log('[exportSubtitleTemplates] 开始导出字幕模板配置', {
includeSystemOnly
});
const result = await window.$mapi.ipAgent.exportSubtitleTemplates({
includeSystemOnly
});
if (result.success) {
console.log('[exportSubtitleTemplates] 导出成功,包含 ' + result.count + ' 个模板');
return result;
} else {
throw new Error(result.message || '导出失败');
}
} catch (error) {
console.error('[exportSubtitleTemplates] 导出异常:', error);
throw error;
}
}
/**
* 导出单个字幕模板为JSON
* @param templateId 模板ID
* @returns 导出的JSON数据
*/
export async function exportSubtitleTemplate(templateId: string): Promise<any> {
try {
console.log('[exportSubtitleTemplate] 开始导出单个字幕模板:', templateId);
const result = await window.$mapi.ipAgent.exportSubtitleTemplateById({
id: templateId
});
if (result.success && result.data) {
console.log('[exportSubtitleTemplate] 导出成功:', result.data.subtitleTemplate.name);
return result.data;
} else {
throw new Error(result.message || '导出失败');
}
} catch (error) {
console.error('[exportSubtitleTemplate] 导出异常:', error);
throw error;
}
}
/**
* 下载JSON文件
* @param data JSON数据
* @param filename 文件名
*/
export function downloadJSON(data: any, filename: string = 'subtitle-templates.json'): void {
try {
const jsonString = JSON.stringify(data, null, 2);
const blob = new Blob([jsonString], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
console.log('[downloadJSON] 文件下载成功:', filename);
} catch (error) {
console.error('[downloadJSON] 文件下载失败:', error);
throw error;
}
}
/**
* 复制字幕模板
* @param templateId 源模板ID
* @param newName 新模板名称(可选)
* @returns 新模板ID
*/
export async function duplicateSubtitleTemplate(templateId: string, newName?: string): Promise<string> {
try {
console.log('[duplicateSubtitleTemplate] 开始复制模板:', {
sourceId: templateId,
newName
});
// 调用后端 IPC API
const result = await window.$mapi.ipAgent.duplicateSubtitleTemplate({
id: templateId,
newName
});
if (result.success && result.id) {
console.log('[duplicateSubtitleTemplate] ✅ 复制成功:', {
newId: result.id,
newName: result.name
});
return result.id;
} else {
throw new Error(result.message || '复制模板失败');
}
} catch (error) {
console.error('[duplicateSubtitleTemplate] ❌ 复制失败:', error);
throw error;
}
}
/**
* 导出所有字幕模板(更新配置文件)
* @param includeSystemOnly 是否仅导出系统模板
*/
export async function exportAndDownloadSubtitleTemplates(includeSystemOnly: boolean = false): Promise<void> {
try {
const result = await exportSubtitleTemplates(includeSystemOnly);
console.log('[exportAndDownloadSubtitleTemplates] 字幕模板已导出到配置文件', {
count: result.count,
configPath: result.configPath
});
} catch (error) {
console.error('[exportAndDownloadSubtitleTemplates] 导出失败:', error);
throw error;
}
}
/**
* 导出并下载单个字幕模板
* @param templateId 模板ID
*/
export async function exportAndDownloadSubtitleTemplate(templateId: string): Promise<void> {
try {
const exportData = await exportSubtitleTemplate(templateId);
const templateName = exportData.subtitleTemplate.name.replace(/[\s\/\\:*?"<>|]/g, '_');
const filename = `subtitle-template-${templateName}.json`;
downloadJSON(exportData, filename);
console.log('[exportAndDownloadSubtitleTemplate] 导出并下载完成:', filename);
} catch (error) {
console.error('[exportAndDownloadSubtitleTemplate] 导出下载失败:', error);
throw error;
}
}
export async function importSubtitleTemplateFromFile(): Promise<{ success: boolean; id?: string; name?: string; message?: string }> {
try {
const result = await window.$mapi.ipAgent.importSubtitleTemplate();
return result;
} catch (error: any) {
console.error('[importSubtitleTemplateFromFile] 导入失败:', error);
return { success: false, message: error?.message || '导入失败' };
}
}
+166
View File
@@ -0,0 +1,166 @@
/**
* 系统模板管理 API
* 用于开发模式下编辑系统字幕和封面模板
*
* ✨ 改进:保存时自动导出到配置文件
*/
import { useDevMode } from '@/composables/useDevMode';
/**
* 获取系统模板列表
*/
export async function getSystemTemplatesList() {
try {
const result = await window.$mapi.subtitleCover.getSystemTemplatesList();
return result;
} catch (error: any) {
console.error('Failed to get system templates list:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 保存/编辑字幕模板并自动导出(开发模式)
* ✨ 新增:保存时自动导出到 system-templates.json
*/
export async function saveSubtitleTemplateWithAutoExport(template: any) {
try {
const isDev = isDevMode();
if (!isDev) {
throw new Error('System templates can only be edited in development mode');
}
const result = await window.$mapi.subtitleCover.saveSubtitleTemplateAndExport(template, isDev);
return result;
} catch (error: any) {
console.error('Failed to save subtitle template:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 保存/编辑封面模板并自动导出(开发模式)
* ✨ 新增:保存时自动导出到 system-templates.json
*/
export async function saveCoverTemplateWithAutoExport(template: any) {
try {
const isDev = isDevMode();
if (!isDev) {
throw new Error('System templates can only be edited in development mode');
}
const result = await window.$mapi.subtitleCover.saveCoverTemplateAndExport(template, isDev);
return result;
} catch (error: any) {
console.error('Failed to save cover template:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 保存/编辑系统模板(仅在开发模式)
*
* @deprecated 请使用 saveSubtitleTemplateWithAutoExport 或 saveCoverTemplateWithAutoExport
*/
export async function saveSystemTemplate(template: any) {
try {
const isDev = isDevMode();
if (!isDev) {
throw new Error('System templates can only be edited in development mode');
}
// 在生产模式下,强制设置 readonly = true
if (!isDev && template.readonly === undefined) {
template.readonly = true;
}
const result = await window.$mapi.subtitleCover.saveSystemTemplate(template, isDev);
return result;
} catch (error: any) {
console.error('Failed to save system template:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 删除系统模板(仅在开发模式,且不能删除系统模板)
*/
export async function deleteSystemTemplate(templateId: string) {
try {
const isDev = useDevMode().isDev.value;
if (!isDev) {
throw new Error('Cannot delete system templates in production mode');
}
const result = await window.$mapi.subtitleCover.deleteSystemTemplate(templateId, isDev);
return result;
} catch (error: any) {
console.error('Failed to delete system template:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 重置系统模板为默认值(仅在开发模式)
*/
export async function resetSystemTemplates() {
try {
const isDev = useDevMode().isDev.value;
if (!isDev) {
throw new Error('System templates can only be reset in development mode');
}
const result = await window.$mapi.subtitleCover.resetSystemTemplates(isDev);
return result;
} catch (error: any) {
console.error('Failed to reset system templates:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 导出系统模板配置到文件(仅在开发模式)
*/
export async function exportSystemTemplatesToFile() {
try {
const isDev = isDevMode();
if (!isDev) {
throw new Error('System templates can only be exported in development mode');
}
const result = await window.$mapi.subtitleCover.exportSystemTemplatesToFile(isDev);
return result;
} catch (error: any) {
console.error('Failed to export system templates:', error);
return {
success: false,
error: error.message || String(error)
};
}
}
/**
* 检查是否为开发模式
*/
export function isDevMode(): boolean {
return useDevMode().isDev.value;
}
+5
View File
@@ -0,0 +1,5 @@
interface ApiResult<T> {
code: number;
msg: string;
data: T;
}
+15
View File
@@ -0,0 +1,15 @@
import {request} from "../lib/api";
export function userInfoApi(): Promise<
ApiResult<{
apiToken: string;
user: object;
data: any;
basic: object;
}>
> {
return request({
url: "app_manager/user_info",
method: "post",
});
}
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="400px" height="400px">
<rect width="100%" height="100%" fill="rgb(241, 242, 243)" />
<path fill="#8bb7f0" d="M8.505,77.5c0.267-12.729,10.704-23,23.495-23h16c12.791,0,23.229,10.271,23.495,23H8.505z"/>
<path fill="#4e7ab5"
d="M48,55c12.347,0,22.453,9.78,22.979,22H9.021C9.547,64.78,19.653,55,32,55H48 M48,54H32 C18.745,54,8,64.745,8,78h64C72,64.745,61.255,54,48,54L48,54z"/>
<path fill="#deb974" d="M40,61.5c-7.009,0-9.215-4.771-9.5-5.47V44.5h19v11.53C49.215,56.729,47.009,61.5,40,61.5z"/>
<path fill="#967a44"
d="M49,45v10.927C48.618,56.797,46.437,61,40,61c-6.444,0-8.623-4.212-9-5.072V45H49 M50,44H30v12.124 c0,0,2.133,5.876,10,5.876c7.867,0,10-5.876,10-5.876V44L50,44z"/>
<path fill="#deb974"
d="M54.286,38.929c-2.875,0-5.215-2.339-5.215-5.214s2.34-5.215,5.215-5.215 c3.703,0,5.214,0.959,5.214,3.31C59.5,34.621,57.164,38.929,54.286,38.929z M25.714,38.929c-2.878,0-5.214-4.308-5.214-7.119 c0-2.351,1.511-3.31,5.214-3.31c2.875,0,5.215,2.34,5.215,5.215S28.589,38.929,25.714,38.929z"/>
<path fill="#967a44"
d="M54.286,29C58.211,29,59,30.075,59,31.81c0,2.829-2.331,6.619-4.714,6.619 c-2.599,0-4.714-2.115-4.714-4.714S51.686,29,54.286,29 M25.714,29c2.599,0,4.714,2.115,4.714,4.714s-2.115,4.714-4.714,4.714 c-2.384,0-4.714-3.79-4.714-6.619C21,30.075,21.789,29,25.714,29 M54.286,28c-3.156,0-5.714,2.558-5.714,5.714 c0,3.156,2.558,5.714,5.714,5.714c3.156,0,5.714-4.463,5.714-7.619C60,28.654,57.442,28,54.286,28L54.286,28z M25.714,28 C22.558,28,20,28.654,20,31.81c0,3.156,2.558,7.619,5.714,7.619c3.156,0,5.714-2.558,5.714-5.714 C31.429,30.558,28.87,28,25.714,28L25.714,28z"/>
<g>
<path fill="#f5ce85"
d="M40,53.5c-1.343,0-2.638-0.495-3.648-1.394l-0.091-0.08l-0.117-0.03 C29.288,50.238,24.5,44.071,24.5,37V18.403c0-3.93,3.196-7.126,7.125-7.126h16.75c3.929,0,7.125,3.196,7.125,7.126V37 c0,7.071-4.788,13.238-11.644,14.996l-0.117,0.03l-0.091,0.08C42.638,53.005,41.343,53.5,40,53.5z"/>
<path fill="#967a44"
d="M48.375,11.778c3.653,0,6.625,2.972,6.625,6.625V37c0,6.842-4.633,12.81-11.268,14.512l-0.235,0.06 l-0.181,0.161C42.398,52.55,41.22,53,40,53s-2.398-0.45-3.316-1.267l-0.181-0.161l-0.235-0.06C29.633,49.81,25,43.842,25,37 V18.403c0-3.653,2.972-6.625,6.625-6.625H48.375 M48.375,10.778H31.625c-4.211,0-7.625,3.414-7.625,7.625V37 c0,7.46,5.112,13.708,12.019,15.48C37.079,53.423,38.47,54,40,54h0c1.53,0,2.921-0.577,3.981-1.52C50.888,50.708,56,44.46,56,37 V18.403C56,14.192,52.586,10.778,48.375,10.778L48.375,10.778z"/>
</g>
<g>
<path fill="#a6714e"
d="M55.5,35.5V28c0-7.021-6.83-10.765-7.121-10.92l-0.352-0.188l-0.262,0.301 c-0.053,0.06-5.359,6.021-14.466,6.021c-3.777,0-8.8,0.703-8.8,6.786v5.5h-0.181c-0.686-1.507-3.819-8.734-3.819-14.877 C20.5,9.783,27.935,2.5,39,2.5c8.037,0,10.44,5.461,10.539,5.693l0.129,0.306L50,8.5c3.528,0,9.5,2.429,9.5,11.53 c0,5.623-3.162,13.793-3.836,15.47H55.5z"/>
<path fill="#7a4f34"
d="M39,3c7.678,0,9.985,5.17,10.077,5.385L49.334,9H50c0.921,0,9,0.31,9,11.03 c0,4.238-1.84,9.983-3,13.181V28c0-7.316-7.083-11.199-7.384-11.361l-0.704-0.377l-0.524,0.603 c-0.051,0.058-5.187,5.849-14.088,5.849c-2.3,0-9.3,0-9.3,7.286v3.477c-1.152-2.863-3-8.183-3-12.855C21,10.082,28.234,3,39,3 M39,2C27.362,2,20,9.962,20,20.623C20,27.684,24,36,24,36h1c0,0,0-4.057,0-6c0-5.336,4.048-6.286,8.3-6.286 c9.46,0,14.843-6.193,14.843-6.193S55,21.198,55,28c0,2.137,0,8,0,8h1c0,0,4-9.535,4-15.97C60,10.995,54.247,8,50,8 C50,8,47.494,2,39,2L39,2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726117140621" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1850" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><path d="M512 932A420 420 0 1 1 512 92a420 420 0 0 1 0 840z m212.58-466.68H486.08a20.76 20.76 0 0 0-20.76 20.76v51.84c0 11.46 9.3 20.76 20.7 20.76h145.2c11.52 0 20.76 9.3 20.76 20.7v10.38c0 34.38-27.84 62.22-62.22 62.22H392.72a20.76 20.76 0 0 1-20.7-20.7V434.24c0-34.38 27.84-62.22 62.16-62.22h290.4c11.4 0 20.7-9.3 20.7-20.76v-51.84a20.76 20.76 0 0 0-20.7-20.76h-290.4a155.52 155.52 0 0 0-155.52 155.58v290.34c0 11.46 9.3 20.76 20.76 20.76h305.88a139.98 139.98 0 0 0 140.04-139.98V486.08a20.76 20.76 0 0 0-20.76-20.76z" fill="#C71D23" p-id="1851"></path></svg>

After

Width:  |  Height:  |  Size: 887 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726117145613" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1997" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><path d="M511.62332577 101.70772891C278.74455939 101.61356015 90.125 290.13895078 90.125 522.82938046 90.125 706.83468204 208.11816406 863.24860468 372.44224295 920.69140625c22.12960391 5.55594296 18.73953671-10.17020077 18.73953754-20.9054133v-72.98060779c-127.78669061 14.97279611-132.96596018-69.59054141-141.53529612-83.71582031C232.3194758 713.52064768 191.35616641 705.98716482 203.59807501 691.86188592c29.09807501-14.97279611 58.76116095 3.76674142 93.13267264 54.52357737 24.86049142 36.81989374 73.35728201 30.60477109 97.93526797 24.4838172 5.36760626-22.12960391 16.85616641-41.90499454 32.67647892-57.25446487-132.40094842-23.73046875-187.58370547-104.52706485-187.58370548-200.57896171 0-46.61342111 15.34946951-89.4601008 45.48339844-124.01995001-19.2103797-56.97195859 1.78920236-105.75125546 4.61425781-113.00223202 54.71191406-4.89676328 111.58970389 39.17410702 116.015625 42.65834298 31.07561407-8.38099924 66.57714844-12.80691952 106.31626639-12.80692035 39.92745548 0 75.5231586 4.61425781 106.88127814 13.08942581 10.64104376-8.09849295 63.37541876-45.95424142 114.22642346-41.33998361 2.7308875 7.25097656 23.25962576 54.90025076 5.17926874 111.11886173 30.51060233 34.65401798 46.04840936 77.87737189 46.04840936 124.58496093 0 96.24023438-55.55943045 177.13099924-188.3370531 200.48479377a120.06487189 120.06487189 0 0 1 35.87820859 85.69335937v105.93959217c0.75334845 8.47516718 0 16.85616641 14.1252789 16.85616641 166.77246094-56.21861014 286.83733282-213.76255545 286.83733282-399.36872187 0-232.78459845-188.71372732-421.21582031-421.40415784-421.21582031z" p-id="1998"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
<!-- Background Circle -->
<circle cx="512" cy="512" r="480" fill="white"/>
<!-- Hexagon Shape -->
<path d="M 512 180 L 712 290 L 712 510 L 512 620 L 312 510 L 312 290 Z"
fill="none" stroke="#e5e7eb" stroke-width="24" stroke-linejoin="round"/>
<!-- Inner Hexagon -->
<path d="M 512 240 L 672 330 L 672 470 L 512 560 L 352 470 L 352 330 Z"
fill="none" stroke="#d1d5db" stroke-width="16" stroke-linejoin="round"/>
<!-- Letter "A" formed by geometric shapes -->
<g transform="translate(512, 512)">
<!-- Left bar of A -->
<rect x="-120" y="-150" width="60" height="300" rx="12" fill="#6366f1"/>
<!-- Right bar of A -->
<rect x="60" y="-150" width="60" height="300" rx="12" fill="#6366f1"/>
<!-- Top horizontal bar -->
<rect x="-90" y="-150" width="180" height="60" rx="12" fill="#8b5cf6"/>
<!-- Middle horizontal bar -->
<rect x="-75" y="-20" width="150" height="50" rx="10" fill="#6366f1"/>
</g>
<!-- Bottom accent circles -->
<circle cx="400" cy="750" r="25" fill="#e5e7eb"/>
<circle cx="512" cy="800" r="18" fill="#d1d5db"/>
<circle cx="624" cy="750" r="25" fill="#e5e7eb"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+45
View File
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
<defs>
<linearGradient id="mainGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />
<stop offset="50%" style="stop-color:#8b5cf6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#d946ef;stop-opacity:1" />
</linearGradient>
<linearGradient id="accentGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#06b6d4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#3b82f6;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background Circle -->
<circle cx="512" cy="512" r="480" fill="url(#mainGradient)"/>
<!-- Hexagon Shape -->
<path d="M 512 180 L 712 290 L 712 510 L 512 620 L 312 510 L 312 290 Z"
fill="none" stroke="white" stroke-width="24" stroke-linejoin="round" opacity="0.3"/>
<!-- Inner Hexagon -->
<path d="M 512 240 L 672 330 L 672 470 L 512 560 L 352 470 L 352 330 Z"
fill="none" stroke="white" stroke-width="16" stroke-linejoin="round" opacity="0.5"/>
<!-- Letter "A" formed by geometric shapes -->
<g transform="translate(512, 512)">
<!-- Left bar of A -->
<rect x="-120" y="-150" width="60" height="300" rx="12" fill="white"/>
<!-- Right bar of A -->
<rect x="60" y="-150" width="60" height="300" rx="12" fill="white"/>
<!-- Top horizontal bar -->
<rect x="-90" y="-150" width="180" height="60" rx="12" fill="url(#accentGradient)"/>
<!-- Middle horizontal bar -->
<rect x="-75" y="-20" width="150" height="50" rx="10" fill="white" opacity="0.9"/>
</g>
<!-- Bottom accent circles -->
<circle cx="400" cy="750" r="25" fill="white" opacity="0.6"/>
<circle cx="512" cy="800" r="18" fill="white" opacity="0.4"/>
<circle cx="624" cy="750" r="25" fill="white" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File

Some files were not shown because too many files have changed in this diff Show More